diff options
| author | Joel Martin <github@martintribe.org> | 2014-04-23 21:46:57 -0500 |
|---|---|---|
| committer | Joel Martin <github@martintribe.org> | 2014-04-23 21:46:57 -0500 |
| commit | 89bd4de1e2704c1bc562788b2c5e4fc08b71a538 (patch) | |
| tree | 3ec33ca7e1030fdef0905317fdf911b8487685f0 /perl/step2_eval.pl | |
| parent | 85cc53f35b8302e13f0014454ac320b971c196db (diff) | |
| download | mal-89bd4de1e2704c1bc562788b2c5e4fc08b71a538.tar.gz mal-89bd4de1e2704c1bc562788b2c5e4fc08b71a538.zip | |
Perl: add vector, hash-map, metadata, atom support. TCO let*
- Changes all collections to be one level of inderection where the top
level is always a hash containing 'meta' and 'val'.
Diffstat (limited to 'perl/step2_eval.pl')
| -rw-r--r-- | perl/step2_eval.pl | 59 |
1 files changed, 41 insertions, 18 deletions
diff --git a/perl/step2_eval.pl b/perl/step2_eval.pl index a448385..1655a29 100644 --- a/perl/step2_eval.pl +++ b/perl/step2_eval.pl @@ -1,9 +1,10 @@ use strict; use warnings FATAL => qw(all); -use readline qw(readline); +use readline qw(mal_readline); use feature qw(switch); use Data::Dumper; +use types qw(_list_Q); use reader; use printer; @@ -25,9 +26,20 @@ sub eval_ast { } } when (/^List/) { - my @lst = map {EVAL($_, $env)} @$ast; + my @lst = map {EVAL($_, $env)} @{$ast->{val}}; return List->new(\@lst); } + when (/^Vector/) { + my @lst = map {EVAL($_, $env)} @{$ast->{val}}; + return Vector->new(\@lst); + } + when (/^HashMap/) { + my $new_hm = {}; + foreach my $k (keys($ast->{val})) { + $new_hm->{$k} = EVAL($ast->get($k), $env); + } + return HashMap->new($new_hm); + } default { return $ast; } @@ -37,13 +49,13 @@ sub eval_ast { sub EVAL { my($ast, $env) = @_; #print "EVAL: " . printer::_pr_str($ast) . "\n"; - if (! ((ref $ast) =~ /^List/)) { + if (! _list_Q($ast)) { return eval_ast($ast, $env); } # apply list my $el = eval_ast($ast, $env); - my $f = $el->[0]; + my $f = $el->nth(0); return &{ $f }($el->rest()); } @@ -60,21 +72,32 @@ sub REP { return PRINT(EVAL(READ($str), $repl_env)); } -$repl_env->{'+'} = sub { Integer->new(${$_[0][0]} + ${$_[0][1]}) }; -$repl_env->{'-'} = sub { Integer->new(${$_[0][0]} - ${$_[0][1]}) }; -$repl_env->{'*'} = sub { Integer->new(${$_[0][0]} * ${$_[0][1]}) }; -$repl_env->{'/'} = sub { Integer->new(${$_[0][0]} / ${$_[0][1]}) }; +$repl_env->{'+'} = sub { Integer->new(${$_[0]->nth(0)} + ${$_[0]->nth(1)}) }; +$repl_env->{'-'} = sub { Integer->new(${$_[0]->nth(0)} - ${$_[0]->nth(1)}) }; +$repl_env->{'*'} = sub { Integer->new(${$_[0]->nth(0)} * ${$_[0]->nth(1)}) }; +$repl_env->{'/'} = sub { Integer->new(${$_[0]->nth(0)} / ${$_[0]->nth(1)}) }; while (1) { - my $line = readline("user> "); + my $line = mal_readline("user> "); if (! defined $line) { last; } - eval { - use autodie; # always "throw" errors - print(REP($line), "\n"); - 1; - }; - if (my $err = $@) { - chomp $err; - print "Error: $err\n"; - } + do { + local $@; + my $ret; + eval { + use autodie; # always "throw" errors + print(REP($line), "\n"); + 1; + } or do { + my $err = $@; + given (ref $err) { + when (/^BlankException/) { + # ignore and continue + } + default { + chomp $err; + print "Error: $err\n"; + } + } + }; + }; } |
