Last active
July 17, 2018 09:14
-
-
Save myfreeer/0fc5834e131e0a4e06b4b949108291c8 to your computer and use it in GitHub Desktop.
Brainfuck interpreter in js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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