65 lines
2.1 KiB
TypeScript
65 lines
2.1 KiB
TypeScript
import { opCodeToName, operandToName, readData, VM } from "./solve_1.ts";
|
|
|
|
class VMCompiler extends VM {
|
|
compileSingleInstruction(pc: number): string {
|
|
const opCode = this.programs[pc];
|
|
const operand = this.programs[pc + 1];
|
|
switch (opCode) {
|
|
case 0:
|
|
return `label${this.pc}: A = (A >> ${operandToName(operand)});`;
|
|
case 1:
|
|
return `label${this.pc}: B = B ^ ${operand};`;
|
|
case 2:
|
|
return `label${this.pc}: B = ${operandToName(operand)} % 8;`;
|
|
case 3:
|
|
return `label${this.pc}: if (A !== 0) goto label${operand};`;
|
|
case 4:
|
|
return `label${this.pc}: B = B ^ C;`;
|
|
case 5:
|
|
return `label${this.pc}: out(${operandToName(operand)} % 8);`;
|
|
case 6:
|
|
return `label${this.pc}: B = (A >> ${operandToName(operand)});`;
|
|
case 7:
|
|
return `label${this.pc}: C = (A >> ${operandToName(operand)});`;
|
|
default:
|
|
throw new Error(`Unknown opCode: ${opCode}`);
|
|
}
|
|
}
|
|
compile(): string {
|
|
let code = "";
|
|
let pc = 0;
|
|
while (pc < this.programs.length) {
|
|
code += this.compileSingleInstruction(pc) + "\n";
|
|
pc += 2;
|
|
}
|
|
return code;
|
|
}
|
|
}
|
|
|
|
if (import.meta.main) {
|
|
const data = await readData("example_3.txt");
|
|
console.log(data.registers);
|
|
data.registers.A = 0b11100101011000000;
|
|
console.log(data.programs.join(","));
|
|
const vm = new VMCompiler(data);
|
|
const text = vm.compile();
|
|
console.log(text);
|
|
const out: number[] = [];
|
|
console.log(out.join(","));
|
|
// vm.registers.A = 3;
|
|
vm.pc = 0;
|
|
const outputs: number[] = [];
|
|
vm.on("out", (value) => {
|
|
outputs.push(value);
|
|
});
|
|
// print code and registers
|
|
while (vm.pc < vm.programs.length) {
|
|
const code = vm.compileSingleInstruction(vm.pc);
|
|
vm.runSingleInstruction();
|
|
console.log(code, vm.registers, vm.registers.C & 7);
|
|
}
|
|
console.log(outputs.join(","));
|
|
}
|
|
|
|
|