From 639e303f7ba2963e32295c4c60d6001e384868e3 Mon Sep 17 00:00:00 2001 From: mryouse Date: Sun, 11 Jun 2023 23:34:25 +0000 Subject: initial commit of apply (sorta works) --- chunk.d | 2 ++ compiler.d | 17 +++++++++++++++++ vm.d | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+) 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; -- cgit v1.2.3