aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chunk.d2
-rw-r--r--compiler.d17
-rw-r--r--vm.d35
3 files changed, 54 insertions, 0 deletions
diff --git a/chunk.d b/chunk.d
index c8d280e..0034426 100644
--- a/chunk.d
+++ b/chunk.d
@@ -236,6 +236,7 @@ enum OpCode {
// LISTS
OP_LIST,
OP_LIST_N,
+ OP_UNGROUP,
// SEQUENCES
OP_CONCAT, // No?
@@ -277,6 +278,7 @@ enum OpCode {
// FUNCTIONS
OP_CALL,
+ OP_CALL_N,
OP_RETURN,
// TYPES
diff --git a/compiler.d b/compiler.d
index f721e86..2480918 100644
--- a/compiler.d
+++ b/compiler.d
@@ -582,6 +582,19 @@ class Compiler {
}
// LISP-Y
+ void compileApply(Form[] args) {
+ if (args.length != 2) {
+ this.error(format("'apply?': expected [2] argument, received %d", to!int(args.length)), -1);
+ return;
+ }
+ ValueType vt1 = this.resolve(args[0], ValueType.ANY); // this should be a function
+ vt1 = this.resolve(args[1], ValueType.ANY);
+
+ // ungroup the list and call the function
+ this.func.chunk.writeOp(OpCode.OP_UNGROUP, args[1].line);
+ this.func.chunk.writeOp(OpCode.OP_CALL_N, args[1].line);
+ }
+
void compileBlock(Form form) {
Block block = cast(Block)form;
this.beginScope();
@@ -1088,6 +1101,9 @@ class Compiler {
break;
// OTHER
+ case "apply":
+ this.compileApply(cons.tail);
+ break;
case "print":
this.compilePrint(cons.tail);
break;
@@ -1223,6 +1239,7 @@ class Compiler {
this.globals["reverse"] = 1;
// OTHER
+ this.globals["apply"] = 2;
this.globals["print"] = 1;
}
diff --git a/vm.d b/vm.d
index 2287f87..1c006dc 100644
--- a/vm.d
+++ b/vm.d
@@ -396,6 +396,18 @@ class VM {
//bStack[bTop + slot - 1] = peekA(0);
this.popA();
break;
+ case OpCode.OP_UNGROUP:
+ Seq seq = asSeq(this.popA());
+ Value length = makeNumberValue(seq.length());
+ Value tmp = makeSeqValue(seq);
+ while (!isNil(tmp)) {
+ //tmp = seq.first();
+ this.pushA(asSeq(tmp).first());
+ tmp = makeSeqValue(asSeq(tmp).rest());
+ }
+ // push the length
+ this.pushA(length);
+ break;
case OpCode.OP_LIST_N:
Value lengthVal = this.popA();
int length = to!int(asNumber(lengthVal));
@@ -638,6 +650,29 @@ class VM {
}
this.current = &this.frames[this.frameCount - 1];
break;
+ case OpCode.OP_CALL_N:
+ double argCount = asNumber(this.popA());
+ // TODO i think i need to move the arguments from stack A to stack B (preserving order)
+ int cnt = to!int(argCount) - 1;
+ Value[] tmp;
+ while (cnt >= 0) {
+ tmp ~= this.popA();
+ cnt--;
+ }
+
+ for (int i = to!int(tmp.length) - 1; i >= 0; i--) {
+ this.pushB(tmp[i]);
+ }
+
+ //if (!callValue(peekA(argCount), argCount)) { // i'm allocating variables wrong
+ if (!this.callValue(this.peekA(0), to!int(argCount))) { // i'm allocating variables wrong
+ return InterpretResult.RUNTIME_ERROR;
+ }
+ this.current = &this.frames[this.frameCount - 1];
+ break;
+
+
+
default:
writeln("unknown opcode to run");
break;