Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Improve cdata support with __xtype field. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA3-256: |
1f1ab704d55f37b5d61bc8abb8ba2b9f |
| User & Date: | imagic 2021-11-10 00:55:08.000 |
Context
|
2021-11-10
| ||
| 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) | |
|
2021-11-08
| ||
| 20:25 | Add low-level API. ... (check-in: be91a3e5fe user: imagic tags: trunk) | |
Changes
Changes to README.adoc.
| ︙ | ︙ | |||
28 29 30 31 32 33 34 | A primitive type is a string. It can be any Lua types from `type()` or additional types like `xtype` or `multifunction`. A non-primitive type is a table defining the type. It contains the `xtype_name`, `xtype_stack` and `xtype_set` fields and should identify as a `xtype`. ==== Value | | > > > > > > | 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | A primitive type is a string. It can be any Lua types from `type()` or additional types like `xtype` or `multifunction`. A non-primitive type is a table defining the type. It contains the `xtype_name`, `xtype_stack` and `xtype_set` fields and should identify as a `xtype`. ==== Value Any Lua value has a type; we will call this the terminal type of the value as opposed to inherited types. If the metatable of a `table` or `userdata` value has a `xtype` field, then the type is the value of that field. If the value is a `cdata`, its type is defined by `xtype.ctype()` or the `\__xtype` field (e.g. through the metatype `__index`) which will call `xtype.ctype()` when encountered. Otherwise, the type is the Lua type returned by `type()`. ==== Inheritance A non-primitive type can inherit from other types, building a stack of types. This stack defines the order in which the types are evaluated, from the terminal type to the least specific inherited types. === Multifunction |
| ︙ | ︙ |
Changes to examples/test_cdata.lua.
1 2 3 4 5 |
-- Test FFI cdata support.
package.path = "src/?.lua;"..package.path
local ffi = require("ffi")
local xtype = require("xtype")
| > | | | | | | | | | | | | | | | | | | | | | | | | | < | | | < | | | | | | | | > > > > > > > > > > > > | 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 |
-- 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
setmetatable(vec2, {
xtype = "xtype",
__call = function(_, ...) return vec2_t(...) end
})
-- instance behavior
ffi.metatype(vec2_t, {
__unm = function(v) return vec2(-v.x, -v.y) end,
__add = xtype.op.add,
__sub = xtype.op.sub,
__mul = xtype.op.mul,
__div = xtype.op.div,
__eq = xtype.op.eq
})
xtype.op.add:define(function(a, b) return vec2(a.x+b.x, a.y+b.y) end, vec2, vec2)
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)
xtype.ctype(ffi.typeof(p), vec2)
assert(r == p)
assert(r == vec2(2,2))
assert(r/p == vec2(1,1))
end
do -- test type acquisition from field
ffi.cdef("typedef struct{} test_field_t;")
local test_field = xtype.create("test_field")
local ctype = ffi.typeof("test_field_t")
ffi.metatype(ctype, {__index = {__xtype = test_field}})
-- checks
assert(xtype.get(ffi.new("test_field_t")) == test_field)
assert(xtype.get(ffi.new("test_field_t*")) == test_field)
local ar = ffi.new("test_field_t[1]")
assert(xtype.get(ar[1]) == test_field)
end
|
Changes to src/xtype.lua.
| ︙ | ︙ | |||
91 92 93 94 95 96 97 |
-- 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
| | > > > > > | 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
-- 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
local xt = ctype_types[tonumber(ffi.typeof(v))]
if not xt then -- try to acquire type from field
local ok; ok, xt = pcall(function(v) return v.__xtype end, v)
if ok then xtype.ctype(ffi.typeof(v), xt) end
end
return xt or v_type
else return v_type end
end
xtype.get = xtype_get
-- Check if a value is of type t.
xtype_is = function(v, t)
check_type(t, 2)
|
| ︙ | ︙ |