xtype (halted)

Check-in [786267d6c7]
Login

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

Overview
Comment:Improve tests and add global test.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 786267d6c7fb57d5fcc89a6f60098b8da022a7e29d877b78e99ec1399508bb4e
User & Date: imagic 2021-11-10 19:31:25.000
Context
2021-11-10
19:37
Support more Lua binary operators. ... (check-in: a12db62772 user: imagic tags: trunk)
19:31
Improve tests and add global test. ... (check-in: 786267d6c7 user: imagic tags: trunk)
00:55
Improve cdata support with __xtype field. ... (check-in: 1f1ab704d5 user: imagic tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to examples/test_cdata.lua.
1
2
3




4
5
6
7
8
9
10
-- Test FFI cdata support.
package.path = "src/?.lua;"..package.path
local ffi = require("ffi")




local xtype = require("xtype")

do -- test vec example
  ffi.cdef("typedef struct{double x, y;} vec2_t;")
  local vec2 = xtype.create("vec2")
  local vec2_t = ffi.typeof("vec2_t")
  -- type behavior


|
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
-- Test FFI cdata support.
package.path = "src/?.lua;"..package.path

-- No need to test if the FFI is not available.
local ffi_ok, ffi = pcall(require, "ffi")
if not ffi_ok then return end

local xtype = require("xtype")

do -- test vec example
  ffi.cdef("typedef struct{double x, y;} vec2_t;")
  local vec2 = xtype.create("vec2")
  local vec2_t = ffi.typeof("vec2_t")
  -- type behavior
25
26
27
28
29
30
31

32
33
34
35
36
37
38
  xtype.op.mul:define(function(v, n) return vec2(v.x*n, v.y*n) end, vec2, "number")
  xtype.op.mul:define(function(n, v) return vec2(v.x*n, v.y*n) end, "number", vec2)
  xtype.op.div:define(function(a, b) return vec2(a.x/b.x, a.y/b.y) end, vec2, vec2)
  xtype.op.div:define(function(v, n) return vec2(v.x/n, v.y/n) end, vec2, "number")
  xtype.op.eq:define(function(a, b) return a.x == b.x and a.y == b.y end, vec2, vec2)
  -- bind
  xtype.ctype(vec2_t, vec2)

  assert(vec2(1,1) == vec2(1,1))
  assert(vec2(1,1)*2 == 2*vec2(1,1))
  assert(vec2(1,1)+vec2(1,1) == vec2(4,4)/2)
  local a = ffi.new("vec2_t[1]", {{2,2}})
  local r = a[0]
  local p = a+0
  xtype.ctype(ffi.typeof(r), vec2)







>







29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
  xtype.op.mul:define(function(v, n) return vec2(v.x*n, v.y*n) end, vec2, "number")
  xtype.op.mul:define(function(n, v) return vec2(v.x*n, v.y*n) end, "number", vec2)
  xtype.op.div:define(function(a, b) return vec2(a.x/b.x, a.y/b.y) end, vec2, vec2)
  xtype.op.div:define(function(v, n) return vec2(v.x/n, v.y/n) end, vec2, "number")
  xtype.op.eq:define(function(a, b) return a.x == b.x and a.y == b.y end, vec2, vec2)
  -- bind
  xtype.ctype(vec2_t, vec2)
  -- checks
  assert(vec2(1,1) == vec2(1,1))
  assert(vec2(1,1)*2 == 2*vec2(1,1))
  assert(vec2(1,1)+vec2(1,1) == vec2(4,4)/2)
  local a = ffi.new("vec2_t[1]", {{2,2}})
  local r = a[0]
  local p = a+0
  xtype.ctype(ffi.typeof(r), vec2)
Changes to examples/test_error.lua.
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
-- Test errors.
package.path = "src/?.lua;"..package.path
local xtype = require("xtype")

-- Expect an error.
local function check(f)
  local ok, err = pcall(f)
  assert(not ok)
  print("[checked]", err)
end


check(function() xtype.create() end)
check(function() xtype.create(5) end)






local mf = xtype.multifunction()
check(function() mf:define(function() end, nil) end)
check(function() mf:define(function() end, 1) end)
check(function() mf:define(nil, "number", nil, "number") end)
mf:define(function() end, "number", "number")
check(function() mf() end)
check(function() mf(5) end)

check(function() mf(5, 5, 5) end)
check(function() mf(5, "5") end)
mf:define(nil, "number", "number")

check(function() mf(5, 5) end)





<
|
|
|
<


>
|
|
|
>
>
>
>
>
|
|
|
|
|
|
|
>
|
|
|
>
|

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
-- Test errors.
package.path = "src/?.lua;"..package.path
local xtype = require("xtype")


local function errcheck(perr, f, ...)
  local ok, err = pcall(f, ...)
  assert(not ok and not not err:find(perr))

end

do -- test xtype
  errcheck("bad argument #1", xtype.create)
  errcheck("bad argument #1", xtype.create, 5)
  errcheck("bad argument #2", xtype.create, "test", 5)
  errcheck("bad argument #2", xtype.is, 5, nil)
  errcheck("bad argument #1", xtype.of, 5, "number")
  errcheck("bad argument #2", xtype.of, "number", 5)
end
do -- test multifunction
  local mf = xtype.multifunction()
  errcheck("type expected", mf.define, mf, function() end, nil)
  errcheck("type expected", mf.define, mf, function() end, 1)
  errcheck("type expected", mf.define, mf, nil, "number", nil, "number")
  mf:define(function() end, "number", "number")
  mf(5,5)
  errcheck("unresolved call signature", mf)
  errcheck("unresolved call signature", mf, 5)
  errcheck("unresolved call signature", mf, 5, 5, 5)
  errcheck("unresolved call signature", mf, 5, "5")
  mf:define(nil, "number", "number")
  errcheck("unresolved call signature", mf, 5, 5)
end

Added examples/test_main.lua.


































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
-- Test type creation and inheritance.
package.path = "src/?.lua;"..package.path
local xtype = require("xtype")

-- Init.

local being = xtype.create("being")
local animal = xtype.create("animal", being)
local mammal = xtype.create("mammal", animal)
local carnivorous = xtype.create("carnivorous")
local omnivorous = xtype.create("omnivorous")
local hominidae = xtype.create("hominidae", mammal, omnivorous)
local canidae = xtype.create("canidae", mammal, carnivorous)
local human = xtype.create("human", hominidae)
local dog = xtype.create("dog", canidae)
local chimera = xtype.create("chimera", human, dog)

local Nina = setmetatable({}, {xtype = human})
local Alexander = setmetatable({}, {xtype = dog})
local Chimera = setmetatable({}, {xtype = chimera})

-- Test.

-- check
assert(xtype.check("number"))
assert(xtype.check(being))
assert(not xtype.check(0))
-- name
assert(xtype.name("number") == "number")
assert(xtype.name(being) == "being")
assert(xtype.name(0) == nil)
-- misc get/is
assert(xtype.get(0) == "number")
assert(xtype.is(0, "number"))
assert(not xtype.is(0, "string"))
assert(xtype.get(being) == "xtype")
-- of
assert(xtype.of("number", "number"))
assert(xtype.of(being, being))
assert(xtype.of(animal, being))
assert(xtype.of(mammal, being))
assert(xtype.of(mammal, animal))
assert(xtype.of(canidae, mammal))
assert(xtype.of(canidae, being))
assert(xtype.of(canidae, carnivorous))
assert(xtype.of(dog, canidae))
assert(xtype.of(human, hominidae))
assert(not xtype.of(human, dog))
-- is
assert(xtype.is(Nina, human))
assert(xtype.is(Alexander, dog))
assert(xtype.is(Chimera, human))
assert(xtype.is(Chimera, dog))
-- typeDist
assert(xtype.typeDist(dog, "number") == nil)
assert(xtype.typeDist(dog, dog) == 0)
assert(xtype.typeDist(dog, being) == 5)
assert(xtype.typeDist(being, dog) == nil)
-- misc low-level
assert(xtype.signDist(xtype.checkSign(dog), xtype.checkSign(being)) == 5)
assert(xtype.signDist(xtype.checkSign(being), xtype.checkSign(dog)) == nil)
assert(xtype.formatSign(xtype.checkSign("number", dog, being)) == "(number, dog, being)")
-- tools
assert(xtype.tpllist("a$", 1, 3, "+") == "a1+a2+a3")
assert(xtype.tplsub("$k = $v", {k = "a", v = 1}) == "a = 1")
Changes to examples/test_multifunction.lua.
1
2
3
4
5
6
7
8
9
10
11
12
-- Test multifunction.
package.path = "src/?.lua;"..package.path
local xtype = require("xtype")

do -- Basic test.
  local op_add = xtype.multifunction()
  local op_mul = xtype.multifunction()
  local op_eq = xtype.multifunction()

  local function build_type(t)
    local ins_mt = {
      xtype = t,




|







1
2
3
4
5
6
7
8
9
10
11
12
-- Test multifunction.
package.path = "src/?.lua;"..package.path
local xtype = require("xtype")

do -- Test operators.
  local op_add = xtype.multifunction()
  local op_mul = xtype.multifunction()
  local op_eq = xtype.multifunction()

  local function build_type(t)
    local ins_mt = {
      xtype = t,
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

  op_eq:define(function(a, b) return a.v == b.v end, Oranges, Oranges)
  op_eq:define(function(a, b)
    return xtype.get(a) == xtype.get(b) and a.v == b.v
  end, Fruits, Fruits)

  local apples = Apples(5)
  local oranges = Oranges(5)



  assert(apples+apples == Apples(10))


  assert(not (apples+oranges == Apples(10)))
  assert(apples+oranges == Fruits(10))
  assert(oranges+apples == Fruits(10))
  assert(apples*3 == Apples(15))
end

do -- Test resolution order.

  local animal = xtype.create("animal")
  local dog = xtype.create("dog", animal)
  local cat = xtype.create("cat", animal)
  local chimera = xtype.create("chimera", cat, dog)

  local what = xtype.multifunction()
  what:define(function() return "animal" end, animal)
  what:define(function() return "cat" end, cat)
  what:define(function() return "dog" end, dog)
  what:define(function() return "chimera" end, chimera)
  local a = setmetatable({}, {xtype = chimera})

  assert(what(a) == "chimera")


  what:define(nil, chimera)
  assert(what(a) == "cat")
  what:define(nil, cat)
  assert(what(a) == "dog")
  what:define(nil, dog)
  assert(what(a) == "animal")


end

do -- Test generator.
  local unpack = table.unpack or unpack
  local count = xtype.multifunction()
  count:addGenerator(function(self, ...)
    local sign = {...}
    self:define(function() return #sign end, unpack(sign))
  end)

  assert(count() == 0)
  assert(count(1, 2, 3) == 3)
  assert(count("a", "b", "c") == 3)
  assert(count(nil, nil, nil) == 3)
  assert(count(1, nil, "c") == 3)




end








>
>
>

>
>





<

>




|






>

>
>






>
>

<







>





>
>
>
>
|
>
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
  op_eq:define(function(a, b) return a.v == b.v end, Oranges, Oranges)
  op_eq:define(function(a, b)
    return xtype.get(a) == xtype.get(b) and a.v == b.v
  end, Fruits, Fruits)

  local apples = Apples(5)
  local oranges = Oranges(5)
  -- checks
  assert(xtype.is(op_eq, "multifunction"))
  assert(xtype.get(op_eq) == "multifunction")
  assert(apples+apples == Apples(10))
  assert(op_add:call(apples, apples) == Apples(10)) -- alternative
  assert(op_add:resolve(Apples, Apples)(apples, apples) == Apples(10)) -- alternative
  assert(not (apples+oranges == Apples(10)))
  assert(apples+oranges == Fruits(10))
  assert(oranges+apples == Fruits(10))
  assert(apples*3 == Apples(15))
end

do -- Test resolution order.
  -- types
  local animal = xtype.create("animal")
  local dog = xtype.create("dog", animal)
  local cat = xtype.create("cat", animal)
  local chimera = xtype.create("chimera", cat, dog)
  -- multifunction
  local what = xtype.multifunction()
  what:define(function() return "animal" end, animal)
  what:define(function() return "cat" end, cat)
  what:define(function() return "dog" end, dog)
  what:define(function() return "chimera" end, chimera)
  local a = setmetatable({}, {xtype = chimera})
  -- checks
  assert(what(a) == "chimera")
  assert(what:call(a) == "chimera") -- alternative
  assert(what:resolve(chimera)(a) == "chimera") -- alternative
  what:define(nil, chimera)
  assert(what(a) == "cat")
  what:define(nil, cat)
  assert(what(a) == "dog")
  what:define(nil, dog)
  assert(what(a) == "animal")
  assert(what:call(a) == "animal") -- alternative
  assert(what:resolve(chimera)(a) == "animal") -- alternative
end

do -- Test generator.
  local unpack = table.unpack or unpack
  local count = xtype.multifunction()
  count:addGenerator(function(self, ...)
    local sign = {...}
    self:define(function() return #sign end, unpack(sign))
  end)
  -- checks
  assert(count() == 0)
  assert(count(1, 2, 3) == 3)
  assert(count("a", "b", "c") == 3)
  assert(count(nil, nil, nil) == 3)
  assert(count(1, nil, "c") == 3)
  -- check low-level API
  for hash, def in pairs(count.definitions) do
    assert(hash == count:hashSign(def.sign))
    assert(#def.sign == def.f())
  end
end
Deleted examples/test_type.lua.
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
-- Test type creation and inheritance.
package.path = "src/?.lua;"..package.path
local xtype = require("xtype")

local being = xtype.create("being")
local animal = xtype.create("animal", being)
local mammal = xtype.create("mammal", animal)
local carnivorous = xtype.create("carnivorous")
local omnivorous = xtype.create("omnivorous")
local hominidae = xtype.create("hominidae", mammal, omnivorous)
local canidae = xtype.create("canidae", mammal, carnivorous)
local human = xtype.create("human", hominidae)
local dog = xtype.create("dog", canidae)
local chimera = xtype.create("chimera", human, dog)

local Nina = setmetatable({}, {xtype = human})
local Alexander = setmetatable({}, {xtype = dog})
local Chimera = setmetatable({}, {xtype = chimera})

assert(xtype.get(0) == "number")
assert(xtype.is(0, "number"))
assert(not xtype.is(0, "string"))
assert(xtype.get(being) == "xtype")
assert(xtype.of(being, being))

assert(xtype.of(animal, being))
assert(xtype.of(mammal, being))
assert(xtype.of(mammal, animal))
assert(xtype.of(canidae, mammal))
assert(xtype.of(canidae, being))
assert(xtype.of(canidae, carnivorous))
assert(xtype.of(dog, canidae))
assert(xtype.of(human, hominidae))
assert(not xtype.of(human, dog))

assert(xtype.is(Nina, human))
assert(xtype.is(Alexander, dog))
assert(xtype.is(Chimera, human))
assert(xtype.is(Chimera, dog))
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<














































































Changes to src/xtype.lua.
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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)







|







35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
local table_pack = table.pack or function(...)
  local t = {...}
  t.n = select("#", ...)
  return t
end

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

-- xtype

local xtype = {}

local function xtype_tostring(t)
Added test.lua.








































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/env luajit
-- or Lua 5.1

-- config
local envs = {"luajit", "lua5.1", "lua5.2", "lua5.3", "lua5.4"}
local tests = {
  "examples/test_main.lua",
  "examples/test_multifunction.lua",
  "examples/test_cdata.lua",
  "examples/test_error.lua"
}
-- test
local errors = 0
for _, env in ipairs(envs) do
  for _, test in ipairs(tests) do
    local status = os.execute(env.." "..test)
    if status ~= 0 then print(env, test, "FAILED"); errors = errors+1 end
  end
end
if errors > 0 then error(errors.." error(s)") end