diff options
| author | Ben Winston | 2023-05-21 16:20:41 -0400 |
|---|---|---|
| committer | Ben Winston | 2023-05-21 16:20:41 -0400 |
| commit | 618de4c70d8916f64781997f3ae538e3e6109d00 (patch) | |
| tree | bcd8ee70d82402407399a49c9cf6914858bd9449 /compiler.d | |
| parent | b1183af95f45ba0162a91f7a308a4846418f03be (diff) | |
if/else, 'and' control flow
Diffstat (limited to 'compiler.d')
| -rw-r--r-- | compiler.d | 116 |
1 files changed, 67 insertions, 49 deletions
@@ -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; } |
