diff --git a/lab17/compiler.js b/lab17/compiler.js index 7a4791d..37179c7 100644 --- a/lab17/compiler.js +++ b/lab17/compiler.js @@ -134,10 +134,9 @@ class Compiler { this.writeByte(ast.value); return; } else if (ast.type === BOOL) { - // - // ***YOUR CODE HERE*** - // // Booleans will be stored as either 1 for true, or as a 0 for false. + this.writeOp('PUSH1'); + this.writeByte(ast.value ? 1 : 0); return; } else if (ast.type === VAR) { // We look up the offset for a variable and push the offset @@ -190,12 +189,35 @@ class Compiler { break; case "if": - // - // ***YOUR CODE HERE*** - // // EXTRA CREDIT! // Add support for if expressions. // The cond.scm file gives you some good examples. + this.writeBytecode(second); + + // get the offset program counter to change it later + this.writeOp('PUSH1'); + const counterOffset = this.offset; + this.writeByte(0x00); + this.writeOp('JUMPI'); + + // else + this.writeBytecode(rest[1]); + // change this to after the then + this.writeOp('PUSH1'); + const elseOffset = this.offset; + this.writeByte(0x00); + this.writeOp('JUMP'); + + // then + const thenOffset = this.offset; + this.writeOp('JUMPDEST'); + this.writeBytecode(rest[0]); + const endOffset = this.offset; + this.writeOp('JUMPDEST'); + + // update the offsets + this.bytecode[counterOffset] = thenOffset; + this.bytecode[elseOffset] = endOffset; break; case "+": diff --git a/lab17/cond.scm b/lab17/cond.scm index 6063809..5503844 100644 --- a/lab17/cond.scm +++ b/lab17/cond.scm @@ -2,3 +2,15 @@ (if #t (println 3) (println 4)) (if #f (println 3) (println 4)) +; PUSH1 1 +; PUSH1 offset_to_then +; JUMPI +; +; #else +; PUSH1 offset_to_end +; JUMP +; +; JUMPDEST @offset_to_then +; #then +; +; JUMPDEST @offset_to_end diff --git a/lab17/op-codes.js b/lab17/op-codes.js index ea24746..8f5250a 100644 --- a/lab17/op-codes.js +++ b/lab17/op-codes.js @@ -27,6 +27,17 @@ let opcodes = { let value = vm.stack.pop(); vm.memory[offset] = value; }}, + 0x56: { mnemonic: 'JUMP', evaluate: (vm) => { + let offset = vm.stack.pop(); + vm.pc = offset; + }}, + 0x57: { mnemonic: 'JUMPI', evaluate: (vm) => { + let offset = vm.stack.pop(); + let condition = vm.stack.pop(); + if (condition) { + vm.pc = offset; + } + }}, 0x5B: { mnemonic: 'JUMPDEST', evaluate: (vm) => { // Does nothing. We could check to make sure that jumps // always land at JUMPDEST opcodes, but it is not totally