1 local utils
= require('utils')
7 function M
._sequential_Q(obj
)
8 return M
._list_Q(obj
) or M
._vector_Q(obj
)
11 function M
._equal_Q(a
,b
)
12 if M
._symbol_Q(a
) and M
._symbol_Q(b
) then
14 elseif M
._sequential_Q(a
) and M
._sequential_Q(b
) then
15 if #a
~= #b
then return false end
16 for i
, v
in ipairs(a
) do
17 if not M
._equal_Q(v
,b
[i
]) then return false end
20 elseif M
._hash_map_Q(a
) and M
._hash_map_Q(b
) then
21 if #a
~= #b
then return false end
22 for k
, v
in pairs(a
) do
23 if not M
._equal_Q(v
,b
[k
]) then return false end
32 if type(obj
) == "function" then
33 return M
.FunctionRef
:new(obj
)
35 if type(obj
) ~= "table" then return obj
end
39 for k
,v
in pairs(obj
) do
43 -- copy metatable and link to original
44 local old_mt
= getmetatable(obj
)
47 for k
,v
in pairs(old_mt
) do
50 setmetatable(new_mt
, old_mt
)
51 setmetatable(new_obj
, new_mt
)
57 function M
.slice(lst
, start
, last
)
58 if last
== nil then last
= #lst
end
61 for i
= start
, last
do
62 new_lst
[#new_lst
+1] = lst
[i
]
71 function M
.MalException
:new(val
)
72 local newObj
= {val
= val
}
74 return setmetatable(newObj
, self
)
76 function M
._malexception_Q(obj
)
77 return utils
.instanceOf(obj
, M
.MalException
)
81 error(M
.MalException
:new(val
))
87 function NilType
:new(val
)
90 return setmetatable(newObj
, self
)
93 function M
._nil_Q(obj
)
98 function M
._string_Q(obj
)
99 return type(obj
) == "string"
105 function M
.Symbol
:new(val
)
106 local newObj
= {val
= val
}
108 return setmetatable(newObj
, self
)
110 function M
._symbol_Q(obj
)
111 return utils
.instanceOf(obj
, M
.Symbol
)
115 function M
._keyword_Q(obj
)
116 return M
._string_Q(obj
) and "\177" == string.sub(obj
,1,1)
123 function M
.List
:new(lst
)
124 local newObj
= lst
and lst
or {}
126 return setmetatable(newObj
, self
)
128 function M
._list_Q(obj
)
129 return utils
.instanceOf(obj
, M
.List
)
131 function M
.List
:slice(start
,last
)
132 return M
.List
:new(M
.slice(self
,start
,last
))
138 function M
.Vector
:new(lst
)
139 local newObj
= lst
and lst
or {}
141 return setmetatable(newObj
, self
)
143 function M
._vector_Q(obj
)
144 return utils
.instanceOf(obj
, M
.Vector
)
146 function M
.Vector
:slice(start
,last
)
147 return M
.Vector
:new(M
.slice(self
,start
,last
))
153 function M
.HashMap
:new(val
)
154 local newObj
= val
and val
or {}
156 return setmetatable(newObj
, self
)
158 function M
.hash_map(...)
159 return M
._assoc_BANG(M
.HashMap
:new(), unpack(arg
))
161 function M
._hash_map_Q(obj
)
162 return utils
.instanceOf(obj
, M
.HashMap
)
164 function M
._assoc_BANG(hm
, ...)
165 for i
= 1, #arg
, 2 do
166 hm
[arg
[i]]
= arg
[i
+1]
170 function M
._dissoc_BANG(hm
, ...)
180 function M
.MalFunc
:new(fn
, ast
, env
, params
)
181 local newObj
= {fn
= fn
, ast
= ast
, env
= env
,
182 params
= params
, ismacro
= false}
184 return setmetatable(newObj
, self
)
186 function M
._malfunc_Q(obj
)
187 return utils
.instanceOf(obj
, M
.MalFunc
)
193 function M
.Atom
:new(val
)
194 local newObj
= {val
= val
}
196 return setmetatable(newObj
, self
)
198 function M
._atom_Q(obj
)
199 return utils
.instanceOf(obj
, M
.Atom
)
205 function M
.FunctionRef
:new(fn
)
206 local newObj
= {fn
= fn
}
207 return setmetatable(newObj
, self
)
209 function M
._functionref_Q(obj
)
210 return utils
.instanceOf(obj
, M
.FunctionRef
)
212 function M
.FunctionRef
:__call(...)