From fbc75bca57a3f66006468fb1a8f3988cdc8227d2 Mon Sep 17 00:00:00 2001 From: mryouse Date: Wed, 7 Jun 2023 22:52:09 -0400 Subject: initial commit of branch --- compiler.d | 38 ++++++++++++++++++++++++++++++++++++++ parser.d | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/compiler.d b/compiler.d index 675ec4c..8cb65ee 100644 --- a/compiler.d +++ b/compiler.d @@ -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; diff --git a/parser.d b/parser.d index 004e1fb..0b31be8 100644 --- a/parser.d +++ b/parser.d @@ -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": -- cgit v1.2.3