Mercurial > urweb
diff lib/js/urweb.js @ 970:8371d12ae63f
Hopefully complete refactoring of Jscomp to output ASTs; partial implementation of interpreter in runtime system (demo/alert works)
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Tue, 22 Sep 2009 12:23:21 -0400 |
parents | 001edfbe2561 |
children | c22e524a6dd3 |
line wrap: on
line diff
--- a/lib/js/urweb.js Tue Sep 22 09:53:05 2009 -0400 +++ b/lib/js/urweb.js Tue Sep 22 12:23:21 2009 -0400 @@ -1,3 +1,17 @@ +// Function versions of operators + +function not(x) { return !x; } +function neg(x) { return -x; } + +function eq(x, y) { return x == y; } +function plus(x, y) { return x + y; } +function minus(x, y) { return x - y; } +function times(x, y) { return x * y; } +function div(x, y) { return x / y; } +function mod(x, y) { return x % y; } +function lt(x, y) { return x < y; } +function le(x, y) { return x <= y; } + // Lists function cons(v, ls) { @@ -765,8 +779,176 @@ // Key events -function kc(e) { - return window.event ? e.keyCode : e.which; +var uw_event = null; + +function kc() { + return window.event ? uw_event.keyCode : uw_event.which; +} + + +// The Ur interpreter + +var urfuncs = []; + +function lookup(env, n) { + while (env != null) { + if (n == 0) + return env.data; + else { + --n; + env = env.next; + } + } + + throw "Out-of-bounds Ur variable reference"; +} + +function exec0(env, e) { + var stack = null; + + while (true) { + switch (e.c) { + case "c": + var v = e.v; + if (stack == null) + return v; + var fr = stack.data; + + switch (fr.c) { + case "s": + e = {c: "c", v: {v: v}}; + stack = stack.next; + break; + case "1": + e = {c: "c", v: {n: fr.n, v: v}}; + stack = stack.next; + break; + case "f": + fr.args[fr.pos++] = v; + if (fr.a == null) { + e = {c: "c", v: fr.f.apply(null, fr.args)}; + stack = stack.next; + } else { + e = fr.a.data; + fr.a = fr.a.next; + } + break; + case "a1": + if (v == null || !v.body) + throw "Ur: applying non-function"; + stack = cons({c: "a2", env: v.env, body: v.body}, stack.next); + e = fr.x; + break; + case "a2": + stack = cons({c: "a3", env: env}, stack.next); + env = cons(v, fr.env); + e = fr.body; + break; + case "a3": + env = fr.env; + stack = stack.next; + break; + case "r": + fr.fs["_" + fr.n] = v; + if (fr.l == null) { + e = {c: "c", v: fr.fs}; + stack = stack.next; + } else { + fr.n = fr.l.data.n; + e = fr.l.data.v; + fr.l = fr.l.next; + } + break; + case ".": + e = {c: "c", v: v["_" + fr.f]}; + stack = stack.next; + break; + case ";": + e = fr.e2; + stack = stack.next; + break; + case "=1": + env = cons(v, env); + e = fr.e2; + stack = stack.next; + break; + case "=": + env = cons(v, env); + e = fr.e2; + stack = cons({c: "a3", env: env}, stack.next); + break; + default: + throw "Unknown Ur continuation kind"; + } + + break; + case "v": + e = {c: "c", v: lookup(env, e.n)}; + break; + case "n": + e = {c: "c", v: urfuncs[e.n]}; + break; + case "s": + stack = cons({c: "s"}, stack); + e = e.v; + break; + case "1": + stack = cons({c: "1", n: e.n}, stack); + e = e.v; + break; + case "f": + if (e.a == null) + e = {c: "c", v: e.f()}; + else { + var args = []; + stack = cons({c: "f", f: e.f, args: args, pos: 0, a: e.a.next}, stack); + e = e.a.data; + } + break; + case "l": + e = {c: "c", v: {env: env, body: e.b}}; + break; + case "a": + stack = cons({c: "a1", x: e.x}, stack); + e = e.f; + break; + case "r": + if (e.l == null) + throw "Empty Ur record in interpretation"; + var fs = {}; + stack = cons({c: "r", n: e.l.data.n, fs: fs, l: e.l.next}, stack); + e = e.l.data; + break; + case ".": + stack = cons({c: ".", f: e.f}, stack); + e = e.r; + break; + case ";": + stack = cons({c: ";", e2: e.e2}, stack); + e = e.e1; + break; + case "=": + stack = cons({c: "=", e2: e.e2}, stack); + e = e.e1; + break; + case "e": + var env0 = env; + var e0 = e.e; + e = {c: "c", v: cs(function() { return exec0(env0, e0); })}; + break; + default: + throw "Unknown Ur expression kind"; + } + } +} + +function exec(e) { + var r = exec0(null, e); + + if (r != null && r.body) + return function(v) { return exec0(cons(v, r.env), r.body); }; + else + return r; }