aboutsummaryrefslogtreecommitdiff
path: root/js/step3_env.js
diff options
context:
space:
mode:
authorJoel Martin <github@martintribe.org>2014-03-24 16:32:24 -0500
committerJoel Martin <github@martintribe.org>2014-03-24 16:32:24 -0500
commit3169070063b2cb877200117ebb384269d73bcb93 (patch)
tree23de3db1ea5c37afd21a45b6ed7771f56a08c0c4 /js/step3_env.js
downloadmal-3169070063b2cb877200117ebb384269d73bcb93.tar.gz
mal-3169070063b2cb877200117ebb384269d73bcb93.zip
Current state of mal for Clojure West lighting talk.
Diffstat (limited to 'js/step3_env.js')
-rw-r--r--js/step3_env.js97
1 files changed, 97 insertions, 0 deletions
diff --git a/js/step3_env.js b/js/step3_env.js
new file mode 100644
index 0000000..5b6e802
--- /dev/null
+++ b/js/step3_env.js
@@ -0,0 +1,97 @@
+var types = require('./types');
+var reader = require('./reader');
+if (typeof module !== 'undefined') {
+ var readline = require('./node_readline');
+}
+
+// read
+function READ(str) {
+ return reader.read_str(str);
+}
+
+// eval
+function eval_ast(ast, env) {
+ if (types.symbol_Q(ast)) {
+ return env.get(ast);
+ } else if (types.list_Q(ast)) {
+ return ast.map(function(a) { return EVAL(a, env); });
+ } else if (types.vector_Q(ast)) {
+ var v = ast.map(function(a) { return EVAL(a, env); });
+ v.__isvector__ = true;
+ return v;
+ } else if (types.hash_map_Q(ast)) {
+ var new_hm = {};
+ for (k in ast) {
+ new_hm[EVAL(k, env)] = EVAL(ast[k], env);
+ }
+ return new_hm;
+ } else {
+ return ast;
+ }
+}
+
+function _EVAL(ast, env) {
+ if (!types.list_Q(ast)) {
+ return eval_ast(ast, env);
+ }
+
+ // apply list
+ var a0 = ast[0], a1 = ast[1], a2 = ast[2], a3 = ast[3];
+ switch (a0.value) {
+ case "def!":
+ var res = EVAL(a2, env);
+ return env.set(a1, res);
+ case "let*":
+ var let_env = new types.Env(env);
+ for (var i=0; i < a1.length; i+=2) {
+ let_env.set(a1[i].value, EVAL(a1[i+1], let_env));
+ }
+ return EVAL(a2, let_env);
+ default:
+ var el = eval_ast(ast, env), f = el[0];
+ return f.apply(f, el.slice(1));
+ }
+}
+
+function EVAL(ast, env) {
+ var result = _EVAL(ast, env);
+ return (typeof result !== "undefined") ? result : null;
+}
+
+// print
+function PRINT(exp) {
+ return types._pr_str(exp, true);
+}
+
+// repl
+var repl_env = new types.Env();
+var rep = function(str) { return PRINT(EVAL(READ(str), repl_env)); };
+_ref = function (k,v) { repl_env.set(k, v); }
+
+_ref('+', function(a,b){return a+b;});
+_ref('-', function(a,b){return a-b;});
+_ref('*', function(a,b){return a*b;});
+_ref('/', function(a,b){return a/b;});
+
+if (typeof require === 'undefined') {
+ // Asynchronous browser mode
+ readline.rlwrap(function(line) { return rep(line); },
+ function(exc) {
+ if (exc instanceof reader.BlankException) { return; }
+ if (exc.stack) { console.log(exc.stack); } else { console.log(exc); }
+ });
+} else if (require.main === module) {
+ // Synchronous node.js commandline mode
+ while (true) {
+ var line = readline.readline("user> ");
+ if (line === null) { break; }
+ try {
+ if (line) { console.log(rep(line)); }
+ } catch (exc) {
+ if (exc instanceof reader.BlankException) { continue; }
+ if (exc.stack) { console.log(exc.stack); } else { console.log(exc); }
+ }
+ }
+} else {
+ exports.rep = rep;
+}