⚠️ Warning: This is a draft ⚠️
This means it might contain formatting issues, incorrect code, conceptual problems, or other severe issues.
If you want to help to improve and eventually enable this page, please fork RosettaGit's repository and open a merge request on GitHub.
{{implementation|Brainfuck}}{{collection|RCBF}} Presented here is the core of a Brainfuck interpreter/debugger written in [[JavaScript]] that is designed to run within a web page. The full source can be found at http://www.quirkster.com/iano/js/bf.html by viewing the page source.
var code; // formatted code
var ip = 0; // current instruction within code
var nest = 0; // current bracket nesting (for Out button)
var ahead = []; // locations of matching brackets
var data = [0]; // data array (mod by +, -)
var dp = 0; // index into data (mod by <, >)
var inp = 0; // current input character (fetch with ,)
var quit = 0; // termination flag
var commands = {
'>':function() { if (++dp >= data.length) data[dp]=0 },
'<':function() { if (--dp < 0) quit++ },
'+':function() { ++data[dp] },
'-':function() { --data[dp] },
'[':function() { if (!data[dp]) ip = ahead[ip]; else ++nest },
']':function() { if ( data[dp]) ip = ahead[ip]; else --nest },
',':function() {
var c = document.getElementById("input").value.charCodeAt(inp++);
data[dp] = isNaN(c) ? 0 : c; // EOF: other options are -1 or no change
},
'.':function() {
var s = document.getElementById("output").innerHTML
+ String.fromCharCode(data[dp]);
s = s.replace(/\n/g,"
").replace(/ /g,"&nbsp;");
document.getElementById("output").innerHTML = s;
},
};
function format(id) {
var el = document.getElementById(id);
code = el.value || el.textContent || el.innerText;
// scan for matching braces
var st = [], back, error = -1;
ahead = [];
for (ip=0; ip<code.length; ip++) {
switch(code[ip]) {
case '[':
st.push(ip);
break;
case ']':
if (st.length == 0) error = ip;
back = st.pop();
ahead[ip] = back;
ahead[back] = ip;
break;
}
}
if (st.length > 0) error = st[0];
init();
if (error >= 0) {
ip = error; // highlight error
alert("Unmatched '"+code[error]+"' at "+error+"!");
}
// show the code in a PRE block (id=code)
dump();
window.scroll(0,document.getElementById("code").offsetTop);
}
function encode(s) {
var e = s.replace(/&/g, "&amp;");
e = e.replace(/</g, "&lt;");
e = e.replace(/>/g, "&gt;");
e = e.replace(/ /g, "&nbsp;");
return e.replace(/\n/g, "
");
}
function dump() {
document.getElementById("code").innerHTML
= encode(code.substring(0,ip))
+ '<span style="background: pink">'
+ encode(code.charAt(ip))
+ "</span>"
+ encode(code.substring(ip+1));
document.getElementById("mem").value = data.join();
}
function init() {
inp = 0; quit = 0; dp = 0;
data = [0]; ip = 0;
document.getElementById("output").innerHTML = "";
}
function done() {
return quit || ip >= code.length;
}
function body() {
var fn;
do {
fn = commands[code.charAt(ip)];
if (fn) fn();
++ip;
} while (fn == null && !done());
}
// button handlers
var tid = 0;
function step() {
var n = document.getElementById("repeat").value - 0;
if (done()) init();
while (--n>=0 && !done())
body();
if (done() && tid) slow(); // stop timer
dump();
}
function out() {
var d = nest;
while (nest>=d && !done())
body();
dump();
}
function slow() {
if (tid) {
clearInterval(tid);
tid = 0;
document.getElementById("slow").value = "Slow";
} else {
var n = document.getElementById("speed").value - 0;
tid = setInterval(step, Math.max(n,10));
document.getElementById("slow").value = "Stop";
}
}
function run() {
while (!done())
body();
dump();
}