aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bytecode/src/bytecode.rs36
-rw-r--r--bytecode/src/encoding.rs6
-rw-r--r--lib/csc/encoding.csc18
3 files changed, 56 insertions, 4 deletions
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<T: Read>(prog: &mut T) -> Result<Option<Op>, 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"));
}
diff --git a/lib/csc/encoding.csc b/lib/csc/encoding.csc
index aceedc8..099beaf 100644
--- a/lib/csc/encoding.csc
+++ b/lib/csc/encoding.csc
@@ -1,6 +1,7 @@
(define-library (csc encoding)
(export encode)
(import (scheme base)
+ (csc format)
(only (csc loop)
loop
return)
@@ -10,10 +11,10 @@
; The format of unboxed constants is described in bytecocde/src/data.rs.
; Boxed values are represented by a pointer to an array on the heap. The
; first position in the array is an integer code indicating what type the
- ; object is. Vectors have code 0, codes for other types are not stable.
- ; Vectors are represented as an array, the first element of which is the
- ; integer 0 (the type code), the second element is the vector length, and
- ; the remaining slots hold the array values.
+ ; object is. Vectors have code 0, pairs have code 2, and codes for other
+ ; types are not stable. Vectors are represented as an array, the first
+ ; element of which is the integer 0 (the type code), the second element is
+ ; the vector length, and the remaining slots hold the array values.
(define (low-byte w n)
@@ -185,6 +186,15 @@
(arg->le-bytes w dest)
(arg->le-bytes w x)
(arg->le-bytes w y))
+ (('cons dest x y)
+ (make-opcode w 18 (is-const? x) (is-const? y))
+ (arg->le-bytes w dest)
+ (arg->le-bytes w x)
+ (arg->le-bytes w y))
+ (('len dest l)
+ (make-opcode w 19 (is-const? l) #f)
+ (arg->le-bytes w dest)
+ (arg->le-bytes w l))
(_ (error "invalid opcode" opcode))))