--- lam.environment local util = require "util" local types = require "types" table.unpack = table.unpack or unpack local global = { -- constants ---- TODO this should be at the reader level ["#t"] = true, ["#f"] = false, } --- Types --- global.luatype = type global.type = types.lamtype global["number?"] = function (x) types.isa(x, "Number") end global["string?"] = function (x) types.isa(x, "String") end global["symbol?"] = function (x) types.isa(x, "Symbol") end global["pair?"] = function (x) types.isa(x, "Pair") end global["is-a?"] = function (x, t) types.isa(x, t) end --- Basic functions --- global.car = function (pair) return pair[1] end global.cdr = function (pair) return pair[2] end -- global.list = types.List global["list?"] = function (x) -- TODO : detect circular lists if type(x) == "table" then if #x == 0 then return true end if type(x[2]) ~= "table" then return false end end return global["list?"](x[2]) end global["null?"] = function (x) return type(x) == "table" and #x == 0 end --- Higher-order functions --- --[[ global.apply = function(fn, ...) local args = {...} local last = args[#args] assert(types.luatype(last) == "table", "Bad apply") table.remove(args) for _, v in ipairs(last) do table.insert(args, v) end return fn(table.unpack(args)) end global.map = function(fn, list) return util.map(fn, list) end --]] --- Math --- -- NOTE: we do not have the full numeric tower yet! for name, func in pairs(math) do global[name] = func end global.fold = function (fn, lis) local out = {} return types.List(out) end global["+"] = function (lis) return return util.reduce({...}, 0, function (a, b) return a + b end) end global["-"] = function (...) local args = {...} if #args == 0 then error("Too few arguments: need at least 1") elseif #args == 1 then return (-args[1]) else local result = args[1] for v = 2, #args do result = result - args[v] end return result end end global["*"] = function (...) local result = 1 for _, v in ipairs({...}) do if v == 0 then return 0 end result = result * v end return result end global["/"] = function (...) local args = {...} if #args == 0 then error("Too few arguments: need at least 1") elseif #args == 1 then if args[1] == 0 then error("Division by zero") end return (1/args[1]) else local result = args[1] for v = 2, #args do if args[v] == 0 then error("Division by zero") end result = result / args[v] end return result end end --[[ global["="] = function (...) for _, v in ipairs({...}) do if not a == b then return false end end return true end global["<"] = function (...) for _, v in ipairs({...}) do if not a < b then return false end end return true end global["<="] = function (...) for _, v in ipairs({...}) do if not a <= b then return false end end return true end global[">"] = function (...) for _, v in ipairs({...}) do if not a > b then return false end end return true end global[">="] = function (...) for _, v in ipairs({...}) do if not a >= b then return false end end return true end --]] --- return global