aboutsummaryrefslogtreecommitdiff
path: root/vm.d
diff options
context:
space:
mode:
Diffstat (limited to 'vm.d')
-rw-r--r--vm.d155
1 files changed, 97 insertions, 58 deletions
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");