aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormryouse2023-05-26 19:21:25 +0000
committermryouse2023-05-26 19:21:25 +0000
commitb57c1630da58d55dbb7855d9de76f776600038ea (patch)
treeda8c22b43de8d4afe9c6caf2120c953e5213c254
parent6261be78421d6a842b21653b069ca7b032f8fecc (diff)
add more opcodes, preparing for HOF
-rw-r--r--chunk.d8
-rw-r--r--dbg.d14
-rw-r--r--vm.d53
3 files changed, 75 insertions, 0 deletions
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);