From dc8a480c65fabf35b99398120aeccca8f2874c6d Mon Sep 17 00:00:00 2001 From: Rose Hogenson Date: Mon, 22 Aug 2022 20:07:06 -0700 Subject: Add a few primitive list operations. --- bytecode/src/bytecode.rs | 36 ++++++++++++++++++++++++++++++++++++ bytecode/src/encoding.rs | 6 ++++++ 2 files changed, 42 insertions(+) (limited to 'bytecode/src') diff --git a/bytecode/src/bytecode.rs b/bytecode/src/bytecode.rs index 41302ad..8c9324b 100644 --- a/bytecode/src/bytecode.rs +++ b/bytecode/src/bytecode.rs @@ -51,6 +51,14 @@ pub enum Op { // Stores a byte at the specified address plus the given offset. PokeByte(Arg, Arg, Arg), + // Lists + // ===== + + // Special case of Alloc for allocating a pair. + Cons(Local, Arg, Arg), + // Length of a list. + Len(Local, Arg), + // Locals // ====== @@ -227,6 +235,32 @@ impl Interpreter { Ok(()) } + fn cons(&mut self, dest: Local, car: Arg, cdr: Arg) -> Result<(), String> { + let p = self.heap.alloc(3, &mut self.locals)?; + self.heap.poke(Value::from_int(2), p, 0)?; + self.heap.poke(self.read_arg(car), p, 1)?; + self.heap.poke(self.read_arg(cdr), p, 2)?; + self.set_arg(dest, Value::from_pointer(p)); + Ok(()) + } + + fn len(&mut self, dest: Local, arg: Arg) -> Result<(), String> { + let mut len = 0; + let mut l = self.read_arg(arg); + while l != Value::NIL { + let p = l.to_pointer()?; + let typecode = self.heap.peek(p, 0)?; + if typecode != Value::from_int(2) { + return Err(String::from("not a list")); + } + + len += 1; + l = self.heap.peek(p, 2)?; + } + self.set_arg(dest, Value::from_int(len)); + Ok(()) + } + fn mov(&mut self, dest: Local, src: Arg) { self.set_arg(dest, self.read_arg(src)); } @@ -298,6 +332,8 @@ impl Interpreter { Op::Poke(word, ptr, offset) => self.poke(word, ptr, offset)?, Op::PeekByte(dest, ptr, offset) => self.peek_byte(dest, ptr, offset)?, Op::PokeByte(word, ptr, offset) => self.poke_byte(word, ptr, offset)?, + Op::Cons(dest, x, y) => self.cons(dest, x, y)?, + Op::Len(dest, l) => self.len(dest, l)?, Op::Mov(dest, src) => self.mov(dest, src), Op::Jmp(addr) => self.jmp(&mut ip, addr)?, Op::JmpIf(cond, addr) => self.jmp_if(&mut ip, cond, addr)?, diff --git a/bytecode/src/encoding.rs b/bytecode/src/encoding.rs index 8fccc1a..44fff51 100644 --- a/bytecode/src/encoding.rs +++ b/bytecode/src/encoding.rs @@ -113,6 +113,12 @@ fn op_decoding(prog: &mut T) -> Result, String> { read_arg(prog, arg1_const)?, read_arg(prog, arg2_const)?, ), + 18 => Op::Cons( + read_local(prog)?, + read_arg(prog, arg1_const)?, + read_arg(prog, arg2_const)?, + ), + 19 => Op::Len(read_local(prog)?, read_arg(prog, arg1_const)?), _ => { return Err(String::from("invalid opcode")); } -- cgit v1.3.1