Skip to content

Instantly share code, notes, and snippets.

@myfreeer
Last active July 17, 2018 09:14
Show Gist options
  • Save myfreeer/0fc5834e131e0a4e06b4b949108291c8 to your computer and use it in GitHub Desktop.
Save myfreeer/0fc5834e131e0a4e06b4b949108291c8 to your computer and use it in GitHub Desktop.
Brainfuck interpreter in js
const brainFuckInput = () => {
const input = prompt('输入一个字符或不输入。\n若输入多个字符,只有输入的第一个字符有效。');
if (input) return input.codePointAt();
else return 0;
};
const brainFuckOutput = (value) => {
console.info(String.fromCodePoint(value));
};
const brainFuck = (code, i=brainFuckInput, o=brainFuckOutput, block=512) => {
let buffer = new Uint8Array(block);
let cursor = 0;
const callStack = [];
for (let index = 0; index < code.length; index++)
switch(code[index]) {
case '>': {
if (++cursor >= buffer.length) {
const newBuffer = new Uint8Array(buffer.length + block);
newBuffer.set(buffer);
buffer = newBuffer;
}
break;
}
case '<': --cursor; break;
case '+': ++buffer[cursor]; break;
case '-': --buffer[cursor]; break;
case '.': o(buffer[cursor]); break;
case ',': buffer[cursor] = i(); break;
case '[': callStack.unshift(index); break;
case ']': {
if (buffer[cursor])
index = callStack[0];
else
callStack.shift();
break;
}
}
};
/**
* BrainFuck DOM Input
* @param {HTMLInputElement} element target input element
*/
const brainFuckDOMInput = (element = document.querySelector('input')) => () => {
return new Promise(r => {
element.onkeydown = ({key, ctrlKey}) => {
if (ctrlKey && key.toLowerCase() == 'c')
return r(0);
if (key === 'Enter')
return r(10);
if (key.length === 1)
return key.codePointAt();
};
});
};
/**
* BrainFuck DOM Output
* @param {Element} element output element
*/
const brainFuckDOMOutput = (element = document.body.lastElementChild) => (value) => {
if (value <= 0) return;
value = String.fromCodePoint(value);
if (element instanceof HTMLInputElement)
element.value += value;
else
element.innerText += value;
};
/**
* Async Brainfuck interpreter
* @param code target BrainFuck code
* @param i async BrainFuck input handler
* @param o BrainFuck output handler
*/
const brainFuckAsync = async(code, i=brainFuckDOMInput(), o=brainFuckDOMOutput(), block=512) => {
let buffer = new Uint8Array(block);
let cursor = 0;
const callStack = [];
for (let index = 0; index < code.length; index++)
switch(code[index]) {
case '>': {
if (++cursor >= buffer.length) {
const newBuffer = new Uint8Array(buffer.length + block);
newBuffer.set(buffer);
buffer = newBuffer;
}
break;
}
case '<': --cursor; break;
case '+': ++buffer[cursor]; break;
case '-': --buffer[cursor]; break;
case '.': o(buffer[cursor]); break;
case ',': buffer[cursor] = await i(); break;
case '[': callStack.unshift(index); break;
case ']': {
if (buffer[cursor])
index = callStack[0];
else
callStack.shift();
break;
}
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment