aboutsummaryrefslogtreecommitdiffstats
path: root/bytecode/src
diff options
context:
space:
mode:
authorRose Hogenson <rhogenson@posteo.net>2022-08-07 15:55:13 -0700
committerRose Hogenson <rhogenson@posteo.net>2022-08-07 15:55:47 -0700
commit35d375807bd84f9c7ca82e28042d20ded7b65498 (patch)
treeba0f34d009cff54ae69adc07eca4cd066f2f5cb7 /bytecode/src
parent72294a6a1a690d396d13a7e3861f4b720e78cdb3 (diff)
downloadchromatopelma-35d375807bd84f9c7ca82e28042d20ded7b65498.tar.zst
Add int<? and eq?.
Diffstat (limited to 'bytecode/src')
-rw-r--r--bytecode/src/bytecode.rs29
-rw-r--r--bytecode/src/encoding.rs5
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"));
}