Skip to content

Commit afec6f2

Browse files
committed
try to check args size at preprocess
1 parent 7bb028e commit afec6f2

File tree

2 files changed

+123
-0
lines changed

2 files changed

+123
-0
lines changed

calcit/debug/check-args.cirru

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
2+
{} (:package |check-args)
3+
:configs $ {} (:init-fn |check-args.main/main!) (:reload-fn |check-args.main/reload!)
4+
:modules $ []
5+
:files $ {}
6+
|check-args.main $ {}
7+
:ns $ quote
8+
ns check-args.main $ :require
9+
[] util.core :refer $ [] log-title inside-eval:
10+
:defs $ {}
11+
12+
|f1 $ quote
13+
defn f1 (a) nil
14+
15+
|f2 $ quote
16+
defn f2 (a ? b) nil
17+
18+
|f3 $ quote
19+
defn f3 (a & b) nil
20+
21+
|main! $ quote
22+
defn main! ()
23+
; "bad case examples for args checking"
24+
f1 1 4
25+
f2 1
26+
f2 1 2
27+
f2 1 2 4
28+
f2
29+
f3 1
30+
f3 1 2
31+
f3 1 2 3
32+
f3

src/runner/preprocess.rs

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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
327418
pub fn preprocess_each_items(
328419
head: &str,

0 commit comments

Comments
 (0)