brainf-interpreter/index.ts

93 lines
2.7 KiB
TypeScript

const memory = Array<number>(3_000).fill(0);
let CI = 0 // Current Instruction
let MA = 0 // Memory Address
let stack: number[] = [];
let inp = "";
let out = "";
function interpret(program: string) {
let fin = false;
while (!fin) {
console.log(CI, program.at(CI))
switch (program.at(CI)) {
case '>':
// Move MA to right
if (MA == memory.length - 1)
// Expand memory if run out of space
memory.push(...Array<number>(10).fill(0))
MA++
break;
case '>':
// Move MA to left
if (MA > 0) MA--
break;
case '+':
// Increment memory location at MA
memory[MA]++
break;
case '-':
// Decrease memory location at MA
memory[MA]--
break;
case '.':
// Output character with value stored at MA
out += String.fromCharCode(memory[MA]);
break;
case ',':
// Read input character and store at at cell at MA
break;
case '[':
// Jump past the next ]
if (memory[MA]) { // If current memory value isn't non-zero, push the current instruction to the stack
stack.push(CI)
} else {
let c = 0; // Count variable, allows to find the matching bracket
while (1) {
CI++
if (!program[CI]) break; // If this is the end of the program, break
if (program[CI] == "[") c++ // If the current instruction is a [, increase the matching count
else if (program[CI] == "]") { // If this is a ]
if (c) c-- // If c is 0, this is a matching bracket, otherwise decrease count to help find it
else break // We are now at the matching ], finish
}
}
}
break;
case ']':
// Jump to the matching [ if non-zero
// Set CI to last instruction value in stack
CI = stack.pop()! - 1;
break;
case undefined:
// End of program
fin = true;
break;
default:
break;
}
CI++
}
console.log(out, memory.filter(x=>x))
}
const argv = Bun.argv.slice(2);
if (argv.length) {
const file = Bun.file(argv[0]);
file.text().then(interpret);
}