3 use warnings FATAL
=> qw(all);
4 no if $] >= 5.018, warnings
=> "experimental::smartmatch";
5 use feature
qw(switch);
7 our @EXPORT_OK = qw(_sequential_Q _equal_Q _clone
8 $nil $true $false _nil_Q _true_Q _false_Q
9 _number_Q _symbol _symbol_Q _string_Q _keyword _keyword_Q _list_Q _vector_Q _sub_Q _function_Q
10 _hash_map _hash_map_Q _assoc_BANG _dissoc_BANG _atom_Q);
17 return _list_Q($_[0]) || _vector_Q($_[0])
22 my ($ota, $otb) = (ref $a, ref $b);
23 if (!(($ota eq $otb) || (_sequential_Q($a) && _sequential_Q($b)))) {
26 if ($a->isa('Symbol')) {
28 } elsif ($a->isa('Sequence')) {
29 if (! (scalar(@$a) == scalar(@$b))) {
32 for (my $i=0; $i<scalar(@$a); $i++) {
33 if (! _equal_Q($a->[$i], $b->[$i])) {
38 } elsif ($a->isa('HashMap')) {
39 if (! (scalar(keys %{ $a->{val} }) == scalar(keys %{ $b->{val} }))) {
42 foreach my $k (keys %{ $a->{val} }) {
43 if (!_equal_Q($a->{val}->{$k}, $b->{val}->{$k})) {
58 return FunctionRef->new( $obj );
61 return bless {%{$obj}}, ref $obj;
69 package BlankException;
70 sub new { my $class = shift; bless String->new("Blank Line") => $class }
77 sub new { my $class = shift; my $s = 'nil'; bless \$s => $class }
81 sub new { my $class = shift; my $s = 'true'; bless \$s => $class }
85 sub new { my $class = shift; my $s = 'false'; bless \$s => $class }
88 our $nil = Nil->new();
89 our $true = True->new();
90 our $false = False->new();
92 sub _nil_Q { return $_[0] eq $nil }
93 sub _true_Q { return $_[0] eq $true }
94 sub _false_Q { return $_[0] eq $false }
99 sub new { my $class = shift; bless \do { my $x=$_[0] }, $class }
101 sub _number_Q { $_[0]->isa('Integer') }
106 sub new { my $class = shift; bless \do { my $x=$_[0] }, $class }
108 sub _symbol_Q { $_[0]->isa('Symbol') }
111 sub _string_Q { $_[0]->isa('String') && ${$_[0]} !~ /^\x{029e}/; }
114 sub _keyword { return String->new(("\x{029e}".$_[0])); }
115 sub _keyword_Q { $_[0]->isa('String') && ${$_[0]} =~ /^\x{029e}/; }
120 sub new { my $class = shift; bless \$_[0] => $class }
128 use overload '@{}' => sub { $_[0]->{val} }, fallback => 1;
129 sub new { my $class = shift; bless {'meta'=>$nil, 'val'=>$_[0]}, $class }
130 sub meta { $_[0]->{meta} }
131 #sub _val { $_[0]->{val}->[$_[1]]->{val}; } # return value of nth item
132 sub rest { my @arr = @{$_[0]->{val}}; List->new([@arr[1..$#arr]]); }
133 sub slice { my @arr = @{$_[0]->{val}}; List->new([@arr[$_[1]..$_[2]]]); }
140 use parent -norequire, 'Sequence';
143 sub _list_Q { $_[0]->isa('List') }
150 use parent -norequire, 'Sequence';
153 sub _vector_Q { $_[0]->isa('Vector') }
160 sub new { my $class = shift; bless {'meta'=>$nil, 'val'=>$_[0]}, $class }
161 sub meta { $_[0]->{meta} }
162 sub get { $_[0]->{val}->{$_[1]}; }
167 return _assoc_BANG($hsh, @_);
173 for(my $i=0; $i<scalar(@lst); $i+=2) {
175 $hsh->{$$str} = $lst[$i+1];
177 return HashMap->new($hsh);
183 for(my $i=0; $i<scalar(@lst); $i++) {
185 delete $hsh->{$$str};
187 return HashMap->new($hsh);
190 sub _hash_map_Q { $_[0]->isa('HashMap') }
197 use overload '&{}' => sub { my $f = shift; sub { $f->apply($_[0]) } };
200 my ($eval, $ast, $env, $params) = @_;
206 'ismacro'=>0}, $class
208 sub meta { $_[0]->{meta} }
211 return Env->new($self->{env}, $self->{params}, $_[1]);
215 return &{ $self->{eval} }($self->{ast}, gen_env($self, $_[1]));
219 sub _sub_Q { (ref $_[0]) =~ /^CODE/ }
220 sub _function_Q { (ref $_[0]) =~ /^Function/ }
227 use overload '&{}' => sub { my $f = shift; sub { $f->apply($_[0]) } };
229 my ($class, $code) = @_;
231 'code'=>$code}, $class
233 sub meta { $_[0]->{meta} }
236 return &{ $self->{code} }($_[1]);
245 sub new { my $class = shift; bless {'meta'=>$nil, 'val'=>$_[0]}, $class }
246 sub meta { $_[0]->{meta} }
249 sub _atom_Q { $_[0]->isa('Atom') }