diff options
| author | Ben Winston | 2023-05-20 22:54:07 -0400 |
|---|---|---|
| committer | Ben Winston | 2023-05-20 22:54:07 -0400 |
| commit | 2ad2be250a68e907b308b120b934edcbfc99ae6e (patch) | |
| tree | 54cd9308286cb4a368a8f7eb11ad9011c74ac58a /compiler.d | |
| parent | 38dc63a67879a42f208b5642a8590e1192e8e2e5 (diff) | |
block scope and local variables (not really working)
Diffstat (limited to 'compiler.d')
| -rw-r--r-- | compiler.d | 134 |
1 files changed, 126 insertions, 8 deletions
@@ -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++; } } |
