diff options
| -rw-r--r-- | chunk.d | 8 | ||||
| -rw-r--r-- | compiler.d | 52 | ||||
| -rw-r--r-- | dbg.d | 8 | ||||
| -rw-r--r-- | parser.d | 24 | ||||
| -rw-r--r-- | vm.d | 155 |
5 files changed, 165 insertions, 82 deletions
@@ -37,12 +37,14 @@ enum OpCode { OP_NEGATE, OP_RETURN, OP_CONSTANT, - OP_DEFINE_GLOBAL, - OP_GET_LOCAL, - OP_SET_LOCAL, + OP_DEF_GLOBAL, OP_GET_GLOBAL, OP_SET_GLOBAL, + OP_DEF_LOCAL, + OP_GET_LOCAL, + OP_SET_LOCAL, OP_POP, + OP_POPB, OP_POP_SCOPE, OP_SUBTRACT, OP_NIL, @@ -91,10 +91,13 @@ class Compiler { } int parseVariable(Def def) { + + writefln("in parseVariable(), scopeDepth is %d", scopeDepth); + declareVariable(def.name); if (scopeDepth > 0) { - //return 0; - return localCount - 1; + return 0; + //return localCount - 1; //return localCount; } @@ -106,7 +109,7 @@ class Compiler { if (scopeDepth > 0) { return; } - func.chunk.writeOp(OpCode.OP_DEFINE_GLOBAL, current.line); + func.chunk.writeOp(OpCode.OP_DEF_GLOBAL, current.line); func.chunk.writeOp(to!ubyte(addr), current.line); } @@ -128,9 +131,13 @@ class Compiler { } } - writefln("> > > creating a local at %d", scopeDepth); + writefln("> > > creating a local '%s' at %d", sym.name, scopeDepth); Local loc = Local(sym, scopeDepth); - locals ~= loc; + if (localCount == locals.length) { + locals ~= loc; + } else { + locals[localCount] = loc; + } localCount++; writefln("localcount is now %d", localCount); } @@ -146,8 +153,9 @@ class Compiler { // are we setting a local? if (scopeDepth > 0) { - func.chunk.writeOp(OpCode.OP_SET_LOCAL, current.line); - func.chunk.writeOp(to!ubyte(addr), current.line); + //func.chunk.writeOp(OpCode.OP_SET_LOCAL, current.line); + func.chunk.writeOp(OpCode.OP_DEF_LOCAL, current.line); + //func.chunk.writeOp(to!ubyte(addr), current.line); } // define the variable @@ -165,7 +173,7 @@ class Compiler { //for (int i = localCount - 1; i >= 0; i--) { for (int i = localCount - 1; i >= 0; i--) { Local local = locals[i]; - writefln(" > > looping, looking at '%s' (%d) (depth: %d)", local.sym.name, i, local.depth); + writefln(" > > looping, looking at '%s' (%d) (depth: %d) (resolving: %s)", local.sym.name, i, local.depth, sym.name); if (local.sym.name == sym.name) { return i; } @@ -177,25 +185,27 @@ class Compiler { void compileSymbol(Form form) { Symbol sym = cast(Symbol)form; - OpCode getOp; - OpCode setOp; + //OpCode getOp; + //OpCode setOp; int arg = resolveLocal(sym); if (arg != -1) { writeln("compiling a LOCAL symbol"); - getOp = OpCode.OP_GET_LOCAL; - setOp = OpCode.OP_SET_LOCAL; // do we need this here + //getOp = OpCode.OP_GET_LOCAL; + func.chunk.writeOp(OpCode.OP_GET_LOCAL, sym.line); + //setOp = OpCode.OP_SET_LOCAL; // do we need this here } else { writeln("compiling a GLOBAL symbol"); arg = func.chunk.addConstant(makeStringValue(sym.name)); - getOp = OpCode.OP_GET_GLOBAL; - setOp = OpCode.OP_SET_GLOBAL; // do we need this here + //getOp = OpCode.OP_GET_GLOBAL; + func.chunk.writeOp(OpCode.OP_GET_GLOBAL, sym.line); + //setOp = OpCode.OP_SET_GLOBAL; // do we need this here } // add the symbol name to the chunk //int addr = func.chunk.addConstant(makeStringValue(sym.name)); // get the variable - func.chunk.writeOp(to!ubyte(getOp), sym.line); + //func.chunk.writeOp(getOp, sym.line); func.chunk.writeOp(to!ubyte(arg), sym.line); //advance(); @@ -222,8 +232,9 @@ class Compiler { while (localCount > 0 && locals[localCount - 1].depth > scopeDepth) { writeln("> > looping, gonna pop"); - func.chunk.writeOp(to!ubyte(OpCode.OP_POP_SCOPE), -1); + //func.chunk.writeOp(to!ubyte(OpCode.OP_POP_SCOPE), -1); //func.chunk.writeOp(to!ubyte(OpCode.OP_POP), -1); + func.chunk.writeOp(OpCode.OP_POPB, -1); localCount--; } } @@ -277,11 +288,13 @@ class Compiler { break; case FormType.DEF: this.compileDef(form); + writeln("DONE COMPILING DEF"); break; case FormType.SYMBOL: this.compileSymbol(form); break; case FormType.BLOCK: + writeln("COMPILING BLOCK"); this.compileBlock(form); break; default: @@ -296,9 +309,16 @@ class Compiler { writeln("compiling"); advance(); while(current.type != FormType.EOF) { + writeln("IN COMPILE LOOP"); resolve(current); + writeln("BOTTOM OF COMPILE LOOP"); + if (current.type == FormType.EOF) { + writeln("got an EOF"); + } } + writeln("outside compile loop"); + return finish(); } @@ -107,6 +107,8 @@ int disassemble(Chunk chunk, int offset) { ubyte inst = chunk.code[offset]; switch (inst) { + case OpCode.OP_DEF_LOCAL: + return byteInstruction("OP_DEF_LOCAL", chunk, offset); case OpCode.OP_GET_LOCAL: return byteInstruction("OP_GET_LOCAL", chunk, offset); case OpCode.OP_SET_LOCAL: @@ -119,12 +121,14 @@ int disassemble(Chunk chunk, int offset) { return simpleInstruction("OP_SUBTRACT", offset); case OpCode.OP_CONSTANT: return constantInstruction("OP_CONSTANT", chunk, offset); - case OpCode.OP_DEFINE_GLOBAL: - return constantInstruction("OP_DEFINE_GLOBAL", chunk, offset); + case OpCode.OP_DEF_GLOBAL: + return constantInstruction("OP_DEF_GLOBAL", chunk, offset); case OpCode.OP_NEGATE: return simpleInstruction("OP_NEGATE", offset); case OpCode.OP_POP: return simpleInstruction("OP_POP", offset); + case OpCode.OP_POPB: + return simpleInstruction("OP_POPB", offset); case OpCode.OP_POP_SCOPE: return simpleInstruction("OP_POP_SCOPE", offset); case OpCode.OP_RETURN: @@ -252,6 +252,7 @@ class Parser { int line; bool peekable() { + writefln("pos %d source %d", pos, source.length); return (pos < source.length); } @@ -259,25 +260,36 @@ class Parser { if (pos < source.length) { return source[pos]; } else { - //writeln("peek returns null"); + writeln("peek returns null"); return '\0'; } } char advance() { + if (!peekable()) { + writeln("trying to advance() beyond the end!!!"); + return '\0'; + } else { + char ret = peek(); + pos++; + return ret; + } + /* char ret = peek(); if (ret != '\0') { pos++; } return ret; + */ } void skipWhitespace() { - while (canFind([' ', '\t', '\r', '\n'], peek())) { + while (peekable() && canFind([' ', '\t', '\r', '\n'], peek())) { if (peek() == '\n') { line++; } - pos++; + //pos++; + advance(); } } @@ -353,6 +365,8 @@ class Parser { advance(); // closing paren + writefln("ending DEF pos %d", pos); + return def; } @@ -406,6 +420,7 @@ class Parser { return new ParseError("unterminated block", line); } + writefln("ending block pos %d", pos); advance(); // consume closing paren return block; @@ -480,6 +495,9 @@ class Parser { default: return parseSymbol(); } + + writeln("FELL THROUGH ON PARSE FORM"); + advance(); return new Atom(0, -1); @@ -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"); |
