diff --git a/src/build/opcode/mod.rs b/src/build/opcode/mod.rs index d6d0eb9..d18d1d9 100644 --- a/src/build/opcode/mod.rs +++ b/src/build/opcode/mod.rs @@ -101,6 +101,7 @@ pub enum Op { Bang, Jump(usize), JumpIfTrue(usize), + JumpIfFalse(usize), // FIXME(jwall): Short circuiting operations // - And(usize) // - Or(usize) @@ -181,6 +182,7 @@ impl<'a> VM<'a> { } Op::Jump(jp) => self.op_jump(*jp)?, Op::JumpIfTrue(jp) => self.op_jump_if_true(*jp)?, + Op::JumpIfFalse(jp) => self.op_jump_if_false(*jp)?, Op::Module(mptr) => self.op_module(idx, *mptr)?, Op::Func(jptr) => self.op_func(idx, *jptr)?, Op::FCall => self.op_fcall()?, @@ -212,6 +214,15 @@ impl<'a> VM<'a> { Ok(()) } + fn op_jump_if_false(&mut self, jp: usize) -> Result<(), Error> { + if let P(Bool(cond)) = self.pop()? { + if !cond { + self.op_jump(jp)?; + } + } + Ok(()) + } + fn op_module(&mut self, idx: usize, jptr: usize) -> Result<(), Error> { let (result_ptr, flds) = match self.pop()? { C(Tuple(flds)) => (None, flds), diff --git a/src/build/opcode/test.rs b/src/build/opcode/test.rs index 78845e5..28ffd89 100644 --- a/src/build/opcode/test.rs +++ b/src/build/opcode/test.rs @@ -16,7 +16,7 @@ use super::scope::Stack; use super::Composite::{List, Tuple}; use super::Op::{ Add, Bind, Cp, DeRef, Div, Element, Equal, FCall, Field, Func, InitList, InitThunk, InitTuple, - Jump, JumpIfTrue, Module, Mul, Noop, Return, Sub, Sym, Val, + Jump, JumpIfFalse, JumpIfTrue, Module, Mul, Noop, Return, Sub, Sym, Val, }; use super::Primitive::{Bool, Float, Int, Str}; use super::Value::{C, P, T}; @@ -355,6 +355,21 @@ fn test_conditional_jump_ops() { ], P(Int(1)), ), + ( + vec![ + Val(Int(1)), + Val(Int(2)), + Equal, + JumpIfFalse(2), + Val(Bool(false)), + JumpIfTrue(2), + Val(Int(1)), + Jump(1), + Val(Int(2)), + Noop, + ], + P(Int(1)), + ), ]; for case in cases.drain(0..) { let mut vm = VM::new(&case.0);