Runtest should fail on bad test data. Fix interop tests.
[jackhill/mal.git] / perl6 / step2_eval.pl
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 }