123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- const prompt = require("prompt-sync")({ sigint: true });
- const Stack = require("./Stack");
- const ComputerParameterMode = require("./ComputerParameterMode");
- const { DeepClone } = require("./common");
- module.exports = class Computer {
- constructor(stack) {
- this._initialMemory = DeepClone(stack);
- this.stack = new Stack(stack);
- this.OPCODES = {
- ADD: 1,
- MULTIPLY: 2,
- INPUT: 3,
- OUTPUT: 4,
- HALT: 99,
- };
- this.parameterMode = ComputerParameterMode.POSITION_MODE;
- }
-
- Run() {
-
- while (this.Execute(this.stack.Get(ComputerParameterMode.IMMEDIATE_MODE)) === true) { }
- }
-
- Execute(rawOpcode) {
- let status = true;
- const opcode = rawOpcode % 100;
-
- switch (opcode) {
- case this.OPCODES.ADD: {
- this.Operation_Add(rawOpcode);
- break;
- }
- case this.OPCODES.MULTIPLY: {
- this.Operation_Multiply(rawOpcode);
- break;
- }
- case this.OPCODES.INPUT: {
- this.Operation_Input();
- break;
- }
- case this.OPCODES.OUTPUT: {
- this.Operation_Output();
- break;
- }
- case this.OPCODES.HALT:
- status = false;
- break;
- default:
- throw Error(`Opcode ${opcode} not found\nMemdump: ${JSON.stringify(this.stack.Dump())}`);
- }
- this.stack.Next();
- return status;
- }
-
- _ParseOperands(...operands) {
- if (this.parameterMode == ComputerParameterMode.IMMEDIATE_MODE) { return operands; }
- return operands.map((operand) => this.stack.Get(operand));
- }
-
- Operation_Add(rawOpcode) {
- const operandLeftMode = ComputerParameterMode.ParseParameterMode(rawOpcode, 1);
- const operandRightMode = ComputerParameterMode.ParseParameterMode(rawOpcode, 2);
- const operandLeft = this.stack.Next().Get(operandLeftMode);
- const operandRight = this.stack.Next().Get(operandRightMode);
- const outputPosition = this.stack.Next().Get(ComputerParameterMode.IMMEDIATE_MODE);
- const newValue = operandLeft + operandRight;
- this.stack.Put(outputPosition, newValue);
- }
-
- Operation_Multiply(rawOpcode) {
- const operandLeftMode = ComputerParameterMode.ParseParameterMode(rawOpcode, 1);
- const operandRightMode = ComputerParameterMode.ParseParameterMode(rawOpcode, 2);
- const operandLeft = this.stack.Next().Get(operandLeftMode);
- const operandRight = this.stack.Next().Get(operandRightMode);
- const outputPosition = this.stack.Next().Get(ComputerParameterMode.IMMEDIATE_MODE);
- const newValue = operandLeft * operandRight;
- this.stack.Put(outputPosition, newValue);
- }
-
- Operation_Input() {
- const outputPosition = this.stack.Next().Get(ComputerParameterMode.IMMEDIATE_MODE);
- let userInput;
- do {
- userInput = Number(prompt("Please enter a number: "));
- } while (Number.isNaN(userInput));
- this.stack.Put(outputPosition, userInput);
- }
-
- Operation_Output() {
- const currAddress = this.stack.pointer;
- const outputPosition = this.stack.Next().Get(ComputerParameterMode.IMMEDIATE_MODE);
- console.log(`OUTPUT FROM ADDRESS ${currAddress}: ${this.stack.GetAtIndex(outputPosition, ComputerParameterMode.IMMEDIATE_MODE)}`);
- }
-
- DumpMemory() {
- console.log(this.stack.Dump());
- }
-
- Reset() {
- this.stack = new Stack(this._initialMemory);
- }
-
- SetMemory(stack) {
- this._initialMemory = DeepClone(stack);
- this.stack = new Stack(stack);
- }
- };
|