Commit | Line | Data |
---|---|---|
31690700 JM |
1 | <?php |
2 | ||
3 | require_once 'readline.php'; | |
4 | require_once 'types.php'; | |
5 | require_once 'reader.php'; | |
ea81a808 JM |
6 | require_once 'printer.php'; |
7 | require_once 'env.php'; | |
31690700 JM |
8 | |
9 | // read | |
10 | function READ($str) { | |
11 | return read_str($str); | |
12 | } | |
13 | ||
14 | // eval | |
15 | function eval_ast($ast, $env) { | |
ea81a808 | 16 | if (_symbol_Q($ast)) { |
b8ee29b2 | 17 | return $env->get($ast); |
ea81a808 JM |
18 | } elseif (_sequential_Q($ast)) { |
19 | if (_list_Q($ast)) { | |
20 | $el = _list(); | |
31690700 | 21 | } else { |
ea81a808 | 22 | $el = _vector(); |
31690700 JM |
23 | } |
24 | foreach ($ast as $a) { $el[] = MAL_EVAL($a, $env); } | |
25 | return $el; | |
ea81a808 JM |
26 | } elseif (_hash_map_Q($ast)) { |
27 | $new_hm = _hash_map(); | |
31690700 JM |
28 | foreach (array_keys($ast->getArrayCopy()) as $key) { |
29 | $new_hm[$key] = MAL_EVAL($ast[$key], $env); | |
30 | } | |
31 | return $new_hm; | |
32 | } else { | |
33 | return $ast; | |
34 | } | |
35 | } | |
36 | ||
37 | function MAL_EVAL($ast, $env) { | |
ea81a808 JM |
38 | #echo "MAL_EVAL: " . _pr_str($ast) . "\n"; |
39 | if (!_list_Q($ast)) { | |
31690700 JM |
40 | return eval_ast($ast, $env); |
41 | } | |
42 | ||
43 | // apply list | |
44 | $a0 = $ast[0]; | |
ea81a808 | 45 | $a0v = (_symbol_Q($a0) ? $a0->value : $a0); |
31690700 JM |
46 | switch ($a0v) { |
47 | case "def!": | |
48 | $res = MAL_EVAL($ast[2], $env); | |
b8ee29b2 | 49 | return $env->set($ast[1], $res); |
31690700 JM |
50 | case "let*": |
51 | $a1 = $ast[1]; | |
52 | $let_env = new Env($env); | |
53 | for ($i=0; $i < count($a1); $i+=2) { | |
b8ee29b2 | 54 | $let_env->set($a1[$i], MAL_EVAL($a1[$i+1], $let_env)); |
31690700 JM |
55 | } |
56 | return MAL_EVAL($ast[2], $let_env); | |
57 | default: | |
58 | $el = eval_ast($ast, $env); | |
59 | $f = $el[0]; | |
60 | return call_user_func_array($f, array_slice($el->getArrayCopy(), 1)); | |
61 | } | |
62 | } | |
63 | ||
64 | ||
65 | function MAL_PRINT($exp) { | |
10b07148 | 66 | return _pr_str($exp, True); |
31690700 JM |
67 | } |
68 | ||
69 | // repl | |
70 | $repl_env = new Env(NULL); | |
71 | function rep($str) { | |
72 | global $repl_env; | |
73 | return MAL_PRINT(MAL_EVAL(READ($str), $repl_env)); | |
74 | } | |
31690700 | 75 | |
b8ee29b2 JM |
76 | $repl_env->set(_symbol('+'), function ($a, $b) { return intval($a + $b,10); }); |
77 | $repl_env->set(_symbol('-'), function ($a, $b) { return intval($a - $b,10); }); | |
78 | $repl_env->set(_symbol('*'), function ($a, $b) { return intval($a * $b,10); }); | |
79 | $repl_env->set(_symbol('/'), function ($a, $b) { return intval($a / $b,10); }); | |
31690700 | 80 | |
86b689f3 | 81 | // repl loop |
31690700 JM |
82 | do { |
83 | try { | |
84 | $line = mal_readline("user> "); | |
85 | if ($line === NULL) { break; } | |
86 | if ($line !== "") { | |
10b07148 | 87 | print(rep($line) . "\n"); |
31690700 JM |
88 | } |
89 | } catch (BlankException $e) { | |
90 | continue; | |
91 | } catch (Exception $e) { | |
92 | echo "Error: " . $e->getMessage() . "\n"; | |
93 | echo $e->getTraceAsString() . "\n"; | |
94 | } | |
95 | } while (true); | |
96 | ||
86b689f3 | 97 | ?> |