@@ -334,7 +334,7 @@ pub(crate) fn evaluate_expression(
334334 evaluated_args. push ( arg) ;
335335 }
336336
337- let function_as_value = resolve_and_call ( function, evaluated_args, environment, span) ?;
337+ resolve_and_call ( function, evaluated_args, environment, span) ?
338338 }
339339 Expression :: FunctionDeclaration {
340340 parameters : arguments,
@@ -991,36 +991,59 @@ fn resolve_and_call(
991991 environment : & Rc < RefCell < Environment > > ,
992992 span : Span ,
993993) -> EvaluationResult {
994- ////////////////////////////
995994 let ExpressionLocation { expression, .. } = function_expression;
996995
997- let function_as_value = if let Expression :: Identifier { resolved, .. } = expression {
996+ let function_as_value = if let Expression :: Identifier { name , resolved, .. } = expression {
998997 let arg_types = args. iter ( ) . map ( |arg| arg. static_type ( ) ) . collect :: < Vec < _ > > ( ) ;
999998
1000999 let opt = match resolved {
10011000 Binding :: None => None ,
10021001 Binding :: Resolved ( var) => Some ( environment. borrow ( ) . get ( * var) ) ,
10031002 Binding :: Dynamic ( dynamic_binding) => dynamic_binding
1004- . iter ( ) // TODO: should we consider the binding order?
1003+ . iter ( )
10051004 . find_map ( |binding| {
10061005 let value = environment. borrow ( ) . get ( * binding) ;
10071006
10081007 let Value :: Function ( fun) = & value else {
10091008 panic ! ( "dynamic binding resolved to non-function type at runtime" ) ;
10101009 } ;
10111010
1012- // Find the first function that matches
10131011 if fun. static_type ( ) . is_fn_and_matches ( & arg_types) {
10141012 return Some ( value) ;
10151013 }
10161014
10171015 None
10181016 } ) ,
10191017 } ;
1018+
1019+ if opt. is_none ( ) {
1020+ if let Binding :: Dynamic ( dynamic_binding) = resolved {
1021+ if let [ left_type, right_type] = arg_types. as_slice ( ) {
1022+ if left_type. supports_vectorization_with ( right_type) {
1023+ let elem_types = vectorized_element_types ( left_type, right_type) ;
1024+ let inner_fn = dynamic_binding. iter ( ) . find_map ( |binding| {
1025+ let value = environment. borrow ( ) . get ( * binding) ;
1026+ let Value :: Function ( fun) = & value else {
1027+ panic ! ( "dynamic binding resolved to non-function type at runtime" ) ;
1028+ } ;
1029+ if fun. static_type ( ) . is_fn_and_matches ( & elem_types) {
1030+ Some ( Rc :: clone ( & fun) )
1031+ } else {
1032+ None
1033+ }
1034+ } ) ;
1035+ if let Some ( inner_fn) = inner_fn {
1036+ return inner_fn. call_vectorized ( & mut args, environment) . add_span ( span) ;
1037+ }
1038+ }
1039+ }
1040+ }
1041+ }
1042+
10201043 opt. ok_or_else ( || {
10211044 FunctionCarrier :: EvaluationError ( EvaluationError :: new (
10221045 format ! (
1023- "Failed to find a function that can handle the arguments ({}) at runtime " ,
1046+ "no function called '{name}' found matches the arguments: ({})" ,
10241047 arg_types. iter( ) . join( ", " )
10251048 ) ,
10261049 function_expression. span ,
@@ -1030,12 +1053,7 @@ fn resolve_and_call(
10301053 evaluate_expression ( function_expression, environment) ?
10311054 } ;
10321055
1033- ////////////////////////////
1034- ////////////////////////////
1035- ////////////////////////////
1036-
10371056 if let Value :: Function ( function) = function_as_value {
1038- // Here we should be able to call without checking types
10391057 function. call ( & mut args, environment) . add_span ( span)
10401058 } else {
10411059 Err ( FunctionCarrier :: EvaluationError ( EvaluationError :: new (
@@ -1048,6 +1066,12 @@ fn resolve_and_call(
10481066 }
10491067}
10501068
1069+ fn vectorized_element_types ( left : & StaticType , right : & StaticType ) -> [ StaticType ; 2 ] {
1070+ let left_elem = left. sequence_element_type ( ) . unwrap_or_else ( || left. clone ( ) ) ;
1071+ let right_elem = right. sequence_element_type ( ) . unwrap_or_else ( || right. clone ( ) ) ;
1072+ [ left_elem, right_elem]
1073+ }
1074+
10511075fn resolve_dynamic_binding (
10521076 binding : & Binding ,
10531077 arg_types : & [ StaticType ] ,
0 commit comments