1use std::cell::Cell;
4use std::fmt;
5use std::fmt::Write;
6use std::sync::LazyLock;
7
8use indexmap::IndexMap;
9use indexmap::IndexSet;
10use wdl_ast::SupportedVersion;
11use wdl_ast::version::V1;
12
13use crate::types::ArrayType;
14use crate::types::Coercible;
15use crate::types::CompoundType;
16use crate::types::MapType;
17use crate::types::Optional;
18use crate::types::PairType;
19use crate::types::PrimitiveType;
20use crate::types::Type;
21
22mod constraints;
23
24pub use constraints::*;
25
26pub const MAX_TYPE_PARAMETERS: usize = 4;
34
35#[allow(clippy::missing_docs_in_private_items)]
36const _: () = assert!(
37 MAX_TYPE_PARAMETERS < usize::BITS as usize,
38 "the maximum number of type parameters cannot exceed the number of bits in usize"
39);
40
41pub const MAX_PARAMETERS: usize = 4;
51
52fn write_uninferred_constraints(
55 s: &mut impl fmt::Write,
56 params: &TypeParameters<'_>,
57) -> Result<(), fmt::Error> {
58 for (i, (name, constraint)) in params
59 .referenced()
60 .filter_map(|(p, ty)| {
61 if ty.is_some() {
63 return None;
64 }
65
66 Some((p.name, p.constraint()?))
67 })
68 .enumerate()
69 {
70 if i == 0 {
71 s.write_str(" where ")?;
72 } else if i > 1 {
73 s.write_str(", ")?;
74 }
75
76 write!(s, "`{name}`: {desc}", desc = constraint.description())?;
77 }
78
79 Ok(())
80}
81
82#[derive(Debug, Clone, PartialEq, Eq)]
85pub enum FunctionBindError {
86 RequiresVersion(SupportedVersion),
88 TooFewArguments(usize),
92 TooManyArguments(usize),
96 ArgumentTypeMismatch {
98 index: usize,
100 expected: String,
102 },
103 Ambiguous {
105 first: String,
107 second: String,
109 },
110}
111
112#[derive(Debug, Clone)]
114pub enum GenericType {
115 Parameter(&'static str),
117 UnqualifiedParameter(&'static str),
121 Array(GenericArrayType),
123 Pair(GenericPairType),
125 Map(GenericMapType),
127}
128
129impl GenericType {
130 pub fn display<'a>(&'a self, params: &'a TypeParameters<'a>) -> impl fmt::Display + 'a {
132 #[allow(clippy::missing_docs_in_private_items)]
133 struct Display<'a> {
134 params: &'a TypeParameters<'a>,
135 ty: &'a GenericType,
136 }
137
138 impl fmt::Display for Display<'_> {
139 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
140 match self.ty {
141 GenericType::Parameter(name) | GenericType::UnqualifiedParameter(name) => {
142 let (_, ty) = self.params.get(name).expect("the name should be present");
143 match ty {
144 Some(ty) => {
145 if let GenericType::UnqualifiedParameter(_) = self.ty {
146 ty.require().fmt(f)
147 } else {
148 ty.fmt(f)
149 }
150 }
151 None => {
152 write!(f, "{name}")
153 }
154 }
155 }
156 GenericType::Array(ty) => ty.display(self.params).fmt(f),
157 GenericType::Pair(ty) => ty.display(self.params).fmt(f),
158 GenericType::Map(ty) => ty.display(self.params).fmt(f),
159 }
160 }
161 }
162
163 Display { params, ty: self }
164 }
165
166 fn infer_type_parameters(
168 &self,
169 ty: &Type,
170 params: &mut TypeParameters<'_>,
171 ignore_constraints: bool,
172 ) {
173 match self {
174 Self::Parameter(name) | Self::UnqualifiedParameter(name) => {
175 let (param, _) = params.get(name).expect("should have parameter");
177
178 if !ignore_constraints {
179 if let Some(constraint) = param.constraint() {
180 if !constraint.satisfied(ty) {
181 return;
182 }
183 }
184 }
185
186 params.set_inferred_type(name, ty.clone());
187 }
188 Self::Array(array) => array.infer_type_parameters(ty, params, ignore_constraints),
189 Self::Pair(pair) => pair.infer_type_parameters(ty, params, ignore_constraints),
190 Self::Map(map) => map.infer_type_parameters(ty, params, ignore_constraints),
191 }
192 }
193
194 fn realize(&self, params: &TypeParameters<'_>) -> Option<Type> {
196 match self {
197 Self::Parameter(name) => {
198 params
199 .get(name)
200 .expect("type parameter should be present")
201 .1
202 }
203 Self::UnqualifiedParameter(name) => params
204 .get(name)
205 .expect("type parameter should be present")
206 .1
207 .map(|ty| ty.require()),
208 Self::Array(ty) => ty.realize(params),
209 Self::Pair(ty) => ty.realize(params),
210 Self::Map(ty) => ty.realize(params),
211 }
212 }
213
214 fn assert_type_parameters(&self, parameters: &[TypeParameter]) {
220 match self {
221 Self::Parameter(n) | Self::UnqualifiedParameter(n) => assert!(
222 parameters.iter().any(|p| p.name == *n),
223 "generic type references unknown type parameter `{n}`"
224 ),
225 Self::Array(a) => a.assert_type_parameters(parameters),
226 Self::Pair(p) => p.assert_type_parameters(parameters),
227 Self::Map(m) => m.assert_type_parameters(parameters),
228 }
229 }
230}
231
232impl From<GenericArrayType> for GenericType {
233 fn from(value: GenericArrayType) -> Self {
234 Self::Array(value)
235 }
236}
237
238impl From<GenericPairType> for GenericType {
239 fn from(value: GenericPairType) -> Self {
240 Self::Pair(value)
241 }
242}
243
244impl From<GenericMapType> for GenericType {
245 fn from(value: GenericMapType) -> Self {
246 Self::Map(value)
247 }
248}
249
250#[derive(Debug, Clone)]
252pub struct GenericArrayType {
253 element_type: Box<FunctionalType>,
255 non_empty: bool,
257}
258
259impl GenericArrayType {
260 pub fn new(element_type: impl Into<FunctionalType>) -> Self {
262 Self {
263 element_type: Box::new(element_type.into()),
264 non_empty: false,
265 }
266 }
267
268 pub fn non_empty(element_type: impl Into<FunctionalType>) -> Self {
270 Self {
271 element_type: Box::new(element_type.into()),
272 non_empty: true,
273 }
274 }
275
276 pub fn element_type(&self) -> &FunctionalType {
278 &self.element_type
279 }
280
281 pub fn is_non_empty(&self) -> bool {
283 self.non_empty
284 }
285
286 pub fn display<'a>(&'a self, params: &'a TypeParameters<'a>) -> impl fmt::Display + 'a {
288 #[allow(clippy::missing_docs_in_private_items)]
289 struct Display<'a> {
290 params: &'a TypeParameters<'a>,
291 ty: &'a GenericArrayType,
292 }
293
294 impl fmt::Display for Display<'_> {
295 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
296 write!(f, "Array[")?;
297 self.ty.element_type.display(self.params).fmt(f)?;
298 write!(f, "]")?;
299
300 if self.ty.is_non_empty() {
301 write!(f, "+")?;
302 }
303
304 Ok(())
305 }
306 }
307
308 Display { params, ty: self }
309 }
310
311 fn infer_type_parameters(
313 &self,
314 ty: &Type,
315 params: &mut TypeParameters<'_>,
316 ignore_constraints: bool,
317 ) {
318 match ty {
319 Type::Union => {
320 self.element_type
321 .infer_type_parameters(&Type::Union, params, ignore_constraints);
322 }
323 Type::Compound(CompoundType::Array(ty), false) => {
324 self.element_type.infer_type_parameters(
325 ty.element_type(),
326 params,
327 ignore_constraints,
328 );
329 }
330 _ => {}
331 }
332 }
333
334 fn realize(&self, params: &TypeParameters<'_>) -> Option<Type> {
336 let ty = self.element_type.realize(params)?;
337 if self.non_empty {
338 Some(ArrayType::non_empty(ty).into())
339 } else {
340 Some(ArrayType::new(ty).into())
341 }
342 }
343
344 fn assert_type_parameters(&self, parameters: &[TypeParameter]) {
350 self.element_type.assert_type_parameters(parameters);
351 }
352}
353
354#[derive(Debug, Clone)]
356pub struct GenericPairType {
357 left_type: Box<FunctionalType>,
359 right_type: Box<FunctionalType>,
361}
362
363impl GenericPairType {
364 pub fn new(
366 left_type: impl Into<FunctionalType>,
367 right_type: impl Into<FunctionalType>,
368 ) -> Self {
369 Self {
370 left_type: Box::new(left_type.into()),
371 right_type: Box::new(right_type.into()),
372 }
373 }
374
375 pub fn left_type(&self) -> &FunctionalType {
377 &self.left_type
378 }
379
380 pub fn right_type(&self) -> &FunctionalType {
382 &self.right_type
383 }
384
385 pub fn display<'a>(&'a self, params: &'a TypeParameters<'a>) -> impl fmt::Display + 'a {
387 #[allow(clippy::missing_docs_in_private_items)]
388 struct Display<'a> {
389 params: &'a TypeParameters<'a>,
390 ty: &'a GenericPairType,
391 }
392
393 impl fmt::Display for Display<'_> {
394 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
395 write!(f, "Pair[")?;
396 self.ty.left_type.display(self.params).fmt(f)?;
397 write!(f, ", ")?;
398 self.ty.right_type.display(self.params).fmt(f)?;
399 write!(f, "]")
400 }
401 }
402
403 Display { params, ty: self }
404 }
405
406 fn infer_type_parameters(
408 &self,
409 ty: &Type,
410 params: &mut TypeParameters<'_>,
411 ignore_constraints: bool,
412 ) {
413 match ty {
414 Type::Union => {
415 self.left_type
416 .infer_type_parameters(&Type::Union, params, ignore_constraints);
417 self.right_type
418 .infer_type_parameters(&Type::Union, params, ignore_constraints);
419 }
420 Type::Compound(CompoundType::Pair(ty), false) => {
421 self.left_type
422 .infer_type_parameters(ty.left_type(), params, ignore_constraints);
423 self.right_type
424 .infer_type_parameters(ty.right_type(), params, ignore_constraints);
425 }
426 _ => {}
427 }
428 }
429
430 fn realize(&self, params: &TypeParameters<'_>) -> Option<Type> {
432 let left_type = self.left_type.realize(params)?;
433 let right_type = self.right_type.realize(params)?;
434 Some(PairType::new(left_type, right_type).into())
435 }
436
437 fn assert_type_parameters(&self, parameters: &[TypeParameter]) {
443 self.left_type.assert_type_parameters(parameters);
444 self.right_type.assert_type_parameters(parameters);
445 }
446}
447
448#[derive(Debug, Clone)]
450pub struct GenericMapType {
451 key_type: Box<FunctionalType>,
453 value_type: Box<FunctionalType>,
455}
456
457impl GenericMapType {
458 pub fn new(key_type: impl Into<FunctionalType>, value_type: impl Into<FunctionalType>) -> Self {
460 Self {
461 key_type: Box::new(key_type.into()),
462 value_type: Box::new(value_type.into()),
463 }
464 }
465
466 pub fn key_type(&self) -> &FunctionalType {
468 &self.key_type
469 }
470
471 pub fn value_type(&self) -> &FunctionalType {
473 &self.value_type
474 }
475
476 pub fn display<'a>(&'a self, params: &'a TypeParameters<'a>) -> impl fmt::Display + 'a {
478 #[allow(clippy::missing_docs_in_private_items)]
479 struct Display<'a> {
480 params: &'a TypeParameters<'a>,
481 ty: &'a GenericMapType,
482 }
483
484 impl fmt::Display for Display<'_> {
485 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
486 write!(f, "Map[")?;
487 self.ty.key_type.display(self.params).fmt(f)?;
488 write!(f, ", ")?;
489 self.ty.value_type.display(self.params).fmt(f)?;
490 write!(f, "]")
491 }
492 }
493
494 Display { params, ty: self }
495 }
496
497 fn infer_type_parameters(
499 &self,
500 ty: &Type,
501 params: &mut TypeParameters<'_>,
502 ignore_constraints: bool,
503 ) {
504 match ty {
505 Type::Union => {
506 self.key_type
507 .infer_type_parameters(&Type::Union, params, ignore_constraints);
508 self.value_type
509 .infer_type_parameters(&Type::Union, params, ignore_constraints);
510 }
511 Type::Compound(CompoundType::Map(ty), false) => {
512 self.key_type
513 .infer_type_parameters(ty.key_type(), params, ignore_constraints);
514 self.value_type
515 .infer_type_parameters(ty.value_type(), params, ignore_constraints);
516 }
517 _ => {}
518 }
519 }
520
521 fn realize(&self, params: &TypeParameters<'_>) -> Option<Type> {
523 let key_type = self.key_type.realize(params)?;
524 let value_type = self.value_type.realize(params)?;
525 Some(MapType::new(key_type, value_type).into())
526 }
527
528 fn assert_type_parameters(&self, parameters: &[TypeParameter]) {
534 self.key_type.assert_type_parameters(parameters);
535 self.value_type.assert_type_parameters(parameters);
536 }
537}
538
539#[derive(Debug, Clone)]
541pub struct TypeParameters<'a> {
542 parameters: &'a [TypeParameter],
544 inferred_types: [Option<Type>; MAX_TYPE_PARAMETERS],
546 referenced: Cell<usize>,
549}
550
551impl<'a> TypeParameters<'a> {
552 pub fn new(parameters: &'a [TypeParameter]) -> Self {
560 assert!(
561 parameters.len() < MAX_TYPE_PARAMETERS,
562 "no more than {MAX_TYPE_PARAMETERS} type parameters is supported"
563 );
564
565 Self {
566 parameters,
567 inferred_types: [const { None }; MAX_TYPE_PARAMETERS],
568 referenced: Cell::new(0),
569 }
570 }
571
572 pub fn get(&self, name: &str) -> Option<(&TypeParameter, Option<Type>)> {
578 let index = self.parameters.iter().position(|p| p.name == name)?;
579
580 self.referenced.set(self.referenced.get() | (1 << index));
582
583 Some((&self.parameters[index], self.inferred_types[index].clone()))
584 }
585
586 pub fn reset(&self) {
588 self.referenced.set(0);
589 }
590
591 pub fn referenced(&self) -> impl Iterator<Item = (&TypeParameter, Option<Type>)> + use<'_> {
594 let mut bits = self.referenced.get();
595 std::iter::from_fn(move || {
596 if bits == 0 {
597 return None;
598 }
599
600 let index = bits.trailing_zeros() as usize;
601 let parameter = &self.parameters[index];
602 let ty = self.inferred_types[index].clone();
603 bits ^= bits & bits.overflowing_neg().0;
604 Some((parameter, ty))
605 })
606 }
607
608 fn set_inferred_type(&mut self, name: &str, ty: Type) {
617 let index = self
618 .parameters
619 .iter()
620 .position(|p| p.name == name)
621 .unwrap_or_else(|| panic!("unknown type parameter `{name}`"));
622
623 self.inferred_types[index].get_or_insert(ty);
624 }
625}
626
627#[derive(Debug, Clone)]
629pub enum FunctionalType {
630 Concrete(Type),
632 Generic(GenericType),
634}
635
636impl FunctionalType {
637 pub fn is_generic(&self) -> bool {
639 matches!(self, Self::Generic(_))
640 }
641
642 pub fn concrete_type(&self) -> Option<&Type> {
646 match self {
647 Self::Concrete(ty) => Some(ty),
648 Self::Generic(_) => None,
649 }
650 }
651
652 pub fn display<'a>(&'a self, params: &'a TypeParameters<'a>) -> impl fmt::Display + 'a {
654 #[allow(clippy::missing_docs_in_private_items)]
655 struct Display<'a> {
656 params: &'a TypeParameters<'a>,
657 ty: &'a FunctionalType,
658 }
659
660 impl fmt::Display for Display<'_> {
661 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
662 match self.ty {
663 FunctionalType::Concrete(ty) => ty.fmt(f),
664 FunctionalType::Generic(ty) => ty.display(self.params).fmt(f),
665 }
666 }
667 }
668
669 Display { params, ty: self }
670 }
671
672 fn infer_type_parameters(
674 &self,
675 ty: &Type,
676 params: &mut TypeParameters<'_>,
677 ignore_constraints: bool,
678 ) {
679 if let Self::Generic(generic) = self {
680 generic.infer_type_parameters(ty, params, ignore_constraints);
681 }
682 }
683
684 fn realize(&self, params: &TypeParameters<'_>) -> Option<Type> {
686 match self {
687 FunctionalType::Concrete(ty) => Some(ty.clone()),
688 FunctionalType::Generic(ty) => ty.realize(params),
689 }
690 }
691
692 fn assert_type_parameters(&self, parameters: &[TypeParameter]) {
698 if let FunctionalType::Generic(ty) = self {
699 ty.assert_type_parameters(parameters)
700 }
701 }
702}
703
704impl From<Type> for FunctionalType {
705 fn from(value: Type) -> Self {
706 Self::Concrete(value)
707 }
708}
709
710impl From<PrimitiveType> for FunctionalType {
711 fn from(value: PrimitiveType) -> Self {
712 Self::Concrete(value.into())
713 }
714}
715
716impl From<GenericType> for FunctionalType {
717 fn from(value: GenericType) -> Self {
718 Self::Generic(value)
719 }
720}
721
722impl From<GenericArrayType> for FunctionalType {
723 fn from(value: GenericArrayType) -> Self {
724 Self::Generic(GenericType::Array(value))
725 }
726}
727
728impl From<GenericPairType> for FunctionalType {
729 fn from(value: GenericPairType) -> Self {
730 Self::Generic(GenericType::Pair(value))
731 }
732}
733
734impl From<GenericMapType> for FunctionalType {
735 fn from(value: GenericMapType) -> Self {
736 Self::Generic(GenericType::Map(value))
737 }
738}
739
740#[derive(Debug)]
742pub struct TypeParameter {
743 name: &'static str,
745 constraint: Option<Box<dyn Constraint>>,
747}
748
749impl TypeParameter {
750 pub fn any(name: &'static str) -> Self {
752 Self {
753 name,
754 constraint: None,
755 }
756 }
757
758 pub fn new(name: &'static str, constraint: impl Constraint + 'static) -> Self {
760 Self {
761 name,
762 constraint: Some(Box::new(constraint)),
763 }
764 }
765
766 pub fn name(&self) -> &str {
768 self.name
769 }
770
771 pub fn constraint(&self) -> Option<&dyn Constraint> {
773 self.constraint.as_deref()
774 }
775}
776
777#[derive(Debug, Clone)]
779enum BindingKind {
780 Equivalence(Type),
785 Coercion(Type),
790}
791
792impl BindingKind {
793 pub fn ret(&self) -> &Type {
795 match self {
796 Self::Equivalence(ty) | Self::Coercion(ty) => ty,
797 }
798 }
799}
800
801#[derive(Debug)]
803pub struct FunctionSignature {
804 minimum_version: Option<SupportedVersion>,
806 type_parameters: Vec<TypeParameter>,
808 required: Option<usize>,
810 parameters: Vec<FunctionalType>,
812 ret: FunctionalType,
814}
815
816impl FunctionSignature {
817 pub fn builder() -> FunctionSignatureBuilder {
819 FunctionSignatureBuilder::new()
820 }
821
822 pub fn minimum_version(&self) -> SupportedVersion {
824 self.minimum_version
825 .unwrap_or(SupportedVersion::V1(V1::Zero))
826 }
827
828 pub fn type_parameters(&self) -> &[TypeParameter] {
830 &self.type_parameters
831 }
832
833 pub fn parameters(&self) -> &[FunctionalType] {
835 &self.parameters
836 }
837
838 pub fn required(&self) -> usize {
843 self.required.unwrap_or(self.parameters.len())
844 }
845
846 pub fn ret(&self) -> &FunctionalType {
848 &self.ret
849 }
850
851 pub fn is_generic(&self) -> bool {
853 self.generic_parameter_count() > 0 || self.ret.is_generic()
854 }
855
856 pub fn generic_parameter_count(&self) -> usize {
858 self.parameters.iter().filter(|p| p.is_generic()).count()
859 }
860
861 pub fn display<'a>(&'a self, params: &'a TypeParameters<'a>) -> impl fmt::Display + 'a {
864 #[allow(clippy::missing_docs_in_private_items)]
865 struct Display<'a> {
866 params: &'a TypeParameters<'a>,
867 sig: &'a FunctionSignature,
868 }
869
870 impl fmt::Display for Display<'_> {
871 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
872 f.write_char('(')?;
873
874 self.params.reset();
875 let required = self.sig.required();
876 for (i, parameter) in self.sig.parameters.iter().enumerate() {
877 if i > 0 {
878 f.write_str(", ")?;
879 }
880
881 if i >= required {
882 f.write_char('<')?;
883 }
884
885 write!(f, "{param}", param = parameter.display(self.params))?;
886
887 if i >= required {
888 f.write_char('>')?;
889 }
890 }
891
892 write!(f, ") -> {ret}", ret = self.sig.ret.display(self.params))?;
893 write_uninferred_constraints(f, self.params)?;
894
895 Ok(())
896 }
897 }
898
899 Display { params, sig: self }
900 }
901
902 fn infer_type_parameters(
907 &self,
908 arguments: &[Type],
909 ignore_constraints: bool,
910 ) -> TypeParameters<'_> {
911 let mut parameters = TypeParameters::new(&self.type_parameters);
912 for (parameter, argument) in self.parameters.iter().zip(arguments.iter()) {
913 parameter.infer_type_parameters(argument, &mut parameters, ignore_constraints);
914 }
915
916 parameters
917 }
918
919 fn insufficient_arguments(&self, arguments: &[Type]) -> bool {
922 arguments.len() < self.required() || arguments.len() > self.parameters.len()
923 }
924
925 fn bind(
935 &self,
936 version: SupportedVersion,
937 arguments: &[Type],
938 ) -> Result<BindingKind, FunctionBindError> {
939 if version < self.minimum_version() {
940 return Err(FunctionBindError::RequiresVersion(self.minimum_version()));
941 }
942
943 let required = self.required();
944 if arguments.len() < required {
945 return Err(FunctionBindError::TooFewArguments(required));
946 }
947
948 if arguments.len() > self.parameters.len() {
949 return Err(FunctionBindError::TooManyArguments(self.parameters.len()));
950 }
951
952 let mut coerced = false;
954 let type_parameters = self.infer_type_parameters(arguments, false);
955 for (i, (parameter, argument)) in self.parameters.iter().zip(arguments.iter()).enumerate() {
956 match parameter.realize(&type_parameters) {
957 Some(ty) => {
958 if !coerced && argument != &ty && argument != &ty.require() {
962 coerced = true;
963 }
964
965 if coerced && !argument.is_coercible_to(&ty) {
966 return Err(FunctionBindError::ArgumentTypeMismatch {
967 index: i,
968 expected: format!("`{ty}`"),
969 });
970 }
971 }
972 None if argument.is_union() => {
973 continue;
975 }
976 None => {
977 type_parameters.reset();
979
980 let mut expected = String::new();
981
982 write!(
983 &mut expected,
984 "`{param}`",
985 param = parameter.display(&type_parameters)
986 )
987 .unwrap();
988
989 write_uninferred_constraints(&mut expected, &type_parameters).unwrap();
990 return Err(FunctionBindError::ArgumentTypeMismatch { index: i, expected });
991 }
992 }
993 }
994
995 let ret = self.ret().realize(&type_parameters).unwrap_or(Type::Union);
999
1000 if coerced {
1001 Ok(BindingKind::Coercion(ret))
1002 } else {
1003 Ok(BindingKind::Equivalence(ret))
1004 }
1005 }
1006}
1007
1008impl Default for FunctionSignature {
1009 fn default() -> Self {
1010 Self {
1011 minimum_version: None,
1012 type_parameters: Default::default(),
1013 required: Default::default(),
1014 parameters: Default::default(),
1015 ret: FunctionalType::Concrete(Type::Union),
1016 }
1017 }
1018}
1019
1020#[derive(Debug, Default)]
1022pub struct FunctionSignatureBuilder(FunctionSignature);
1023
1024impl FunctionSignatureBuilder {
1025 pub fn new() -> Self {
1027 Self(Default::default())
1028 }
1029
1030 pub fn min_version(mut self, version: SupportedVersion) -> Self {
1032 self.0.minimum_version = Some(version);
1033 self
1034 }
1035
1036 pub fn type_parameter(
1038 mut self,
1039 name: &'static str,
1040 constraint: impl Constraint + 'static,
1041 ) -> Self {
1042 self.0
1043 .type_parameters
1044 .push(TypeParameter::new(name, constraint));
1045 self
1046 }
1047
1048 pub fn any_type_parameter(mut self, name: &'static str) -> Self {
1050 self.0.type_parameters.push(TypeParameter::any(name));
1051 self
1052 }
1053
1054 pub fn parameter(mut self, ty: impl Into<FunctionalType>) -> Self {
1056 self.0.parameters.push(ty.into());
1057 self
1058 }
1059
1060 pub fn ret(mut self, ret: impl Into<FunctionalType>) -> Self {
1065 self.0.ret = ret.into();
1066 self
1067 }
1068
1069 pub fn required(mut self, required: usize) -> Self {
1071 self.0.required = Some(required);
1072 self
1073 }
1074
1075 pub fn build(self) -> FunctionSignature {
1081 let sig = self.0;
1082
1083 if let Some(required) = sig.required {
1086 if required > sig.parameters.len() {
1087 panic!("number of required parameters exceeds the number of parameters");
1088 }
1089 }
1090
1091 assert!(
1092 sig.type_parameters.len() <= MAX_TYPE_PARAMETERS,
1093 "too many type parameters"
1094 );
1095
1096 assert!(
1097 sig.parameters.len() <= MAX_PARAMETERS,
1098 "too many parameters"
1099 );
1100
1101 for param in sig.parameters.iter() {
1103 param.assert_type_parameters(&sig.type_parameters)
1104 }
1105
1106 sig.ret().assert_type_parameters(&sig.type_parameters);
1107
1108 sig
1109 }
1110}
1111
1112#[derive(Debug, Clone)]
1114pub struct Binding<'a> {
1115 return_type: Type,
1117 index: usize,
1121 signature: &'a FunctionSignature,
1123}
1124
1125impl Binding<'_> {
1126 pub fn return_type(&self) -> &Type {
1128 &self.return_type
1129 }
1130
1131 pub fn index(&self) -> usize {
1135 self.index
1136 }
1137
1138 pub fn signature(&self) -> &FunctionSignature {
1140 self.signature
1141 }
1142}
1143
1144#[derive(Debug)]
1146pub enum Function {
1147 Monomorphic(MonomorphicFunction),
1149 Polymorphic(PolymorphicFunction),
1151}
1152
1153impl Function {
1154 pub fn minimum_version(&self) -> SupportedVersion {
1156 match self {
1157 Self::Monomorphic(f) => f.minimum_version(),
1158 Self::Polymorphic(f) => f.minimum_version(),
1159 }
1160 }
1161
1162 pub fn param_min_max(&self, version: SupportedVersion) -> Option<(usize, usize)> {
1167 match self {
1168 Self::Monomorphic(f) => f.param_min_max(version),
1169 Self::Polymorphic(f) => f.param_min_max(version),
1170 }
1171 }
1172
1173 pub fn bind<'a>(
1175 &'a self,
1176 version: SupportedVersion,
1177 arguments: &[Type],
1178 ) -> Result<Binding<'a>, FunctionBindError> {
1179 match self {
1180 Self::Monomorphic(f) => f.bind(version, arguments),
1181 Self::Polymorphic(f) => f.bind(version, arguments),
1182 }
1183 }
1184
1185 pub fn realize_unconstrained_return_type(&self, arguments: &[Type]) -> Type {
1193 match self {
1194 Self::Monomorphic(f) => {
1195 let type_parameters = f.signature.infer_type_parameters(arguments, true);
1196 f.signature
1197 .ret()
1198 .realize(&type_parameters)
1199 .unwrap_or(Type::Union)
1200 }
1201 Self::Polymorphic(f) => {
1202 let mut ty = None;
1203
1204 for signature in &f.signatures {
1207 let type_parameters = signature.infer_type_parameters(arguments, true);
1208 let ret_ty = signature
1209 .ret()
1210 .realize(&type_parameters)
1211 .unwrap_or(Type::Union);
1212
1213 if ty.get_or_insert(ret_ty.clone()) != &ret_ty {
1214 return Type::Union;
1215 }
1216 }
1217
1218 ty.unwrap_or(Type::Union)
1219 }
1220 }
1221 }
1222}
1223
1224#[derive(Debug)]
1229pub struct MonomorphicFunction {
1230 signature: FunctionSignature,
1232}
1233
1234impl MonomorphicFunction {
1235 pub fn new(signature: FunctionSignature) -> Self {
1237 Self { signature }
1238 }
1239
1240 pub fn minimum_version(&self) -> SupportedVersion {
1242 self.signature.minimum_version()
1243 }
1244
1245 pub fn param_min_max(&self, version: SupportedVersion) -> Option<(usize, usize)> {
1250 if version < self.signature.minimum_version() {
1251 return None;
1252 }
1253
1254 Some((self.signature.required(), self.signature.parameters.len()))
1255 }
1256
1257 pub fn signature(&self) -> &FunctionSignature {
1259 &self.signature
1260 }
1261
1262 pub fn bind<'a>(
1264 &'a self,
1265 version: SupportedVersion,
1266 arguments: &[Type],
1267 ) -> Result<Binding<'a>, FunctionBindError> {
1268 let return_type = self.signature.bind(version, arguments)?.ret().clone();
1269 Ok(Binding {
1270 return_type,
1271 index: 0,
1272 signature: &self.signature,
1273 })
1274 }
1275}
1276
1277impl From<MonomorphicFunction> for Function {
1278 fn from(value: MonomorphicFunction) -> Self {
1279 Self::Monomorphic(value)
1280 }
1281}
1282
1283#[derive(Debug)]
1289pub struct PolymorphicFunction {
1290 signatures: Vec<FunctionSignature>,
1292}
1293
1294impl PolymorphicFunction {
1295 pub fn new(signatures: Vec<FunctionSignature>) -> Self {
1301 assert!(
1302 signatures.len() > 1,
1303 "a polymorphic function must have at least two signatures"
1304 );
1305
1306 Self { signatures }
1307 }
1308
1309 pub fn minimum_version(&self) -> SupportedVersion {
1311 self.signatures
1312 .iter()
1313 .fold(None, |v: Option<SupportedVersion>, s| {
1314 Some(
1315 v.map(|v| v.min(s.minimum_version()))
1316 .unwrap_or_else(|| s.minimum_version()),
1317 )
1318 })
1319 .expect("there should be at least one signature")
1320 }
1321
1322 pub fn param_min_max(&self, version: SupportedVersion) -> Option<(usize, usize)> {
1327 let mut min = usize::MAX;
1328 let mut max = 0;
1329 for sig in self
1330 .signatures
1331 .iter()
1332 .filter(|s| s.minimum_version() <= version)
1333 {
1334 min = std::cmp::min(min, sig.required());
1335 max = std::cmp::max(max, sig.parameters().len());
1336 }
1337
1338 if min == usize::MAX {
1339 return None;
1340 }
1341
1342 Some((min, max))
1343 }
1344
1345 pub fn signatures(&self) -> &[FunctionSignature] {
1347 &self.signatures
1348 }
1349
1350 pub fn bind<'a>(
1354 &'a self,
1355 version: SupportedVersion,
1356 arguments: &[Type],
1357 ) -> Result<Binding<'a>, FunctionBindError> {
1358 let min_version = self.minimum_version();
1360 if version < min_version {
1361 return Err(FunctionBindError::RequiresVersion(min_version));
1362 }
1363
1364 let (min, max) = self
1366 .param_min_max(version)
1367 .expect("should have at least one signature for the version");
1368 if arguments.len() < min {
1369 return Err(FunctionBindError::TooFewArguments(min));
1370 }
1371
1372 if arguments.len() > max {
1373 return Err(FunctionBindError::TooManyArguments(max));
1374 }
1375
1376 let mut max_mismatch_index = 0;
1383 let mut expected_types = IndexSet::new();
1384
1385 for generic in [false, true] {
1386 let mut exact: Option<(usize, Type)> = None;
1387 let mut coercion1: Option<(usize, Type)> = None;
1388 let mut coercion2 = None;
1389 for (index, signature) in self.signatures.iter().enumerate().filter(|(_, s)| {
1390 s.is_generic() == generic
1391 && s.minimum_version() <= version
1392 && !s.insufficient_arguments(arguments)
1393 }) {
1394 match signature.bind(version, arguments) {
1395 Ok(BindingKind::Equivalence(ty)) => {
1396 if let Some((previous, _)) = exact {
1398 return Err(FunctionBindError::Ambiguous {
1399 first: self.signatures[previous]
1400 .display(&TypeParameters::new(
1401 &self.signatures[previous].type_parameters,
1402 ))
1403 .to_string(),
1404 second: self.signatures[index]
1405 .display(&TypeParameters::new(
1406 &self.signatures[index].type_parameters,
1407 ))
1408 .to_string(),
1409 });
1410 }
1411
1412 exact = Some((index, ty));
1413 }
1414 Ok(BindingKind::Coercion(ty)) => {
1415 if coercion1.is_none() {
1419 coercion1 = Some((index, ty));
1420 } else {
1421 coercion2.get_or_insert(index);
1422 }
1423 }
1424 Err(FunctionBindError::ArgumentTypeMismatch { index, expected }) => {
1425 if index > max_mismatch_index {
1427 max_mismatch_index = index;
1428 expected_types.clear();
1429 }
1430
1431 if index == max_mismatch_index {
1432 expected_types.insert(expected);
1433 }
1434 }
1435 Err(
1436 FunctionBindError::RequiresVersion(_)
1437 | FunctionBindError::Ambiguous { .. }
1438 | FunctionBindError::TooFewArguments(_)
1439 | FunctionBindError::TooManyArguments(_),
1440 ) => unreachable!("should not encounter these errors due to above filter"),
1441 }
1442 }
1443
1444 if let Some((index, ty)) = exact {
1445 return Ok(Binding {
1446 return_type: ty,
1447 index,
1448 signature: &self.signatures[index],
1449 });
1450 }
1451
1452 if let Some(previous) = coercion2 {
1454 let index = coercion1.unwrap().0;
1455 return Err(FunctionBindError::Ambiguous {
1456 first: self.signatures[previous]
1457 .display(&TypeParameters::new(
1458 &self.signatures[previous].type_parameters,
1459 ))
1460 .to_string(),
1461 second: self.signatures[index]
1462 .display(&TypeParameters::new(
1463 &self.signatures[index].type_parameters,
1464 ))
1465 .to_string(),
1466 });
1467 }
1468
1469 if let Some((index, ty)) = coercion1 {
1470 return Ok(Binding {
1471 return_type: ty,
1472 index,
1473 signature: &self.signatures[index],
1474 });
1475 }
1476 }
1477
1478 assert!(!expected_types.is_empty());
1479
1480 let mut expected = String::new();
1481 for (i, ty) in expected_types.iter().enumerate() {
1482 if i > 0 {
1483 if expected_types.len() == 2 {
1484 expected.push_str(" or ");
1485 } else if i == expected_types.len() - 1 {
1486 expected.push_str(", or ");
1487 } else {
1488 expected.push_str(", ");
1489 }
1490 }
1491
1492 expected.push_str(ty);
1493 }
1494
1495 Err(FunctionBindError::ArgumentTypeMismatch {
1496 index: max_mismatch_index,
1497 expected,
1498 })
1499 }
1500}
1501
1502impl From<PolymorphicFunction> for Function {
1503 fn from(value: PolymorphicFunction) -> Self {
1504 Self::Polymorphic(value)
1505 }
1506}
1507
1508#[derive(Debug)]
1510pub struct StandardLibrary {
1511 functions: IndexMap<&'static str, Function>,
1513 array_int: Type,
1515 array_string: Type,
1517 array_file: Type,
1519 array_object: Type,
1521 array_string_non_empty: Type,
1523 array_array_string: Type,
1525 map_string_string: Type,
1527 map_string_int: Type,
1529}
1530
1531impl StandardLibrary {
1532 pub fn function(&self, name: &str) -> Option<&Function> {
1534 self.functions.get(name)
1535 }
1536
1537 pub fn functions(&self) -> impl ExactSizeIterator<Item = (&'static str, &Function)> {
1539 self.functions.iter().map(|(n, f)| (*n, f))
1540 }
1541
1542 pub fn array_int_type(&self) -> &Type {
1544 &self.array_int
1545 }
1546
1547 pub fn array_string_type(&self) -> &Type {
1549 &self.array_string
1550 }
1551
1552 pub fn array_file_type(&self) -> &Type {
1554 &self.array_file
1555 }
1556
1557 pub fn array_object_type(&self) -> &Type {
1559 &self.array_object
1560 }
1561
1562 pub fn array_string_non_empty_type(&self) -> &Type {
1564 &self.array_string_non_empty
1565 }
1566
1567 pub fn array_array_string_type(&self) -> &Type {
1569 &self.array_array_string
1570 }
1571
1572 pub fn map_string_string_type(&self) -> &Type {
1574 &self.map_string_string
1575 }
1576
1577 pub fn map_string_int_type(&self) -> &Type {
1579 &self.map_string_int
1580 }
1581}
1582
1583pub static STDLIB: LazyLock<StandardLibrary> = LazyLock::new(|| {
1585 let array_int: Type = ArrayType::new(PrimitiveType::Integer).into();
1586 let array_string: Type = ArrayType::new(PrimitiveType::String).into();
1587 let array_file: Type = ArrayType::new(PrimitiveType::File).into();
1588 let array_object: Type = ArrayType::new(Type::Object).into();
1589 let array_string_non_empty: Type = ArrayType::non_empty(PrimitiveType::String).into();
1590 let array_array_string: Type = ArrayType::new(array_string.clone()).into();
1591 let map_string_string: Type = MapType::new(PrimitiveType::String, PrimitiveType::String).into();
1592 let map_string_int: Type = MapType::new(PrimitiveType::String, PrimitiveType::Integer).into();
1593 let mut functions = IndexMap::new();
1594
1595 assert!(
1597 functions
1598 .insert(
1599 "floor",
1600 MonomorphicFunction::new(
1601 FunctionSignature::builder()
1602 .parameter(PrimitiveType::Float)
1603 .ret(PrimitiveType::Integer)
1604 .build(),
1605 )
1606 .into(),
1607 )
1608 .is_none()
1609 );
1610
1611 assert!(
1613 functions
1614 .insert(
1615 "ceil",
1616 MonomorphicFunction::new(
1617 FunctionSignature::builder()
1618 .parameter(PrimitiveType::Float)
1619 .ret(PrimitiveType::Integer)
1620 .build(),
1621 )
1622 .into(),
1623 )
1624 .is_none()
1625 );
1626
1627 assert!(
1629 functions
1630 .insert(
1631 "round",
1632 MonomorphicFunction::new(
1633 FunctionSignature::builder()
1634 .parameter(PrimitiveType::Float)
1635 .ret(PrimitiveType::Integer)
1636 .build(),
1637 )
1638 .into(),
1639 )
1640 .is_none()
1641 );
1642
1643 assert!(
1645 functions
1646 .insert(
1647 "min",
1648 PolymorphicFunction::new(vec![
1649 FunctionSignature::builder()
1650 .min_version(SupportedVersion::V1(V1::One))
1651 .parameter(PrimitiveType::Integer)
1652 .parameter(PrimitiveType::Integer)
1653 .ret(PrimitiveType::Integer)
1654 .build(),
1655 FunctionSignature::builder()
1656 .min_version(SupportedVersion::V1(V1::One))
1657 .parameter(PrimitiveType::Integer)
1658 .parameter(PrimitiveType::Float)
1659 .ret(PrimitiveType::Float)
1660 .build(),
1661 FunctionSignature::builder()
1662 .min_version(SupportedVersion::V1(V1::One))
1663 .parameter(PrimitiveType::Float)
1664 .parameter(PrimitiveType::Integer)
1665 .ret(PrimitiveType::Float)
1666 .build(),
1667 FunctionSignature::builder()
1668 .min_version(SupportedVersion::V1(V1::One))
1669 .parameter(PrimitiveType::Float)
1670 .parameter(PrimitiveType::Float)
1671 .ret(PrimitiveType::Float)
1672 .build(),
1673 ],)
1674 .into(),
1675 )
1676 .is_none()
1677 );
1678
1679 assert!(
1681 functions
1682 .insert(
1683 "max",
1684 PolymorphicFunction::new(vec![
1685 FunctionSignature::builder()
1686 .min_version(SupportedVersion::V1(V1::One))
1687 .parameter(PrimitiveType::Integer)
1688 .parameter(PrimitiveType::Integer)
1689 .ret(PrimitiveType::Integer)
1690 .build(),
1691 FunctionSignature::builder()
1692 .min_version(SupportedVersion::V1(V1::One))
1693 .parameter(PrimitiveType::Integer)
1694 .parameter(PrimitiveType::Float)
1695 .ret(PrimitiveType::Float)
1696 .build(),
1697 FunctionSignature::builder()
1698 .min_version(SupportedVersion::V1(V1::One))
1699 .parameter(PrimitiveType::Float)
1700 .parameter(PrimitiveType::Integer)
1701 .ret(PrimitiveType::Float)
1702 .build(),
1703 FunctionSignature::builder()
1704 .min_version(SupportedVersion::V1(V1::One))
1705 .parameter(PrimitiveType::Float)
1706 .parameter(PrimitiveType::Float)
1707 .ret(PrimitiveType::Float)
1708 .build(),
1709 ],)
1710 .into(),
1711 )
1712 .is_none()
1713 );
1714
1715 assert!(
1717 functions
1718 .insert(
1719 "find",
1720 MonomorphicFunction::new(
1721 FunctionSignature::builder()
1722 .min_version(SupportedVersion::V1(V1::Two))
1723 .parameter(PrimitiveType::String)
1724 .parameter(PrimitiveType::String)
1725 .ret(Type::from(PrimitiveType::String).optional())
1726 .build(),
1727 )
1728 .into(),
1729 )
1730 .is_none()
1731 );
1732
1733 assert!(
1735 functions
1736 .insert(
1737 "matches",
1738 MonomorphicFunction::new(
1739 FunctionSignature::builder()
1740 .min_version(SupportedVersion::V1(V1::Two))
1741 .parameter(PrimitiveType::String)
1742 .parameter(PrimitiveType::String)
1743 .ret(PrimitiveType::Boolean)
1744 .build(),
1745 )
1746 .into(),
1747 )
1748 .is_none()
1749 );
1750
1751 assert!(
1753 functions
1754 .insert(
1755 "sub",
1756 MonomorphicFunction::new(
1757 FunctionSignature::builder()
1758 .parameter(PrimitiveType::String)
1759 .parameter(PrimitiveType::String)
1760 .parameter(PrimitiveType::String)
1761 .ret(PrimitiveType::String)
1762 .build(),
1763 )
1764 .into(),
1765 )
1766 .is_none()
1767 );
1768
1769 assert!(
1771 functions
1772 .insert(
1773 "basename",
1774 PolymorphicFunction::new(vec![
1775 FunctionSignature::builder()
1776 .required(1)
1777 .parameter(PrimitiveType::File)
1778 .parameter(PrimitiveType::String)
1779 .ret(PrimitiveType::String)
1780 .build(),
1781 FunctionSignature::builder()
1786 .min_version(SupportedVersion::V1(V1::Two))
1787 .required(1)
1788 .parameter(PrimitiveType::String)
1789 .parameter(PrimitiveType::String)
1790 .ret(PrimitiveType::String)
1791 .build(),
1792 FunctionSignature::builder()
1793 .min_version(SupportedVersion::V1(V1::Two))
1794 .required(1)
1795 .parameter(PrimitiveType::Directory)
1796 .parameter(PrimitiveType::String)
1797 .ret(PrimitiveType::String)
1798 .build(),
1799 ],)
1800 .into(),
1801 )
1802 .is_none()
1803 );
1804
1805 assert!(
1807 functions
1808 .insert(
1809 "join_paths",
1810 PolymorphicFunction::new(vec![
1811 FunctionSignature::builder()
1812 .min_version(SupportedVersion::V1(V1::Two))
1813 .parameter(PrimitiveType::File)
1814 .parameter(PrimitiveType::String)
1815 .ret(PrimitiveType::File)
1816 .build(),
1817 FunctionSignature::builder()
1818 .min_version(SupportedVersion::V1(V1::Two))
1819 .parameter(PrimitiveType::File)
1820 .parameter(array_string_non_empty.clone())
1821 .ret(PrimitiveType::File)
1822 .build(),
1823 FunctionSignature::builder()
1824 .min_version(SupportedVersion::V1(V1::Two))
1825 .parameter(array_string_non_empty.clone())
1826 .ret(PrimitiveType::File)
1827 .build(),
1828 ],)
1829 .into(),
1830 )
1831 .is_none()
1832 );
1833
1834 assert!(
1836 functions
1837 .insert(
1838 "glob",
1839 MonomorphicFunction::new(
1840 FunctionSignature::builder()
1841 .parameter(PrimitiveType::String)
1842 .ret(array_file.clone())
1843 .build(),
1844 )
1845 .into(),
1846 )
1847 .is_none()
1848 );
1849
1850 assert!(
1852 functions
1853 .insert(
1854 "size",
1855 PolymorphicFunction::new(vec![
1856 FunctionSignature::builder()
1859 .min_version(SupportedVersion::V1(V1::Two))
1860 .required(1)
1861 .parameter(Type::None)
1862 .parameter(PrimitiveType::String)
1863 .ret(PrimitiveType::Float)
1864 .build(),
1865 FunctionSignature::builder()
1866 .required(1)
1867 .parameter(Type::from(PrimitiveType::File).optional())
1868 .parameter(PrimitiveType::String)
1869 .ret(PrimitiveType::Float)
1870 .build(),
1871 FunctionSignature::builder()
1876 .min_version(SupportedVersion::V1(V1::Two))
1877 .required(1)
1878 .parameter(Type::from(PrimitiveType::String).optional())
1879 .parameter(PrimitiveType::String)
1880 .ret(PrimitiveType::Float)
1881 .build(),
1882 FunctionSignature::builder()
1883 .min_version(SupportedVersion::V1(V1::Two))
1884 .required(1)
1885 .parameter(Type::from(PrimitiveType::Directory).optional())
1886 .parameter(PrimitiveType::String)
1887 .ret(PrimitiveType::Float)
1888 .build(),
1889 FunctionSignature::builder()
1890 .required(1)
1891 .type_parameter("X", SizeableConstraint)
1892 .parameter(GenericType::Parameter("X"))
1893 .parameter(PrimitiveType::String)
1894 .ret(PrimitiveType::Float)
1895 .build(),
1896 ],)
1897 .into(),
1898 )
1899 .is_none()
1900 );
1901
1902 assert!(
1904 functions
1905 .insert(
1906 "stdout",
1907 MonomorphicFunction::new(
1908 FunctionSignature::builder()
1909 .ret(PrimitiveType::File)
1910 .build(),
1911 )
1912 .into(),
1913 )
1914 .is_none()
1915 );
1916
1917 assert!(
1919 functions
1920 .insert(
1921 "stderr",
1922 MonomorphicFunction::new(
1923 FunctionSignature::builder()
1924 .ret(PrimitiveType::File)
1925 .build(),
1926 )
1927 .into(),
1928 )
1929 .is_none()
1930 );
1931
1932 assert!(
1934 functions
1935 .insert(
1936 "read_string",
1937 MonomorphicFunction::new(
1938 FunctionSignature::builder()
1939 .parameter(PrimitiveType::File)
1940 .ret(PrimitiveType::String)
1941 .build(),
1942 )
1943 .into(),
1944 )
1945 .is_none()
1946 );
1947
1948 assert!(
1950 functions
1951 .insert(
1952 "read_int",
1953 MonomorphicFunction::new(
1954 FunctionSignature::builder()
1955 .parameter(PrimitiveType::File)
1956 .ret(PrimitiveType::Integer)
1957 .build(),
1958 )
1959 .into(),
1960 )
1961 .is_none()
1962 );
1963
1964 assert!(
1966 functions
1967 .insert(
1968 "read_float",
1969 MonomorphicFunction::new(
1970 FunctionSignature::builder()
1971 .parameter(PrimitiveType::File)
1972 .ret(PrimitiveType::Float)
1973 .build(),
1974 )
1975 .into(),
1976 )
1977 .is_none()
1978 );
1979
1980 assert!(
1982 functions
1983 .insert(
1984 "read_boolean",
1985 MonomorphicFunction::new(
1986 FunctionSignature::builder()
1987 .parameter(PrimitiveType::File)
1988 .ret(PrimitiveType::Boolean)
1989 .build(),
1990 )
1991 .into(),
1992 )
1993 .is_none()
1994 );
1995
1996 assert!(
1998 functions
1999 .insert(
2000 "read_lines",
2001 MonomorphicFunction::new(
2002 FunctionSignature::builder()
2003 .parameter(PrimitiveType::File)
2004 .ret(array_string.clone())
2005 .build(),
2006 )
2007 .into(),
2008 )
2009 .is_none()
2010 );
2011
2012 assert!(
2014 functions
2015 .insert(
2016 "write_lines",
2017 MonomorphicFunction::new(
2018 FunctionSignature::builder()
2019 .parameter(array_string.clone())
2020 .ret(PrimitiveType::File)
2021 .build(),
2022 )
2023 .into(),
2024 )
2025 .is_none()
2026 );
2027
2028 assert!(
2030 functions
2031 .insert(
2032 "read_tsv",
2033 PolymorphicFunction::new(vec![
2034 FunctionSignature::builder()
2035 .parameter(PrimitiveType::File)
2036 .ret(array_array_string.clone())
2037 .build(),
2038 FunctionSignature::builder()
2039 .min_version(SupportedVersion::V1(V1::Two))
2040 .parameter(PrimitiveType::File)
2041 .parameter(PrimitiveType::Boolean)
2042 .ret(array_object.clone())
2043 .build(),
2044 FunctionSignature::builder()
2045 .min_version(SupportedVersion::V1(V1::Two))
2046 .parameter(PrimitiveType::File)
2047 .parameter(PrimitiveType::Boolean)
2048 .parameter(array_string.clone())
2049 .ret(array_object.clone())
2050 .build(),
2051 ],)
2052 .into(),
2053 )
2054 .is_none()
2055 );
2056
2057 assert!(
2059 functions
2060 .insert(
2061 "write_tsv",
2062 PolymorphicFunction::new(vec![
2063 FunctionSignature::builder()
2064 .parameter(array_array_string.clone())
2065 .ret(PrimitiveType::File)
2066 .build(),
2067 FunctionSignature::builder()
2068 .min_version(SupportedVersion::V1(V1::Two))
2069 .parameter(array_array_string.clone())
2070 .parameter(PrimitiveType::Boolean)
2071 .parameter(array_string.clone())
2072 .ret(PrimitiveType::File)
2073 .build(),
2074 FunctionSignature::builder()
2075 .min_version(SupportedVersion::V1(V1::Two))
2076 .type_parameter("S", PrimitiveStructConstraint)
2077 .required(1)
2078 .parameter(GenericArrayType::new(GenericType::Parameter("S")))
2079 .parameter(PrimitiveType::Boolean)
2080 .parameter(array_string.clone())
2081 .ret(PrimitiveType::File)
2082 .build(),
2083 ],)
2084 .into(),
2085 )
2086 .is_none()
2087 );
2088
2089 assert!(
2091 functions
2092 .insert(
2093 "read_map",
2094 MonomorphicFunction::new(
2095 FunctionSignature::builder()
2096 .parameter(PrimitiveType::File)
2097 .ret(map_string_string.clone())
2098 .build(),
2099 )
2100 .into(),
2101 )
2102 .is_none()
2103 );
2104
2105 assert!(
2107 functions
2108 .insert(
2109 "write_map",
2110 MonomorphicFunction::new(
2111 FunctionSignature::builder()
2112 .parameter(map_string_string.clone())
2113 .ret(PrimitiveType::File)
2114 .build(),
2115 )
2116 .into(),
2117 )
2118 .is_none()
2119 );
2120
2121 assert!(
2123 functions
2124 .insert(
2125 "read_json",
2126 MonomorphicFunction::new(
2127 FunctionSignature::builder()
2128 .parameter(PrimitiveType::File)
2129 .ret(Type::Union)
2130 .build(),
2131 )
2132 .into(),
2133 )
2134 .is_none()
2135 );
2136
2137 assert!(
2139 functions
2140 .insert(
2141 "write_json",
2142 MonomorphicFunction::new(
2143 FunctionSignature::builder()
2144 .type_parameter("X", JsonSerializableConstraint)
2145 .parameter(GenericType::Parameter("X"))
2146 .ret(PrimitiveType::File)
2147 .build(),
2148 )
2149 .into(),
2150 )
2151 .is_none()
2152 );
2153
2154 assert!(
2156 functions
2157 .insert(
2158 "read_object",
2159 MonomorphicFunction::new(
2160 FunctionSignature::builder()
2161 .parameter(PrimitiveType::File)
2162 .ret(Type::Object)
2163 .build(),
2164 )
2165 .into(),
2166 )
2167 .is_none()
2168 );
2169
2170 assert!(
2172 functions
2173 .insert(
2174 "read_objects",
2175 MonomorphicFunction::new(
2176 FunctionSignature::builder()
2177 .parameter(PrimitiveType::File)
2178 .ret(array_object.clone())
2179 .build(),
2180 )
2181 .into(),
2182 )
2183 .is_none()
2184 );
2185
2186 assert!(
2188 functions
2189 .insert(
2190 "write_object",
2191 PolymorphicFunction::new(vec![
2192 FunctionSignature::builder()
2193 .parameter(Type::Object)
2194 .ret(PrimitiveType::File)
2195 .build(),
2196 FunctionSignature::builder()
2197 .min_version(SupportedVersion::V1(V1::One))
2198 .type_parameter("S", PrimitiveStructConstraint)
2199 .parameter(GenericType::Parameter("S"))
2200 .ret(PrimitiveType::File)
2201 .build(),
2202 ],)
2203 .into(),
2204 )
2205 .is_none()
2206 );
2207
2208 assert!(
2210 functions
2211 .insert(
2212 "write_objects",
2213 PolymorphicFunction::new(vec![
2214 FunctionSignature::builder()
2215 .parameter(array_object.clone())
2216 .ret(PrimitiveType::File)
2217 .build(),
2218 FunctionSignature::builder()
2219 .min_version(SupportedVersion::V1(V1::One))
2220 .type_parameter("S", PrimitiveStructConstraint)
2221 .parameter(GenericArrayType::new(GenericType::Parameter("S")))
2222 .ret(PrimitiveType::File)
2223 .build(),
2224 ],)
2225 .into(),
2226 )
2227 .is_none()
2228 );
2229
2230 assert!(
2232 functions
2233 .insert(
2234 "prefix",
2235 MonomorphicFunction::new(
2236 FunctionSignature::builder()
2237 .type_parameter("P", PrimitiveTypeConstraint)
2238 .parameter(PrimitiveType::String)
2239 .parameter(GenericArrayType::new(GenericType::Parameter("P")))
2240 .ret(array_string.clone())
2241 .build(),
2242 )
2243 .into(),
2244 )
2245 .is_none()
2246 );
2247
2248 assert!(
2250 functions
2251 .insert(
2252 "suffix",
2253 MonomorphicFunction::new(
2254 FunctionSignature::builder()
2255 .min_version(SupportedVersion::V1(V1::One))
2256 .type_parameter("P", PrimitiveTypeConstraint)
2257 .parameter(PrimitiveType::String)
2258 .parameter(GenericArrayType::new(GenericType::Parameter("P")))
2259 .ret(array_string.clone())
2260 .build(),
2261 )
2262 .into(),
2263 )
2264 .is_none()
2265 );
2266
2267 assert!(
2269 functions
2270 .insert(
2271 "quote",
2272 MonomorphicFunction::new(
2273 FunctionSignature::builder()
2274 .min_version(SupportedVersion::V1(V1::One))
2275 .type_parameter("P", PrimitiveTypeConstraint)
2276 .parameter(GenericArrayType::new(GenericType::Parameter("P")))
2277 .ret(array_string.clone())
2278 .build(),
2279 )
2280 .into(),
2281 )
2282 .is_none()
2283 );
2284
2285 assert!(
2287 functions
2288 .insert(
2289 "squote",
2290 MonomorphicFunction::new(
2291 FunctionSignature::builder()
2292 .min_version(SupportedVersion::V1(V1::One))
2293 .type_parameter("P", PrimitiveTypeConstraint)
2294 .parameter(GenericArrayType::new(GenericType::Parameter("P")))
2295 .ret(array_string.clone())
2296 .build(),
2297 )
2298 .into(),
2299 )
2300 .is_none()
2301 );
2302
2303 assert!(
2305 functions
2306 .insert(
2307 "sep",
2308 MonomorphicFunction::new(
2309 FunctionSignature::builder()
2310 .min_version(SupportedVersion::V1(V1::One))
2311 .type_parameter("P", PrimitiveTypeConstraint)
2312 .parameter(PrimitiveType::String)
2313 .parameter(GenericArrayType::new(GenericType::Parameter("P")))
2314 .ret(PrimitiveType::String)
2315 .build(),
2316 )
2317 .into(),
2318 )
2319 .is_none()
2320 );
2321
2322 assert!(
2324 functions
2325 .insert(
2326 "range",
2327 MonomorphicFunction::new(
2328 FunctionSignature::builder()
2329 .parameter(PrimitiveType::Integer)
2330 .ret(array_int.clone())
2331 .build(),
2332 )
2333 .into(),
2334 )
2335 .is_none()
2336 );
2337
2338 assert!(
2340 functions
2341 .insert(
2342 "transpose",
2343 MonomorphicFunction::new(
2344 FunctionSignature::builder()
2345 .any_type_parameter("X")
2346 .parameter(GenericArrayType::new(GenericArrayType::new(
2347 GenericType::Parameter("X"),
2348 )))
2349 .ret(GenericArrayType::new(GenericArrayType::new(
2350 GenericType::Parameter("X"),
2351 )))
2352 .build(),
2353 )
2354 .into(),
2355 )
2356 .is_none()
2357 );
2358
2359 assert!(
2361 functions
2362 .insert(
2363 "cross",
2364 MonomorphicFunction::new(
2365 FunctionSignature::builder()
2366 .any_type_parameter("X")
2367 .any_type_parameter("Y")
2368 .parameter(GenericArrayType::new(GenericType::Parameter("X")))
2369 .parameter(GenericArrayType::new(GenericType::Parameter("Y")))
2370 .ret(GenericArrayType::new(GenericPairType::new(
2371 GenericType::Parameter("X"),
2372 GenericType::Parameter("Y"),
2373 )))
2374 .build(),
2375 )
2376 .into(),
2377 )
2378 .is_none()
2379 );
2380
2381 assert!(
2383 functions
2384 .insert(
2385 "zip",
2386 MonomorphicFunction::new(
2387 FunctionSignature::builder()
2388 .any_type_parameter("X")
2389 .any_type_parameter("Y")
2390 .parameter(GenericArrayType::new(GenericType::Parameter("X")))
2391 .parameter(GenericArrayType::new(GenericType::Parameter("Y")))
2392 .ret(GenericArrayType::new(GenericPairType::new(
2393 GenericType::Parameter("X"),
2394 GenericType::Parameter("Y"),
2395 )))
2396 .build(),
2397 )
2398 .into(),
2399 )
2400 .is_none()
2401 );
2402
2403 assert!(
2405 functions
2406 .insert(
2407 "unzip",
2408 MonomorphicFunction::new(
2409 FunctionSignature::builder()
2410 .min_version(SupportedVersion::V1(V1::One))
2411 .any_type_parameter("X")
2412 .any_type_parameter("Y")
2413 .parameter(GenericArrayType::new(GenericPairType::new(
2414 GenericType::Parameter("X"),
2415 GenericType::Parameter("Y"),
2416 )))
2417 .ret(GenericPairType::new(
2418 GenericArrayType::new(GenericType::Parameter("X")),
2419 GenericArrayType::new(GenericType::Parameter("Y")),
2420 ))
2421 .build(),
2422 )
2423 .into(),
2424 )
2425 .is_none()
2426 );
2427
2428 assert!(
2430 functions
2431 .insert(
2432 "contains",
2433 MonomorphicFunction::new(
2434 FunctionSignature::builder()
2435 .min_version(SupportedVersion::V1(V1::Two))
2436 .type_parameter("P", PrimitiveTypeConstraint)
2437 .parameter(GenericArrayType::new(GenericType::Parameter("P")))
2438 .parameter(GenericType::Parameter("P"))
2439 .ret(PrimitiveType::Boolean)
2440 .build(),
2441 )
2442 .into(),
2443 )
2444 .is_none()
2445 );
2446
2447 assert!(
2449 functions
2450 .insert(
2451 "chunk",
2452 MonomorphicFunction::new(
2453 FunctionSignature::builder()
2454 .min_version(SupportedVersion::V1(V1::Two))
2455 .any_type_parameter("X")
2456 .parameter(GenericArrayType::new(GenericType::Parameter("X")))
2457 .parameter(PrimitiveType::Integer)
2458 .ret(GenericArrayType::new(GenericArrayType::new(
2459 GenericType::Parameter("X"),
2460 )))
2461 .build(),
2462 )
2463 .into(),
2464 )
2465 .is_none()
2466 );
2467
2468 assert!(
2470 functions
2471 .insert(
2472 "flatten",
2473 MonomorphicFunction::new(
2474 FunctionSignature::builder()
2475 .any_type_parameter("X")
2476 .parameter(GenericArrayType::new(GenericArrayType::new(
2477 GenericType::Parameter("X")
2478 )))
2479 .ret(GenericArrayType::new(GenericType::Parameter("X")))
2480 .build(),
2481 )
2482 .into(),
2483 )
2484 .is_none()
2485 );
2486
2487 assert!(
2489 functions
2490 .insert(
2491 "select_first",
2492 MonomorphicFunction::new(
2495 FunctionSignature::builder()
2496 .any_type_parameter("X")
2497 .required(1)
2498 .parameter(GenericArrayType::new(GenericType::Parameter("X")))
2499 .parameter(GenericType::UnqualifiedParameter("X"))
2500 .ret(GenericType::UnqualifiedParameter("X"))
2501 .build(),
2502 )
2503 .into(),
2504 )
2505 .is_none()
2506 );
2507
2508 assert!(
2510 functions
2511 .insert(
2512 "select_all",
2513 MonomorphicFunction::new(
2514 FunctionSignature::builder()
2515 .any_type_parameter("X")
2516 .parameter(GenericArrayType::new(GenericType::Parameter("X")))
2517 .ret(GenericArrayType::new(GenericType::UnqualifiedParameter(
2518 "X"
2519 )))
2520 .build(),
2521 )
2522 .into(),
2523 )
2524 .is_none()
2525 );
2526
2527 assert!(
2529 functions
2530 .insert(
2531 "as_pairs",
2532 MonomorphicFunction::new(
2533 FunctionSignature::builder()
2534 .min_version(SupportedVersion::V1(V1::One))
2535 .type_parameter("K", PrimitiveTypeConstraint)
2536 .any_type_parameter("V")
2537 .parameter(GenericMapType::new(
2538 GenericType::Parameter("K"),
2539 GenericType::Parameter("V")
2540 ))
2541 .ret(GenericArrayType::new(GenericPairType::new(
2542 GenericType::Parameter("K"),
2543 GenericType::Parameter("V")
2544 )))
2545 .build(),
2546 )
2547 .into(),
2548 )
2549 .is_none()
2550 );
2551
2552 assert!(
2554 functions
2555 .insert(
2556 "as_map",
2557 MonomorphicFunction::new(
2558 FunctionSignature::builder()
2559 .min_version(SupportedVersion::V1(V1::One))
2560 .type_parameter("K", PrimitiveTypeConstraint)
2561 .any_type_parameter("V")
2562 .parameter(GenericArrayType::new(GenericPairType::new(
2563 GenericType::Parameter("K"),
2564 GenericType::Parameter("V")
2565 )))
2566 .ret(GenericMapType::new(
2567 GenericType::Parameter("K"),
2568 GenericType::Parameter("V")
2569 ))
2570 .build(),
2571 )
2572 .into(),
2573 )
2574 .is_none()
2575 );
2576
2577 assert!(
2579 functions
2580 .insert(
2581 "keys",
2582 PolymorphicFunction::new(vec![
2583 FunctionSignature::builder()
2584 .min_version(SupportedVersion::V1(V1::One))
2585 .type_parameter("K", PrimitiveTypeConstraint)
2586 .any_type_parameter("V")
2587 .parameter(GenericMapType::new(
2588 GenericType::Parameter("K"),
2589 GenericType::Parameter("V")
2590 ))
2591 .ret(GenericArrayType::new(GenericType::Parameter("K")))
2592 .build(),
2593 FunctionSignature::builder()
2594 .min_version(SupportedVersion::V1(V1::Two))
2595 .type_parameter("S", StructConstraint)
2596 .parameter(GenericType::Parameter("S"))
2597 .ret(array_string.clone())
2598 .build(),
2599 FunctionSignature::builder()
2600 .min_version(SupportedVersion::V1(V1::Two))
2601 .parameter(Type::Object)
2602 .ret(array_string.clone())
2603 .build(),
2604 ])
2605 .into(),
2606 )
2607 .is_none()
2608 );
2609
2610 assert!(
2612 functions
2613 .insert(
2614 "contains_key",
2615 PolymorphicFunction::new(vec![
2616 FunctionSignature::builder()
2617 .min_version(SupportedVersion::V1(V1::Two))
2618 .type_parameter("K", PrimitiveTypeConstraint)
2619 .any_type_parameter("V")
2620 .parameter(GenericMapType::new(
2621 GenericType::Parameter("K"),
2622 GenericType::Parameter("V")
2623 ))
2624 .parameter(GenericType::Parameter("K"))
2625 .ret(PrimitiveType::Boolean)
2626 .build(),
2627 FunctionSignature::builder()
2628 .min_version(SupportedVersion::V1(V1::Two))
2629 .parameter(Type::Object)
2630 .parameter(PrimitiveType::String)
2631 .ret(PrimitiveType::Boolean)
2632 .build(),
2633 FunctionSignature::builder()
2634 .min_version(SupportedVersion::V1(V1::Two))
2635 .any_type_parameter("V")
2636 .parameter(GenericMapType::new(
2637 PrimitiveType::String,
2638 GenericType::Parameter("V")
2639 ))
2640 .parameter(array_string.clone())
2641 .ret(PrimitiveType::Boolean)
2642 .build(),
2643 FunctionSignature::builder()
2644 .min_version(SupportedVersion::V1(V1::Two))
2645 .type_parameter("S", StructConstraint)
2646 .parameter(GenericType::Parameter("S"))
2647 .parameter(array_string.clone())
2648 .ret(PrimitiveType::Boolean)
2649 .build(),
2650 FunctionSignature::builder()
2651 .min_version(SupportedVersion::V1(V1::Two))
2652 .parameter(Type::Object)
2653 .parameter(array_string.clone())
2654 .ret(PrimitiveType::Boolean)
2655 .build(),
2656 ])
2657 .into(),
2658 )
2659 .is_none()
2660 );
2661
2662 assert!(
2664 functions
2665 .insert(
2666 "values",
2667 MonomorphicFunction::new(
2668 FunctionSignature::builder()
2669 .min_version(SupportedVersion::V1(V1::Two))
2670 .type_parameter("K", PrimitiveTypeConstraint)
2671 .any_type_parameter("V")
2672 .parameter(GenericMapType::new(
2673 GenericType::Parameter("K"),
2674 GenericType::Parameter("V")
2675 ))
2676 .ret(GenericArrayType::new(GenericType::Parameter("V")))
2677 .build(),
2678 )
2679 .into(),
2680 )
2681 .is_none()
2682 );
2683
2684 assert!(
2686 functions
2687 .insert(
2688 "collect_by_key",
2689 MonomorphicFunction::new(
2690 FunctionSignature::builder()
2691 .min_version(SupportedVersion::V1(V1::One))
2692 .type_parameter("K", PrimitiveTypeConstraint)
2693 .any_type_parameter("V")
2694 .parameter(GenericArrayType::new(GenericPairType::new(
2695 GenericType::Parameter("K"),
2696 GenericType::Parameter("V")
2697 )))
2698 .ret(GenericMapType::new(
2699 GenericType::Parameter("K"),
2700 GenericArrayType::new(GenericType::Parameter("V"))
2701 ))
2702 .build(),
2703 )
2704 .into(),
2705 )
2706 .is_none()
2707 );
2708
2709 assert!(
2711 functions
2712 .insert(
2713 "defined",
2714 MonomorphicFunction::new(
2715 FunctionSignature::builder()
2716 .any_type_parameter("X")
2717 .parameter(GenericType::Parameter("X"))
2718 .ret(PrimitiveType::Boolean)
2719 .build(),
2720 )
2721 .into(),
2722 )
2723 .is_none()
2724 );
2725
2726 assert!(
2728 functions
2729 .insert(
2730 "length",
2731 PolymorphicFunction::new(vec![
2732 FunctionSignature::builder()
2733 .any_type_parameter("X")
2734 .parameter(GenericArrayType::new(GenericType::Parameter("X")))
2735 .ret(PrimitiveType::Integer)
2736 .build(),
2737 FunctionSignature::builder()
2738 .any_type_parameter("K")
2739 .any_type_parameter("V")
2740 .parameter(GenericMapType::new(
2741 GenericType::Parameter("K"),
2742 GenericType::Parameter("V")
2743 ))
2744 .ret(PrimitiveType::Integer)
2745 .build(),
2746 FunctionSignature::builder()
2747 .parameter(Type::Object)
2748 .ret(PrimitiveType::Integer)
2749 .build(),
2750 FunctionSignature::builder()
2751 .parameter(PrimitiveType::String)
2752 .ret(PrimitiveType::Integer)
2753 .build(),
2754 ])
2755 .into(),
2756 )
2757 .is_none()
2758 );
2759
2760 StandardLibrary {
2761 functions,
2762 array_int,
2763 array_string,
2764 array_file,
2765 array_object,
2766 array_string_non_empty,
2767 array_array_string,
2768 map_string_string,
2769 map_string_int,
2770 }
2771});
2772
2773#[cfg(test)]
2774mod test {
2775 use pretty_assertions::assert_eq;
2776
2777 use super::*;
2778
2779 #[test]
2780 fn verify_stdlib_signatures() {
2781 let mut signatures = Vec::new();
2782 for (name, f) in STDLIB.functions() {
2783 match f {
2784 Function::Monomorphic(f) => {
2785 let params = TypeParameters::new(&f.signature.type_parameters);
2786 signatures.push(format!("{name}{sig}", sig = f.signature.display(¶ms)));
2787 }
2788 Function::Polymorphic(f) => {
2789 for signature in &f.signatures {
2790 let params = TypeParameters::new(&signature.type_parameters);
2791 signatures.push(format!("{name}{sig}", sig = signature.display(¶ms)));
2792 }
2793 }
2794 }
2795 }
2796
2797 assert_eq!(
2798 signatures,
2799 [
2800 "floor(Float) -> Int",
2801 "ceil(Float) -> Int",
2802 "round(Float) -> Int",
2803 "min(Int, Int) -> Int",
2804 "min(Int, Float) -> Float",
2805 "min(Float, Int) -> Float",
2806 "min(Float, Float) -> Float",
2807 "max(Int, Int) -> Int",
2808 "max(Int, Float) -> Float",
2809 "max(Float, Int) -> Float",
2810 "max(Float, Float) -> Float",
2811 "find(String, String) -> String?",
2812 "matches(String, String) -> Boolean",
2813 "sub(String, String, String) -> String",
2814 "basename(File, <String>) -> String",
2815 "basename(String, <String>) -> String",
2816 "basename(Directory, <String>) -> String",
2817 "join_paths(File, String) -> File",
2818 "join_paths(File, Array[String]+) -> File",
2819 "join_paths(Array[String]+) -> File",
2820 "glob(String) -> Array[File]",
2821 "size(None, <String>) -> Float",
2822 "size(File?, <String>) -> Float",
2823 "size(String?, <String>) -> Float",
2824 "size(Directory?, <String>) -> Float",
2825 "size(X, <String>) -> Float where `X`: any compound type that recursively \
2826 contains a `File` or `Directory`",
2827 "stdout() -> File",
2828 "stderr() -> File",
2829 "read_string(File) -> String",
2830 "read_int(File) -> Int",
2831 "read_float(File) -> Float",
2832 "read_boolean(File) -> Boolean",
2833 "read_lines(File) -> Array[String]",
2834 "write_lines(Array[String]) -> File",
2835 "read_tsv(File) -> Array[Array[String]]",
2836 "read_tsv(File, Boolean) -> Array[Object]",
2837 "read_tsv(File, Boolean, Array[String]) -> Array[Object]",
2838 "write_tsv(Array[Array[String]]) -> File",
2839 "write_tsv(Array[Array[String]], Boolean, Array[String]) -> File",
2840 "write_tsv(Array[S], <Boolean>, <Array[String]>) -> File where `S`: any structure \
2841 containing only primitive types",
2842 "read_map(File) -> Map[String, String]",
2843 "write_map(Map[String, String]) -> File",
2844 "read_json(File) -> Union",
2845 "write_json(X) -> File where `X`: any JSON-serializable type",
2846 "read_object(File) -> Object",
2847 "read_objects(File) -> Array[Object]",
2848 "write_object(Object) -> File",
2849 "write_object(S) -> File where `S`: any structure containing only primitive types",
2850 "write_objects(Array[Object]) -> File",
2851 "write_objects(Array[S]) -> File where `S`: any structure containing only \
2852 primitive types",
2853 "prefix(String, Array[P]) -> Array[String] where `P`: any primitive type",
2854 "suffix(String, Array[P]) -> Array[String] where `P`: any primitive type",
2855 "quote(Array[P]) -> Array[String] where `P`: any primitive type",
2856 "squote(Array[P]) -> Array[String] where `P`: any primitive type",
2857 "sep(String, Array[P]) -> String where `P`: any primitive type",
2858 "range(Int) -> Array[Int]",
2859 "transpose(Array[Array[X]]) -> Array[Array[X]]",
2860 "cross(Array[X], Array[Y]) -> Array[Pair[X, Y]]",
2861 "zip(Array[X], Array[Y]) -> Array[Pair[X, Y]]",
2862 "unzip(Array[Pair[X, Y]]) -> Pair[Array[X], Array[Y]]",
2863 "contains(Array[P], P) -> Boolean where `P`: any primitive type",
2864 "chunk(Array[X], Int) -> Array[Array[X]]",
2865 "flatten(Array[Array[X]]) -> Array[X]",
2866 "select_first(Array[X], <X>) -> X",
2867 "select_all(Array[X]) -> Array[X]",
2868 "as_pairs(Map[K, V]) -> Array[Pair[K, V]] where `K`: any primitive type",
2869 "as_map(Array[Pair[K, V]]) -> Map[K, V] where `K`: any primitive type",
2870 "keys(Map[K, V]) -> Array[K] where `K`: any primitive type",
2871 "keys(S) -> Array[String] where `S`: any structure",
2872 "keys(Object) -> Array[String]",
2873 "contains_key(Map[K, V], K) -> Boolean where `K`: any primitive type",
2874 "contains_key(Object, String) -> Boolean",
2875 "contains_key(Map[String, V], Array[String]) -> Boolean",
2876 "contains_key(S, Array[String]) -> Boolean where `S`: any structure",
2877 "contains_key(Object, Array[String]) -> Boolean",
2878 "values(Map[K, V]) -> Array[V] where `K`: any primitive type",
2879 "collect_by_key(Array[Pair[K, V]]) -> Map[K, Array[V]] where `K`: any primitive \
2880 type",
2881 "defined(X) -> Boolean",
2882 "length(Array[X]) -> Int",
2883 "length(Map[K, V]) -> Int",
2884 "length(Object) -> Int",
2885 "length(String) -> Int",
2886 ]
2887 );
2888 }
2889
2890 #[test]
2891 fn it_binds_a_simple_function() {
2892 let f = STDLIB.function("floor").expect("should have function");
2893 assert_eq!(f.minimum_version(), SupportedVersion::V1(V1::Zero));
2894
2895 let e = f
2896 .bind(SupportedVersion::V1(V1::Zero), &[])
2897 .expect_err("bind should fail");
2898 assert_eq!(e, FunctionBindError::TooFewArguments(1));
2899
2900 let e = f
2901 .bind(
2902 SupportedVersion::V1(V1::One),
2903 &[PrimitiveType::String.into(), PrimitiveType::Boolean.into()],
2904 )
2905 .expect_err("bind should fail");
2906 assert_eq!(e, FunctionBindError::TooManyArguments(1));
2907
2908 let e = f
2910 .bind(
2911 SupportedVersion::V1(V1::Two),
2912 &[PrimitiveType::String.into()],
2913 )
2914 .expect_err("bind should fail");
2915 assert_eq!(
2916 e,
2917 FunctionBindError::ArgumentTypeMismatch {
2918 index: 0,
2919 expected: "`Float`".into()
2920 }
2921 );
2922
2923 let binding = f
2925 .bind(SupportedVersion::V1(V1::Zero), &[Type::Union])
2926 .expect("bind should succeed");
2927 assert_eq!(binding.index(), 0);
2928 assert_eq!(binding.return_type().to_string(), "Int");
2929
2930 let binding = f
2932 .bind(
2933 SupportedVersion::V1(V1::One),
2934 &[PrimitiveType::Float.into()],
2935 )
2936 .expect("bind should succeed");
2937 assert_eq!(binding.index(), 0);
2938 assert_eq!(binding.return_type().to_string(), "Int");
2939
2940 let binding = f
2942 .bind(
2943 SupportedVersion::V1(V1::Two),
2944 &[PrimitiveType::Integer.into()],
2945 )
2946 .expect("bind should succeed");
2947 assert_eq!(binding.index(), 0);
2948 assert_eq!(binding.return_type().to_string(), "Int");
2949 }
2950
2951 #[test]
2952 fn it_binds_a_generic_function() {
2953 let f = STDLIB.function("values").expect("should have function");
2954 assert_eq!(f.minimum_version(), SupportedVersion::V1(V1::Two));
2955
2956 let e = f
2957 .bind(SupportedVersion::V1(V1::Zero), &[])
2958 .expect_err("bind should fail");
2959 assert_eq!(
2960 e,
2961 FunctionBindError::RequiresVersion(SupportedVersion::V1(V1::Two))
2962 );
2963
2964 let e = f
2965 .bind(SupportedVersion::V1(V1::Two), &[])
2966 .expect_err("bind should fail");
2967 assert_eq!(e, FunctionBindError::TooFewArguments(1));
2968
2969 let e = f
2970 .bind(
2971 SupportedVersion::V1(V1::Two),
2972 &[PrimitiveType::String.into(), PrimitiveType::Boolean.into()],
2973 )
2974 .expect_err("bind should fail");
2975 assert_eq!(e, FunctionBindError::TooManyArguments(1));
2976
2977 let e = f
2979 .bind(
2980 SupportedVersion::V1(V1::Two),
2981 &[PrimitiveType::String.into()],
2982 )
2983 .expect_err("bind should fail");
2984 assert_eq!(
2985 e,
2986 FunctionBindError::ArgumentTypeMismatch {
2987 index: 0,
2988 expected: "`Map[K, V]` where `K`: any primitive type".into()
2989 }
2990 );
2991
2992 let binding = f
2994 .bind(SupportedVersion::V1(V1::Two), &[Type::Union])
2995 .expect("bind should succeed");
2996 assert_eq!(binding.index(), 0);
2997 assert_eq!(binding.return_type().to_string(), "Array[Union]");
2998
2999 let ty: Type = MapType::new(PrimitiveType::String, PrimitiveType::String).into();
3001 let binding = f
3002 .bind(SupportedVersion::V1(V1::Two), &[ty])
3003 .expect("bind should succeed");
3004 assert_eq!(binding.index(), 0);
3005 assert_eq!(binding.return_type().to_string(), "Array[String]");
3006
3007 let ty: Type = MapType::new(PrimitiveType::String, Type::Object).into();
3009 let binding = f
3010 .bind(SupportedVersion::V1(V1::Two), &[ty])
3011 .expect("bind should succeed");
3012 assert_eq!(binding.index(), 0);
3013 assert_eq!(binding.return_type().to_string(), "Array[Object]");
3014
3015 let ty: Type = MapType::new(
3017 Type::from(PrimitiveType::String).optional(),
3018 PrimitiveType::Boolean,
3019 )
3020 .into();
3021 let binding = f
3022 .bind(SupportedVersion::V1(V1::Two), &[ty])
3023 .expect("bind should succeed");
3024 assert_eq!(binding.index(), 0);
3025 assert_eq!(binding.return_type().to_string(), "Array[Boolean]");
3026 }
3027
3028 #[test]
3029 fn it_removes_qualifiers() {
3030 let f = STDLIB.function("select_all").expect("should have function");
3031 assert_eq!(f.minimum_version(), SupportedVersion::V1(V1::Zero));
3032
3033 let array_string: Type = ArrayType::new(PrimitiveType::String).into();
3035 let binding = f
3036 .bind(SupportedVersion::V1(V1::One), &[array_string])
3037 .expect("bind should succeed");
3038 assert_eq!(binding.index(), 0);
3039 assert_eq!(binding.return_type().to_string(), "Array[String]");
3040
3041 let array_optional_string: Type =
3043 ArrayType::new(Type::from(PrimitiveType::String).optional()).into();
3044 let binding = f
3045 .bind(SupportedVersion::V1(V1::One), &[array_optional_string])
3046 .expect("bind should succeed");
3047 assert_eq!(binding.index(), 0);
3048 assert_eq!(binding.return_type().to_string(), "Array[String]");
3049
3050 let binding = f
3052 .bind(SupportedVersion::V1(V1::Two), &[Type::Union])
3053 .expect("bind should succeed");
3054 assert_eq!(binding.index(), 0);
3055 assert_eq!(binding.return_type().to_string(), "Array[Union]");
3056
3057 let array_string = Type::from(ArrayType::new(PrimitiveType::String)).optional();
3059 let array_array_string = ArrayType::new(array_string).into();
3060 let binding = f
3061 .bind(SupportedVersion::V1(V1::Zero), &[array_array_string])
3062 .expect("bind should succeed");
3063 assert_eq!(binding.index(), 0);
3064 assert_eq!(binding.return_type().to_string(), "Array[Array[String]]");
3065 }
3066
3067 #[test]
3068 fn it_binds_concrete_overloads() {
3069 let f = STDLIB.function("max").expect("should have function");
3070 assert_eq!(f.minimum_version(), SupportedVersion::V1(V1::One));
3071
3072 let e = f
3073 .bind(SupportedVersion::V1(V1::One), &[])
3074 .expect_err("bind should fail");
3075 assert_eq!(e, FunctionBindError::TooFewArguments(2));
3076
3077 let e = f
3078 .bind(
3079 SupportedVersion::V1(V1::Two),
3080 &[
3081 PrimitiveType::String.into(),
3082 PrimitiveType::Boolean.into(),
3083 PrimitiveType::File.into(),
3084 ],
3085 )
3086 .expect_err("bind should fail");
3087 assert_eq!(e, FunctionBindError::TooManyArguments(2));
3088
3089 let binding = f
3091 .bind(
3092 SupportedVersion::V1(V1::One),
3093 &[PrimitiveType::Integer.into(), PrimitiveType::Integer.into()],
3094 )
3095 .expect("binding should succeed");
3096 assert_eq!(binding.index(), 0);
3097 assert_eq!(binding.return_type().to_string(), "Int");
3098
3099 let binding = f
3101 .bind(
3102 SupportedVersion::V1(V1::Two),
3103 &[PrimitiveType::Integer.into(), PrimitiveType::Float.into()],
3104 )
3105 .expect("binding should succeed");
3106 assert_eq!(binding.index(), 1);
3107 assert_eq!(binding.return_type().to_string(), "Float");
3108
3109 let binding = f
3111 .bind(
3112 SupportedVersion::V1(V1::One),
3113 &[PrimitiveType::Float.into(), PrimitiveType::Integer.into()],
3114 )
3115 .expect("binding should succeed");
3116 assert_eq!(binding.index(), 2);
3117 assert_eq!(binding.return_type().to_string(), "Float");
3118
3119 let binding = f
3121 .bind(
3122 SupportedVersion::V1(V1::Two),
3123 &[PrimitiveType::Float.into(), PrimitiveType::Float.into()],
3124 )
3125 .expect("binding should succeed");
3126 assert_eq!(binding.index(), 3);
3127 assert_eq!(binding.return_type().to_string(), "Float");
3128
3129 let e = f
3131 .bind(
3132 SupportedVersion::V1(V1::One),
3133 &[PrimitiveType::String.into(), PrimitiveType::Integer.into()],
3134 )
3135 .expect_err("binding should fail");
3136 assert_eq!(
3137 e,
3138 FunctionBindError::ArgumentTypeMismatch {
3139 index: 0,
3140 expected: "`Int` or `Float`".into()
3141 }
3142 );
3143
3144 let e = f
3146 .bind(
3147 SupportedVersion::V1(V1::Two),
3148 &[PrimitiveType::Integer.into(), PrimitiveType::String.into()],
3149 )
3150 .expect_err("binding should fail");
3151 assert_eq!(
3152 e,
3153 FunctionBindError::ArgumentTypeMismatch {
3154 index: 1,
3155 expected: "`Int` or `Float`".into()
3156 }
3157 );
3158
3159 let e = f
3161 .bind(
3162 SupportedVersion::V1(V1::One),
3163 &[PrimitiveType::String.into(), PrimitiveType::Float.into()],
3164 )
3165 .expect_err("binding should fail");
3166 assert_eq!(
3167 e,
3168 FunctionBindError::ArgumentTypeMismatch {
3169 index: 0,
3170 expected: "`Int` or `Float`".into()
3171 }
3172 );
3173
3174 let e = f
3176 .bind(
3177 SupportedVersion::V1(V1::Two),
3178 &[PrimitiveType::Float.into(), PrimitiveType::String.into()],
3179 )
3180 .expect_err("binding should fail");
3181 assert_eq!(
3182 e,
3183 FunctionBindError::ArgumentTypeMismatch {
3184 index: 1,
3185 expected: "`Int` or `Float`".into()
3186 }
3187 );
3188 }
3189
3190 #[test]
3191 fn it_binds_generic_overloads() {
3192 let f = STDLIB
3193 .function("select_first")
3194 .expect("should have function");
3195 assert_eq!(f.minimum_version(), SupportedVersion::V1(V1::Zero));
3196
3197 let e = f
3198 .bind(SupportedVersion::V1(V1::Zero), &[])
3199 .expect_err("bind should fail");
3200 assert_eq!(e, FunctionBindError::TooFewArguments(1));
3201
3202 let e = f
3203 .bind(
3204 SupportedVersion::V1(V1::One),
3205 &[
3206 PrimitiveType::String.into(),
3207 PrimitiveType::Boolean.into(),
3208 PrimitiveType::File.into(),
3209 ],
3210 )
3211 .expect_err("bind should fail");
3212 assert_eq!(e, FunctionBindError::TooManyArguments(2));
3213
3214 let e = f
3216 .bind(
3217 SupportedVersion::V1(V1::Two),
3218 &[PrimitiveType::Integer.into()],
3219 )
3220 .expect_err("binding should fail");
3221 assert_eq!(
3222 e,
3223 FunctionBindError::ArgumentTypeMismatch {
3224 index: 0,
3225 expected: "`Array[X]`".into()
3226 }
3227 );
3228
3229 let array: Type = ArrayType::non_empty(Type::from(PrimitiveType::String).optional()).into();
3231 let binding = f
3232 .bind(SupportedVersion::V1(V1::Zero), &[array.clone()])
3233 .expect("binding should succeed");
3234 assert_eq!(binding.index(), 0);
3235 assert_eq!(binding.return_type().to_string(), "String");
3236
3237 let binding = f
3239 .bind(
3240 SupportedVersion::V1(V1::One),
3241 &[array.clone(), PrimitiveType::String.into()],
3242 )
3243 .expect("binding should succeed");
3244 assert_eq!(binding.index(), 0);
3245 assert_eq!(binding.return_type().to_string(), "String");
3246
3247 let e = f
3249 .bind(
3250 SupportedVersion::V1(V1::Two),
3251 &[array.clone(), PrimitiveType::Integer.into()],
3252 )
3253 .expect_err("binding should fail");
3254 assert_eq!(
3255 e,
3256 FunctionBindError::ArgumentTypeMismatch {
3257 index: 1,
3258 expected: "`String`".into()
3259 }
3260 );
3261
3262 let array: Type = ArrayType::new(Type::from(PrimitiveType::String).optional()).into();
3264 let binding = f
3265 .bind(SupportedVersion::V1(V1::Zero), &[array.clone()])
3266 .expect("binding should succeed");
3267 assert_eq!(binding.index(), 0);
3268 assert_eq!(binding.return_type().to_string(), "String");
3269
3270 let binding = f
3272 .bind(
3273 SupportedVersion::V1(V1::One),
3274 &[array.clone(), PrimitiveType::String.into()],
3275 )
3276 .expect("binding should succeed");
3277 assert_eq!(binding.index(), 0);
3278 assert_eq!(binding.return_type().to_string(), "String");
3279
3280 let e = f
3282 .bind(
3283 SupportedVersion::V1(V1::Two),
3284 &[array, PrimitiveType::Integer.into()],
3285 )
3286 .expect_err("binding should fail");
3287 assert_eq!(
3288 e,
3289 FunctionBindError::ArgumentTypeMismatch {
3290 index: 1,
3291 expected: "`String`".into()
3292 }
3293 );
3294 }
3295}