Commit | Line | Data |
---|---|---|
4f725b5c | 1 | require "./printer" |
2 | ||
fdf28b76 | 3 | module Mal |
7fe6282e | 4 | class Type |
9b8a3da9 | 5 | alias Func = (Array(Type) -> Type) |
7fe6282e | 6 | |
6e7390b7 | 7 | property :is_macro, :meta |
9bbb8ccc | 8 | |
7fe6282e | 9 | def initialize(@val : ValueType) |
9bbb8ccc | 10 | @is_macro = false |
5185c56e | 11 | @meta = nil.as(Type | Nil) |
7fe6282e | 12 | end |
13 | ||
14 | def initialize(other : Type) | |
9b8a3da9 | 15 | @val = other.unwrap |
6e7390b7 | 16 | @is_macro = other.is_macro |
17 | @meta = other.meta | |
7fe6282e | 18 | end |
afc3a8d5 | 19 | |
2c76c2ff | 20 | def unwrap |
21 | @val | |
22 | end | |
9b8a3da9 | 23 | |
9bbb8ccc | 24 | def macro? |
25 | @is_macro | |
26 | end | |
27 | ||
4f725b5c | 28 | def to_s |
29 | pr_str(self) | |
30 | end | |
31 | ||
6e7390b7 | 32 | def dup |
33 | Type.new(@val).tap do |t| | |
34 | t.is_macro = @is_macro | |
35 | t.meta = @meta | |
36 | end | |
37 | end | |
38 | ||
ce0696d5 | 39 | def ==(other : Type) |
9b8a3da9 | 40 | @val == other.unwrap |
41 | end | |
42 | ||
43 | macro rel_op(*ops) | |
44 | {% for op in ops %} | |
45 | def {{op.id}}(other : Mal::Type) | |
46 | l, r = @val, other.unwrap | |
7546ae18 | 47 | {% for t in [Int64, String] %} |
9b8a3da9 | 48 | if l.is_a?({{t}}) && r.is_a?({{t}}) |
49 | return (l) {{op.id}} (r) | |
50 | end | |
51 | {% end %} | |
52 | if l.is_a?(Symbol) && r.is_a?(Symbol) | |
53 | return l.str {{op.id}} r.str | |
54 | end | |
55 | false | |
56 | end | |
57 | {% end %} | |
58 | end | |
59 | ||
60 | rel_op :<, :>, :<=, :>= | |
afc3a8d5 | 61 | end |
eec5fc4f | 62 | |
5185c56e OR |
63 | class Symbol |
64 | property :str | |
65 | ||
66 | def initialize(@str : String) | |
67 | end | |
68 | ||
69 | def ==(other : Symbol) | |
70 | @str == other.str | |
71 | end | |
72 | end | |
73 | ||
74 | class List < Array(Type) | |
75 | end | |
76 | ||
77 | class Vector < Array(Type) | |
78 | end | |
79 | ||
80 | class HashMap < Hash(String, Type) | |
81 | end | |
82 | ||
83 | class Atom | |
84 | property :val | |
85 | ||
86 | def initialize(@val : Type) | |
87 | end | |
88 | ||
89 | def ==(rhs : Atom) | |
90 | @val == rhs.val | |
91 | end | |
92 | end | |
93 | ||
94 | class Closure | |
95 | property :ast, :params, :env, :fn | |
96 | ||
97 | def initialize(@ast : Type, @params : Array(Mal::Type) | List | Vector, @env : Env, @fn : Func) | |
98 | end | |
99 | end | |
100 | ||
101 | alias Type::ValueType = Nil | Bool | Int64 | String | Symbol | List | Vector | HashMap | Func | Closure | Atom | |
9b8a3da9 | 102 | alias Func = Type::Func |
fdf28b76 | 103 | end |
51be5007 | 104 | |
ce0696d5 | 105 | macro gen_type(t, *args) |
106 | Mal::Type.new {{t.id}}.new({{*args}}) | |
51be5007 | 107 | end |
09fb509e | 108 | |
109 | class Array | |
110 | def to_mal(t = Mal::List) | |
5185c56e | 111 | each_with_object(t.new) { |e, l| l << e } |
09fb509e | 112 | end |
113 | end |