1 local utils
= require('utils')
2 local types
= require('types')
3 local reader
= require('reader')
4 local printer
= require('printer')
5 local readline
= require('readline')
6 local socket
= require('socket')
8 local Nil
, List
, HashMap
, _pr_str
= types
.Nil
, types
.List
, types
.HashMap
, printer
._pr_str
16 utils
.map(function(e
) return _pr_str(e
, true) end, arg
), " ")
21 utils
.map(function(e
) return _pr_str(e
, false) end, arg
), "")
26 utils
.map(function(e
) return _pr_str(e
, true) end, arg
), " "))
33 utils
.map(function(e
) return _pr_str(e
, false) end, arg
), " "))
40 for line
in io
.lines(file
) do
41 lines
[#lines
+1] = line
43 return table.concat(lines
, "\n") .. "\n"
46 function do_readline(prompt
)
47 local line
= readline
.readline(prompt
)
57 function assoc(hm
, ...)
58 return types
._assoc_BANG(types
.copy(hm
), unpack(arg
))
61 function dissoc(hm
, ...)
62 return types
._dissoc_BANG(types
.copy(hm
), unpack(arg
))
67 if res
== nil then return Nil
end
73 for k
,v
in pairs(hm
) do
81 for k
,v
in pairs(hm
) do
87 -- sequential functions
90 local new_lst
= lst
:slice(1)
91 table.insert(new_lst
, 1, a
)
92 return List
:new(new_lst
)
99 table.insert(new_lst
, arg
[i
][j
])
102 return List
:new(new_lst
)
105 function nth(seq
, idx
)
106 if idx
+1 <= #seq
then
109 types
.throw("nth: index out of range")
125 return List
:new(a
:slice(2))
129 function apply(f
, ...)
130 if types
._malfunc_Q(f
) then
133 local args
= concat(types
.slice(arg
, 1, #arg
-1),
135 return f(unpack(args
))
139 if types
._malfunc_Q(f
) then
142 return List
:new(utils
.map(f
, lst
))
145 -- metadata functions
148 local m
= getmetatable(obj
)
149 if m
== nil or m
.meta
== nil then return Nil
end
153 function with_meta(obj
, meta
)
154 local new_obj
= types
.copy(obj
)
155 getmetatable(new_obj
).meta
= meta
161 function swap_BANG(atm
,f
,...)
162 if types
._malfunc_Q(f
) then
165 local args
= List
:new(arg
)
166 table.insert(args
, 1, atm
.val
)
167 atm
.val
= f(unpack(args
))
171 local function conj(obj
, ...)
172 local new_obj
= types
.copy(obj
)
173 if types
._list_Q(new_obj
) then
174 for i
, v
in ipairs(arg
) do
175 table.insert(new_obj
, 1, v
)
178 for i
, v
in ipairs(arg
) do
179 table.insert(new_obj
, v
)
185 local function seq(obj
, ...)
186 if obj
== Nil
or #obj
== 0 then
188 elseif types
._list_Q(obj
) then
190 elseif types
._vector_Q(obj
) then
192 elseif types
._string_Q(obj
) then
195 chars
[#chars
+1] = string.sub(obj
,i
,i
)
197 return List
:new(chars
)
202 local function lua_to_mal(a
)
205 elseif type(a
) == "boolean" or type(a
) == "number" or type(a
) == "string" then
207 elseif type(a
) == "table" then
208 local first_key
, _
= next(a
)
209 if first_key
== nil then
211 elseif type(first_key
) == "number" then
213 for i
, v
in ipairs(a
) do
214 list
[i
] = lua_to_mal(v
)
216 return List
:new(list
)
219 for k
, v
in pairs(a
) do
220 hashmap
[lua_to_mal(k
)] = lua_to_mal(v
)
222 return HashMap
:new(hashmap
)
228 local function lua_eval(str
)
229 local f
, err
= loadstring("return "..str
)
231 types
.throw("lua-eval: can't load code: "..err
)
233 return lua_to_mal(f())
237 ['='] = types
._equal_Q
,
240 ['nil?'] = function(a
) return a
==Nil
end,
241 ['true?'] = function(a
) return a
==true end,
242 ['false?'] = function(a
) return a
==false end,
243 symbol
= function(a
) return types
.Symbol
:new(a
) end,
244 ['symbol?'] = function(a
) return types
._symbol_Q(a
) end,
245 ['string?'] = function(a
) return types
._string_Q(a
) and "\177" ~= string.sub(a
,1,1) end,
246 keyword
= function(a
) return "\177"..a
end,
247 ['keyword?'] = function(a
) return types
._keyword_Q(a
) end,
253 ['read-string'] = reader
.read_str
,
254 readline
= do_readline
,
257 ['<'] = function(a
,b
) return a
<b
end,
258 ['<='] = function(a
,b
) return a
<=b
end,
259 ['>'] = function(a
,b
) return a
>b
end,
260 ['>='] = function(a
,b
) return a
>=b
end,
261 ['+'] = function(a
,b
) return a
+b
end,
262 ['-'] = function(a
,b
) return a
-b
end,
263 ['*'] = function(a
,b
) return a
*b
end,
264 ['/'] = function(a
,b
) return math
.floor(a
/b
) end,
265 ['time-ms'] = function() return math
.floor(socket
.gettime() * 1000) end,
267 list
= function(...) return List
:new(arg
) end,
268 ['list?'] = function(a
) return types
._list_Q(a
) end,
269 vector
= function(...) return types
.Vector
:new(arg
) end,
270 ['vector?'] = types
._vector_Q
,
271 ['hash-map'] = types
.hash_map
,
272 ['map?'] = types
._hash_map_Q
,
276 ['contains?'] = function(a
,b
) return a
[b
] ~= nil end,
280 ['sequential?'] = types
._sequential_Q
,
286 ['empty?'] = function(a
) return a
==Nil
or #a
== 0 end,
287 count
= function(a
) return #a
end,
294 ['with-meta'] = with_meta
,
295 atom
= function(a
) return types
.Atom
:new(a
) end,
296 ['atom?'] = types
._atom_Q
,
297 deref
= function(a
) return a
.val
end,
298 ['reset!'] = function(a
,b
) a
.val
= b
; return b
end,
299 ['swap!'] = swap_BANG
,
301 ['lua-eval'] = lua_eval
,