aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chunk.d8
-rw-r--r--compiler.d52
-rw-r--r--dbg.d8
-rw-r--r--parser.d24
-rw-r--r--vm.d155
5 files changed, 165 insertions, 82 deletions
diff --git a/chunk.d b/chunk.d
index 571cf25..d6a9b5a 100644
--- a/chunk.d
+++ b/chunk.d
@@ -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,
diff --git a/compiler.d b/compiler.d
index 7a198ee..a7a5bfa 100644
--- a/compiler.d
+++ b/compiler.d
@@ -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();
}
diff --git a/dbg.d b/dbg.d
index 18526db..89ae8c1 100644
--- a/dbg.d
+++ b/dbg.d
@@ -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:
diff --git a/parser.d b/parser.d
index 978b218..80e1626 100644
--- a/parser.d
+++ b/parser.d
@@ -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);
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");