diff options
| author | Rose Hogenson <rhogenson@posteo.net> | 2022-08-27 19:30:16 -0700 |
|---|---|---|
| committer | Rose Hogenson <rhogenson@posteo.net> | 2022-08-27 19:30:16 -0700 |
| commit | 59ca512ec8f099a7d4c8aa4392f939d1aa5aee5d (patch) | |
| tree | 870b95b19f19c035df62171fdcbaa1ae041e76ae /bytecode/src/bytecode.rs | |
| parent | 55a9ceb549911e598be213bdb755272e0f9c4a5c (diff) | |
| download | chromatopelma-59ca512ec8f099a7d4c8aa4392f939d1aa5aee5d.tar.zst | |
Implement multiple return values.
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)?, |
