|
@@ -18,10 +18,22 @@ module.exports = class Computer {
|
|
|
MULTIPLY: 2,
|
|
|
INPUT: 3,
|
|
|
OUTPUT: 4,
|
|
|
+ JUMP_IF_TRUE: 5,
|
|
|
+ JUMP_IF_FALSE: 6,
|
|
|
+ LESS_THAN: 7,
|
|
|
+ EQUALS: 8,
|
|
|
HALT: 99,
|
|
|
};
|
|
|
|
|
|
this.parameterMode = ComputerParameterMode.POSITION_MODE;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Whether the Execute loop should skip moving the pointer after running the opcode
|
|
|
+ *
|
|
|
+ * Some opcodes, such as JUMP_IF_TRUE set the stack pointer, and as such shouldn't have
|
|
|
+ * the Execute function move it after the opcode finishes executing.
|
|
|
+ */
|
|
|
+ this.skipNext = false;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -44,6 +56,7 @@ module.exports = class Computer {
|
|
|
*/
|
|
|
Execute(rawOpcode) {
|
|
|
let status = true;
|
|
|
+ this.skipNext = false;
|
|
|
|
|
|
const opcode = rawOpcode % 100;
|
|
|
|
|
@@ -65,14 +78,24 @@ module.exports = class Computer {
|
|
|
this.Operation_Output();
|
|
|
break;
|
|
|
}
|
|
|
+ case this.OPCODES.JUMP_IF_TRUE: {
|
|
|
+ this.Operation_JumpIf(rawOpcode, true);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case this.OPCODES.JUMP_IF_FALSE: {
|
|
|
+ this.Operation_JumpIf(rawOpcode, false);
|
|
|
+ break;
|
|
|
+ }
|
|
|
case this.OPCODES.HALT:
|
|
|
status = false;
|
|
|
break;
|
|
|
default:
|
|
|
- throw Error(`Opcode ${opcode} not found\nMemdump: ${JSON.stringify(this.stack.Dump())}`);
|
|
|
+ throw Error(`Opcode ${opcode} not found\nMemdump: ${JSON.stringify(this.stack.Dump())}\nPointer: ${this.stack.pointer}`);
|
|
|
}
|
|
|
|
|
|
- this.stack.Next();
|
|
|
+ if (!this.skipNext) {
|
|
|
+ this.stack.Next();
|
|
|
+ }
|
|
|
|
|
|
return status;
|
|
|
}
|
|
@@ -167,6 +190,31 @@ module.exports = class Computer {
|
|
|
console.log(`OUTPUT FROM ADDRESS ${currAddress}: ${this.stack.GetAtIndex(outputPosition, ComputerParameterMode.IMMEDIATE_MODE)}`);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Execute the Jump_If_True and Jump_If_False opcodes
|
|
|
+ *
|
|
|
+ * Jumps to a given address in memory if the value at next address is memory matches
|
|
|
+ * the given true/false condition.
|
|
|
+ *
|
|
|
+ * @param {number} rawOpcode The opcode in memory used to make this call
|
|
|
+ * @param {boolean} testCondition The value the memory value should be compared against
|
|
|
+ * @returns {void}
|
|
|
+ */
|
|
|
+ Operation_JumpIf(rawOpcode, testCondition) {
|
|
|
+ const paramMode = ComputerParameterMode.ParseParameterMode(rawOpcode, 1);
|
|
|
+ const jumpAddressMode = ComputerParameterMode.ParseParameterMode(rawOpcode, 2);
|
|
|
+
|
|
|
+ const param = this.stack.Next().Get(paramMode);
|
|
|
+ const jumpAddress = this.stack.Next().Get(jumpAddressMode);
|
|
|
+
|
|
|
+ const performJump = !!param == testCondition;
|
|
|
+
|
|
|
+ if (performJump) {
|
|
|
+ this.skipNext = true;
|
|
|
+ this.stack.SetPointerAddress(jumpAddress);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Outputs the computer's stack to the console
|
|
|
* @returns {void}
|