use strict;
-use warnings FATAL => qw(all);
+use warnings FATAL => "recursion";
no if $] >= 5.018, warnings => "experimental::smartmatch";
+use feature qw(switch);
use File::Basename;
use lib dirname (__FILE__);
-use List::Util qw(pairs pairmap);
-use readline qw(mal_readline set_rl_mode);
-use feature qw(switch);
+
use Data::Dumper;
+use List::Util qw(pairs pairmap);
+use Scalar::Util qw(blessed);
-use types qw($nil $true $false _sequential_Q _symbol_Q _list_Q _clone);
+use readline qw(mal_readline set_rl_mode);
+use types qw($nil $true $false _symbol_Q _list_Q);
use reader;
use printer;
use env;
# eval
sub is_pair {
my ($x) = @_;
- return _sequential_Q($x) && @$x;
+ return $x->isa('Mal::Sequence') && @$x;
}
sub quasiquote {
# Continue loop (TCO)
}
when ('defmacro!') {
- my $func = _clone(EVAL($a2, $env));
+ my $func = EVAL($a2, $env)->clone;
$func->{ismacro} = 1;
return $env->set($a1, $func);
}
return macroexpand($a1, $env);
}
when ('try*') {
- do {
- local $@;
- my $ret;
- eval {
- use autodie; # always "throw" errors
- $ret = EVAL($a1, $env);
- 1;
- } or do {
- my $err = $@;
- if ($a2 && ${$a2->[0]} eq 'catch*') {
- my $exc;
- if (ref $err) {
- $exc = $err;
- } else {
- $exc = Mal::String->new(substr $err, 0, -1);
- }
- my $catch_env =
- Mal::Env->new($env, Mal::List->new([$a2->[1]]),
- Mal::List->new([$exc]));
- return EVAL($a2->[2], $catch_env)
- } else {
- die $err;
- }
- };
- return $ret;
- };
+ local $@;
+ my $ret = eval { EVAL($a1, $env) };
+ return $ret unless $@;
+ if ($a2 && ${$a2->[0]} eq 'catch*') {
+ my $exc;
+ if (defined(blessed $@) && $@->isa('Mal::Type')) {
+ $exc = $@;
+ } else {
+ chomp(my $msg = $@);
+ $exc = Mal::String->new($msg);
+ }
+ my $catch_env = Mal::Env->new($env, [$a2->[1]], [$exc]);
+ return EVAL($a2->[2], $catch_env)
+ } else {
+ die $@;
+ }
}
when ('do') {
eval_ast($ast->slice(1, $#$ast-1), $env);
# core.mal: defined using the language itself
REP(q[(def! not (fn* (a) (if a false true)))]);
-REP(q[(def! load-file (fn* (f) (eval (read-string (str "(do " (slurp f) ")")))))]);
+REP(q[(def! load-file (fn* (f) (eval (read-string (str "(do " (slurp f) "\nnil)")))))]);
REP(q[(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (list 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw "odd number of forms to cond")) (cons 'cond (rest (rest xs)))))))]);
-
if (@ARGV && $ARGV[0] eq "--raw") {
set_rl_mode("raw");
shift @ARGV;
local $@;
my $ret;
eval {
- use autodie; # always "throw" errors
print(REP($line), "\n");
1;
} or do {
my $err = $@;
- if ($err->isa('Mal::BlankException')) {
+ if (defined(blessed $err) && $err->isa('Mal::BlankException')) {
# ignore and continue
+ } elsif (defined(blessed $err) && $err->isa('Mal::Type')) {
+ print "Error: ".printer::_pr_str($err)."\n";
} else {
- if (ref $err) {
- print "Error: ".printer::_pr_str($err)."\n";
- } else {
- chomp $err;
- print "Error: $err\n";
- }
+ chomp $err;
+ print "Error: $err\n";
}
};
};