aboutsummaryrefslogtreecommitdiff
path: root/vm.d
diff options
context:
space:
mode:
Diffstat (limited to 'vm.d')
-rw-r--r--vm.d202
1 files changed, 103 insertions, 99 deletions
diff --git a/vm.d b/vm.d
index 7e91de1..6fc6df7 100644
--- a/vm.d
+++ b/vm.d
@@ -53,50 +53,50 @@ class VM {
}
void pushFrame(CallFrame frame) {
- if (this.frameCount < frames.length) {
+ if (this.frameCount < this.frames.length) {
this.frames[this.frameCount] = frame;
} else {
this.frames ~= frame;
}
- current = &frames[this.frameCount];
- frameCount++;
+ this.current = &this.frames[this.frameCount];
+ this.frameCount++;
}
Value peekA(int offset) {
- if (offset >= aTop) {
- writefln("offset of %d greater than stack size %d", offset, aTop);
+ if (offset >= this.aTop) {
+ writefln("offset of %d greater than stack size %d", offset, this.aTop);
}
- return this.aStack[aTop - offset - 1];
+ return this.aStack[this.aTop - offset - 1];
}
Value popA() {
- if (aTop > 0) {
- aTop--;
+ if (this.aTop > 0) {
+ this.aTop--;
} else {
writeln("popA() on an empty stack!!");
}
- return aStack[aTop];
+ return this.aStack[this.aTop];
}
//InterpretResult push(Value value) {
void pushA(Value value) {
- if (aStack.length > aTop) {
- aStack[aTop] = value;
+ if (this.aStack.length > this.aTop) {
+ this.aStack[this.aTop] = value;
} else {
- aStack ~= value;
+ this.aStack ~= value;
}
- aTop++;
+ this.aTop++;
}
Value popB() {
- if (bTop > 0) {
- bTop--;
+ if (this.bTop > 0) {
+ this.bTop--;
//current.frameStart--;
} else {
writeln("popB() on an empty stack!!");
}
//return bStack[bTop];
- return current.slots[bTop - current.frameStart - 1];
+ return this.current.slots[this.bTop - this.current.frameStart - 1];
}
@@ -113,22 +113,22 @@ class VM {
current.frameStart++;
*/
- if (bStack.length > bTop) {
- bStack[bTop] = value;
+ if (this.bStack.length > this.bTop) {
+ this.bStack[this.bTop] = value;
} else {
- bStack ~= value;
+ this.bStack ~= value;
}
- bTop++;
+ this.bTop++;
}
ubyte readByte() {
- return current.func.chunk.code[current.ip++];
+ return this.current.func.chunk.code[this.current.ip++];
}
uint readShort() {
- current.ip += 2;
- uint high = current.func.chunk.code[current.ip - 2] << 8;
- uint low = current.func.chunk.code[current.ip - 1];
+ this.current.ip += 2;
+ uint high = this.current.func.chunk.code[this.current.ip - 2] << 8;
+ uint low = this.current.func.chunk.code[this.current.ip - 1];
return high | low;
//return 0;
@@ -199,7 +199,7 @@ class VM {
if (isObj(callee)) {
switch (callee.as.obj.type) {
case ObjType.FUNCTION:
- return call(asFunction(callee), argCount);
+ return this.call(asFunction(callee), argCount);
case ObjType.SCRIPT:
writeln("trying to call the script?");
break;
@@ -214,34 +214,35 @@ class VM {
}
bool call(Function func, int argCount) {
- CallFrame frame = { func, 0, bStack, bTop - argCount - 1 }; // i need to do sthg with argCount
+ CallFrame frame = { func, 0, this.bStack, this.bTop - argCount - 1 }; // i need to do sthg with argCount
//frames ~= frame;
//frameCount++;
- pushFrame(frame);
+ this.pushFrame(frame);
return true;
}
InterpretResult run() {
writeln("== VM running ==");
+ writefln("> > > framecount: %d", this.frameCount);
while (true) {
if (DEBUG) {
writeln(" Stacks:");
write(" A> ");
for (int i = 0; i < aTop; i++) {
- writef("[ %s ]", printableValue(aStack[i]));
+ writef("[ %s ]", printableValue(this.aStack[i]));
}
write("\n B> ");
for (int i = 0; i < bTop; i++) {
//writef("[ %s ]", printableValue(bStack[i]));
- writef("[ %s ]", printableValue(current.slots[i]));
+ writef("[ %s ]", printableValue(this.current.slots[i]));
}
write("\n constants> ");
- for (int i = 0; i < current.func.chunk.constants.length; i++) {
- writef("[ %s ]", printableValue(current.func.chunk.constants[i]));
+ for (int i = 0; i < this.current.func.chunk.constants.length; i++) {
+ writef("[ %s ]", printableValue(this.current.func.chunk.constants[i]));
}
writeln("\n--");
- disassemble(current.func.chunk, current.ip);
+ disassemble(this.current.func.chunk, this.current.ip);
}
/*
@@ -256,101 +257,101 @@ class VM {
ubyte inst;
switch (inst = this.readByte()) {
case OpCode.OP_DEF_GLOBAL:
- Value name = current.func.chunk.constants[readByte()];
+ Value name = this.current.func.chunk.constants[this.readByte()];
if (!isString(name)) {
writefln("variables must be strings, got %s", printableValue(name));
return InterpretResult.RUNTIME_ERROR; // TODO error
}
- Value val = popA();
- globals[asString(name)] = val;
+ Value val = this.popA();
+ this.globals[asString(name)] = val;
break;
case OpCode.OP_GET_GLOBAL:
- Value name = current.func.chunk.constants[readByte()];
+ Value name = this.current.func.chunk.constants[this.readByte()];
//writefln(asString(name));
if (!isString(name)) {
writefln("variables must be strings, got %s", printableValue(name));
return InterpretResult.RUNTIME_ERROR; // TODO error
}
- Value* member = asString(name) in globals;
+ Value* member = asString(name) in this.globals;
if (member is null) {
writefln("no such variable: %s", printableValue(name));
return InterpretResult.RUNTIME_ERROR; // TODO error
}
- pushA(*member); // do i need to dereference?
+ this.pushA(*member); // do i need to dereference?
break;
case OpCode.OP_DEF_LOCAL:
- Value val = popA();
- pushB(val);
+ Value val = this.popA();
+ this.pushB(val);
//current.slots ~= val;
break;
case OpCode.OP_GET_LOCAL:
- ubyte slot = readByte();
+ ubyte slot = this.readByte();
//pushA(bStack[bTop - slot - 1]);
//pushA(current.slots[slot - 1]);
//pushA(current.slots[current.frameStart + slot + 1]);
- pushA(current.slots[current.frameStart + slot]);
+ pushA(this.current.slots[this.current.frameStart + slot]);
break;
case OpCode.OP_SET_LOCAL:
- ubyte slot = readByte();
+ ubyte slot = this.readByte();
//bStack[bTop + slot - 1] = peekA(0);
- current.slots[slot] = peekA(0);
+ this.current.slots[slot] = this.peekA(0);
//bStack[bTop + slot - 1] = peekA(0);
- popA();
+ this.popA();
break;
case OpCode.OP_CONSTANT:
- Value constant = current.func.chunk.constants[readByte()];
+ Value constant = this.current.func.chunk.constants[this.readByte()];
//Value constant = current.func.chunk.constants[b];
- pushA(constant);
+ this.pushA(constant);
break;
case OpCode.OP_NEGATE:
- if (!isNumber(peekA(0))) {
+ if (!isNumber(this.peekA(0))) {
writeln("negate operand must be a number");
return InterpretResult.RUNTIME_ERROR;
}
- double val = asNumber(popA());
- pushA(makeNumberValue(val * -1));
+ double val = asNumber(this.popA());
+ this.pushA(makeNumberValue(val * -1));
break;
case OpCode.OP_TYPE_CHECK_LIST:
- if (!isList(peekA(0))) {
+ if (!isList(this.peekA(0))) {
writeln("VM type check: not a list!");
return InterpretResult.RUNTIME_ERROR; // TODO error
}
break;
case OpCode.OP_TYPE_CHECK_STRING:
- if (!isString(peekA(0))) {
+ if (!isString(this.peekA(0))) {
writeln("VM type check: not a string!");
return InterpretResult.RUNTIME_ERROR; // TODO error
}
break;
case OpCode.OP_TYPE_CHECK_NUMBER:
- if (!isNumber(peekA(0))) {
+ if (!isNumber(this.peekA(0))) {
writeln("VM type check: not a number!");
return InterpretResult.RUNTIME_ERROR; // TODO error
}
break;
case OpCode.OP_TYPE_CHECK_BOOLEAN:
- if (!isBoolean(peekA(0))) {
+ if (!isBoolean(this.peekA(0))) {
writeln("VM type check: not a boolean!");
return InterpretResult.RUNTIME_ERROR; // TODO error
}
break;
case OpCode.OP_FIRST:
- Value val = popA();
+ Value val = this.popA();
List lst = cast(List)val.as.obj; // TODO this needs better checking
int addr = lst.first();
writefln("got this address: %d", addr);
- Value first = current.func.chunk.constants[to!ubyte(addr)];
- pushA(first);
+ Value first = this.current.func.chunk.constants[to!ubyte(addr)];
+ this.pushA(first);
break;
case OpCode.OP_ADD:
- Value b = popA();
+ Value b = this.popA();
/*
if (!isNumber(b)) {
writeln("b is not a number!");
return InterpretResult.RUNTIME_ERROR; // TODO error
}
*/
- Value a = popA();
+ Value a = this.popA();
/*
if (!isNumber(a)) {
writeln("a is not a number!");
@@ -359,17 +360,17 @@ class VM {
*/
double bnum = asNumber(b);
double anum = asNumber(a);
- pushA(makeNumberValue(anum + bnum));
+ this.pushA(makeNumberValue(anum + bnum));
break;
case OpCode.OP_SUBTRACT:
- Value b = popA();
+ Value b = this.popA();
/*
if (!isNumber(b)) {
writeln("b is not a number!");
return InterpretResult.RUNTIME_ERROR; // TODO error
}
*/
- Value a = popA();
+ Value a = this.popA();
/*
if (!isNumber(a)) {
writeln("a is not a number!");
@@ -378,36 +379,36 @@ class VM {
*/
double bnum = asNumber(b);
double anum = asNumber(a);
- pushA(makeNumberValue(anum - bnum));
+ this.pushA(makeNumberValue(anum - bnum));
break;
case OpCode.OP_NOT:
- Value val = popA();
+ Value val = this.popA();
bool bval = asBoolean(val);
- pushA(makeBooleanValue(!bval));
+ this.pushA(makeBooleanValue(!bval));
break;
case OpCode.OP_CONCAT:
- Value b = popA();
- Value a = popA();
+ Value b = this.popA();
+ Value a = this.popA();
string bstr = asString(b);
string astr = asString(a);
- pushA(makeStringValue(astr ~ bstr));
+ this.pushA(makeStringValue(astr ~ bstr));
break;
case OpCode.OP_GREATER:
- Value b = popA();
- Value a = popA();
+ Value b = this.popA();
+ Value a = this.popA();
double bnum = asNumber(b);
double anum = asNumber(a);
- pushA(makeBooleanValue(anum > bnum));
+ this.pushA(makeBooleanValue(anum > bnum));
break;
case OpCode.OP_LESS:
- Value b = popA();
+ Value b = this.popA();
/*
if (!isNumber(b)) {
writeln("b is not a number!");
return InterpretResult.RUNTIME_ERROR; // TODO error
}
*/
- Value a = popA();
+ Value a = this.popA();
/*
if (!isNumber(a)) {
writeln("a is not a number!");
@@ -416,85 +417,85 @@ class VM {
*/
double bnum = asNumber(b);
double anum = asNumber(a);
- pushA(makeBooleanValue(anum < bnum));
+ this.pushA(makeBooleanValue(anum < bnum));
break;
case OpCode.OP_RETURN:
- Value ret = popA();
- popA(); // function
+ Value ret = this.popA();
+ this.popA(); // function
this.frameCount--;
if (this.frameCount == 1) {
writefln("returned %s", printableValue(ret));
return InterpretResult.OK;
}
// do something with the stack top/frame slots??
- while(bTop > current.frameStart + 1) {
- popB();
+ while(bTop > this.current.frameStart + 1) {
+ this.popB();
}
- pushA(ret);
- current = &frames[this.frameCount -1];
+ this.pushA(ret);
+ this.current = &this.frames[this.frameCount -1];
break;
case OpCode.OP_POP:
- popA();
+ this.popA();
break;
case OpCode.OP_POPB:
- popB();
+ this.popB();
break;
case OpCode.OP_POP_SCOPE: // pop the n-1 position
- Value val = popA();
- popA(); // throw this one away
- pushA(val);
+ Value val = this.popA();
+ this.popA(); // throw this one away
+ this.pushA(val);
break;
case OpCode.OP_JUMP:
- uint offset = readShort();
+ uint offset = this.readShort();
//ip += offset;
- current.ip += offset;
+ this.current.ip += offset;
break;
case OpCode.OP_JUMP_IF_FALSE:
- uint offset = readShort();
- if (!isBoolean(peekA(0))) {
+ uint offset = this.readShort();
+ if (!isBoolean(this.peekA(0))) {
writeln("expecting a boolean condition");
return InterpretResult.RUNTIME_ERROR; // TODO error
}
- if (!asBoolean(peekA(0))) {
+ if (!asBoolean(this.peekA(0))) {
//ip += offset;
- current.ip += offset;
+ this.current.ip += offset;
}
break;
case OpCode.OP_JUMP_IF_TRUE:
- uint offset = readShort();
+ uint offset = this.readShort();
/*
if (!isBoolean(peekA(0))) {
writeln("expecting a boolean condition");
return InterpretResult.RUNTIME_ERROR; // TODO error
}
*/
- if (asBoolean(peekA(0))) {
- current.ip += offset;
+ if (asBoolean(this.peekA(0))) {
+ this.current.ip += offset;
}
break;
case OpCode.OP_CALL:
- ubyte argCount = readByte();
+ ubyte argCount = this.readByte();
// TODO i think i need to move the arguments from stack A to stack B (preserving order)
int cnt = to!int(argCount) - 1;
Value[] tmp;
while (cnt >= 0) {
- tmp ~= popA();
+ tmp ~= this.popA();
cnt--;
}
foreach (Value val ; tmp) {
- pushB(val);
+ this.pushB(val);
}
//if (!callValue(peekA(argCount), argCount)) { // i'm allocating variables wrong
- if (!callValue(peekA(0), argCount)) { // i'm allocating variables wrong
+ if (!this.callValue(this.peekA(0), argCount)) { // i'm allocating variables wrong
return InterpretResult.RUNTIME_ERROR;
}
- current = &frames[this.frameCount - 1];
+ this.current = &this.frames[this.frameCount - 1];
break;
default:
writeln("unknown opcode to run");
@@ -512,6 +513,9 @@ InterpretResult interpret(string source, VM vm) {
// vm.globals[":int"] = makeTypeValue(":int");
+ // reset the frame count (why do i need to do this?)
+ vm.frameCount = 0;
+
vm.pushA(makeObjValue(func));
CallFrame frame = { func, 0, vm.bStack, 0 };
vm.pushFrame(frame);