Brainfuck
HTML
<div id="controls">
<textarea id="source">+++++++++++++++++++</textarea>
</div>
<canvas id="view"></canvas>
CSS
#controls {
position: absolute;
left:0;
top:0;
right:0;
z-index: 3;
}
#controls textarea {
width: 90%;
margin-left: 30px;
}
#view {
background: #fff;
}
body, html {
background: #444;
width: 100%;
height: 100%;
margin: 0px;
}
JavaScript
var view = document.getElementById("view");
var context = view.getContext("2d");
var slider = document.getElementById("slider");
var area = {
top: 0,
left: 0,
right: 640,
bottom: 480
};
function hsla(step) {
return 'hsla(' + ((step * 30) | 0) + ',70%,70%,1)';
}
function Brainfuck() {
this.ip = 0;
this.source = "";
this.jmp = [];
this.jmpz = [];
this.ptr = 0;
this.memory = new Uint8Array(256);
this.output = "";
this.time = 0;
}
function sanitize(code){
return code.replace(/[^<>+-\[\],\.]/g, "");
}
Brainfuck.prototype = {
compile: function (source) {
this.time = 0;
this.finished = false;
this.jmp = [];
this.jmpz = [];
this.source = sanitize(source);
var jmps = [];
for (var ip = 0; ip < this.source.length; ip += 1) {
switch (this.source[ip]) {
case "[":
jmps.push(ip);
this.jmp[ip] = ip + 1;
break;
case "]":
var ret = jmps.pop();
this.jmp[ip] = ret;
this.jmpz[ret] = ip + 1;
break;
default:
this.jmp[ip] = ip + 1;
}
}
if (jmps.length !== 0) {
throw "Unmatched loop.";
}
},
step: function () {
this.time += 1;
if (this.ip >= this.source.length) {
this.finished = true;
return;
}
switch (this.source[this.ip]) {
case ">":
this.ptr = (this.ptr + 1) % 256;
break;
case "<":
this.ptr = (this.ptr - 1 + 256) % 256;
break;
case "+":
this.memory[this.ptr] += 1;
break;
case "-":
this.memory[this.ptr] -= 1;
break;
case "]":
this.ip =...