From 3169070063b2cb877200117ebb384269d73bcb93 Mon Sep 17 00:00:00 2001 From: Joel Martin Date: Mon, 24 Mar 2014 16:32:24 -0500 Subject: Current state of mal for Clojure West lighting talk. --- php/step6_file.php | 142 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 php/step6_file.php (limited to 'php/step6_file.php') diff --git a/php/step6_file.php b/php/step6_file.php new file mode 100644 index 0000000..8e923e1 --- /dev/null +++ b/php/step6_file.php @@ -0,0 +1,142 @@ +get($ast->value); + } elseif (list_Q($ast) || vector_Q($ast)) { + if (list_Q($ast)) { + $el = new_list(); + } else { + $el = new_vector(); + } + foreach ($ast as $a) { $el[] = MAL_EVAL($a, $env); } + return $el; + } elseif (hash_map_Q($ast)) { + $new_hm = new_hash_map(); + foreach (array_keys($ast->getArrayCopy()) as $key) { + $new_hm[$key] = MAL_EVAL($ast[$key], $env); + } + return $new_hm; + } else { + return $ast; + } +} + +function MAL_EVAL($ast, $env) { + while (true) { + #echo "MAL_EVAL: " . _pr_str($ast) . "\n"; + if (!list_Q($ast)) { + return eval_ast($ast, $env); + } + + // apply list + $a0 = $ast[0]; + $a0v = (symbol_Q($a0) ? $a0->value : $a0); + switch ($a0v) { + case "def!": + $res = MAL_EVAL($ast[2], $env); + return $env->set($ast[1]->value, $res); + case "let*": + $a1 = $ast[1]; + $let_env = new Env($env); + for ($i=0; $i < count($a1); $i+=2) { + $let_env->set($a1[$i]->value, MAL_EVAL($a1[$i+1], $let_env)); + } + return MAL_EVAL($ast[2], $let_env); + case "do": + eval_ast($ast->slice(1, -1), $env); + $ast = $ast[count($ast)-1]; + break; + case "if": + $cond = MAL_EVAL($ast[1], $env); + if ($cond === NULL || $cond === false) { + if (count($ast) === 4) { $ast = $ast[3]; } + else { $ast = NULL; } + } else { + $ast = $ast[2]; + } + break; + case "fn*": + return new_function('MAL_EVAL', 'native', + new_hash_map('exp', $ast[2], + 'env', $env, + 'params', $ast[1])); + default: + $el = eval_ast($ast, $env); + $f = $el[0]; + $args = array_slice($el->getArrayCopy(), 1); + if ($f->type === 'native') { + $ast = $f->meta['exp']; + $env = new Env($f->meta['env'], $f->meta['params'], $args); + } else { + return $f->apply($args); + } + } + } +} + +// print +function MAL_PRINT($exp) { + return _pr_str($exp, True) . "\n"; +} + +// repl +$repl_env = new Env(NULL); +function rep($str) { + global $repl_env; + return MAL_PRINT(MAL_EVAL(READ($str), $repl_env)); +} +function _ref($k, $v) { + global $repl_env; + $repl_env->set($k, new_function($v)); +} +// Import types functions +foreach ($types_ns as $k=>$v) { _ref($k, $v); } + +_ref('read-string', 'read_str'); +_ref('eval', function($ast) { + global $repl_env; return MAL_EVAL($ast, $repl_env); +}); +_ref('slurp', function($f) { + return file_get_contents($f); +}); +_ref('slurp-do', function($f) { + return "(do " . file_get_contents($f) . ")"; +}); + +// Defined using the language itself +rep("(def! not (fn* (a) (if a false true)))"); +rep("(def! load-file (fn* (f) (eval (read-string (slurp-do f)))))"); + +if (count($argv) > 1) { + for ($i=1; $i < count($argv); $i++) { + rep('(load-file "' . $argv[$i] . '")'); + } +} else { + do { + try { + $line = mal_readline("user> "); + if ($line === NULL) { break; } + if ($line !== "") { + print(rep($line)); + } + } catch (BlankException $e) { + continue; + } catch (Exception $e) { + echo "Error: " . $e->getMessage() . "\n"; + echo $e->getTraceAsString() . "\n"; + } + } while (true); +} + +?> -- cgit v1.2.3