aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormryouse2023-06-06 19:45:47 -0400
committermryouse2023-06-06 19:45:47 -0400
commit87ee44163d0f7ec86963cefea51e721ce4eb156c (patch)
tree7f3ef821f7ee1437b1df5558255f37d00bb6198e
parent7393da674216aa3dd737db7ec4a3418ca025871c (diff)
initial commit of most and last
-rw-r--r--chunk.d28
-rw-r--r--compiler.d28
-rw-r--r--vm.d8
3 files changed, 64 insertions, 0 deletions
diff --git a/chunk.d b/chunk.d
index 55772dc..21ebb9d 100644
--- a/chunk.d
+++ b/chunk.d
@@ -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
diff --git a/compiler.d b/compiler.d
index 0c90a45..6756882 100644
--- a/compiler.d
+++ b/compiler.d
@@ -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;
diff --git a/vm.d b/vm.d
index e34e4bc..a8d3d6e 100644
--- a/vm.d
+++ b/vm.d
@@ -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()));