From 618de4c70d8916f64781997f3ae538e3e6109d00 Mon Sep 17 00:00:00 2001 From: Ben Winston Date: Sun, 21 May 2023 16:20:41 -0400 Subject: if/else, 'and' control flow --- vm.d | 66 +++++++++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 45 insertions(+), 21 deletions(-) (limited to 'vm.d') 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; -- cgit v1.2.3