diff --git a/crates/saft-bytecode/src/compiler.rs b/crates/saft-bytecode/src/compiler.rs index 1ecf7a8..4b94edf 100644 --- a/crates/saft-bytecode/src/compiler.rs +++ b/crates/saft-bytecode/src/compiler.rs @@ -103,11 +103,11 @@ impl Compiler { Ok((chunk, self.items.clone())) } - fn compile_fn(&mut self, function: Spanned<&ir::Function>) -> Result, Error> { + fn compile_fn(&mut self, function: Spanned<&ir::Function>) -> Result { fn inner( compiler: &mut Compiler, function: Spanned<&ir::Function>, - ) -> Result, Error> { + ) -> Result { let Spanned { s, v: function } = function; let ir::Function { params, body } = function; @@ -119,10 +119,10 @@ impl Compiler { compiler.compile_block(body, &mut chunk)?; chunk.emit(Op::Return, s); - Ok(Rc::new(SaftFunction { + Ok(SaftFunction { arity: params.len(), - chunk, - })) + chunk: Rc::new(chunk), + }) } let prev_i = self.stack_i; diff --git a/crates/saft-bytecode/src/item.rs b/crates/saft-bytecode/src/item.rs index bbe04a8..55a5da4 100644 --- a/crates/saft-bytecode/src/item.rs +++ b/crates/saft-bytecode/src/item.rs @@ -1,8 +1,6 @@ -use std::rc::Rc; - use crate::value::SaftFunction; -#[derive(Clone)] +#[derive(Clone, Debug)] pub enum Item { - SaftFunction(Rc), + SaftFunction(SaftFunction), } diff --git a/crates/saft-bytecode/src/value.rs b/crates/saft-bytecode/src/value.rs index ba765aa..7a80d76 100644 --- a/crates/saft-bytecode/src/value.rs +++ b/crates/saft-bytecode/src/value.rs @@ -11,13 +11,13 @@ pub enum Value { #[derive(Debug, Clone)] pub enum Function { - SaftFunction(Rc), + SaftFunction(SaftFunction), } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct SaftFunction { pub arity: usize, - pub chunk: Chunk, + pub chunk: Rc, } impl Value { diff --git a/crates/saft-bytecode/src/vm.rs b/crates/saft-bytecode/src/vm.rs index f2e7ff4..e71b27c 100644 --- a/crates/saft-bytecode/src/vm.rs +++ b/crates/saft-bytecode/src/vm.rs @@ -96,7 +96,12 @@ impl Vm { pub fn interpret_chunk(&mut self, chunk: Rc) -> Result<(), Error> { self.call_stack.push(CallFrame::new(chunk, 0)); - self.run() + let res = self.run(); + println!( + "final stack: {:?}", + self.stack.iter().map(|v| v.repr()).collect::>() + ); + res } pub fn interpret_expr(&mut self, chunk: Rc) -> Result { @@ -105,6 +110,8 @@ impl Vm { } fn run(&mut self) -> Result<(), Error> { + // println!("{:?}", self.call_stack.last().unwrap().chunk); + // println!("{:?}", self.items); while { let call_frame = self.call_stack.last().unwrap(); call_frame.i < call_frame.chunk.end() @@ -120,6 +127,12 @@ impl Vm { } fn eval_op(&mut self, op: &Op, s: &Span) -> Result<(), Error> { + // println!( + // "{:?}", + // self.stack.iter().map(|v| v.repr()).collect::>() + // ); + // println!("{:?}", op); + match op { Op::Pop => { self.pop(); @@ -127,7 +140,14 @@ impl Vm { Op::PopN(n) => { self.stack.truncate(self.stack.len() - n); } - Op::Return => todo!(), + Op::Return => { + let call_frame = self.call_stack.pop().unwrap(); + let ret = self.pop(); + self.stack.truncate(call_frame.stack_base); + self.push(ret); + + return Ok(()); + } Op::Nil => self.push(Value::Nil), Op::Bool(b) => self.push(Value::Num(Num::Bool(*b))), Op::Float(f) => self.push(Value::Num(Num::Float(*f))), @@ -185,7 +205,29 @@ impl Vm { } self.push(v); } - Op::Call(_) => {} + Op::Call(n_args) => { + let args = self.popn(*n_args); + let fun = self.pop(); + + match fun { + Value::Function(Function::SaftFunction(fun)) => { + self.call_stack.last_mut().unwrap().i += 1; + self.enter_frame(fun.chunk.clone()); + for arg in args { + self.push(arg); + } + } + _ => { + exotic!( + "Uncallable", + s, + format!("Value of type '{}' is not callable", fun.ty().name()) + ) + } + } + + return Ok(()); + } Op::Index => { let index = self.pop(); let indexable = self.pop(); @@ -246,6 +288,10 @@ impl Vm { self.stack.pop().unwrap() } + fn popn(&mut self, n: usize) -> Vec { + self.stack.split_off(self.stack.len() - n) + } + #[allow(unused)] fn peek(&self) -> &Value { self.stack.last().unwrap() @@ -296,4 +342,13 @@ impl Vm { pub fn get_stack(&self) -> &Vec { &self.stack } + + fn enter_frame(&mut self, chunk: Rc) { + let stack_base = self.stack.len(); + self.call_stack.push(CallFrame { + i: 0, + stack_base, + chunk, + }) + } }