fix loop validation bugs

This commit is contained in:
Scott Richmond 2024-12-12 19:28:55 -05:00
parent ac4bd0fb55
commit 49a0b0f8a7
4 changed files with 30 additions and 13 deletions

View File

@ -52,7 +52,6 @@ fn ordered? {
fn assoc? { fn assoc? {
"Returns true if a value is an associative collection: a dict or a pkg." "Returns true if a value is an associative collection: a dict or a pkg."
(d as :dict) -> true (d as :dict) -> true
(p as :pkg) -> true
(_) -> false (_) -> false
} }

View File

@ -10,6 +10,6 @@ fn dec (n as :number) -> base :sub (n, 1)
fn sub (x as :number, y as :number) -> base :sub (x, y) fn sub (x as :number, y as :number) -> base :sub (x, y)
fn panics! () -> add ("foo", "bar") fn print!(x) -> base :print! (x)
#{add, dec, sub, panics!} #{add, dec, sub, print!}

View File

@ -169,6 +169,11 @@ pub fn run(src: &'static str) {
v6or.validate(); v6or.validate();
if !v6or.errors.is_empty() {
report_invalidation(v6or.errors);
return;
}
prelude_fn_info.extend(&mut v6or.fn_info.into_iter()); prelude_fn_info.extend(&mut v6or.fn_info.into_iter());
let mut proc = Process { let mut proc = Process {
@ -191,8 +196,13 @@ pub fn run(src: &'static str) {
pub fn main() { pub fn main() {
let src = " let src = "
fn foo () -> panics! () loop (10) with {
foo () (0) -> :done
(n) -> {
print! (n)
recur (dec (n))
}
}
"; ";
run(src); run(src);
// struct_scalpel::print_dissection_info::<value::Value>() // struct_scalpel::print_dissection_info::<value::Value>()

View File

@ -536,32 +536,40 @@ impl<'a, 'src: 'a> Validator<'a, 'src> {
unreachable!() unreachable!()
}; };
dbg!(&input);
let tailpos = self.status.tail_position;
self.status.tail_position = true;
let in_loop = self.status.in_loop; let in_loop = self.status.in_loop;
let arity = self.status.loop_arity; let outer_arity = self.status.loop_arity;
self.status.in_loop = true; self.status.in_loop = true;
self.status.loop_arity = input.len() as u8; let loop_arity = input.len() as u8;
self.status.loop_arity = loop_arity;
for clause in body { for clause in body {
let (expr, span) = clause; let (expr, span) = clause;
self.ast = expr; self.ast = expr;
self.span = *span; self.span = *span;
match self.arity() { let arity = self.arity();
dbg!(&arity);
match arity {
Arity::Fixed(clause_arity) => { Arity::Fixed(clause_arity) => {
if clause_arity != arity { if clause_arity != loop_arity {
self.err(format!("mismatched arity: expected {arity} arguments in `loop` clause; got {clause_arity}")) self.err(format!("mismatched arity: expected {loop_arity} arguments in `loop` clause; got {clause_arity}"))
} }
} }
Arity::Splat(clause_arity) => { Arity::Splat(clause_arity) => {
if clause_arity > arity { if clause_arity > loop_arity {
self.err(format!("mismathced arity: expected {arity} arguments in `loop` clause; this clause takes {clause_arity} or more")) self.err(format!("mismathced arity: expected {loop_arity} arguments in `loop` clause; this clause takes {clause_arity} or more"))
} }
} }
}; };
self.validate(); self.validate();
} }
self.status.tail_position = tailpos;
self.status.in_loop = in_loop; self.status.in_loop = in_loop;
self.status.loop_arity = arity; self.status.loop_arity = outer_arity;
} }
Recur(args) => { Recur(args) => {
if !self.status.in_loop { if !self.status.in_loop {