diff options
Diffstat (limited to 'bytecode/src')
| -rw-r--r-- | bytecode/src/bytecode.rs | 29 | ||||
| -rw-r--r-- | bytecode/src/encoding.rs | 5 |
2 files changed, 32 insertions, 2 deletions
diff --git a/bytecode/src/bytecode.rs b/bytecode/src/bytecode.rs index bde3721..313b2fb 100644 --- a/bytecode/src/bytecode.rs +++ b/bytecode/src/bytecode.rs @@ -29,6 +29,9 @@ pub enum Op { // Remainder from Div. Mod(Local, Arg, Arg), + // x < y + Less(Local, Arg, Arg), + // Heap // ====== @@ -75,6 +78,9 @@ pub enum Op { // - nil: 3 // - symbol: 4 TypeOf(Local, Arg), + + // Loads #t if the arguments are equal, #f otherwise. + Equal(Local, Arg, Arg), } struct Interpreter { @@ -119,14 +125,27 @@ impl Interpreter { fn div(&mut self, dest: Local, x: Arg, y: Arg) -> Result<(), String> { let n1 = self.read_arg(x).to_int()?; let n2 = self.read_arg(y).to_int()?; - self.set_arg(dest, Value::from_int(n1.wrapping_div(n2))); + self.set_arg( + dest, + Value::from_int(n1.checked_div(n2).expect("division by zero")), + ); Ok(()) } fn fn_mod(&mut self, dest: Local, x: Arg, y: Arg) -> Result<(), String> { let n1 = self.read_arg(x).to_int()?; let n2 = self.read_arg(y).to_int()?; - self.set_arg(dest, Value::from_int(n1.wrapping_rem(n2))); + self.set_arg( + dest, + Value::from_int(n1.checked_rem(n2).expect("division by zero")), + ); + Ok(()) + } + + fn less(&mut self, dest: Local, x: Arg, y: Arg) -> Result<(), String> { + let n1 = self.read_arg(x).to_int()?; + let n2 = self.read_arg(y).to_int()?; + self.set_arg(dest, Value::from_bool(n1 < n2)); Ok(()) } @@ -250,6 +269,10 @@ impl Interpreter { Ok(()) } + fn equal(&mut self, dest: Local, x: Arg, y: Arg) { + self.set_arg(dest, Value::from_bool(self.read_arg(x) == self.read_arg(y))); + } + fn eval(&mut self, prog: &[Op]) -> Result<u8, String> { let mut ip = 0; loop { @@ -264,6 +287,7 @@ impl Interpreter { Op::Mul(dest, x, y) => self.mul(dest, x, y)?, Op::Div(dest, x, y) => self.div(dest, x, y)?, Op::Mod(dest, x, y) => self.fn_mod(dest, x, y)?, + Op::Less(dest, x, y) => self.less(dest, x, y)?, Op::Alloc(dest, size) => self.alloc(dest, size)?, Op::AllocBytevector(dest, size) => self.alloc_bytevector(dest, size)?, Op::Peek(dest, ptr, offset) => self.peek(dest, ptr, offset)?, @@ -278,6 +302,7 @@ impl Interpreter { return Ok((n & 0xff) as u8); } Op::TypeOf(dest, arg) => self.type_of(dest, arg)?, + Op::Equal(dest, x, y) => self.equal(dest, x, y), } } } diff --git a/bytecode/src/encoding.rs b/bytecode/src/encoding.rs index b3e84ac..6e86103 100644 --- a/bytecode/src/encoding.rs +++ b/bytecode/src/encoding.rs @@ -103,6 +103,11 @@ fn op_decoding<T: Read>(prog: &mut T) -> Result<Option<Op>, String> { 13 => Op::Exit(read_arg(prog, arg1_const)?), 14 => Op::AllocBytevector(read_local(prog)?, read_arg(prog, arg1_const)?), 15 => Op::TypeOf(read_local(prog)?, read_arg(prog, arg1_const)?), + 16 => Op::Less( + read_local(prog)?, + read_arg(prog, arg1_const)?, + read_arg(prog, arg2_const)?, + ), _ => { return Err(String::from("invalid opcode")); } |
