summaryrefslogtreecommitdiffstats
path: root/bytecode/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'bytecode/src/main.rs')
-rw-r--r--bytecode/src/main.rs87
1 files changed, 87 insertions, 0 deletions
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<dyn Error>> {
+ 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<dyn Error>> {
+ let args: Vec<OsString> = std::env::args_os().collect();
+ if args.len() != 2 {
+ return Err(Box::from("usage: bytecode <file>"));
+ }
+ 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);
+ }
+}