|
13 | 13 |
|
14 | 14 |
|
15 | 15 | subset Number of Str where -> $x {
|
16 |
| - so $x ~~ /^^ \d+ ( '.' \d* )? $$/ } |
| 16 | + so $x ~~ /^^ <[-+]>?\d+ ( '.' \d* )? $$/ } |
17 | 17 |
|
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 | + } |
24 | 24 |
|
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 } |
29 | 31 | }
|
30 |
| - method Str { $.name } |
31 |
| -} |
32 | 32 |
|
33 | 33 |
|
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 | + } |
40 | 45 | }
|
41 |
| - else { |
42 |
| - fail "Not found symbol '$key'" unless $.outer; |
43 |
| - $.outer.resolve($key) |
| 46 | + method merge(*@env) { |
| 47 | + %.scope = %.scope, %(@env) |
44 | 48 | }
|
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] } |
63 | 65 | }
|
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; |
80 | 80 |
|
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); } |
85 | 89 | }
|
86 | 90 | when 'lambda' | 'λ' {
|
87 | 91 | my ($vars, $exp) = @x;
|
|
90 | 94 | my $new-env = Env.new(scope => %x , outer => self);
|
91 | 95 | $new-env.evaluate-tokens($exp)
|
92 | 96 | },
|
93 |
| - desc => "function:{$vars[]}" ); |
| 97 | + desc => "closure:arity:{$vars.elems}" ); |
94 | 98 |
|
95 | 99 | }
|
96 | 100 | when 'begin' {
|
|
119 | 123 |
|
120 | 124 | our %*BUILTINS =
|
121 | 125 | '+' => -> *@a { [+] @a },
|
122 |
| -'-' => -> *@a { [-] @a }, |
| 126 | +'-' => -> *@a { +@a > 1 ?? [-] @a !! - @a[0] }, |
123 | 127 | '*' => -> *@a { [*] @a },
|
124 | 128 | '/' => -> *@a { [/] @a },
|
125 | 129 | 'abs' => -> $a { abs $a },
|
|
0 commit comments