xtype (halted)

Check-in [37988572a5]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Improve API checks.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 37988572a57a23d9c81afd20cfa6076d20de3064930ef3a0f8df60bec42a02a3
User & Date: imagic 2021-11-08 19:30:44.000
Context
2021-11-08
20:25
Add low-level API. ... (check-in: be91a3e5fe user: imagic tags: trunk)
19:30
Improve API checks. ... (check-in: 37988572a5 user: imagic tags: trunk)
2021-01-26
20:30
Minor example fix. ... (check-in: 4ba6c66a6c user: imagic tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/xtype.lua.
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
local table_unpack = table.unpack or unpack
local type, select = type, select
local table_pack = table.pack or function(...)
  local t = {...}
  t.n = select("#", ...)
  return t
end





-- xtype

local xtype = {}

local function xtype_tostring(t)
  local mt = getmetatable(t)
  mt.__tostring = nil
  local str = string.gsub(tostring(t), "table:", "xtype<"..t.xtype_name..">:", 1)
  mt.__tostring = xtype_tostring
  return str
end

local type_mt = {
  xtype = "xtype",
  __tostring = xtype_tostring
}





-- Create a type.
--
-- The created type is a table with 3 fields: xtype_name, xtype_stack and xtype_set.
-- The table can be modified as long as the xtype fields are left untouched.
-- A default metatable is set; it can be replaced at the condition that the
-- type would still be recognized as a "xtype".
--
-- name: human-readable string (doesn't have to be unique)
-- ...: base types, be specific in descending order
-- return created type
function xtype.create(name, ...)
  if type(name) ~= "string" then error("invalid name") end
  -- check base types
  local bases = table_pack(...)
  for i=1, bases.n do
    local base = bases[i]
    if not (type(base) == "string" or (type(base) == "table" and base.xtype_name)) then
      error("invalid base type #"..i)
    end
  end
  -- create
  local t = setmetatable({
    xtype_name = name,
    xtype_stack = {},
    xtype_set = {}
  }, type_mt)
  -- append self







>
>
>
>

















>
>
>
>












|


|
<
<
<
<
<







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
local table_unpack = table.unpack or unpack
local type, select = type, select
local table_pack = table.pack or function(...)
  local t = {...}
  t.n = select("#", ...)
  return t
end

local function error_arg(index, expected)
  error("bad argument #2 ("..expected.." expected)")
end

-- xtype

local xtype = {}

local function xtype_tostring(t)
  local mt = getmetatable(t)
  mt.__tostring = nil
  local str = string.gsub(tostring(t), "table:", "xtype<"..t.xtype_name..">:", 1)
  mt.__tostring = xtype_tostring
  return str
end

local type_mt = {
  xtype = "xtype",
  __tostring = xtype_tostring
}

local function check_type(v, index)
  if not (type(v) == "string" or xtype.is(v, "xtype")) then error_arg(index, "type") end
end

-- Create a type.
--
-- The created type is a table with 3 fields: xtype_name, xtype_stack and xtype_set.
-- The table can be modified as long as the xtype fields are left untouched.
-- A default metatable is set; it can be replaced at the condition that the
-- type would still be recognized as a "xtype".
--
-- name: human-readable string (doesn't have to be unique)
-- ...: base types, be specific in descending order
-- return created type
function xtype.create(name, ...)
  if type(name) ~= "string" then error_arg(1, "string") end
  -- check base types
  local bases = table_pack(...)
  for i=1, bases.n do check_type(bases[i], i+1) end





  -- create
  local t = setmetatable({
    xtype_name = name,
    xtype_stack = {},
    xtype_set = {}
  }, type_mt)
  -- append self
124
125
126
127
128
129
130
131



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148

149
150
151
152
153
154
155

156
157
158
159
160
161
162
163
-- different ctype qualifiers should match the same type.
--
-- ctype: cdata ctype object
-- t: (optional) type
-- return bound type
function xtype.ctype(ctype, t)
  local id = tonumber(ctype)
  if t and not ctype_types[id] then ctype_types[id] = t end



  return ctype_types[id]
end

-- Get terminal type of a value.
local function xtype_get(v)
  local v_type = type(v)
  if v_type == "table" or v_type == "userdata" then
    local mt = getmetatable(v)
    return mt and mt.xtype or v_type
  elseif v_type == "cdata" then
    return ctype_types[tonumber(ffi.typeof(v))] or v_type
  else return v_type end
end
xtype.get = xtype_get

-- Check if a value is of type t.
function xtype.is(v, t)

  local vt = xtype_get(v)
  if type(vt) == "table" then return vt.xtype_set[t] ~= nil
  else return vt == t end
end

-- Check if a type is of type ot.
function xtype.of(t, ot)

  if type(t) == "table" then return t.xtype_set[ot] ~= nil
  else return t == ot end
end

-- Multifunction.

local function multifunction_tostring(t)
  local mt = getmetatable(t)







|
>
>
>

















>

|





>
|







127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
-- different ctype qualifiers should match the same type.
--
-- ctype: cdata ctype object
-- t: (optional) type
-- return bound type
function xtype.ctype(ctype, t)
  local id = tonumber(ctype)
  if t and not ctype_types[id] then
    check_type(t, 2)
    ctype_types[id] = t
  end
  return ctype_types[id]
end

-- Get terminal type of a value.
local function xtype_get(v)
  local v_type = type(v)
  if v_type == "table" or v_type == "userdata" then
    local mt = getmetatable(v)
    return mt and mt.xtype or v_type
  elseif v_type == "cdata" then
    return ctype_types[tonumber(ffi.typeof(v))] or v_type
  else return v_type end
end
xtype.get = xtype_get

-- Check if a value is of type t.
function xtype.is(v, t)
  check_type(t, 2)
  local vt = xtype_get(v)
  if type(vt) == "table" then return vt.xtype_set[t]
  else return vt == t end
end

-- Check if a type is of type ot.
function xtype.of(t, ot)
  check_type(t, 1); check_type(ot, 2)
  if type(t) == "table" then return t.xtype_set[ot]
  else return t == ot end
end

-- Multifunction.

local function multifunction_tostring(t)
  local mt = getmetatable(t)
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
  for _, t in ipairs(sign) do node = node[t] end
  return node[1]
end

-- Check and return signature.
local function check_sign(...)
  local sign = table_pack(...)
  for i=1, sign.n do
    local t = sign[i]
    if type(t) ~= "table" and type(t) ~= "string" then
      error("invalid signature type #"..i)
    end
  end
  return sign
end

-- return formatted signature string
local function format_sign(sign)
  local names = {}
  for _, t in ipairs(sign) do







|
<
<
<
<
<







201
202
203
204
205
206
207
208





209
210
211
212
213
214
215
  for _, t in ipairs(sign) do node = node[t] end
  return node[1]
end

-- Check and return signature.
local function check_sign(...)
  local sign = table_pack(...)
  for i=1, sign.n do check_type(sign[i], i) end





  return sign
end

-- return formatted signature string
local function format_sign(sign)
  local names = {}
  for _, t in ipairs(sign) do