diff options
| author | mryouse | 2023-05-25 01:14:59 +0000 |
|---|---|---|
| committer | mryouse | 2023-05-25 01:14:59 +0000 |
| commit | cb64344f44cdbcd31f4d775bd1865b1af142bba3 (patch) | |
| tree | 3a69ebbd65dd9f4f5248ce46562ee0d6d0c6cbd3 | |
| parent | c08e9c793b138da5b373d6cb66a2eb599ea77397 (diff) | |
reference instance variables, and reset framecount in 'interpret'
| -rw-r--r-- | compiler.d | 258 | ||||
| -rw-r--r-- | vm.d | 202 |
2 files changed, 232 insertions, 228 deletions
@@ -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++; } } @@ -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); |
