aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormryouse2023-05-25 01:14:59 +0000
committermryouse2023-05-25 01:14:59 +0000
commitcb64344f44cdbcd31f4d775bd1865b1af142bba3 (patch)
tree3a69ebbd65dd9f4f5248ce46562ee0d6d0c6cbd3
parentc08e9c793b138da5b373d6cb66a2eb599ea77397 (diff)
reference instance variables, and reset framecount in 'interpret'
-rw-r--r--compiler.d258
-rw-r--r--vm.d202
2 files changed, 232 insertions, 228 deletions
diff --git a/compiler.d b/compiler.d
index 3b684d4..665fe61 100644
--- a/compiler.d
+++ b/compiler.d
@@ -34,7 +34,7 @@ class Compiler {
int outerIdx;
void advance() {
- previous = current;
+ this.previous = this.current;
/*
if (outer.type != FormType.EOF && outerIdx < outer) {
current = parser.parseForm();
@@ -42,12 +42,12 @@ class Compiler {
}
*/
- current = parser.parseForm();
+ this.current = this.parser.parseForm();
}
void compileNil(Form form) {
- form.compile(func);
- advance();
+ form.compile(this.func);
+ this.advance();
}
TC typeCheck(ValueType actual, ValueType expecting) {
@@ -120,8 +120,8 @@ class Compiler {
}
}
*/
- TC tc = typeCheck(atom.value.type, expecting);
- form.compile(func);
+ TC tc = this.typeCheck(atom.value.type, expecting);
+ form.compile(this.func);
//if (tc.exact) {
//} else if (tc.maybe) {
@@ -135,7 +135,7 @@ class Compiler {
}
*/
- advance();
+ this.advance();
@@ -180,8 +180,8 @@ class Compiler {
void compileAdd(Form[] args, ValueType expecting) {
int line = args[0].line;
- resolve(args[0], expecting);
- func.chunk.writeOp(OpCode.OP_TYPE_CHECK_NUMBER, line);
+ this.resolve(args[0], expecting);
+ this.func.chunk.writeOp(OpCode.OP_TYPE_CHECK_NUMBER, line);
// (+ n) always returns n
if (args.length == 1) {
@@ -189,26 +189,26 @@ class Compiler {
}
for (int i = 1; i < args.length; i++) {
- resolve(args[i], expecting);
- func.chunk.writeOp(OpCode.OP_TYPE_CHECK_NUMBER, line);
- func.chunk.writeOp(OpCode.OP_ADD, line);
+ this.resolve(args[i], expecting);
+ this.func.chunk.writeOp(OpCode.OP_TYPE_CHECK_NUMBER, line);
+ this.func.chunk.writeOp(OpCode.OP_ADD, line);
}
}
void compileNegate(Form arg) {
- resolve(arg);
- func.chunk.writeOp(OpCode.OP_TYPE_CHECK_NUMBER, currentLine);
- func.chunk.writeOp(OpCode.OP_NEGATE, currentLine);
+ this.resolve(arg);
+ this.func.chunk.writeOp(OpCode.OP_TYPE_CHECK_NUMBER, arg.line);
+ this.func.chunk.writeOp(OpCode.OP_NEGATE, arg.line);
}
ValueType compileSubtract(Form[] args, ValueType expected) {
ValueType vt;
- vt = resolve(args[0], expected);
- func.chunk.writeOp(OpCode.OP_TYPE_CHECK_NUMBER, currentLine);
+ vt = this.resolve(args[0], expected);
+ this.func.chunk.writeOp(OpCode.OP_TYPE_CHECK_NUMBER, args[0].line);
for (int i = 1; i < args.length; i++) {
- vt = resolve(args[i], expected);
- func.chunk.writeOp(OpCode.OP_TYPE_CHECK_NUMBER, currentLine);
- func.chunk.writeOp(OpCode.OP_SUBTRACT, currentLine);
+ vt = this.resolve(args[i], expected);
+ this.func.chunk.writeOp(OpCode.OP_TYPE_CHECK_NUMBER, args[i].line);
+ this.func.chunk.writeOp(OpCode.OP_SUBTRACT, args[i].line);
}
return ValueType.NUMBER;
}
@@ -217,10 +217,10 @@ class Compiler {
ValueType compileLess(Form[] args, ValueType expected) {
if (args.length != 2) {
writeln("'<' requires 2 arguments");
- advance();
+ this.advance();
return ValueType.NIL;
}
- ValueType vt1 = resolve(args[0], ValueType.NUMBER);
+ ValueType vt1 = this.resolve(args[0], ValueType.NUMBER);
/*
TC tc1 = typeCheck(vt1, expected);
if (tc1.maybe) {
@@ -229,9 +229,9 @@ class Compiler {
writeln("COMPILE ERROR: bad type (less)");
}
*/
- func.chunk.writeOp(OpCode.OP_TYPE_CHECK_NUMBER, currentLine);
+ this.func.chunk.writeOp(OpCode.OP_TYPE_CHECK_NUMBER, args[0].line);
- ValueType vt2 = resolve(args[1], ValueType.NUMBER);
+ ValueType vt2 = this.resolve(args[1], ValueType.NUMBER);
/*
TC tc2 = typeCheck(vt2, expected);
if (tc2.maybe) {
@@ -240,14 +240,14 @@ class Compiler {
writeln("COMPILE ERROR: bad type (less)");
}
*/
- func.chunk.writeOp(OpCode.OP_TYPE_CHECK_NUMBER, currentLine);
+ this.func.chunk.writeOp(OpCode.OP_TYPE_CHECK_NUMBER, args[1].line);
//ValueType vt1 = resolve(args[0], expected);
//func.chunk.writeOp(OpCode.OP_TYPE_CHECK_NUMBER, currentLine);
//ValueType vt2 = resolve(args[1], expected);
//func.chunk.writeOp(OpCode.OP_TYPE_CHECK_NUMBER, currentLine);
- func.chunk.writeOp(OpCode.OP_LESS, currentLine);
+ this.func.chunk.writeOp(OpCode.OP_LESS, args[1].line);
// this should probably return a ValueType
return ValueType.BOOLEAN;
@@ -256,16 +256,16 @@ class Compiler {
ValueType compileGreater(Form[] args) {
if (args.length != 2) {
writeln("'>' requires 2 arguments");
- advance();
+ this.advance();
return ValueType.NIL;
}
- ValueType vt1 = resolve(args[0], ValueType.NUMBER);
- func.chunk.writeOp(OpCode.OP_TYPE_CHECK_NUMBER, currentLine);
+ ValueType vt1 = this.resolve(args[0], ValueType.NUMBER);
+ this.func.chunk.writeOp(OpCode.OP_TYPE_CHECK_NUMBER, args[0].line);
- ValueType vt2 = resolve(args[1], ValueType.NUMBER);
- func.chunk.writeOp(OpCode.OP_TYPE_CHECK_NUMBER, currentLine);
+ ValueType vt2 = this.resolve(args[1], ValueType.NUMBER);
+ this.func.chunk.writeOp(OpCode.OP_TYPE_CHECK_NUMBER, args[1].line);
- func.chunk.writeOp(OpCode.OP_GREATER, currentLine);
+ this.func.chunk.writeOp(OpCode.OP_GREATER, args[1].line);
// this should probably return a ValueType
return ValueType.BOOLEAN;
@@ -275,12 +275,12 @@ class Compiler {
//int parseVariable(Def def) {
int parseVariable(Symbol sym) {
- declareVariable(sym);
+ this.declareVariable(sym);
if (this.scopeDepth > 0) {
return 0;
}
- int addr = func.chunk.addConstant(makeStringValue(sym.name));
+ int addr = this.func.chunk.addConstant(makeStringValue(sym.name));
return addr;
}
@@ -288,8 +288,8 @@ class Compiler {
if (this.scopeDepth > 0) {
return;
}
- func.chunk.writeOp(OpCode.OP_DEF_GLOBAL, current.line);
- func.chunk.writeOp(to!ubyte(addr), current.line);
+ this.func.chunk.writeOp(OpCode.OP_DEF_GLOBAL, this.current.line);
+ this.func.chunk.writeOp(to!ubyte(addr), this.current.line);
}
void declareVariable(Symbol sym) {
@@ -298,8 +298,8 @@ class Compiler {
return;
}
- for (int i = localCount - 1; i >= 0; i--) {
- Local local = locals[i];
+ for (int i = this.localCount - 1; i >= 0; i--) {
+ Local local = this.locals[i];
if (local.depth != -1 && local.depth < this.scopeDepth) {
break;
}
@@ -311,30 +311,30 @@ class Compiler {
}
Local loc = Local(sym, this.scopeDepth);
- if (localCount == locals.length) {
- locals ~= loc;
+ if (this.localCount == this.locals.length) {
+ this.locals ~= loc;
} else {
- locals[localCount] = loc;
+ this.locals[this.localCount] = loc;
}
- localCount++;
+ this.localCount++;
}
void compileDef(Form form, ValueType expecting) {
Def def = cast(Def)form;
// resolve the value
- resolve(def.val, expecting);
+ this.resolve(def.val, expecting);
// add the variable name to the chunk (if applicable)
- int addr = parseVariable(def.name);
+ int addr = this.parseVariable(def.name);
// are we setting a local?
if (this.scopeDepth > 0) {
- func.chunk.writeOp(OpCode.OP_DEF_LOCAL, def.line);
+ this.func.chunk.writeOp(OpCode.OP_DEF_LOCAL, def.line);
}
// define the variable
- defineVariable(addr);
+ this.defineVariable(addr);
}
/*
@@ -345,8 +345,8 @@ class Compiler {
*/
int resolveLocal(Symbol sym) {
- for (int i = localCount - 1; i >= 0; i--) {
- Local local = locals[i];
+ for (int i = this.localCount - 1; i >= 0; i--) {
+ Local local = this.locals[i];
if (local.sym.name == sym.name) {
return i;
}
@@ -363,7 +363,7 @@ class Compiler {
}
Symbol sym = cast(Symbol)form;
- int arg = resolveLocal(sym);
+ int arg = this.resolveLocal(sym);
if (arg != -1) {
this.func.chunk.writeOp(OpCode.OP_GET_LOCAL, sym.line);
} else {
@@ -376,19 +376,19 @@ class Compiler {
// get the variable
this.func.chunk.writeOp(to!ubyte(arg), sym.line);
- advance();
+ this.advance();
}
int jump(OpCode type) {
- func.chunk.writeOp(to!ubyte(type), current.line);
- func.chunk.writeOp(0xff, current.line);
- func.chunk.writeOp(0xff, current.line);
- return to!int(func.chunk.code.length) - 2;
+ this.func.chunk.writeOp(to!ubyte(type), this.current.line);
+ this.func.chunk.writeOp(0xff, this.current.line);
+ this.func.chunk.writeOp(0xff, this.current.line);
+ return to!int(this.func.chunk.code.length) - 2;
}
void patchJump(int offset) {
// additional -2 to account for the 2 byte jump itself
- int jmp = to!int(func.chunk.code.length) - offset - 2;
+ int jmp = to!int(this.func.chunk.code.length) - offset - 2;
// TODO check to make sure we didn't jump too far?
@@ -399,96 +399,96 @@ class Compiler {
void compileIf(Form form) {
If if_ = cast(If)form;
- resolve(if_.cond);
- func.chunk.writeOp(OpCode.OP_TYPE_CHECK_BOOLEAN, if_.line);
+ this.resolve(if_.cond);
+ this.func.chunk.writeOp(OpCode.OP_TYPE_CHECK_BOOLEAN, if_.line);
- int thenJump = jump(OpCode.OP_JUMP_IF_FALSE);
+ int thenJump = this.jump(OpCode.OP_JUMP_IF_FALSE);
this.func.chunk.writeOp(OpCode.OP_POP, if_.line);
- resolve(if_.thenForm);
+ this.resolve(if_.thenForm);
- int elseJump = jump(OpCode.OP_JUMP);
+ int elseJump = this.jump(OpCode.OP_JUMP);
- patchJump(thenJump);
+ this.patchJump(thenJump);
this.func.chunk.writeOp(OpCode.OP_POP, if_.line);
if (if_.hasElse) {
- resolve(if_.elseForm);
+ this.resolve(if_.elseForm);
}
- patchJump(elseJump);
+ this.patchJump(elseJump);
}
void compileAnd(Form form) {
And and_ = cast(And)form;
- resolve(and_.clauses[0]);
- func.chunk.writeOp(OpCode.OP_TYPE_CHECK_BOOLEAN, currentLine);
+ this.resolve(and_.clauses[0]);
+ this.func.chunk.writeOp(OpCode.OP_TYPE_CHECK_BOOLEAN, and_.clauses[0].line);
int[] jumps;
- jumps ~= jump(OpCode.OP_JUMP_IF_FALSE);
+ jumps ~= this.jump(OpCode.OP_JUMP_IF_FALSE);
int count = 1;
while (count < and_.clauses.length) {
- this.func.chunk.writeOp(OpCode.OP_POP, currentLine);
- resolve(and_.clauses[count]);
- func.chunk.writeOp(OpCode.OP_TYPE_CHECK_BOOLEAN, currentLine);
- jumps ~= jump(OpCode.OP_JUMP_IF_FALSE);
+ this.func.chunk.writeOp(OpCode.OP_POP, and_.clauses[count].line);
+ this.resolve(and_.clauses[count]);
+ this.func.chunk.writeOp(OpCode.OP_TYPE_CHECK_BOOLEAN, and_.clauses[count].line);
+ jumps ~= this.jump(OpCode.OP_JUMP_IF_FALSE);
count++;
}
// patch all the jumps
foreach (int jmp; jumps) {
- patchJump(jmp);
+ this.patchJump(jmp);
}
}
void compileOr(Form form) {
Or or_ = cast(Or)form;
- resolve(or_.clauses[0]);
- func.chunk.writeOp(OpCode.OP_TYPE_CHECK_BOOLEAN, currentLine);
+ this.resolve(or_.clauses[0]);
+ this.func.chunk.writeOp(OpCode.OP_TYPE_CHECK_BOOLEAN, or_.clauses[0].line);
int[] jumps;
- jumps ~= jump(OpCode.OP_JUMP_IF_TRUE);
+ jumps ~= this.jump(OpCode.OP_JUMP_IF_TRUE);
int count = 1;
while (count < or_.clauses.length) {
- this.func.chunk.writeOp(OpCode.OP_POP, or_.line);
- resolve(or_.clauses[count]);
- func.chunk.writeOp(OpCode.OP_TYPE_CHECK_BOOLEAN, currentLine);
- jumps ~= jump(OpCode.OP_JUMP_IF_TRUE);
+ this.func.chunk.writeOp(OpCode.OP_POP, or_.clauses[count].line);
+ this.resolve(or_.clauses[count]);
+ this.func.chunk.writeOp(OpCode.OP_TYPE_CHECK_BOOLEAN, or_.clauses[count].line);
+ jumps ~= this.jump(OpCode.OP_JUMP_IF_TRUE);
count++;
}
// patch all the jumps
foreach (int jmp; jumps) {
- patchJump(jmp);
+ this.patchJump(jmp);
}
}
ValueType compileNot(Form[] args) {
- ValueType vt = resolve(args[0], ValueType.BOOLEAN);
- func.chunk.writeOp(OpCode.OP_TYPE_CHECK_BOOLEAN, currentLine);
- func.chunk.writeOp(OpCode.OP_NOT, currentLine);
+ ValueType vt = this.resolve(args[0], ValueType.BOOLEAN);
+ this.func.chunk.writeOp(OpCode.OP_TYPE_CHECK_BOOLEAN, args[0].line);
+ this.func.chunk.writeOp(OpCode.OP_NOT, args[0].line);
return vt;
}
ValueType compileConcat(Form[] args) {
- ValueType vt = resolve(args[0], ValueType.STRING);
+ ValueType vt = this.resolve(args[0], ValueType.STRING);
for (int i = 1; i < args.length; i++) {
- vt = resolve(args[i], ValueType.STRING);
- func.chunk.writeOp(OpCode.OP_TYPE_CHECK_STRING, currentLine);
- func.chunk.writeOp(OpCode.OP_CONCAT, currentLine);
+ vt = this.resolve(args[i], ValueType.STRING);
+ this.func.chunk.writeOp(OpCode.OP_TYPE_CHECK_STRING, args[i].line);
+ this.func.chunk.writeOp(OpCode.OP_CONCAT, args[i].line);
}
return ValueType.STRING;
}
void compileBlock(Form form) {
Block block = cast(Block)form;
- beginScope();
+ this.beginScope();
foreach (Form inner; block.blockBody) {
- resolve(inner);
+ this.resolve(inner);
}
- endScope();
+ this.endScope();
}
void beginScope() {
@@ -499,21 +499,21 @@ class Compiler {
this.scopeDepth--;
- while (localCount > 0 &&
- locals[localCount - 1].depth > this.scopeDepth) {
- func.chunk.writeOp(OpCode.OP_POPB, -1);
- localCount--;
+ while (this.localCount > 0 &&
+ this.locals[this.localCount - 1].depth > this.scopeDepth) {
+ this.func.chunk.writeOp(OpCode.OP_POPB, -1);
+ this.localCount--;
}
}
void call(Form[] args) {
//ubyte argCount = argumentList();
foreach (Form f ; args) {
- resolve(f);
+ this.resolve(f);
}
- func.chunk.writeOp(OpCode.OP_CALL, -1);
+ this.func.chunk.writeOp(OpCode.OP_CALL, -1);
//func.chunk.writeOp(argCount, -1);
- func.chunk.writeOp(to!ubyte(args.length), -1);
+ this.func.chunk.writeOp(to!ubyte(args.length), -1);
}
void compileList(Form[] args) {
@@ -521,7 +521,7 @@ class Compiler {
ValueType vt;
int addr;
foreach (Form arg ; args) {
- vt = resolve(arg, ValueType.ANY);
+ vt = this.resolve(arg, ValueType.ANY);
// how do we get at the address?
addr = to!int(this.func.chunk.constants.length) - 1; // this is probably often wrong
lst.addItem(addr);
@@ -543,7 +543,7 @@ class Compiler {
writeln("COMPILE ERROR: 'first' expects exactly one argument");
return;
}
- ValueType vt = resolve(args[0], ValueType.OBJ); // TODO need a new type
+ ValueType vt = this.resolve(args[0], ValueType.OBJ); // TODO need a new type
this.func.chunk.writeOp(OpCode.OP_TYPE_CHECK_LIST, args[0].line);
// pop the value off the stack
@@ -558,9 +558,9 @@ class Compiler {
Func f = cast(Func)form;
// name the function
- int global = parseVariable(f.name);
+ int global = this.parseVariable(f.name);
- Compiler compiler = new Compiler(ObjType.FUNCTION, parser, f.name.name);
+ Compiler compiler = new Compiler(ObjType.FUNCTION, this.parser, f.name.name);
compiler.beginScope();
if (f.args.type != FormType.NIL) {
@@ -590,12 +590,12 @@ class Compiler {
// write the function as a Value
Function outFunc = compiler.finish();
- func.chunk.writeOp(OpCode.OP_CONSTANT, f.line);
- int funcAddr = func.chunk.addConstant(makeObjValue(outFunc));
- func.chunk.writeOp(to!ubyte(funcAddr), f.line);
+ this.func.chunk.writeOp(OpCode.OP_CONSTANT, f.line);
+ int funcAddr = this.func.chunk.addConstant(makeObjValue(outFunc));
+ this.func.chunk.writeOp(to!ubyte(funcAddr), f.line);
// define the global variable
- defineVariable(global);
+ this.defineVariable(global);
}
ValueType compileCons(Form form, ValueType expected) {
@@ -603,59 +603,59 @@ class Compiler {
Form head = cons.head;
if (head.type != FormType.SYMBOL) {
writeln("cons must start with a symbol");
- advance();
+ this.advance();
return ValueType.NIL;
}
Symbol sym = cast(Symbol)head;
switch (sym.name) {
case "+":
- compileAdd(cons.tail, ValueType.NUMBER);
+ this.compileAdd(cons.tail, ValueType.NUMBER);
break;
case "-":
if (cons.tail.length == 1) {
- compileNegate(cons.tail[0]);
+ this.compileNegate(cons.tail[0]);
} else {
- return compileSubtract(cons.tail, ValueType.NUMBER);
+ return this.compileSubtract(cons.tail, ValueType.NUMBER);
}
break;
case "<":
- return compileLess(cons.tail, ValueType.NUMBER);
+ return this.compileLess(cons.tail, ValueType.NUMBER);
break;
case "<=":
- ValueType vt = compileGreater(cons.tail);
- func.chunk.writeOp(OpCode.OP_NOT, cons.line);
+ ValueType vt = this.compileGreater(cons.tail);
+ this.func.chunk.writeOp(OpCode.OP_NOT, cons.line);
return vt;
case ">":
- return compileGreater(cons.tail);
+ return this.compileGreater(cons.tail);
break;
case ">=":
- ValueType vt = compileLess(cons.tail, ValueType.NUMBER);
- func.chunk.writeOp(OpCode.OP_NOT, cons.line);
+ ValueType vt = this.compileLess(cons.tail, ValueType.NUMBER);
+ this.func.chunk.writeOp(OpCode.OP_NOT, cons.line);
return vt;
case "not":
- return compileNot(cons.tail);
+ return this.compileNot(cons.tail);
// STRINGS
case "concat":
- return compileConcat(cons.tail);
+ return this.compileConcat(cons.tail);
// LISTS
case "first":
- compileFirst(cons.tail);
+ this.compileFirst(cons.tail);
break;
case "list":
//return compileList(cons.tail);
- compileList(cons.tail);
+ this.compileList(cons.tail);
break;
default:
/*
writefln("unsure how to compile %s", sym.name);
advance();
*/
- resolve(head);
- call(cons.tail);
- advance();
+ this.resolve(head);
+ this.call(cons.tail);
+ this.advance();
break;
}
return ValueType.NIL;
@@ -664,7 +664,7 @@ class Compiler {
ValueType resolve(Form form, const ValueType expecting = ValueType.ANY) {
//printForm(form);
- currentLine = form.line;
+ this.currentLine = form.line;
switch(form.type) {
case FormType.ATOM:
this.compileAtom(form, expecting);
@@ -699,23 +699,23 @@ class Compiler {
default:
write("not sure how to resolve: ");
printForm(form);
- advance();
+ this.advance();
break;
}
return ValueType.NIL;
}
Function compile() {
- advance();
+ this.advance();
while(current.type != FormType.EOF) {
- resolve(current);
+ this.resolve(current);
}
- return finish();
+ return this.finish();
}
Function finish() {
- this.func.chunk.writeOp(OpCode.OP_RETURN, current.line);
+ this.func.chunk.writeOp(OpCode.OP_RETURN, this.current.line);
if (DEBUG) {
disassembleChunk(this.func.chunk, to!string(func));
}
@@ -727,7 +727,7 @@ class Compiler {
this.func = new Function(type, name);
//localCount = 0;
- locals ~= Local(new Symbol("", -1), 0);
- localCount++;
+ this.locals ~= Local(new Symbol("", -1), 0);
+ this.localCount++;
}
}
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);