7 our @EXPORT_OK = qw(_equal_Q thaw_key
14 unless ((ref $a eq ref $b) ||
15 ($a->isa('Mal::Sequence') && $b->isa('Mal::Sequence'))) {
18 if ($a->isa('Mal::Sequence')) {
19 unless (scalar(@$a) == scalar(@$b)) {
22 for (my $i=0; $i<scalar(@$a); $i++) {
23 unless (_equal_Q($a->[$i], $b->[$i])) {
28 } elsif ($a->isa('Mal::HashMap')) {
29 unless (scalar(keys %$a) == scalar(keys %$b)) {
32 foreach my $k (keys %$a) {
33 unless (_equal_Q($a->{$k}, $b->{$k})) {
48 package Mal::BlankException;
49 sub new { my $class = shift; bless Mal::String->new("Blank Line") => $class }
52 # Superclass for all kinds of mal value
62 use parent -norequire, 'Mal::Type';
63 # Overload stringification so that its result is something
64 # suitable for use as a hash-map key. The important thing here is
65 # that strings and keywords are distinct: support for other kinds
66 # of scalar is a bonus.
67 use overload '""' => sub { my $self = shift; ref($self) . " " . $$self },
69 sub new { my ($class, $value) = @_; bless \$value, $class }
72 # This function converts hash-map keys back into full objects
75 my ($class, $value) = split(/ /, $_[0], 2);
76 return $class->new($value);
81 use parent -norequire, 'Mal::Scalar';
82 # Allow nil to be treated as an empty list or hash-map.
83 use overload '@{}' => sub { [] }, '%{}' => sub { {} }, fallback => 1;
84 sub rest { Mal::List->new([]) }
88 use parent -norequire, 'Mal::Scalar';
92 use parent -norequire, 'Mal::Scalar';
95 our $nil = Mal::Nil->new('nil');
96 our $true = Mal::True->new('true');
97 our $false = Mal::False->new('false');
101 package Mal::Integer;
102 use parent -norequire, 'Mal::Scalar';
108 use parent -norequire, 'Mal::Scalar';
114 use parent -norequire, 'Mal::Scalar';
119 package Mal::Keyword;
120 use parent -norequire, 'Mal::Scalar';
127 package Mal::Sequence;
128 use parent -norequire, 'Mal::Type';
129 sub new { my $class = shift; bless $_[0], $class }
130 sub rest { my $arr = $_[0]; Mal::List->new([@$arr[1..$#$arr]]); }
131 sub clone { my $self = shift; ref($self)->new([@$self]) }
138 use parent -norequire, 'Mal::Sequence';
146 use parent -norequire, 'Mal::Sequence';
153 package Mal::HashMap;
154 use parent -norequire, 'Mal::Type';
155 use List::Util qw(pairmap);
156 use Scalar
::Util
qw(reftype);
158 my ($class, $src) = @_;
159 if (reftype
($src) eq 'ARRAY') {
162 return bless $src, $class;
164 sub clone
{ my $self = shift; ref($self)->new({%$self}) }
171 package Mal
::Callable
;
172 use parent
-norequire
, 'Mal::Type';
173 sub new
{ my $class = shift; bless $_[0], $class }
174 sub clone
{ my $self = shift; bless sub { goto &$self }, ref($self) }
178 package Mal
::Function
;
179 use parent
-norequire
, 'Mal::Callable';
184 use parent
-norequire
, 'Mal::Callable';
192 use parent
-norequire
, 'Mal::Type';
193 sub new
{ my ($class, $val) = @_; bless \
$val, $class }
194 sub clone
{ my $self = shift; ref($self)->new($$self) }