From 17face3633686e374aa0859271ccf462a48e60aa Mon Sep 17 00:00:00 2001 From: Rose Hogenson Date: Sun, 4 Feb 2024 16:46:20 -0800 Subject: Rewrite the bytecode interpreter in Rust. --- bytecode/src/main.rs | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 bytecode/src/main.rs (limited to 'bytecode/src/main.rs') diff --git a/bytecode/src/main.rs b/bytecode/src/main.rs new file mode 100644 index 0000000..a4970e0 --- /dev/null +++ b/bytecode/src/main.rs @@ -0,0 +1,87 @@ +mod encoding; +mod heap; +mod value; + +use encoding::{Arg, Op}; +use heap::Heap; +use std::error::Error; +use std::ffi::OsString; +use std::io::{stderr, Write}; +use value::Value; + +struct State { + i: usize, + heap: Heap, +} + +impl State { + fn read_arg(&self, a: Arg) -> Value { + match a { + Arg::Local(l) => self.heap.locals[usize::from(l)], + Arg::Const(c) => c, + } + } + + fn op(&mut self, op: Op) -> Result<(), Box> { + match op { + Op::Alloc(op) => { + let Some(i) = self.read_arg(op.size).to_int() else { + return Err(Box::from("alloc needs an int")); + }; + self.heap.locals[usize::from(op.out)] = Value::from_pointer(self.heap.alloc(i)?); + } + Op::Call => { + let Some(i) = self.heap.locals[0].to_int() else { + return Err(Box::from("call needs an int")); + }; + self.i = usize::try_from(i)?; + } + Op::Poke(op) => { + let Some(p) = self.heap.locals[usize::from(op.ptr)].to_pointer() else { + return Err(Box::from("poke needs a pointer")); + }; + self.heap.poke(p + op.offset, self.read_arg(op.val))?; + } + Op::Peek(op) => { + let Some(p) = self.read_arg(op.val).to_pointer() else { + return Err(Box::from("peek needs a pointer")); + }; + self.heap.locals[usize::from(op.out)] = self.heap.peek(p + op.offset)?; + } + Op::Shuf(op) => { + self.heap.locals[usize::from(op.out)] = self.read_arg(op.val); + } + Op::Exit(op) => { + let Some(i) = self.read_arg(op.val).to_int() else { + std::process::exit(255); + }; + std::process::exit(i as i32); + } + } + Ok(()) + } +} + +fn run() -> Result<(), Box> { + let args: Vec = std::env::args_os().collect(); + if args.len() != 2 { + return Err(Box::from("usage: bytecode ")); + } + let prog = std::fs::read(&args[1])?; + let mut st = State { + i: 0, + heap: Heap::new(), + }; + loop { + let (n, op) = Op::parse(&prog[st.i..])?; + st.i += n; + st.op(op)?; + } +} + +fn main() { + if let Err(err) = run() { + let _ = writeln!(stderr(), "FAIL: {}", err); + std::process::exit(255); + } +} -- cgit v1.3.1