aboutsummaryrefslogtreecommitdiff
path: root/vm.d
diff options
context:
space:
mode:
authorBen Winston2023-05-21 16:20:41 -0400
committerBen Winston2023-05-21 16:20:41 -0400
commit618de4c70d8916f64781997f3ae538e3e6109d00 (patch)
treebcd8ee70d82402407399a49c9cf6914858bd9449 /vm.d
parentb1183af95f45ba0162a91f7a308a4846418f03be (diff)
if/else, 'and' control flow
Diffstat (limited to 'vm.d')
-rw-r--r--vm.d66
1 files changed, 45 insertions, 21 deletions
diff --git a/vm.d b/vm.d
index 99016f2..45f3742 100644
--- a/vm.d
+++ b/vm.d
@@ -31,7 +31,6 @@ class VM {
Value peekA(int offset) {
if (offset >= aTop) {
- //if (offset > this.topOffset) {
writefln("offset of %d greater than stack size %d", offset, aTop);
}
return this.aStack[aTop - offset - 1];
@@ -79,6 +78,16 @@ class VM {
return this.func.chunk.code[this.ip++];
}
+ uint readShort() {
+ ip += 2;
+ uint high = this.func.chunk.code[ip - 2] << 8;
+ uint low = this.func.chunk.code[ip - 1];
+ return high | low;
+
+
+ //return 0;
+ }
+
bool isNumber(Value value) {
return value.type == ValueType.NUMBER;
}
@@ -87,6 +96,10 @@ class VM {
return value.type == ValueType.STRING;
}
+ bool isBoolean(Value value) {
+ return value.type == ValueType.BOOLEAN;
+ }
+
double asNumber(Value value) {
return value.as.number;
}
@@ -95,9 +108,20 @@ class VM {
return value.as.str;
}
+ bool asBoolean(Value value) {
+ return value.as.boolean;
+ }
+
+ /*
+ bool isFalsey(Value val) {
+ return isBoolean(val) && val.as.boolean;
+ }
+ */
+
InterpretResult run() {
- //int ip = 0; // TODO this is wrong
+ writeln("== VM running ==");
while (true) {
+ writeln(" Stacks:");
write(" A> ");
for (int i = 0; i < aTop; i++) {
writef("[ %s ]", printableValue(aStack[i]));
@@ -130,14 +154,12 @@ class VM {
globals[asString(name)] = val;
break;
case OpCode.OP_GET_GLOBAL:
- writeln("in OP_GET_GLOBAL");
Value name = func.chunk.constants[readByte()];
writefln(asString(name));
if (!isString(name)) {
writefln("variables must be strings, got %s", printableValue(name));
return InterpretResult.RUNTIME_ERROR; // TODO error
}
- writefln(asString(name));
Value* member = asString(name) in globals;
if (member is null) {
writefln("no such variable: %s", printableValue(name));
@@ -146,31 +168,17 @@ class VM {
pushA(*member); // do i need to dereference?
break;
case OpCode.OP_DEF_LOCAL:
- //Value name = func.chunk.constants[readByte()];
- writefln("in OP_DEF_LOCAL");
- //Value val = peekA(0);
Value val = popA();
pushB(val);
break;
-
-
case OpCode.OP_GET_LOCAL:
ubyte slot = readByte();
- writefln("getting local '%d' stackTop '%d'", slot, bTop);
- //push(stack[topOffset + slot - 2]);
- //push(stack[topOffset + slot]);
- pushA(bStack[bTop - slot - 1]); // NOTE change to bStack
- //push(stack[slot]);
+ pushA(bStack[bTop - slot - 1]);
break;
case OpCode.OP_SET_LOCAL:
- //writeln("in SET_LOCAL");
ubyte slot = readByte();
- //stack[slot] = peek(0);
- bStack[bTop + slot - 1] = peekA(0); // NOTE change to bStack
- popA(); // NOTE changed to bStack
- //pop();
- //stack[slot] = pop();
- writefln("setting local '%d' stackTop '%d'", slot, bTop);
+ bStack[bTop + slot - 1] = peekA(0);
+ popA();
break;
case OpCode.OP_CONSTANT:
Value constant = this.func.chunk.constants[this.readByte()];
@@ -244,6 +252,22 @@ class VM {
popA(); // throw this one away
pushA(val);
break;
+
+ case OpCode.OP_JUMP:
+ uint offset = readShort();
+ ip += offset;
+ break;
+
+ case OpCode.OP_JUMP_IF_FALSE:
+ uint offset = readShort();
+ if (!isBoolean(peekA(0))) {
+ writeln("if expects a boolean condition");
+ return InterpretResult.RUNTIME_ERROR; // TODO error
+ }
+ if (!asBoolean(peekA(0))) {
+ ip += offset;
+ }
+ break;
default:
writeln("unknown opcode to run");
break;