aboutsummaryrefslogtreecommitdiff
path: root/compiler.d
diff options
context:
space:
mode:
Diffstat (limited to 'compiler.d')
-rw-r--r--compiler.d134
1 files changed, 126 insertions, 8 deletions
diff --git a/compiler.d b/compiler.d
index 739f887..7a198ee 100644
--- a/compiler.d
+++ b/compiler.d
@@ -23,9 +23,11 @@ class Compiler {
FunctionType type;
Parser* parser;
Local[] locals;
+ int localCount;
int scopeDepth;
Form current;
Form previous;
+
Form outer;
int outerIdx;
@@ -88,31 +90,142 @@ class Compiler {
func.chunk.writeOp(OpCode.OP_LESS, current.line);
}
- void compileDef(Form form) {
- Def def = cast(Def)form;
+ int parseVariable(Def def) {
+ declareVariable(def.name);
+ if (scopeDepth > 0) {
+ //return 0;
+ return localCount - 1;
+ //return localCount;
+ }
- // add the variable name to the chunk
int addr = func.chunk.addConstant(makeStringValue(def.name.name));
+ return addr;
+ }
+
+ void defineVariable(int addr) {
+ if (scopeDepth > 0) {
+ return;
+ }
+ func.chunk.writeOp(OpCode.OP_DEFINE_GLOBAL, current.line);
+ func.chunk.writeOp(to!ubyte(addr), current.line);
+ }
+
+ void declareVariable(Symbol sym) {
+
+ if (scopeDepth == 0) {
+ return;
+ }
+
+ for (int i = localCount - 1; i >= 0; i--) {
+ Local local = locals[i];
+ if (local.depth != -1 && local.depth < scopeDepth) {
+ break;
+ }
+
+ if (sym.name == local.sym.name) {
+ writefln("ERROR: already a variable named '%s' in this scope", sym.name);
+ return;
+ }
+ }
+
+ writefln("> > > creating a local at %d", scopeDepth);
+ Local loc = Local(sym, scopeDepth);
+ locals ~= loc;
+ localCount++;
+ writefln("localcount is now %d", localCount);
+ }
+
+ void compileDef(Form form) {
+ Def def = cast(Def)form;
// resolve the value
resolve(def.val);
+ // add the variable name to the chunk (if applicable)
+ int addr = parseVariable(def);
+
+ // 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);
+ }
+
// 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)", local.sym.name, i, local.depth);
+ if (local.sym.name == sym.name) {
+ return i;
+ }
+ }
+
+ return -1;
}
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;
+ 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
+ }
+
// add the symbol name to the chunk
- int addr = func.chunk.addConstant(makeStringValue(sym.name));
+ //int addr = func.chunk.addConstant(makeStringValue(sym.name));
// get the variable
- func.chunk.writeOp(OpCode.OP_GET_GLOBAL, sym.line);
- func.chunk.writeOp(to!ubyte(addr), sym.line);
+ func.chunk.writeOp(to!ubyte(getOp), sym.line);
+ func.chunk.writeOp(to!ubyte(arg), sym.line);
- advance();
+ //advance();
+ }
+
+ void compileBlock(Form form) {
+ Block block = cast(Block)form;
+ beginScope();
+ foreach (Form inner; block.blockBody) {
+ resolve(inner);
+ }
+ endScope();
+ }
+
+ void beginScope() {
+ scopeDepth++;
+ }
+
+ 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);
+ localCount--;
+ }
}
void compileCons(Form form) {
@@ -168,6 +281,9 @@ class Compiler {
case FormType.SYMBOL:
this.compileSymbol(form);
break;
+ case FormType.BLOCK:
+ this.compileBlock(form);
+ break;
default:
write("not sure how to resolve: ");
printForm(form);
@@ -199,6 +315,8 @@ class Compiler {
this.parser = parser;
this.func = new Function();
this.type = type;
- locals ~= Local(new Symbol("", -1), 0);
+ localCount = 0;
+ //locals ~= Local(new Symbol("", -1), 0);
+ //localCount++;
}
}