aboutsummaryrefslogtreecommitdiff
path: root/compiler.d
diff options
context:
space:
mode:
Diffstat (limited to 'compiler.d')
-rw-r--r--compiler.d116
1 files changed, 67 insertions, 49 deletions
diff --git a/compiler.d b/compiler.d
index a7a5bfa..c05aeaa 100644
--- a/compiler.d
+++ b/compiler.d
@@ -92,13 +92,9 @@ 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 localCount;
}
int addr = func.chunk.addConstant(makeStringValue(def.name.name));
@@ -131,7 +127,6 @@ class Compiler {
}
}
- writefln("> > > creating a local '%s' at %d", sym.name, scopeDepth);
Local loc = Local(sym, scopeDepth);
if (localCount == locals.length) {
locals ~= loc;
@@ -139,7 +134,6 @@ class Compiler {
locals[localCount] = loc;
}
localCount++;
- writefln("localcount is now %d", localCount);
}
void compileDef(Form form) {
@@ -153,27 +147,16 @@ class Compiler {
// are we setting a local?
if (scopeDepth > 0) {
- //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
defineVariable(addr);
- /*
- func.chunk.writeOp(OpCode.OP_DEFINE_GLOBAL, current.line);
- func.chunk.writeOp(to!ubyte(addr), current.line);
- */
-
- // is this right?
- //func.chunk.writeOp(OpCode.OP_POP, def.line);
}
int resolveLocal(Symbol sym) {
- //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) (resolving: %s)", local.sym.name, i, local.depth, sym.name);
if (local.sym.name == sym.name) {
return i;
}
@@ -185,32 +168,80 @@ class Compiler {
void compileSymbol(Form form) {
Symbol sym = cast(Symbol)form;
- //OpCode getOp;
- //OpCode setOp;
int arg = resolveLocal(sym);
if (arg != -1) {
- writeln("compiling a LOCAL symbol");
- //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;
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(getOp, sym.line);
func.chunk.writeOp(to!ubyte(arg), sym.line);
//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;
+ }
+
+ void patchJump(int offset) {
+ // additional -2 to account for the 2 byte jump itself
+ int jmp = to!int(func.chunk.code.length) - offset - 2;
+
+ // TODO check to make sure we didn't jump too far?
+
+ this.func.chunk.code[offset] = (jmp >> 8) & 0xff;
+ this.func.chunk.code[offset + 1] = jmp & 0xff;
+ }
+
+ void compileIf(Form form) {
+ If if_ = cast(If)form;
+
+ resolve(if_.cond);
+
+ int thenJump = jump(OpCode.OP_JUMP_IF_FALSE);
+ this.func.chunk.writeOp(OpCode.OP_POP, if_.line);
+
+ resolve(if_.thenForm);
+
+ int elseJump = jump(OpCode.OP_JUMP);
+
+ patchJump(thenJump);
+ this.func.chunk.writeOp(OpCode.OP_POP, if_.line);
+
+ if (if_.hasElse) {
+ resolve(if_.elseForm);
+ }
+
+ patchJump(elseJump);
+
+ }
+
+ void compileAnd(Form form) {
+ And and_ = cast(And)form;
+
+ resolve(and_.clauses[0]);
+ int[] jumps;
+ jumps ~= jump(OpCode.OP_JUMP_IF_FALSE);
+ int count = 1;
+ while (count < and_.clauses.length) {
+ this.func.chunk.writeOp(OpCode.OP_POP, and_.line);
+ resolve(and_.clauses[count]);
+ jumps ~= jump(OpCode.OP_JUMP_IF_FALSE);
+ count++;
+ }
+
+ // patch all the jumps
+ foreach (int jmp; jumps) {
+ patchJump(jmp);
+ }
+ }
+
void compileBlock(Form form) {
Block block = cast(Block)form;
beginScope();
@@ -226,14 +257,10 @@ class Compiler {
void endScope() {
- writefln("> > ending scope at depth %d", scopeDepth);
scopeDepth--;
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), -1);
func.chunk.writeOp(OpCode.OP_POPB, -1);
localCount--;
}
@@ -274,8 +301,7 @@ class Compiler {
}
void resolve(Form form) {
- write("resolving: ");
- printForm(form);
+ //printForm(form);
switch(form.type) {
case FormType.ATOM:
this.compileAtom(form);
@@ -288,15 +314,19 @@ 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;
+ case FormType.IF:
+ this.compileIf(form);
+ break;
+ case FormType.AND:
+ this.compileAnd(form);
+ break;
default:
write("not sure how to resolve: ");
printForm(form);
@@ -306,28 +336,16 @@ class Compiler {
}
Function compile() {
- 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();
}
Function finish() {
- //emitReturn();
- writeln("finishing the compiler!");
-
this.func.chunk.writeOp(OpCode.OP_RETURN, current.line);
- writeln("wrote a return code");
return func;
}