From b57c1630da58d55dbb7855d9de76f776600038ea Mon Sep 17 00:00:00 2001 From: mryouse Date: Fri, 26 May 2023 19:21:25 +0000 Subject: add more opcodes, preparing for HOF --- chunk.d | 8 ++++++++ dbg.d | 14 ++++++++++++++ vm.d | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+) diff --git a/chunk.d b/chunk.d index b6a5348..63d5bae 100644 --- a/chunk.d +++ b/chunk.d @@ -186,6 +186,14 @@ enum OpCode { OP_JUMP_IF_FALSE, OP_JUMP_IF_TRUE, + OP_IS_NIL, + OP_DUPLICATE, + OP_DUPLICATE_2, + OP_ROTATE_N, + OP_ZERO, + OP_INCREMENT, + OP_LIST_N, + OP_CALL, OP_LIST, diff --git a/dbg.d b/dbg.d index 64669ea..7e92eb5 100644 --- a/dbg.d +++ b/dbg.d @@ -153,6 +153,20 @@ int disassemble(Chunk chunk, int offset) { ubyte inst = chunk.code[offset]; switch (inst) { + case OpCode.OP_IS_NIL: + return simpleInstruction("OP_IS_NIL", offset); + case OpCode.OP_DUPLICATE: + return simpleInstruction("OP_DUPLICATE", offset); + case OpCode.OP_DUPLICATE_2: + return simpleInstruction("OP_DUPLICATE_2", offset); + case OpCode.OP_ROTATE_N: + return simpleInstruction("OP_ROTATE_N", offset); + case OpCode.OP_ZERO: + return simpleInstruction("OP_ZERO", offset); + case OpCode.OP_INCREMENT: + return simpleInstruction("OP_INCREMENT", offset); + case OpCode.OP_LIST_N: + return simpleInstruction("OP_LIST_N", offset); case OpCode.OP_DEF_LOCAL: return byteInstruction("OP_DEF_LOCAL", chunk, offset); case OpCode.OP_GET_LOCAL: diff --git a/vm.d b/vm.d index 6ab2e96..75f6328 100644 --- a/vm.d +++ b/vm.d @@ -174,6 +174,11 @@ class VM { return value.type == ValueType.SEQ; } + bool isNil(Value value) { + return isList(value) && + value.as.seq.length() == 0; + } + bool isList(Value value) { return isSeq(value) && seqTypeOf(value) == SeqType.LIST; } @@ -287,6 +292,45 @@ class VM { ubyte inst; switch (inst = this.readByte()) { + case OpCode.OP_IS_NIL: + Value val = this.popA(); + this.pushA(makeBooleanValue(isNil(val))); + break; + case OpCode.OP_DUPLICATE: + this.pushA(this.peekA(0)); + break; + case OpCode.OP_DUPLICATE_2: + this.pushA(this.peekA(1)); + this.pushA(this.peekA(1)); + break; + case OpCode.OP_ROTATE_N: + int n = to!int(this.readByte()); + + // pop the top of the stack + Value top = this.popA(); + + // pop the next n-1 values + Value[] inner; + for (int i = 0; i < n - 1; i++) { + inner ~= this.popA(); + } + + // push the top + this.pushA(top); + + // push the other values (preserve order) + for (int i = n - 1; i >= 0; i--) { + this.pushA(inner[i]); + } + break; + case OpCode.OP_ZERO: + this.pushA(makeNumberValue(0)); + break; + case OpCode.OP_INCREMENT: + Value val = this.popA(); + double num = asNumber(val); + this.pushA(makeNumberValue(num + 1)); + break; case OpCode.OP_DEF_GLOBAL: Value name = this.current.func.chunk.constants[this.readByte()]; if (!isString(name)) { @@ -340,6 +384,15 @@ class VM { //bStack[bTop + slot - 1] = peekA(0); this.popA(); break; + case OpCode.OP_LIST_N: + Value lengthVal = this.popA(); + int length = to!int(asNumber(lengthVal)); + List lst = new List(length); + for (int i = length - 1; i >= 0; i--) { + lst.addItemAtIndex(this.popA(), i); + } + this.pushA(makeSeqValue(lst)); + break; case OpCode.OP_LIST: int length = to!int(this.readByte()); List lst = new List(length); -- cgit v1.2.3