recursion works, so does mutual recursion; function call bugfixes
This commit is contained in:
parent
f4ade4938c
commit
e580d68809
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
18
src/vm.rs
18
src/vm.rs
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user