diff options
| author | mryouse | 2023-05-26 19:21:25 +0000 |
|---|---|---|
| committer | mryouse | 2023-05-26 19:21:25 +0000 |
| commit | b57c1630da58d55dbb7855d9de76f776600038ea (patch) | |
| tree | da8c22b43de8d4afe9c6caf2120c953e5213c254 | |
| parent | 6261be78421d6a842b21653b069ca7b032f8fecc (diff) | |
add more opcodes, preparing for HOF
| -rw-r--r-- | chunk.d | 8 | ||||
| -rw-r--r-- | dbg.d | 14 | ||||
| -rw-r--r-- | vm.d | 53 |
3 files changed, 75 insertions, 0 deletions
@@ -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, @@ -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: @@ -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); |
