@@ -225,6 +225,7 @@ fn process_list_call(
225225 let head = & chunk_xs. pop_front ( ) . unwrap ( ) ;
226226 let ( head_form, head_evaled) = preprocess_expr ( & head, scope_defs, file_ns, program_code, check_warnings) ?;
227227 let args = & chunk_xs;
228+ let def_name = grab_def_name ( head) ;
228229
229230 // println!(
230231 // "handling list call: {} {:?}, {}",
@@ -312,6 +313,16 @@ fn process_list_call(
312313 _ => Err ( format ! ( "unknown syntax: {}" , head) ) ,
313314 } ,
314315 ( Calcit :: Thunk ( ..) , _) => Err ( format ! ( "does not know how to preprocess a thunk: {}" , head) ) ,
316+
317+ ( _, Some ( Calcit :: Fn ( f_name, _name_ns, _id, _scope, f_args, _f_body) ) ) => {
318+ check_fn_args ( & f_args, args, file_ns, & f_name, & def_name, check_warnings) ;
319+ let mut ys = im:: vector![ head_form] ;
320+ for a in args {
321+ let ( form, _v) = preprocess_expr ( & a, scope_defs, file_ns, program_code, check_warnings) ?;
322+ ys. push_back ( form) ;
323+ }
324+ Ok ( ( Calcit :: List ( ys) , None ) )
325+ }
315326 ( _, _) => {
316327 let mut ys = im:: vector![ head_form] ;
317328 for a in args {
@@ -323,6 +334,86 @@ fn process_list_call(
323334 }
324335}
325336
337+ // detects arguments of top-level functions when possible
338+ fn check_fn_args (
339+ defined_args : & CalcitItems ,
340+ params : & CalcitItems ,
341+ file_ns : & str ,
342+ f_name : & str ,
343+ def_name : & str ,
344+ check_warnings : & RefCell < Vec < String > > ,
345+ ) {
346+ let mut i = 0 ;
347+ let mut j = 0 ;
348+ let mut optional = false ;
349+
350+ loop {
351+ let d = defined_args. get ( i) ;
352+ let r = params. get ( j) ;
353+
354+ match ( d, r) {
355+ ( None , None ) => return ,
356+ ( _, Some ( Calcit :: Symbol ( sym, ..) ) ) if sym == "&" => {
357+ // dynamic values, can't tell yet
358+ return ;
359+ }
360+ ( Some ( Calcit :: Symbol ( sym, ..) ) , _) if sym == "&" => {
361+ // dynamic args rule, all okay
362+ return ;
363+ }
364+ ( Some ( Calcit :: Symbol ( sym, ..) ) , _) if sym == "?" => {
365+ // dynamic args rule, all okay
366+ optional = true ;
367+ i = i + 1 ;
368+ continue ;
369+ }
370+ ( Some ( _) , None ) => {
371+ if optional {
372+ i = i + 1 ;
373+ j = j + 1 ;
374+ continue ;
375+ } else {
376+ let mut warnings = check_warnings. borrow_mut ( ) ;
377+ warnings. push ( format ! (
378+ "[Warn] lack of args in {} `{}` with `{}`, at {}/{}" ,
379+ f_name,
380+ primes:: CrListWrap ( defined_args. to_owned( ) ) ,
381+ primes:: CrListWrap ( params. to_owned( ) ) ,
382+ file_ns,
383+ def_name
384+ ) ) ;
385+ return ;
386+ }
387+ }
388+ ( None , Some ( _) ) => {
389+ let mut warnings = check_warnings. borrow_mut ( ) ;
390+ warnings. push ( format ! (
391+ "[Warn] too many args for {} `{}` with `{}`, at {}/{}" ,
392+ f_name,
393+ primes:: CrListWrap ( defined_args. to_owned( ) ) ,
394+ primes:: CrListWrap ( params. to_owned( ) ) ,
395+ file_ns,
396+ def_name
397+ ) ) ;
398+ return ;
399+ }
400+ ( Some ( _) , Some ( _) ) => {
401+ i = i + 1 ;
402+ j = j + 1 ;
403+ continue ;
404+ }
405+ }
406+ }
407+ }
408+
409+ // TODO this native implementation only handles symbols
410+ fn grab_def_name ( x : & Calcit ) -> String {
411+ match x {
412+ Calcit :: Symbol ( _, _, def_name, _) => def_name. to_owned ( ) ,
413+ _ => String :: from ( "??" ) ,
414+ }
415+ }
416+
326417// tradition rule for processing exprs
327418pub fn preprocess_each_items (
328419 head : & str ,
0 commit comments