loop arity checking

This commit is contained in:
Scott Richmond 2024-12-10 18:07:31 -05:00
parent e9b52e1488
commit dde9ac4bff
2 changed files with 21 additions and 7 deletions

View File

@ -167,7 +167,9 @@ pub fn run(src: &'static str) {
pub fn main() { pub fn main() {
let src = " let src = "
do 42 > recur () loop () with {
() -> :baz
}
"; ";
run(src); run(src);
// struct_scalpel::print_dissection_info::<value::Value>() // struct_scalpel::print_dissection_info::<value::Value>()

View File

@ -18,6 +18,7 @@ impl VErr {
struct VStatus { struct VStatus {
tail_position: bool, tail_position: bool,
in_loop: bool, in_loop: bool,
loop_arity: u8,
last_term: bool, last_term: bool,
has_placeholder: bool, has_placeholder: bool,
used_bindings: Vec<String>, used_bindings: Vec<String>,
@ -60,6 +61,7 @@ impl<'a> Validator<'a> {
status: VStatus { status: VStatus {
tail_position: false, tail_position: false,
in_loop: false, in_loop: false,
loop_arity: 0,
last_term: false, last_term: false,
has_placeholder: false, has_placeholder: false,
used_bindings: vec![], used_bindings: vec![],
@ -429,15 +431,19 @@ impl<'a> Validator<'a> {
self.ast = expr; self.ast = expr;
self.validate(); self.validate();
let in_loop = self.status.in_loop; let Ast::Tuple(input) = expr else {
self.status.in_loop = true; unreachable!()
};
// let (expr, span) = body; let in_loop = self.status.in_loop;
// self.span = span; let arity = self.status.loop_arity;
// self.expr = expr; self.status.in_loop = true;
// self.validate(); self.status.loop_arity = input.len() as u8;
// for clause in body {}
self.status.in_loop = in_loop; self.status.in_loop = in_loop;
self.status.loop_arity = arity;
} }
Ast::Recur(args) => { Ast::Recur(args) => {
if !self.status.in_loop { if !self.status.in_loop {
@ -448,6 +454,12 @@ impl<'a> Validator<'a> {
self.err("you may only use `recur` in tail position".to_string()); self.err("you may only use `recur` in tail position".to_string());
} }
let num_args = args.len() as u8;
let loop_arity = self.status.loop_arity;
if num_args != loop_arity {
self.err(format!("loop arity mismatch: loop has arity of {loop_arity}; `recur` called with {num_args} arguments"))
}
self.status.tail_position = false; self.status.tail_position = false;
for arg in args { for arg in args {
let (expr, span) = arg; let (expr, span) = arg;