basic function calls, still with bugs!
This commit is contained in:
parent
22d1ceb3e8
commit
681176282c
|
@ -286,9 +286,9 @@ fn get_builtin(name: &str, arity: usize) -> Option<Op> {
|
|||
pub struct Compiler {
|
||||
pub chunk: Chunk,
|
||||
pub bindings: Vec<Binding>,
|
||||
scope_depth: isize,
|
||||
match_depth: usize,
|
||||
stack_depth: usize,
|
||||
pub scope_depth: isize,
|
||||
pub match_depth: usize,
|
||||
pub stack_depth: usize,
|
||||
pub spans: Vec<SimpleSpan>,
|
||||
pub nodes: Vec<&'static Ast>,
|
||||
pub ast: &'static Ast,
|
||||
|
@ -837,10 +837,8 @@ impl Compiler {
|
|||
// visit all the args
|
||||
// then store them
|
||||
// then call the function
|
||||
for (register_slot, arg) in args.iter().enumerate() {
|
||||
for arg in args {
|
||||
self.visit(arg);
|
||||
self.emit_op(Op::StoreAt);
|
||||
self.emit_byte(register_slot);
|
||||
}
|
||||
|
||||
self.emit_op(Op::PushBinding);
|
||||
|
@ -982,7 +980,7 @@ impl Compiler {
|
|||
Some(compiler) => compiler,
|
||||
None => {
|
||||
let mut compiler = Compiler::new(clause, self.name, self.src);
|
||||
compiler.emit_op(Op::Load);
|
||||
// compiler.emit_op(Op::Load);
|
||||
compiler.stack_depth += arity;
|
||||
compiler.scope_depth += 1;
|
||||
compiler.emit_op(Op::ResetMatch);
|
||||
|
|
|
@ -78,7 +78,9 @@ pub fn run(src: &'static str) {
|
|||
pub fn main() {
|
||||
env::set_var("RUST_BACKTRACE", "1");
|
||||
let src = "
|
||||
(1, 2, 3)
|
||||
fn foo (_) -> [1, 2, 3]
|
||||
|
||||
foo (1)
|
||||
";
|
||||
run(src);
|
||||
}
|
||||
|
|
162
src/vm.rs
162
src/vm.rs
|
@ -102,7 +102,7 @@ impl Vm {
|
|||
let base_fn = Value::Fn(Rc::new(cell));
|
||||
let base_frame = CallFrame {
|
||||
function: base_fn.clone(),
|
||||
stack_base: 1,
|
||||
stack_base: 0,
|
||||
ip: 0,
|
||||
arity: 0,
|
||||
};
|
||||
|
@ -111,15 +111,7 @@ impl Vm {
|
|||
call_stack: Vec::with_capacity(64),
|
||||
frame: base_frame,
|
||||
ip: 0,
|
||||
return_register: [
|
||||
Value::Nothing,
|
||||
Value::Nothing,
|
||||
Value::Nothing,
|
||||
Value::Nothing,
|
||||
Value::Nothing,
|
||||
Value::Nothing,
|
||||
Value::Nothing,
|
||||
],
|
||||
return_register: [const { Value::Nothing }; 7],
|
||||
matches: false,
|
||||
match_depth: 0,
|
||||
result: None,
|
||||
|
@ -180,6 +172,7 @@ impl Vm {
|
|||
}
|
||||
|
||||
pub fn interpret(&mut self) {
|
||||
loop {
|
||||
let Some(byte) = self.chunk().bytecode.get(self.ip) else {
|
||||
self.result = Some(Ok(self.stack.pop().unwrap()));
|
||||
return;
|
||||
|
@ -247,15 +240,13 @@ impl Vm {
|
|||
let jump_len = self.chunk().bytecode[self.ip + 1];
|
||||
let cond = self.pop();
|
||||
match cond {
|
||||
Value::Number(0.0) => {
|
||||
Value::Number(x) if x <= 0.0 => {
|
||||
self.ip += jump_len as usize + 2;
|
||||
self.interpret()
|
||||
}
|
||||
Value::Number(..) => {
|
||||
self.ip += 2;
|
||||
self.interpret()
|
||||
}
|
||||
_ => self.panic("repeat requires a number"),
|
||||
_ => return self.panic("repeat requires a number"),
|
||||
}
|
||||
}
|
||||
Pop => {
|
||||
|
@ -268,7 +259,8 @@ impl Vm {
|
|||
self.ip += 2;
|
||||
}
|
||||
PushBinding => {
|
||||
let binding_idx = self.chunk().bytecode[self.ip + 1] as usize;
|
||||
let binding_idx =
|
||||
self.chunk().bytecode[self.ip + 1] as usize + self.frame.stack_base;
|
||||
let binding_value = self.stack[binding_idx].clone();
|
||||
self.push(binding_value);
|
||||
self.ip += 2;
|
||||
|
@ -313,7 +305,6 @@ impl Vm {
|
|||
let val_type = self.chunk().kw_from(val_type).unwrap();
|
||||
self.matches = val_type == as_type;
|
||||
self.ip += 1;
|
||||
self.interpret()
|
||||
}
|
||||
MatchNil => {
|
||||
let idx = self.stack.len() - self.match_depth as usize - 1;
|
||||
|
@ -321,7 +312,6 @@ impl Vm {
|
|||
self.matches = true;
|
||||
};
|
||||
self.ip += 1;
|
||||
self.interpret()
|
||||
}
|
||||
MatchTrue => {
|
||||
let idx = self.stack.len() - self.match_depth as usize - 1;
|
||||
|
@ -339,7 +329,7 @@ impl Vm {
|
|||
}
|
||||
PanicIfNoMatch => {
|
||||
if !self.matches {
|
||||
self.panic("no match");
|
||||
return self.panic("no match");
|
||||
} else {
|
||||
self.ip += 1;
|
||||
}
|
||||
|
@ -364,7 +354,7 @@ impl Vm {
|
|||
let tuple_len = self.chunk().bytecode[self.ip + 1];
|
||||
let tuple_members = self.stack.split_off(self.stack.len() - tuple_len as usize);
|
||||
let tuple = Value::Tuple(Rc::new(tuple_members));
|
||||
self.stack.push(tuple);
|
||||
self.push(tuple);
|
||||
self.ip += 2;
|
||||
}
|
||||
LoadTuple => {
|
||||
|
@ -376,7 +366,7 @@ impl Vm {
|
|||
self.push(member.clone());
|
||||
}
|
||||
}
|
||||
_ => self.panic("internal error: expected tuple"),
|
||||
_ => return self.panic("internal error: expected tuple"),
|
||||
};
|
||||
self.ip += 1;
|
||||
}
|
||||
|
@ -384,7 +374,7 @@ impl Vm {
|
|||
let list_len = self.chunk().bytecode[self.ip + 1];
|
||||
let list_members = self.stack.split_off(self.stack.len() - list_len as usize);
|
||||
let list = Value::List(Box::new(Vector::from(list_members)));
|
||||
self.stack.push(list);
|
||||
self.push(list);
|
||||
self.ip += 2;
|
||||
}
|
||||
MatchList => {
|
||||
|
@ -406,7 +396,7 @@ impl Vm {
|
|||
self.push(member.clone());
|
||||
}
|
||||
}
|
||||
_ => self.panic("internal error: expected tuple"),
|
||||
_ => return self.panic("internal error: expected tuple"),
|
||||
};
|
||||
self.ip += 1;
|
||||
}
|
||||
|
@ -422,7 +412,7 @@ impl Vm {
|
|||
let value = dict_iter.next().unwrap();
|
||||
dict.insert(*key, value.clone());
|
||||
}
|
||||
self.stack.push(Value::Dict(Box::new(dict)));
|
||||
self.push(Value::Dict(Box::new(dict)));
|
||||
self.ip += 2;
|
||||
}
|
||||
LoadDictValue => {
|
||||
|
@ -449,7 +439,7 @@ impl Vm {
|
|||
}
|
||||
PushBox => {
|
||||
let val = self.pop();
|
||||
self.stack.push(Value::Box(Rc::new(RefCell::new(val))));
|
||||
self.push(Value::Box(Rc::new(RefCell::new(val))));
|
||||
self.ip += 1;
|
||||
}
|
||||
GetKey => {
|
||||
|
@ -493,7 +483,7 @@ impl Vm {
|
|||
self.push(Value::Number(x as usize as f64));
|
||||
self.ip += 1;
|
||||
} else {
|
||||
self.panic("repeat requires a number");
|
||||
return self.panic("repeat requires a number");
|
||||
}
|
||||
}
|
||||
Decrement => {
|
||||
|
@ -501,95 +491,93 @@ impl Vm {
|
|||
if let Value::Number(x) = val {
|
||||
self.push(Value::Number(x - 1.0));
|
||||
self.ip += 1;
|
||||
self.interpret()
|
||||
} else {
|
||||
self.panic("you may only decrement a number");
|
||||
return self.panic("you may only decrement a number");
|
||||
}
|
||||
}
|
||||
Duplicate => {
|
||||
self.push(self.peek().clone());
|
||||
self.ip += 1;
|
||||
self.interpret()
|
||||
}
|
||||
MatchDepth => {
|
||||
self.match_depth = self.chunk().bytecode[self.ip + 1];
|
||||
self.ip += 2;
|
||||
self.interpret()
|
||||
}
|
||||
PanicNoWhen | PanicNoMatch => self.panic("no match"),
|
||||
|
||||
PanicNoWhen | PanicNoMatch => {
|
||||
return self.panic("no match");
|
||||
}
|
||||
Eq => {
|
||||
let first = self.stack.pop().unwrap();
|
||||
let second = self.stack.pop().unwrap();
|
||||
let first = self.pop();
|
||||
let second = self.pop();
|
||||
if first == second {
|
||||
self.stack.push(Value::True)
|
||||
self.push(Value::True)
|
||||
} else {
|
||||
self.stack.push(Value::False)
|
||||
self.push(Value::False)
|
||||
}
|
||||
self.ip += 1;
|
||||
}
|
||||
Add => {
|
||||
let first = self.stack.pop().unwrap();
|
||||
let second = self.stack.pop().unwrap();
|
||||
let first = self.pop();
|
||||
let second = self.pop();
|
||||
if let (Value::Number(x), Value::Number(y)) = (first, second) {
|
||||
self.stack.push(Value::Number(x + y))
|
||||
self.push(Value::Number(x + y))
|
||||
} else {
|
||||
self.panic("`add` requires two numbers")
|
||||
return self.panic("`add` requires two numbers");
|
||||
}
|
||||
self.ip += 1;
|
||||
}
|
||||
Sub => {
|
||||
let first = self.stack.pop().unwrap();
|
||||
let second = self.stack.pop().unwrap();
|
||||
let first = self.pop();
|
||||
let second = self.pop();
|
||||
if let (Value::Number(x), Value::Number(y)) = (first, second) {
|
||||
self.stack.push(Value::Number(y - x))
|
||||
self.push(Value::Number(y - x))
|
||||
} else {
|
||||
self.panic("`sub` requires two numbers")
|
||||
return self.panic("`sub` requires two numbers");
|
||||
}
|
||||
self.ip += 1;
|
||||
}
|
||||
Mult => {
|
||||
let first = self.stack.pop().unwrap();
|
||||
let second = self.stack.pop().unwrap();
|
||||
let first = self.pop();
|
||||
let second = self.pop();
|
||||
if let (Value::Number(x), Value::Number(y)) = (first, second) {
|
||||
self.stack.push(Value::Number(x * y))
|
||||
self.push(Value::Number(x * y))
|
||||
} else {
|
||||
self.panic("`mult` requires two numbers")
|
||||
return self.panic("`mult` requires two numbers");
|
||||
}
|
||||
self.ip += 1;
|
||||
}
|
||||
Div => {
|
||||
let first = self.stack.pop().unwrap();
|
||||
let second = self.stack.pop().unwrap();
|
||||
let first = self.pop();
|
||||
let second = self.pop();
|
||||
if let (Value::Number(x), Value::Number(y)) = (first, second) {
|
||||
if x == 0.0 {
|
||||
self.panic("division by 0")
|
||||
return self.panic("division by 0");
|
||||
}
|
||||
self.stack.push(Value::Number(y / x))
|
||||
self.push(Value::Number(y / x))
|
||||
} else {
|
||||
self.panic("`div` requires two numbers")
|
||||
return self.panic("`div` requires two numbers");
|
||||
}
|
||||
self.ip += 1;
|
||||
}
|
||||
Unbox => {
|
||||
let the_box = self.stack.pop().unwrap();
|
||||
let the_box = self.pop();
|
||||
let inner = if let Value::Box(b) = the_box {
|
||||
b.borrow().clone()
|
||||
} else {
|
||||
return self.panic("`unbox` requires a box");
|
||||
};
|
||||
self.stack.push(inner);
|
||||
self.push(inner);
|
||||
self.ip += 1;
|
||||
}
|
||||
BoxStore => {
|
||||
let new_value = self.stack.pop().unwrap();
|
||||
let the_box = self.stack.pop().unwrap();
|
||||
let new_value = self.pop();
|
||||
let the_box = self.pop();
|
||||
if let Value::Box(b) = the_box {
|
||||
b.replace(new_value.clone());
|
||||
} else {
|
||||
return self.panic("`store` requires a box");
|
||||
}
|
||||
self.stack.push(new_value);
|
||||
self.push(new_value);
|
||||
self.ip += 1;
|
||||
}
|
||||
Assert => {
|
||||
|
@ -600,8 +588,8 @@ impl Vm {
|
|||
self.ip += 1;
|
||||
}
|
||||
Get => {
|
||||
let key = self.stack.pop().unwrap();
|
||||
let dict = self.stack.pop().unwrap();
|
||||
let key = self.pop();
|
||||
let dict = self.pop();
|
||||
let value = match (key, dict) {
|
||||
(Value::Keyword(k), Value::Dict(d)) => {
|
||||
d.as_ref().get(&k).unwrap_or(&Value::Nil).clone()
|
||||
|
@ -609,12 +597,12 @@ impl Vm {
|
|||
(Value::Keyword(_), _) => Value::Nil,
|
||||
_ => return self.panic("keys must be keywords"),
|
||||
};
|
||||
self.stack.push(value);
|
||||
self.push(value);
|
||||
self.ip += 1;
|
||||
}
|
||||
At => {
|
||||
let idx = self.stack.pop().unwrap();
|
||||
let ordered = self.stack.pop().unwrap();
|
||||
let idx = self.pop();
|
||||
let ordered = self.pop();
|
||||
let value = match (ordered, idx) {
|
||||
(Value::List(l), Value::Number(i)) => {
|
||||
l.get(i as usize).unwrap_or(&Value::Nil).clone()
|
||||
|
@ -625,7 +613,7 @@ impl Vm {
|
|||
(_, Value::Number(_)) => Value::Nil,
|
||||
_ => return self.panic("indexes must be numbers"),
|
||||
};
|
||||
self.stack.push(value);
|
||||
self.push(value);
|
||||
self.ip += 1;
|
||||
}
|
||||
Not => {
|
||||
|
@ -639,7 +627,7 @@ impl Vm {
|
|||
}
|
||||
Panic => {
|
||||
let msg = self.pop().show(self.chunk());
|
||||
self.panic_with(msg);
|
||||
return self.panic_with(msg);
|
||||
}
|
||||
EmptyString => {
|
||||
self.push(Value::String(Rc::new("".to_string())));
|
||||
|
@ -667,8 +655,50 @@ impl Vm {
|
|||
self.push(stringified);
|
||||
self.ip += 1;
|
||||
}
|
||||
Call => todo!(),
|
||||
Return => todo!(),
|
||||
Call => {
|
||||
let arity = self.chunk().bytecode[self.ip + 1];
|
||||
self.ip += 2;
|
||||
|
||||
let val = self.pop();
|
||||
let Value::Fn(_) = val else {
|
||||
return self
|
||||
.panic_with(format!("{} is not a function", val.show(self.chunk())));
|
||||
};
|
||||
|
||||
let mut frame = CallFrame {
|
||||
function: val,
|
||||
arity,
|
||||
stack_base: self.stack.len() - arity as usize,
|
||||
ip: 0,
|
||||
};
|
||||
|
||||
swap(&mut self.frame, &mut frame);
|
||||
frame.ip = self.ip;
|
||||
|
||||
self.call_stack.push(frame);
|
||||
self.ip = 0;
|
||||
|
||||
if crate::DEBUG_RUN {
|
||||
println!(
|
||||
"== calling into {} ==",
|
||||
self.frame.function.show(self.chunk())
|
||||
);
|
||||
}
|
||||
}
|
||||
Return => {
|
||||
if crate::DEBUG_RUN {
|
||||
println!(
|
||||
"== returning from {} ==",
|
||||
self.frame.function.show(self.chunk())
|
||||
)
|
||||
}
|
||||
self.frame = self.call_stack.pop().unwrap();
|
||||
self.ip = self.frame.ip;
|
||||
let mut value = Value::Nothing;
|
||||
swap(&mut self.return_register[0], &mut value);
|
||||
self.push(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user