Repository navigation
Expand file tree
/
Copy pathwdrpapercomputer.js
More file actions
143 lines (138 loc) · 4.26 KB
/
Copy pathwdrpapercomputer.js
File metadata and controls
143 lines (138 loc) · 4.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// WDR Paper Computer Emulator
// Instruction descriptor
// Default Instructions
const STP = 0;
const ISZ = 1;
const JMP = 2;
const INC = 3;
const DEC = 4;
// Additional Instructions
const INP = 5;
const DAT = 6;
class Instruction {
constructor(type, value = null, operand = null) {
this.type = type;
this.value = value;
this.operand = operand;
}
}
class Program {
constructor(code, registers = 32) {
// Create Counter
this.counter = 0;
this.cycles = 0;
// Initialize Code String
this.code = "";
// Initialize Flags
this.running = true;
// Initialize Registers
this.registers = Array(registers);
// Reset to Default
this.reset();
// Compile code
this.instructions = [];
// Loop through lines
var lines = code.split("\n");
for (var line in lines) {
try {
this.compile(lines[line]);
}
catch (error) {
throw "Error on Line " + line + ": " + error;
}
}
}
reset() { this.running = true; this.counter = 0; this.cycles = 0; this.registers.fill(0); }
instruction() { return (this.counter < this.instructions.length) ? this.instructions[this.counter] : Instruction(STP); }
compile(line) {
// Separate out comments and split by spaces and make non case sensitive
var token = line.toLowerCase().split("#")[0].split(" ");
// Get Instruction
var instruction = token[0];
var value = parseInt(token[1]);
var operand = parseInt(token[2]);
// Skip if empty
if (instruction == "") return;
// Encode instruction
switch (instruction) {
case "stp":
this.instructions.push(new Instruction(STP));
this.code += "stp\n";
break;
case "isz":
if (isNaN(value)) throw "Expected Number as Register Operand";
this.instructions.push(new Instruction(ISZ, value));
this.code += "isz "+value+"\n";
break;
case "jmp":
if (isNaN(value)) throw "Expected Number as Address Operand";
this.instructions.push(new Instruction(JMP, value));
this.code += "jmp "+value+"\n";
break;
case "inc":
if (isNaN(value)) throw "Expected Number as Register Operand";
this.instructions.push(new Instruction(INC, value));
this.code += "inc "+value+"\n";
break;
case "dec":
if (isNaN(value)) throw "Expected Number as Register Operand";
this.instructions.push(new Instruction(DEC, value));
this.code += "dec "+value+"\n";
break;
// Additional Intructions
case "inp":
if (isNaN(value)) throw "Expected Number as Register Operand";
this.instructions.push(new Instruction(INP, value));
this.code += "inp "+value+"\n";
break;
case "dat":
if (isNaN(value)) throw "Expected Number as Register Operand";
if (isNaN(operand)) throw "Expected Number as Value Operand";
this.instructions.push(new Instruction(DAT, value, operand));
this.code += "dat "+value+" "+operand+"\n";
break;
default:
throw "Unknown Instruction: " + "\"" + token[0] + "\"";
}
}
clock() {
// Skip if not running
if (!this.running) return;
// Process instruction
this.cycles ++;
switch (this.instruction().type) {
case STP:
this.running = false;
break;
case ISZ:
if (this.registers[this.instruction().value-1] == 0)
this.counter += 2;
else
this.counter ++;
break;
case JMP:
this.counter = this.instruction().value-1;
break;
case INC:
this.registers[this.instruction().value-1] ++;
this.counter ++;
break;
case DEC:
this.registers[this.instruction().value-1] --;
this.counter ++;
break;
// Additional Instuctions
case INP:
this.registers[this.instruction().value-1] = parseInt(window.prompt("Program Input"));
while (isNaN(this.registers[this.instruction().value])) {
this.registers[this.instruction().value-1] = parseInt(window.prompt("Program Input (Must be a Number)"));
}
this.counter ++;
break;
case DAT:
this.registers[this.instruction().value-1] = this.instruction().operand;
this.counter ++;
break;
}
}
}