Merge pull request #361 from asarhaddon/exercise-native-implementations
[jackhill/mal.git] / perl6 / types.pm
1 unit module types;
2
3 class X::MalException is Exception is export {}
4 class X::MalNoTokens is X::MalException is export {
5 method message() { "got no tokens" }
6 }
7 class X::MalIncomplete is X::MalException is export {
8 has $.end;
9 method message() { "expected '$.end', got EOF" }
10 }
11 class X::MalUnexpected is X::MalException is export {
12 has $.token;
13 method message() { "unexpected '$.token'" }
14 }
15 class X::MalNotFound is X::MalException is export {
16 has $.name;
17 method message() { "'$.name' not found" }
18 }
19 class X::MalOutOfRange is X::MalException is export {
20 method message() { "nth: index out of range" }
21 }
22 class X::MalThrow is X::MalException is export {
23 has $.value;
24 }
25
26 role MalValue is export {
27 has $.val is rw;
28 method CALL-ME ($val) { self.new(:$val) }
29 }
30 role MalSequence is export {
31 has $.val handles <cache AT-POS EXISTS-POS elems end iterator>;
32 has $.meta is rw;
33 method CALL-ME ($val) { self.new(:$val) }
34 }
35 role MalCallable is export {
36 has &.fn;
37 method apply (*@_) { &!fn(|@_) }
38 }
39 role MalMeta is export {
40 has $.meta is rw;
41 }
42
43 class MalNil does MalValue is export {
44 method seq { self }
45 }
46 class MalTrue does MalValue is export {}
47 class MalFalse does MalValue is export {}
48
49 our $NIL is export = MalNil('nil');
50 our $TRUE is export = MalTrue('true');
51 our $FALSE is export = MalFalse('false');
52
53 class MalSymbol does MalValue does MalMeta is export {}
54
55 class MalList does MalSequence is export {
56 method conj (@args) { return self.new(val => [|@args.reverse, |$.val]) }
57 method seq { return self.elems ?? self !! $NIL }
58 }
59
60 class MalVector does MalSequence is export {
61 method conj (@args) { return self.new(val => [|$.val, |@args]) }
62 method seq { return self.elems ?? MalList(self.val) !! $NIL }
63 }
64
65 class MalHashMap does MalMeta is export {
66 has $.val handles <cache AT-KEY EXISTS-KEY elems pairs keys values kv>;
67 method CALL-ME ($val) { self.new(:$val) }
68 }
69
70 class MalNumber does MalValue is export {}
71
72 class MalString does MalValue is export {
73 method seq {
74 return self.val.chars
75 ?? MalList(self.val.comb.map({MalString($_)}))
76 !! $NIL;
77 }
78 }
79
80 class MalCode does MalCallable does MalMeta is export {
81 method CALL-ME (&fn) { self.new(:&fn) }
82 }
83
84 class MalFunction does MalCallable does MalMeta is export {
85 has $.ast;
86 has @.params;
87 has $.env;
88 has $.is_macro is rw = False;
89 method CALL-ME ($ast, $env, @params, &fn) {
90 self.bless(:$ast, :$env, :@params, :&fn);
91 }
92 }
93
94 class MalAtom does MalValue does MalMeta is export {}