@@ -7,6 +7,7 @@ use super::{
77 builtin:: { BuiltinParam , BuiltinParamName } ,
88} ;
99use crate :: {
10+ destructure:: destruct,
1011 error:: { Error :: * , Result } ,
1112 evaluate_named,
1213 gc:: GcHashMap ,
@@ -50,60 +51,77 @@ pub fn parse_function_call(
5051 throw ! ( TooManyArgsFunctionHas ( params. len( ) ) )
5152 }
5253
53- let mut filled_args = 0 ;
54+ let mut filled_named = 0 ;
55+ let mut filled_positionals = 0 ;
5456
5557 args. unnamed_iter ( s. clone ( ) , ctx. clone ( ) , tailstrict, & mut |id, arg| {
5658 let name = params[ id] . 0 . clone ( ) ;
57- passed_args . insert ( name, arg) ;
58- filled_args += 1 ;
59+ destruct ( & name, arg, & mut passed_args ) ? ;
60+ filled_positionals += 1 ;
5961 Ok ( ( ) )
6062 } ) ?;
6163
6264 args. named_iter ( s, ctx, tailstrict, & mut |name, value| {
6365 // FIXME: O(n) for arg existence check
64- if !params. iter ( ) . any ( |p| & p. 0 == name) {
66+ if !params. iter ( ) . any ( |p| p. 0 . name ( ) . as_ref ( ) == Some ( name) ) {
6567 throw ! ( UnknownFunctionParameter ( ( name as & str ) . to_owned( ) ) ) ;
6668 }
6769 if passed_args. insert ( name. clone ( ) , value) . is_some ( ) {
6870 throw ! ( BindingParameterASecondTime ( name. clone( ) ) ) ;
6971 }
70- filled_args += 1 ;
72+ filled_named += 1 ;
7173 Ok ( ( ) )
7274 } ) ?;
7375
74- if filled_args < params. len ( ) {
76+ if filled_named + filled_positionals < params. len ( ) {
7577 // Some args are unset, but maybe we have defaults for them
7678 // Default values should be created in newly created context
7779 let fctx = Context :: new_future ( ) ;
78- let mut defaults = GcHashMap :: with_capacity ( params. len ( ) - filled_args) ;
80+ let mut defaults =
81+ GcHashMap :: with_capacity ( params. len ( ) - filled_named - filled_positionals) ;
7982
80- for param in params. iter ( ) . filter ( |p| p. 1 . is_some ( ) ) {
81- if passed_args. contains_key ( & param. 0 . clone ( ) ) {
83+ for ( idx, param) in params. iter ( ) . enumerate ( ) . filter ( |p| p. 1 . 1 . is_some ( ) ) {
84+ if let Some ( name) = param. 0 . name ( ) {
85+ if passed_args. contains_key ( & name) {
86+ continue ;
87+ }
88+ } else if idx < filled_positionals {
8289 continue ;
8390 }
8491
85- defaults . insert (
86- param. 0 . clone ( ) ,
92+ destruct (
93+ & param. 0 ,
8794 Thunk :: new ( tb ! ( EvaluateNamedThunk {
8895 ctx: fctx. clone( ) ,
89- name: param. 0 . clone ( ) ,
96+ name: param. 0 . name ( ) . unwrap_or_else ( || "<destruct>" . into ( ) ) ,
9097 value: param. 1 . clone( ) . expect( "default exists" ) ,
9198 } ) ) ,
92- ) ;
93- filled_args += 1 ;
99+ & mut defaults,
100+ ) ?;
101+ if param. 0 . name ( ) . is_some ( ) {
102+ filled_named += 1 ;
103+ } else {
104+ filled_positionals += 1 ;
105+ }
94106 }
95107
96- // Some args still wasn 't filled
97- if filled_args != params. len ( ) {
108+ // Some args still weren 't filled
109+ if filled_named + filled_positionals != params. len ( ) {
98110 for param in params. iter ( ) . skip ( args. unnamed_len ( ) ) {
99111 let mut found = false ;
100112 args. named_names ( & mut |name| {
101- if name == & param. 0 {
113+ if Some ( name) == param. 0 . name ( ) . as_ref ( ) {
102114 found = true ;
103115 }
104116 } ) ;
105117 if !found {
106- throw ! ( FunctionParameterNotBoundInCall ( param. 0 . clone( ) ) ) ;
118+ throw ! ( FunctionParameterNotBoundInCall (
119+ param
120+ . 0
121+ . clone( )
122+ . name( )
123+ . unwrap_or_else( || "<destruct>" . into( ) )
124+ ) ) ;
107125 }
108126 }
109127 unreachable ! ( ) ;
@@ -189,7 +207,7 @@ pub fn parse_builtin_call(
189207
190208/// Creates Context, which has all argument default values applied
191209/// and with unbound values causing error to be returned
192- pub fn parse_default_function_call ( body_ctx : Context , params : & ParamsDesc ) -> Context {
210+ pub fn parse_default_function_call ( body_ctx : Context , params : & ParamsDesc ) -> Result < Context > {
193211 #[ derive( Trace ) ]
194212 struct DependsOnUnbound ( IStr ) ;
195213 impl ThunkValue for DependsOnUnbound {
@@ -205,23 +223,27 @@ pub fn parse_default_function_call(body_ctx: Context, params: &ParamsDesc) -> Co
205223
206224 for param in params. iter ( ) {
207225 if let Some ( v) = & param. 1 {
208- bindings . insert (
209- param. 0 . clone ( ) ,
226+ destruct (
227+ & param. 0 . clone ( ) ,
210228 Thunk :: new ( tb ! ( EvaluateNamedThunk {
211229 ctx: fctx. clone( ) ,
212- name: param. 0 . clone ( ) ,
230+ name: param. 0 . name ( ) . unwrap_or_else ( || "<destruct>" . into ( ) ) ,
213231 value: v. clone( ) ,
214232 } ) ) ,
215- ) ;
233+ & mut bindings,
234+ ) ?;
216235 } else {
217- bindings. insert (
218- param. 0 . clone ( ) ,
219- Thunk :: new ( tb ! ( DependsOnUnbound ( param. 0 . clone( ) ) ) ) ,
220- ) ;
236+ destruct (
237+ & param. 0 ,
238+ Thunk :: new ( tb ! ( DependsOnUnbound (
239+ param. 0 . name( ) . unwrap_or_else( || "<destruct>" . into( ) )
240+ ) ) ) ,
241+ & mut bindings,
242+ ) ?;
221243 }
222244 }
223245
224- body_ctx
246+ Ok ( body_ctx
225247 . extend ( bindings, None , None , None )
226- . into_future ( fctx)
248+ . into_future ( fctx) )
227249}
0 commit comments