diff --git a/examples/test.lua b/examples/test.lua index 5eadab2..a8385a5 100644 --- a/examples/test.lua +++ b/examples/test.lua @@ -5,5 +5,14 @@ function add(x) end end +function min(x, y) + local m = x + if y < x then + m = y + end + return m +end + print(max(11, 9)) -print(add(10)(15)) \ No newline at end of file +print(add(10)(15)) +print(min(11, 9)) \ No newline at end of file diff --git a/src/vm.rs b/src/vm.rs index decb72c..f135b18 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -42,6 +42,10 @@ pub enum Instruction { Add(u16, u16, u16), /// R(A) := R(B) < R(C) LessThan(u16, u16, u16), + /// PC += sAx + Jmp(i32), + /// if (R(B) <=> C) then R(A) := R(B) else PC++ + Test(u16, u16, u16), /// [func] [params.len()] [ret_regs.len()] /// R(A), ... R(A+C-2) := R(A)(R(A+1), ... R(A+B-1)) Call(u16, u16, u16), @@ -62,6 +66,8 @@ impl Debug for Instruction { Instruction::GetGlobal(arg0, arg1) => write!(f, "GETGLOBAL {} {}", arg0, arg1), Instruction::GetUpVal(arg0, arg1) => write!(f, "GETUPVAL {} {}", arg0, arg1), Instruction::SetUpVal(arg0, arg1) => write!(f, "SETUPVAL {} {}", arg0, arg1), + Instruction::Jmp(arg0) => write!(f, "JMP {}", arg0), + Instruction::Test(arg0, arg1, arg2) => write!(f, "TEST {} {} {}", arg0, arg1, arg2), Instruction::Call(arg0, arg1, arg2) => write!(f, "CALL {} {} {}", arg0, arg1, arg2), Instruction::Close(arg0) => write!(f, "CLOSE {}", arg0), Instruction::Closure(arg0, arg1) => write!(f, "CLOSURE {} {}", arg0, arg1), @@ -263,6 +269,21 @@ impl ClosureRunner { *self.closure.upvalues.get(upvalreg).unwrap().borrow_mut() = self.stack.get(reg).cloned().unwrap_or(Value::Nil); } + Instruction::Jmp(b) => { + self.program_counter = (self.program_counter as i32 + *b) as usize + } + Instruction::Test(a, b, c) => { + let is_true = match self.stack.get(b).unwrap_or(&Value::Nil) { + Value::Number(val) => (*val as u16) == *c, + _ => false, + }; + if is_true { + self.stack + .insert(*a, self.stack.get(b).cloned().unwrap_or(Value::Nil)); + } else { + self.program_counter += 1; + } + } Instruction::Call(func_reg, param_len, ret_len) => { let param_start_func_reg = if *param_len == 0 { self.function_register