Commit | Line | Data |
---|---|---|
a7081401 HÖS |
1 | use v6; |
2 | use lib IO::Path.new($?FILE).dirname; | |
3 | use reader; | |
4 | use printer; | |
5 | use types; | |
6 | ||
7 | sub read ($str) { | |
8 | return read_str($str); | |
9 | } | |
10 | ||
11 | sub eval_ast ($ast, $env) { | |
12 | given $ast { | |
13 | when MalSymbol { $env{$ast.val} || die X::MalNotFound.new(name => $ast.val) } | |
14 | when MalList { MalList([$ast.map({ eval($_, $env) })]) } | |
15 | when MalVector { MalVector([$ast.map({ eval($_, $env) })]) } | |
16 | when MalHashMap { MalHashMap($ast.kv.map({ $^a => eval($^b, $env) }).Hash) } | |
17 | default { $ast // $NIL } | |
18 | } | |
19 | } | |
20 | ||
21 | sub eval ($ast, $env) { | |
22 | return eval_ast($ast, $env) if $ast !~~ MalList; | |
23 | return $ast if !$ast.elems; | |
24 | ||
25 | my ($func, @args) = eval_ast($ast, $env).val; | |
26 | my $arglist = MalList(@args); | |
27 | return $func.apply($arglist); | |
28 | } | |
29 | ||
30 | sub print ($exp) { | |
31 | return pr_str($exp, True); | |
32 | } | |
33 | ||
34 | my $repl_env; | |
35 | ||
36 | sub rep ($str) { | |
37 | return print(eval(read($str), $repl_env)); | |
38 | } | |
39 | ||
40 | sub MAIN { | |
41 | $repl_env<+> = MalCode({ MalNumber($^a[0].val + $^a[1].val) }); | |
42 | $repl_env<-> = MalCode({ MalNumber($^a[0].val - $^a[1].val) }); | |
43 | $repl_env<*> = MalCode({ MalNumber($^a[0].val * $^a[1].val) }); | |
44 | $repl_env</> = MalCode({ MalNumber(($^a[0].val / $^a[1].val).Int) }); | |
45 | ||
46 | while (my $line = prompt 'user> ').defined { | |
47 | say rep($line); | |
48 | CATCH { | |
49 | when X::MalException { .Str.say } | |
50 | } | |
51 | } | |
52 | } |