recursion works, so does mutual recursion; function call bugfixes

This commit is contained in:
Scott Richmond 2025-06-20 12:32:15 -04:00
parent f4ade4938c
commit e580d68809
3 changed files with 51 additions and 10 deletions

View File

@ -367,7 +367,7 @@ fn is_binding(expr: &Spanned<Ast>) -> bool {
let (ast, _) = expr;
use Ast::*;
match ast {
Let(..) | LBox(..) => true,
Let(..) | LBox(..) | FnDeclaration(..) => true,
Fn(name, ..) => !name.is_empty(),
_ => false,
}
@ -1209,7 +1209,19 @@ impl<'a> Compiler<'a> {
}
MatchClause(..) => unreachable!(),
Fn(name, body, doc) => {
let name = if name.is_empty() { "anonymous" } else { name };
let is_anon = name.is_empty();
if !is_anon {
let declared = self.chunk.constants.iter().any(|val| match val {
Value::Fn(lfn) => lfn.name() == *name,
_ => false,
});
if !declared {
let declaration = Value::Fn(Rc::new(LFn::Declared { name }));
self.emit_constant(declaration);
self.bind(name);
}
}
let FnBody(fn_body) = &body.as_ref().0 else {
unreachable!()
@ -1268,8 +1280,8 @@ impl<'a> Compiler<'a> {
for idx in tup_jump_idxes {
compiler.patch_jump(idx, compiler.len() - idx - 3);
}
compiler.emit_op(Op::PopN);
compiler.emit_byte(arity as usize);
// compiler.emit_op(Op::PopN);
// compiler.emit_byte(arity as usize);
compiler.patch_jump(jump_idx, compiler.len() - jump_idx - 3);
let mut no_match_jumps = vec![];
no_match_jumps.push(compiler.stub_jump(Op::JumpIfNoMatch));
@ -1337,8 +1349,23 @@ impl<'a> Compiler<'a> {
// TODO: check if the function is already declared, and pull out the relevant OnceCell if need be
let the_fn = Value::Fn(Rc::new(lfn));
self.emit_constant(the_fn);
self.bind(name);
// self.emit_constant(the_fn);
// self.bind(name);
if !is_anon {
let declaration_idx = self
.chunk
.constants
.iter()
.position(|val| match val {
Value::Fn(declaration) => declaration.name() == *name,
_ => false,
})
.unwrap();
self.chunk.constants[declaration_idx] = the_fn;
} else {
self.emit_constant(the_fn)
}
for upvalue in upvalues {
self.emit_op(Op::SetUpvalue);

View File

@ -75,7 +75,11 @@ pub fn run(src: &'static str) {
pub fn main() {
env::set_var("RUST_BACKTRACE", "1");
let src = "
fn two
fn one (x, y) -> two (x, y)
fn two (:foo, x) -> (:done, x)
one (:fool, :bar)
";
run(src);
}

View File

@ -872,6 +872,7 @@ impl Vm {
for i in 0..arity as usize {
self.return_register[arity as usize - i - 1] = self.pop();
}
self.print_stack();
// then pop everything back to the current stack frame
self.stack.truncate(self.frame.stack_base);
@ -892,11 +893,16 @@ impl Vm {
let gathered_args = Vector::from(splatted_args);
self.push(Value::List(Box::new(gathered_args)));
}
let arity = splat_arity.min(arity);
let arity = if splat_arity > 0 {
splat_arity.min(arity)
} else {
arity
};
let mut frame = CallFrame {
function: val,
arity,
stack_base: self.stack.len() - arity as usize - 1,
stack_base: self.stack.len() - arity as usize,
ip: 0,
};
@ -972,11 +978,15 @@ impl Vm {
let gathered_args = Vector::from(splatted_args);
self.push(Value::List(Box::new(gathered_args)));
}
let arity = splat_arity.min(arity);
let arity = if splat_arity > 0 {
splat_arity.min(arity)
} else {
arity
};
let mut frame = CallFrame {
function: val,
arity,
stack_base: self.stack.len() - arity as usize - 1,
stack_base: self.stack.len() - arity as usize,
ip: 0,
};