diff options
Diffstat (limited to 'bytecode/src')
| -rw-r--r-- | bytecode/src/encoding.rs | 43 | ||||
| -rw-r--r-- | bytecode/src/heap.rs | 4 | ||||
| -rw-r--r-- | bytecode/src/main.rs | 28 |
3 files changed, 73 insertions, 2 deletions
diff --git a/bytecode/src/encoding.rs b/bytecode/src/encoding.rs index 8bec753..80fcc58 100644 --- a/bytecode/src/encoding.rs +++ b/bytecode/src/encoding.rs @@ -68,6 +68,26 @@ pub struct Div { } #[derive(Debug, Clone, Copy)] +pub struct Less { + pub out: u8, + pub val1: Arg, + pub val2: Arg, +} + +#[derive(Debug, Clone, Copy)] +pub struct Eq { + pub out: u8, + pub val1: Arg, + pub val2: Arg, +} + +#[derive(Debug, Clone, Copy)] +pub struct If { + pub test: Arg, + pub target: usize, +} + +#[derive(Debug, Clone, Copy)] pub enum Op { Alloc(Alloc), Call, @@ -79,6 +99,9 @@ pub enum Op { Sub(Sub), Mul(Mul), Div(Div), + Less(Less), + Eq(Eq), + If(If), } struct Reader<'a> { @@ -198,6 +221,26 @@ impl Op { let val2 = r.parse_arg(arg2_const)?; Op::Div(Div { out, val1, val2 }) } + 11 => { + let out = r.parse_local()?; + let val1 = r.parse_arg(arg1_const)?; + let val2 = r.parse_arg(arg2_const)?; + Op::Less(Less { out, val1, val2 }) + } + 12 => { + let out = r.parse_local()?; + let val1 = r.parse_arg(arg1_const)?; + let val2 = r.parse_arg(arg2_const)?; + Op::Eq(Eq { out, val1, val2 }) + } + 13 => { + let test = r.parse_arg(arg1_const)?; + let Some(itarget) = r.parse_value()?.to_int() else { + return Err(Box::from("invalid target")); + }; + let target = usize::try_from(itarget)?; + Op::If(If { test, target }) + } _ => { return Err(Box::from(format!("invalid code {}", code))); } diff --git a/bytecode/src/heap.rs b/bytecode/src/heap.rs index 45ce283..970db7d 100644 --- a/bytecode/src/heap.rs +++ b/bytecode/src/heap.rs @@ -1,7 +1,7 @@ use crate::value::Value; use std::error::Error; -pub const NUM_LOCALS: usize = 8; +pub const NUM_LOCALS: usize = 256; #[derive(Debug)] pub struct Heap { @@ -27,7 +27,7 @@ impl Heap { let Some(q) = Value(self.buf[p]).to_pointer() else { return false; }; - return self.first_active == (q < self.buf.len() / 2); + self.first_active == (q < self.buf.len() / 2) } fn alloc_size(&self, p: usize) -> usize { diff --git a/bytecode/src/main.rs b/bytecode/src/main.rs index bbc0ddd..4cba4ef 100644 --- a/bytecode/src/main.rs +++ b/bytecode/src/main.rs @@ -96,6 +96,34 @@ impl State { }; self.heap.locals[usize::from(op.out)] = Value::from_int(res); } + Op::Less(op) => { + let Some(v1) = self.read_arg(op.val1).to_int() else { + return Err(Box::from("less needs an int")); + }; + let Some(v2) = self.read_arg(op.val2).to_int() else { + return Err(Box::from("less needs an int")); + }; + let res = if v1 < v2 { 1 } else { 0 }; + self.heap.locals[usize::from(op.out)] = Value::from_int(res); + } + Op::Eq(op) => { + let Some(v1) = self.read_arg(op.val1).to_int() else { + return Err(Box::from("eq needs an int")); + }; + let Some(v2) = self.read_arg(op.val2).to_int() else { + return Err(Box::from("eq needs an int")); + }; + let res = if v1 == v2 { 1 } else { 0 }; + self.heap.locals[usize::from(op.out)] = Value::from_int(res); + } + Op::If(op) => { + let Some(t) = self.read_arg(op.test).to_int() else { + return Err(Box::from("if needs an int")); + }; + if t != 0 { + self.i = op.target; + } + } } Ok(()) } |
