diff options
| -rw-r--r-- | chunk.d | 1 | ||||
| -rw-r--r-- | compiler.d | 23 | ||||
| -rw-r--r-- | dbg.d | 2 | ||||
| -rw-r--r-- | parser.d | 37 | ||||
| -rw-r--r-- | vm.d | 12 |
5 files changed, 74 insertions, 1 deletions
@@ -51,6 +51,7 @@ enum OpCode { OP_JUMP, OP_JUMP_IF_FALSE, + OP_JUMP_IF_TRUE, } class Chunk { @@ -242,6 +242,26 @@ class Compiler { } } + void compileOr(Form form) { + Or or_ = cast(Or)form; + + resolve(or_.clauses[0]); + int[] jumps; + jumps ~= jump(OpCode.OP_JUMP_IF_TRUE); + int count = 1; + while (count < or_.clauses.length) { + this.func.chunk.writeOp(OpCode.OP_POP, or_.line); + resolve(or_.clauses[count]); + jumps ~= jump(OpCode.OP_JUMP_IF_TRUE); + count++; + } + + // patch all the jumps + foreach (int jmp; jumps) { + patchJump(jmp); + } + } + void compileBlock(Form form) { Block block = cast(Block)form; beginScope(); @@ -327,6 +347,9 @@ class Compiler { case FormType.AND: this.compileAnd(form); break; + case FormType.OR: + this.compileOr(form); + break; default: write("not sure how to resolve: "); printForm(form); @@ -147,6 +147,8 @@ int disassemble(Chunk chunk, int offset) { return jumpInstruction("OP_JUMP", 1, chunk, offset); case OpCode.OP_JUMP_IF_FALSE: return jumpInstruction("OP_JUMP_IF_FALSE", 1, chunk, offset); + case OpCode.OP_JUMP_IF_TRUE: + return jumpInstruction("OP_JUMP_IF_TRUE", 1, chunk, offset); default: writeln("unknown opcode?"); @@ -16,6 +16,7 @@ enum FormType { BLOCK, IF, AND, + OR, EOF, PARSE_ERROR @@ -176,6 +177,20 @@ class And : Form { } } +class Or : Form { + + Form[] clauses; + + this(int line) { + this.line = line; + this.type = FormType.OR; + } + + void addClause(Form clause) { + clauses ~= clause; + } +} + class Func : Form { Symbol name; @@ -480,6 +495,26 @@ class Parser { } + Form parseOr() { + Or or_ = new Or(line); + char next; + while(peekable()) { + next = peek(); + if (next == ')') { + break; + } + or_.addClause(parseForm()); + } + + if (!peekable()) { + return new ParseError("unterminated or", line); + } + + advance(); // consume closing paren + + return or_; + } + Form parseBlock() { Block block = new Block(line); char next; @@ -526,6 +561,8 @@ class Parser { return parseIf(); case "and": return parseAnd(); + case "or": + return parseOr(); default: break; } @@ -261,13 +261,23 @@ class VM { case OpCode.OP_JUMP_IF_FALSE: uint offset = readShort(); if (!isBoolean(peekA(0))) { - writeln("if expects a boolean condition"); + writeln("expecting a boolean condition"); return InterpretResult.RUNTIME_ERROR; // TODO error } if (!asBoolean(peekA(0))) { ip += offset; } break; + case OpCode.OP_JUMP_IF_TRUE: + uint offset = readShort(); + if (!isBoolean(peekA(0))) { + writeln("expecting a boolean condition"); + return InterpretResult.RUNTIME_ERROR; // TODO error + } + if (asBoolean(peekA(0))) { + ip += offset; + } + break; default: writeln("unknown opcode to run"); break; |
