Merge pull request #440 from aasimk2000/add-nil-if-test
[jackhill/mal.git] / crystal / types.cr
CommitLineData
4f725b5c 1require "./printer"
2
fdf28b76 3module 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 103end
51be5007 104
ce0696d5 105macro gen_type(t, *args)
106 Mal::Type.new {{t.id}}.new({{*args}})
51be5007 107end
09fb509e 108
109class Array
110 def to_mal(t = Mal::List)
5185c56e 111 each_with_object(t.new) { |e, l| l << e }
09fb509e 112 end
113end