Skip to content

Commit c69d9c5

Browse files
committed
[interpreters] Fix negative nums, (define (...) ..) syntax
1 parent 28599a2 commit c69d9c5

File tree

1 file changed

+66
-62
lines changed

1 file changed

+66
-62
lines changed

categories/interpreters/lisp.pl

100644100755
Lines changed: 66 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -13,75 +13,79 @@
1313

1414

1515
subset Number of Str where -> $x {
16-
so $x ~~ /^^ \d+ ( '.' \d* )? $$/ }
16+
so $x ~~ /^^ <[-+]>?\d+ ( '.' \d* )? $$/ }
1717

18-
class Func {
19-
has Callable $.code;
20-
has Str $.desc;
21-
method eval(@a) { $.code.(|@a) }
22-
method gist { "#<{$.desc}>" }
23-
}
18+
class Func {
19+
has Callable $.code;
20+
has Str $.desc;
21+
method eval(@a) { $.code.(|@a) }
22+
method gist { "#<{$.desc}>" }
23+
}
2424

25-
class Symbol {
26-
has $.name;
27-
method CALL-ME($x) {
28-
Symbol.new(name => $x);
25+
class Symbol {
26+
has $.name;
27+
method CALL-ME($x) {
28+
Symbol.new(name => $x);
29+
}
30+
method Str { $.name }
2931
}
30-
method Str { $.name }
31-
}
3232

3333

34-
class Env {
35-
has %.scope;
36-
has Env $.outer;
37-
method resolve($key) is rw {
38-
if %.scope{$key}:exists {
39-
%.scope{$key}
34+
class Env {
35+
has %.scope;
36+
has Env $.outer;
37+
method resolve($key) is rw {
38+
if %.scope{$key}:exists {
39+
%.scope{$key}
40+
}
41+
else {
42+
fail "Not found symbol '$key'" unless $.outer;
43+
$.outer.resolve($key)
44+
}
4045
}
41-
else {
42-
fail "Not found symbol '$key'" unless $.outer;
43-
$.outer.resolve($key)
46+
method merge(*@env) {
47+
%.scope = %.scope, %(@env)
4448
}
45-
}
46-
method merge(*@env) {
47-
%.scope = %.scope, %(@env)
48-
}
49-
multi method evaluate-tokens(Number $x) {
50-
$x
51-
}
52-
multi method evaluate-tokens(Symbol $x) {
53-
self.resolve($x)
54-
}
55-
multi method evaluate-tokens(Positional $x) {
56-
my @x = @($x);
57-
fail "Syntax error" if +@x == 0;
58-
my $verb = @x.shift;
59-
given $verb {
60-
when 'quote' {
61-
if @x[0] ~~ Positional {
62-
[ @x[0] ];
49+
multi method evaluate-tokens(Number $x) {
50+
$x
51+
}
52+
multi method evaluate-tokens(Symbol $x) {
53+
self.resolve($x)
54+
}
55+
multi method evaluate-tokens(Positional $x) {
56+
my @x = @($x);
57+
fail "Syntax error" if +@x == 0;
58+
my $verb = @x.shift;
59+
given $verb {
60+
when 'quote' {
61+
if @x[0] ~~ Positional {
62+
[ @x[0] ];
63+
}
64+
else { @x[0] }
6365
}
64-
else { @x[0] }
65-
}
66-
when 'if' {
67-
my ($test,
68-
$conseq,
69-
$alt) = @x;
70-
self.evaluate-tokens(
71-
self.evaluate-tokens($test)
72-
?? $conseq
73-
!! $alt
74-
)
75-
}
76-
when 'set!' {
77-
my ($var, $exp) = @x;
78-
self.resolve($var) = self.evaluate-tokens($exp);
79-
#return $var;
66+
when 'if' {
67+
my ($test,
68+
$conseq,
69+
$alt) = @x;
70+
self.evaluate-tokens(
71+
self.evaluate-tokens($test)
72+
?? $conseq
73+
!! $alt
74+
)
75+
}
76+
when 'set!' {
77+
my ($var, $exp) = @x;
78+
self.resolve($var) = self.evaluate-tokens($exp);
79+
#return $var;
8080

81-
}
82-
when 'define' {
83-
my ($var, $exp) = @x;
84-
$.scope{$var} =self.evaluate-tokens($exp);
81+
}
82+
when 'define' {
83+
my ($var, $exp) = @x;
84+
if $var ~~ Positional {
85+
$.scope{$var[0]} =
86+
self.evaluate-tokens([ Symbol('λ'), [ $var[1..*] ], $exp]);
87+
}
88+
else { $.scope{$var} =self.evaluate-tokens($exp); }
8589
}
8690
when 'lambda' | 'λ' {
8791
my ($vars, $exp) = @x;
@@ -90,7 +94,7 @@
9094
my $new-env = Env.new(scope => %x , outer => self);
9195
$new-env.evaluate-tokens($exp)
9296
},
93-
desc => "function:{$vars[]}" );
97+
desc => "closure:arity:{$vars.elems}" );
9498

9599
}
96100
when 'begin' {
@@ -119,7 +123,7 @@
119123

120124
our %*BUILTINS =
121125
'+' => -> *@a { [+] @a },
122-
'-' => -> *@a { [-] @a },
126+
'-' => -> *@a { +@a > 1 ?? [-] @a !! - @a[0] },
123127
'*' => -> *@a { [*] @a },
124128
'/' => -> *@a { [/] @a },
125129
'abs' => -> $a { abs $a },

0 commit comments

Comments
 (0)