diff options
| -rw-r--r-- | chunk.d | 6 | ||||
| -rw-r--r-- | compiler.d | 15 | ||||
| -rw-r--r-- | vm.d | 4 |
3 files changed, 25 insertions, 0 deletions
@@ -45,6 +45,7 @@ abstract class Seq { SeqType type; abstract Value first(); abstract Seq rest(); + abstract int length(); } class List : Seq { @@ -71,6 +72,10 @@ class List : Seq { return ret; } + override int length() { + return to!int(this.inner.length); + } + override string toString() { return format("list ('%s' + %d)", printableValue(this.inner[0]), this.inner.length - 1); } @@ -108,6 +113,7 @@ enum OpCode { OP_FIRST, // No? OP_REST, + OP_LENGTH, OP_TYPE_CHECK_NUMBER, OP_TYPE_CHECK_BOOLEAN, @@ -521,6 +521,18 @@ class Compiler { this.func.chunk.writeOp(to!ubyte(length), args[0].line); } + void compileLength(Form[] args) { + // TODO how do we identify/propagate errors? + if (args.length != 1) { + writeln("COMPILE ERROR: 'first' expects exactly one argument"); + return; + } + ValueType vt = this.resolve(args[0], ValueType.SEQ); // TODO need a new type + this.func.chunk.writeOp(OpCode.OP_TYPE_CHECK_SEQ, args[0].line); + + this.func.chunk.writeOp(OpCode.OP_LENGTH, args[0].line); + } + void compileFirst(Form[] args) { // TODO how do we identify/propagate errors? if (args.length != 1) { @@ -676,6 +688,9 @@ class Compiler { case "first": this.compileFirst(cons.tail); break; + case "length": + this.compileLength(cons.tail); + break; case "list": //return compileList(cons.tail); this.compileList(cons.tail); @@ -395,6 +395,10 @@ class VM { Seq seq = asSeq(this.popA()); this.pushA(makeSeqValue(seq.rest())); break; + case OpCode.OP_LENGTH: + Seq seq = asSeq(this.popA()); + this.pushA(makeNumberValue(seq.length())); + break; case OpCode.OP_ADD: Value b = this.popA(); /* |
