diff options
| author | mryouse | 2023-06-06 19:45:47 -0400 |
|---|---|---|
| committer | mryouse | 2023-06-06 19:45:47 -0400 |
| commit | 87ee44163d0f7ec86963cefea51e721ce4eb156c (patch) | |
| tree | 7f3ef821f7ee1437b1df5558255f37d00bb6198e | |
| parent | 7393da674216aa3dd737db7ec4a3418ca025871c (diff) | |
initial commit of most and last
| -rw-r--r-- | chunk.d | 28 | ||||
| -rw-r--r-- | compiler.d | 28 | ||||
| -rw-r--r-- | vm.d | 8 |
3 files changed, 64 insertions, 0 deletions
@@ -45,6 +45,8 @@ abstract class Seq { SeqType type; abstract Value first(); abstract Seq rest(); + abstract Seq most(); + abstract Value last(); abstract int length(); abstract bool isIn(Value val); } @@ -70,6 +72,14 @@ class String : Seq { return new String(this.str[1..$]); } + override Seq most() { + return new String(this.str[0..$ - 1]); + } + + override Value last() { + return makeStringValue(to!string(this.str[$ - 1])); + } + override int length() { return to!int(str.length); } @@ -133,6 +143,22 @@ class List : Seq { return ret; } + override Seq most() { + if (this.inner.length == 0) { + return new List(0); + } + int newLength = to!int(this.inner.length) - 1; + List ret = new List(newLength); + for (int i = 0; i < newLength; i++) { + ret.addItemAtIndex(this.inner[i], i); + } + return ret; + } + + override Value last() { + return this.inner[$ - 1]; // this fails on NIL + } + override int length() { return to!int(this.inner.length); } @@ -195,7 +221,9 @@ enum OpCode { OP_APPEND, OP_FIRST, // No? OP_LENGTH, + OP_LAST, OP_MEMBER, + OP_MOST, OP_REST, // DEFINITIONS/VARIABLES @@ -603,6 +603,17 @@ class Compiler { this.func.chunk.writeOp(OpCode.OP_FIRST, args[0].line); } + void compileLast(Form[] args) { + // TODO how do we identify/propagate errors? + if (args.length != 1) { + this.error("'last': expected [1] argument, received ?", -1); + 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_LAST, args[0].line); + } + void compileIn(Form[] args) { // TODO how do we identify/propagate errors? if (args.length != 2) { @@ -628,6 +639,17 @@ class Compiler { this.func.chunk.writeOp(OpCode.OP_LENGTH, args[0].line); } + void compileMost(Form[] args) { + // TODO how do we identify/propagate errors? + if (args.length != 1) { + this.error("'most': expected [1] argument, received ?", -1); + return; + } + ValueType vt = this.resolve(args[0], ValueType.OBJ); // TODO need a new type + this.func.chunk.writeOp(OpCode.OP_TYPE_CHECK_SEQ, args[0].line); + this.func.chunk.writeOp(OpCode.OP_MOST, args[0].line); + } + void compileRest(Form[] args) { // TODO how do we identify/propagate errors? if (args.length != 1) { @@ -806,12 +828,18 @@ class Compiler { case "in?": this.compileIn(cons.tail); break; + case "last": + this.compileLast(cons.tail); + break; case "length": this.compileLength(cons.tail); break; case "list": this.compileList(cons.tail); break; + case "most": + this.compileMost(cons.tail); + break; case "rest": this.compileRest(cons.tail); break; @@ -463,6 +463,14 @@ class VM { Seq seq = asSeq(this.popA()); this.pushA(makeSeqValue(seq.rest())); break; + case OpCode.OP_MOST: + Seq seq = asSeq(this.popA()); + this.pushA(makeSeqValue(seq.most())); + break; + case OpCode.OP_LAST: + Seq seq = asSeq(this.popA()); + this.pushA(seq.last()); + break; case OpCode.OP_LENGTH: Seq seq = asSeq(this.popA()); this.pushA(makeNumberValue(seq.length())); |
