1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
--- lam.types
local types = {}
local util = require "util"
table.unpack = table.unpack or unpack
--- Converting between types
types.globalns = {} -- namespace
types.Symbol =
function (name, ns, aliases)
ns = ns or types.globalns
aliases = aliases or {}
if ns[name] then return ns[name] end
local sym = { name = name, aliases = aliases }
ns[name] = sym
for _,a in ipairs(aliases) do
ns[a] = sym
end
local mt = {
__type = "Symbol",
__tostring = function (self) return self.name end,
}
return setmetatable(sym, mt)
end
types.Number = tonumber
types.String =
function (str)
local s = {
value = str,
escape =
function(self)
return self:gsub("\"", "\\\"")
end,
}
local mt = {
__type = "String",
__tostring =
function (self)
return string.format(
"\"%s\"",
self:escape())
end,
}
return setmetatable(s, mt)
end
types.Cons =
function (a, b)
assert(a ~= nil and b ~= nil,
"Need two non-nil arguments in a pair")
local s = { a, b }
local mt = {
__type = "Pair",
__tostring =
function (p)
local out = {}
local car, cdr = p[1], p[2]
while cdr do
table.insert(out, tostring(car))
if type(cdr) == "table" then
car = cdr[1]
cdr = cdr[2]
else
table.insert(out, ".")
table.insert(out, cdr)
break
end
end
return "("..table.concat(out, " ")..")"
end
}
return setmetatable(s, mt)
end
types.List =
function (tbl)
local function tolist(base, items)
if #items == 0 then return base end
return tolist(
types.Cons(table.remove(items), base),
items)
end
return tolist({}, tbl)
end
--- Determining types
types.lamtype =
function (x)
if type(x) == "number" then
return "Number"
elseif getmetatable(x) and getmetatable(x).__type then
return getmetatable(x).__type
else
return type(x)
end
end
--- Type predicates
types.isa =
function (x, t)
return types.lamtype(x) == t
end
---
return types
|