diff options
Diffstat (limited to 'bytecode/src/bytecode.rs')
| -rw-r--r-- | bytecode/src/bytecode.rs | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/bytecode/src/bytecode.rs b/bytecode/src/bytecode.rs index 8c9324b..73c8f53 100644 --- a/bytecode/src/bytecode.rs +++ b/bytecode/src/bytecode.rs @@ -58,6 +58,8 @@ pub enum Op { Cons(Local, Arg, Arg), // Length of a list. Len(Local, Arg), + // Checks that a list has length 1, and gets its first element. + AssertSingleton(Local, Arg), // Locals // ====== @@ -261,6 +263,29 @@ impl Interpreter { Ok(()) } + fn assert_singleton(&mut self, dest: Local, arg: Arg) -> Result<(), String> { + let a = self.read_arg(arg); + if a == Value::NIL { + return Err(String::from( + "wrong number of arguments passed to continuation (0)", + )); + } + let l = self.read_arg(arg).to_pointer()?; + let typecode = self.heap.peek(l, 0)?; + if typecode != Value::from_int(2) { + return Err(String::from("not a list")); + } + let cdr = self.heap.peek(l, 2)?; + if cdr != Value::NIL { + return Err(String::from( + "wrong number of arguments passed to continuation", + )); + } + let car = self.heap.peek(l, 1)?; + self.set_arg(dest, car); + Ok(()) + } + fn mov(&mut self, dest: Local, src: Arg) { self.set_arg(dest, self.read_arg(src)); } @@ -334,6 +359,7 @@ impl Interpreter { 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::AssertSingleton(dest, l) => self.assert_singleton(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)?, |
