diff options
| author | Rose Hogenson <rhogenson@posteo.net> | 2022-08-07 15:55:13 -0700 |
|---|---|---|
| committer | Rose Hogenson <rhogenson@posteo.net> | 2022-08-07 15:55:47 -0700 |
| commit | 35d375807bd84f9c7ca82e28042d20ded7b65498 (patch) | |
| tree | ba0f34d009cff54ae69adc07eca4cd066f2f5cb7 | |
| parent | 72294a6a1a690d396d13a7e3861f4b720e78cdb3 (diff) | |
| download | chromatopelma-35d375807bd84f9c7ca82e28042d20ded7b65498.tar.zst | |
Add int<? and eq?.
| -rw-r--r-- | bytecode/src/bytecode.rs | 29 | ||||
| -rw-r--r-- | bytecode/src/encoding.rs | 5 | ||||
| -rw-r--r-- | lib/csc/encoding.csc | 5 |
3 files changed, 37 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")); } diff --git a/lib/csc/encoding.csc b/lib/csc/encoding.csc index 9afa40f..83258c8 100644 --- a/lib/csc/encoding.csc +++ b/lib/csc/encoding.csc @@ -175,6 +175,11 @@ (make-opcode w 15 (is-const? x) #f) (arg->le-bytes w dest) (arg->le-bytes w x)) + (('int<? dest x y) + (make-opcode w 16 (is-const? x) (is-const? y)) + (arg->le-bytes w dest) + (arg->le-bytes w x) + (arg->le-bytes w y)) (_ (error "invalid opcode" opcode)))) |
