Skip to content

Instantly share code, notes, and snippets.

@kissarat
Last active October 28, 2021 06:54
Show Gist options
  • Save kissarat/fd68c72aa9009226d015c1c876d96e3c to your computer and use it in GitHub Desktop.
Save kissarat/fd68c72aa9009226d015c1c876d96e3c to your computer and use it in GitHub Desktop.
const Op = {
Left: '<',
Right: '>',
Inc: '+',
Dec: '-',
Output: '.',
Input: ',',
Start: '[',
End: ']'
}
const Abc = Object.values(Op)
const Numbers = '0123456789'.split('')
// const maxTime = 40 * 100
const maxTime = 20 * 1024 * 1024
class Brainfuck {
constructor({
pointer = 0,
memory = new Int32Array(512 * 1024),
} = {}) {
this.pointer = pointer
this.memory = memory
this.time = 0
}
clone() {
return new BrainfuckMachine(this)
}
static *scan(str) {
let repeat = 1
let number = []
for (const code of str) {
if (Numbers.includes(code)) {
number.push(code)
continue
} else if (number.length > 0) {
repeat = +number.join('')
number = []
}
if (Abc.includes(code)) {
for (let i = 0; i < repeat; i++) {
yield code
}
repeat = 1
}
}
}
*read(program = []) {
let position = 0
let stack = 0
for (;
position < program.length;
position++, this.time++) {
if (this.time > maxTime) {
break
}
const code = program[position]
// console.log(position, code, this.memory[this.pointer])
switch (code) {
case Op.Left:
this.pointer--;
break;
case Op.Right: {
this.pointer++;
if (this.pointer >= this.memory.length) {
this.memory[this.pointer] = 0
}
break;
}
case Op.Inc:
this.memory[this.pointer]++
break;
case Op.Dec:
this.memory[this.pointer]--
break;
case Op.Output:
yield this.memory[this.pointer]
break;
case Op.Input:
this.memory[this.pointer] = yield
break;
case Op.Start: {
if (!this.memory[this.pointer]) {
stack++
while (stack > 0) {
position++
if (program[position] === Op.Start) {
stack++
} else if (program[position] === Op.End) {
stack--
}
}
} else {
continue
}
break
}
case Op.End: {
if (!this.memory[this.pointer]) {
continue
} else {
if(program[position] === Op.End) {
stack++
}
while(stack > 0) {
position--
if (program[position] === Op.Start) {
stack--
} else if (program[position] === Op.End) {
stack++
}
}
}
break
}
default:
throw new Error(`Unknown operation ${code}`)
}
}
}
run(program = []) {
return Array.from(this.read(program))
}
}
const program = Array.from(Brainfuck.scan(`
+[.6+[4-.]]
`))
console.log(program)
const bf = new Brainfuck()
bf.run(program)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment