From b1183af95f45ba0162a91f7a308a4846418f03be Mon Sep 17 00:00:00 2001 From: Ben Winston Date: Sun, 21 May 2023 13:57:41 -0400 Subject: move to using 2 stacks --- vm.d | 155 ++++++++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 97 insertions(+), 58 deletions(-) (limited to 'vm.d') diff --git a/vm.d b/vm.d index 3988d14..99016f2 100644 --- a/vm.d +++ b/vm.d @@ -15,9 +15,12 @@ enum InterpretResult { } class VM { - int topOffset = 0; + //int topOffset = 0; ubyte ip = 0; - Value[] stack; + Value[] aStack; + int aTop = 0; + Value[] bStack; + int bTop = 0; //ObjFunction func; Function func; Value[string] globals; @@ -26,31 +29,50 @@ class VM { this.func = func; } - Value peek(int offset) { - if (offset >= this.topOffset) { + Value peekA(int offset) { + if (offset >= aTop) { //if (offset > this.topOffset) { - writefln("offset of %d greater than stack size %d", offset, topOffset); + writefln("offset of %d greater than stack size %d", offset, aTop); } - return this.stack[topOffset - offset - 1]; + return this.aStack[aTop - offset - 1]; } - Value pop() { - if (this.topOffset > 0) { - this.topOffset--; + Value popA() { + if (aTop > 0) { + aTop--; } else { - writeln("pop() on an empty stack!!"); + writeln("popA() on an empty stack!!"); } - return this.stack[this.topOffset]; + return aStack[aTop]; } //InterpretResult push(Value value) { - void push(Value value) { - if (this.stack.length > this.topOffset) { - this.stack[topOffset] = value; + void pushA(Value value) { + if (aStack.length > aTop) { + aStack[aTop] = value; } else { - this.stack ~= value; + aStack ~= value; } - this.topOffset++; + aTop++; + } + + Value popB() { + if (bTop > 0) { + bTop--; + } else { + writeln("popB() on an empty stack!!"); + } + return bStack[bTop]; + } + + + void pushB(Value value) { + if (bStack.length > bTop) { + bStack[bTop] = value; + } else { + bStack ~= value; + } + bTop++; } ubyte readByte() { @@ -76,9 +98,13 @@ class VM { InterpretResult run() { //int ip = 0; // TODO this is wrong while (true) { - write(" "); - for (int i = 0; i < this.topOffset; i++) { - writef("[ %s ]", printableValue(this.stack[i])); + write(" A> "); + for (int i = 0; i < aTop; i++) { + writef("[ %s ]", printableValue(aStack[i])); + } + write("\n B> "); + for (int i = 0; i < bTop; i++) { + writef("[ %s ]", printableValue(bStack[i])); } writeln("\n--"); @@ -94,32 +120,15 @@ class VM { disassemble(this.func.chunk, this.ip); ubyte inst; switch (inst = this.readByte()) { - case OpCode.OP_DEFINE_GLOBAL: + case OpCode.OP_DEF_GLOBAL: Value name = func.chunk.constants[readByte()]; if (!isString(name)) { writefln("variables must be strings, got %s", printableValue(name)); return InterpretResult.RUNTIME_ERROR; // TODO error } - Value val = pop(); + Value val = popA(); globals[asString(name)] = val; break; - case OpCode.OP_GET_LOCAL: - ubyte slot = readByte(); - writefln("getting local '%d' stackTop '%d'", slot, topOffset); - //push(stack[topOffset + slot - 2]); - //push(stack[topOffset + slot]); - push(stack[topOffset - 2 + slot]); - //push(stack[slot]); - break; - case OpCode.OP_SET_LOCAL: - //writeln("in SET_LOCAL"); - ubyte slot = readByte(); - //stack[slot] = peek(0); - stack[topOffset + slot - 1] = peek(0); - //pop(); - //stack[slot] = pop(); - writefln("setting local '%d' stackTop '%d'", slot, topOffset); - break; case OpCode.OP_GET_GLOBAL: writeln("in OP_GET_GLOBAL"); Value name = func.chunk.constants[readByte()]; @@ -134,76 +143,106 @@ class VM { writefln("no such variable: %s", printableValue(name)); return InterpretResult.RUNTIME_ERROR; // TODO error } - push(*member); // do i need to dereference? + 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]); + 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); break; - case OpCode.OP_CONSTANT: + case OpCode.OP_CONSTANT: Value constant = this.func.chunk.constants[this.readByte()]; - this.push(constant); + pushA(constant); break; case OpCode.OP_NEGATE: - if (!isNumber(peek(0))) { + if (!isNumber(peekA(0))) { writeln("negate operand must be a number"); return InterpretResult.RUNTIME_ERROR; } - double val = asNumber(pop()); - push(makeNumberValue(val * -1)); + double val = asNumber(popA()); + pushA(makeNumberValue(val * -1)); break; case OpCode.OP_ADD: - Value b = this.pop(); + Value b = popA(); if (!isNumber(b)) { writeln("b is not a number!"); return InterpretResult.RUNTIME_ERROR; // TODO error } - Value a = this.pop(); + Value a = popA(); if (!isNumber(a)) { writeln("a is not a number!"); return InterpretResult.RUNTIME_ERROR; // TODO error } double bnum = asNumber(b); double anum = asNumber(a); - push(makeNumberValue(anum + bnum)); + pushA(makeNumberValue(anum + bnum)); break; case OpCode.OP_SUBTRACT: - Value b = this.pop(); + Value b = popA(); if (!isNumber(b)) { writeln("b is not a number!"); return InterpretResult.RUNTIME_ERROR; // TODO error } - Value a = this.pop(); + Value a = popA(); if (!isNumber(a)) { writeln("a is not a number!"); return InterpretResult.RUNTIME_ERROR; // TODO error } double bnum = asNumber(b); double anum = asNumber(a); - push(makeNumberValue(anum - bnum)); + pushA(makeNumberValue(anum - bnum)); break; case OpCode.OP_LESS: - Value b = this.pop(); + Value b = popA(); if (!isNumber(b)) { writeln("b is not a number!"); return InterpretResult.RUNTIME_ERROR; // TODO error } - Value a = this.pop(); + Value a = popA(); if (!isNumber(a)) { writeln("a is not a number!"); return InterpretResult.RUNTIME_ERROR; // TODO error } double bnum = asNumber(b); double anum = asNumber(a); - push(makeBooleanValue(anum < bnum)); + pushA(makeBooleanValue(anum < bnum)); break; case OpCode.OP_RETURN: - Value ret = this.pop(); + Value ret = popA(); writefln("returned %s", printableValue(ret)); return InterpretResult.OK; case OpCode.OP_POP: - pop(); + popA(); + break; + case OpCode.OP_POPB: + popB(); break; case OpCode.OP_POP_SCOPE: // pop the n-1 position - Value val = pop(); - pop(); // throw this one away - push(val); + Value val = popA(); + popA(); // throw this one away + pushA(val); break; default: writeln("unknown opcode to run"); -- cgit v1.2.3