-
Notifications
You must be signed in to change notification settings - Fork 0
/
compiled.js
131 lines (118 loc) · 3.63 KB
/
compiled.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
var drawingfn = null;
var time = 0;
var dictionary = {
// Math
"+": "s.push(s.pop() + s.pop());",
"*": "s.push(s.pop() * s.pop());",
"mod": "var v = s.pop(); s.push(s.pop() % v);",
"sin": "s.push(Math.sin(s.pop()));",
"cos": "s.push(Math.cos(s.pop()));",
"tan": "s.push(Math.tan(s.pop()));",
"xor": "s.push(s.pop() ^ s.pop());",
// Stack shuffling
"dup": "var v = s.pop(); s.push(v); s.push(v);",
"drop": "s.pop();",
"swap": "var v = s.pop(), w = s.pop(); s.push(v); s.push(w);",
"rot": "var v = s.pop(), w = s.pop(), x =s.pop(); s.push(w,v,x);",
"?": "var f = s.pop(), t = s.pop(), test=s.pop(); s.push(test ? t : f);",
"call": "s.pop()();",
"dip": "var v = s.pop(), w = s.pop(); s.push(v); s.pop()(); s.push(w);",
// debug
"dbg": "console.log(s.pop());"
};
var specials = {
":": function(dict, tokens, idx) {
var end = matchingIndex(":", ";", tokens, idx);
dict[tokens[idx+1]] = compile(dict, tokens.slice(idx+2,end));
return ["", end];
},
"[": function(dict, tokens, idx) {
var end = matchingIndex("[", "]", tokens, idx);
return [makeFun(dict, tokens.slice(idx+1,end)), end];
},
"(": function(dict, tokens, idx) {
var end = matchingIndex("(", ")", tokens, idx);
return ["", end];
},
"'": function(_, tokens, idx) { return ["s.push('" + tokens[idx+1] + "');", idx+1]; }
};
function matchingIndex(left, right, tokens, startIdx) {
var i = startIdx + 1, balance = 1;
while(balance > 0 && i < tokens.length) { // todo: forloopify
if(tokens[i] == left) balance++;
else if(tokens[i] == right) balance--;
i++;
}
return --i;
}
function makeFun(dict, tokens) {
return "s.push(function(){" + compile(dict, tokens) + "});";
}
function parseNum(token) {
return "s.push(" + token + ");";
}
function compile(dict, tokens) {
var str = "";
for(var i = 0; i < tokens.length; i++) {
var token = tokens[i];
if(specials[token]) {
ret = specials[token](dict, tokens, i);
str += ret[0];
i = ret[1];
} else {
str += dict[token] || parseNum(token);
}
}
return str;
}
function i(stack, dict, str){
var js = compile(dict, str.trim().split(/\s+/g));
console.log(js);
return new Function("s", js)(stack);
}
//Drawing
function draw() {
if(!drawingfn) return;
var img = ctx.createImageData(canvas.width, canvas.height);
time += 5 //= Date.now();//%512;
var s = [];
for(var y = 0; y < img.height; y++) {
for(var x = 0; x < img.width; x++) {
var index = (x + y * img.width) * 4;
s.push(time, y, x);
//var s = [time, y, x];
drawingfn(s);
var b = s.pop(), g = s.pop(), r = s.pop();
img.data[index + 0] = r; // r
img.data[index + 1] = g; // g
img.data[index + 2] = b; // b
img.data[index + 3] = 255; // a
}
}
ctx.putImageData(img, 0, 0);
}
// TODO: real dip, better solution ot swapping out draw?
function init() {
dict = Object.create(dictionary);
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
code = document.getElementById("code");
output = document.getElementById("output");
// Shift + Enter to eval and draw
window.addEventListener("keydown", function(e) {
if(e.shiftKey && e.which == 13 && code.value) {
var stack = [];
dict = Object.create(dictionary);
i(stack, dict, code.value);
drawingfn = dict.draw ? new Function("s", dict.draw) : null;
console.log(stack, dict);
draw();
output.innerHTML = "" + stack;
e.preventDefault(); // stop Enters newline
return false;
}
return true;
});
setInterval(draw, 50);
}
window.onload = init;