diff --git a/src/interpreter/context.rs b/src/interpreter/context.rs index d073b2e..ee75b08 100644 --- a/src/interpreter/context.rs +++ b/src/interpreter/context.rs @@ -28,6 +28,16 @@ impl<'s> Context<'s> { } } + /// Execute whole function and return last value on stack (or nil) + pub fn execute(&mut self) -> Result> { + let len = self.fun.bytecode.len(); + while self.pc < len { + self.tick()?; + } + + Ok(self.stack.pop().unwrap_or(Value::Nil)) + } + /// Execute next instruction pub fn tick(&mut self) -> Result<()> { use Instruction::*; @@ -41,10 +51,25 @@ impl<'s> Context<'s> { Call(n) if n >= self.stack.len() => return Err(IndexOutOfBoundsError::Stack.into()), Call(n) => { let fun = self.stack_pop()?; + let mut args = self.stack.split_off(self.stack.len() - n); match fun { - Value::Function(_) => todo!("function calls"), + Value::Function(fun) => { + if fun.locals_len > args.len() { + args.resize(fun.locals_len, Value::Nil); + } + + self.stack.push( + Context { + stack: vec![], + locals: args, + pc: 0, + fun, + } + .execute()?, + ); + } Value::NativeFun(NativeFun(f)) => { - let v = f(&self.stack.split_off(self.stack.len() - n)); + let v = f(&args); self.stack.push(v); } _ => unimplemented!("invalid function type"),