diff options
| author | mryouse | 2023-06-06 20:27:18 -0400 |
|---|---|---|
| committer | mryouse | 2023-06-06 20:27:18 -0400 |
| commit | 59d076f6dc179315b6dfc1c141dc9ee48cc66a54 (patch) | |
| tree | ec667f8146e12299404ab11d52fed2e8d79c62b3 | |
| parent | 87ee44163d0f7ec86963cefea51e721ce4eb156c (diff) | |
initial commit of reverse
| -rw-r--r-- | chunk.d | 20 | ||||
| -rw-r--r-- | compiler.d | 15 | ||||
| -rw-r--r-- | vm.d | 4 |
3 files changed, 39 insertions, 0 deletions
@@ -47,6 +47,7 @@ abstract class Seq { abstract Seq rest(); abstract Seq most(); abstract Value last(); + abstract Seq reverse(); abstract int length(); abstract bool isIn(Value val); } @@ -76,6 +77,15 @@ class String : Seq { return new String(this.str[0..$ - 1]); } + override Seq reverse() { + string s = ""; + int end = to!int(this.str.length) - 1; + for (int i = end; i >= 0; i--) { + s ~= this.str[i]; + } + return new String(s); + } + override Value last() { return makeStringValue(to!string(this.str[$ - 1])); } @@ -155,6 +165,15 @@ class List : Seq { return ret; } + override Seq reverse() { + int length = to!int(this.inner.length); + List ret = new List(length); + for (int i = 0; i < length; i++) { + ret.addItemAtIndex(this.inner[i], length - i - 1); + } + return ret; + } + override Value last() { return this.inner[$ - 1]; // this fails on NIL } @@ -225,6 +244,7 @@ enum OpCode { OP_MEMBER, OP_MOST, OP_REST, + OP_REVERSE, // DEFINITIONS/VARIABLES OP_CONSTANT, @@ -662,6 +662,18 @@ class Compiler { this.func.chunk.writeOp(OpCode.OP_REST, args[0].line); } + void compileReverse(Form[] args) { + // TODO how do we identify/propagate errors? + if (args.length != 1) { + this.error("'reverse': 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_REVERSE, args[0].line); + } + // TERMINAL void compilePrint(Form[] args) { if (args.length != 1) { @@ -843,6 +855,9 @@ class Compiler { case "rest": this.compileRest(cons.tail); break; + case "reverse": + this.compileReverse(cons.tail); + break; // OTHER case "print": @@ -475,6 +475,10 @@ class VM { Seq seq = asSeq(this.popA()); this.pushA(makeNumberValue(seq.length())); break; + case OpCode.OP_REVERSE: + Seq seq = asSeq(this.popA()); + this.pushA(makeSeqValue(seq.reverse())); + break; case OpCode.OP_MEMBER: Seq seq = asSeq(this.popA()); Value val = this.popA(); |
