diff options
| author | mryouse | 2023-06-07 22:52:09 -0400 |
|---|---|---|
| committer | mryouse | 2023-06-07 22:52:09 -0400 |
| commit | fbc75bca57a3f66006468fb1a8f3988cdc8227d2 (patch) | |
| tree | 48c37fe529dcb55d2bd8516841c516d799ef05a9 | |
| parent | 730a6d777530a33fbb8df86df8b16d842b12c283 (diff) | |
initial commit of branch
| -rw-r--r-- | compiler.d | 38 | ||||
| -rw-r--r-- | parser.d | 38 |
2 files changed, 76 insertions, 0 deletions
@@ -83,6 +83,41 @@ class Compiler { } } + void compileBranch(Form form) { + + Branch branch = cast(Branch)form; + + Cons clause; + int[] endJumps; + int currentJump; + foreach (Form cl ; branch.clauses) { + // resolve the condition + clause = cast(Cons)cl; + this.resolve(clause.head); + this.func.chunk.writeOp(OpCode.OP_TYPE_CHECK_BOOLEAN, clause.line); + + // write a jump spot and pop + currentJump = this.jump(OpCode.OP_JUMP_IF_FALSE); + this.func.chunk.writeOp(OpCode.OP_POP, clause.line); + + // resolve the result of the condition (only executes if true) + foreach (Form f ; clause.tail) { + this.resolve(f); + } + + // jump to the end (if we got here) + endJumps ~= this.jump(OpCode.OP_JUMP); + + // this is where we jump to if the condition was false + this.patchJump(currentJump); + } + + // patch all the end jumps + foreach (int jmp; endJumps) { + this.patchJump(jmp); + } + } + void compileIf(Form form) { If if_ = cast(If)form; @@ -908,6 +943,9 @@ class Compiler { case FormType.IF: this.compileIf(form); break; + case FormType.BRANCH: + this.compileBranch(form); + break; case FormType.AND: this.compileAnd(form); break; @@ -17,6 +17,7 @@ enum FormType { DEF, BLOCK, IF, + BRANCH, AND, OR, @@ -157,6 +158,20 @@ class If : Form { } +class Branch : Form { + + Form[] clauses; + + this(int line) { + this.line = line; + this.type = FormType.BRANCH; + } + + void addClause(Form clause) { + this.clauses ~= clause; + } +} + class And : Form { Form[] clauses; @@ -605,6 +620,27 @@ class Parser { return if_; } + Form parseBranch() { + Branch branch = new Branch(-1); + Form f; + char next; + while(peekable()) { + next = peek(); + if (next == ')') { + break; + } + branch.addClause(parseForm()); + } + + if (!peekable()) { + return new ParseError("unterminated branch", line); + } + + advance(); // consume closing paren + + return branch; + } + Form parseAnd() { And and_ = new And(line); char next; @@ -691,6 +727,8 @@ class Parser { return parseBlock(); case "if": return parseIf(); + case "branch": + return parseBranch(); case "and": return parseAnd(); case "or": |
