-
Notifications
You must be signed in to change notification settings - Fork 1
/
base.t
70 lines (59 loc) · 1.74 KB
/
base.t
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
-- SPDX-FileCopyrightText: 2024 René Hiemstra <rrhiemstar@gmail.com>
-- SPDX-FileCopyrightText: 2024 Torsten Keßler <t.kessler@posteo.de>
--
-- SPDX-License-Identifier: MIT
local concept = require("concept")
local Base = {}
function Base:new(name, func)
local base = {name = name}
setmetatable(base, {__index = self})
local mt = getmetatable(base)
function mt:__call(T)
func(T)
end
function mt.__mul(B1, B2)
local function impl(T)
B1(T)
B2(T)
end
return Base:new(B1.name .. "And" .. B2.name, impl)
end
return base
end
local AbstractBase = Base:new("AbstractBase",
function(T)
assert(terralib.types.istype(T))
assert(T:isstruct())
local Self = concept.Concept:new("Self" .. tostring(T))
Self:addimplementations{T}
for key, val in pairs({staticmethods = {}, templates = {}, Self = Self}) do
if T.key == nil then
rawset(T, key, val)
end
end
Self.methods = T.methods
Self.staticmethods = T.staticmethods
Self.templates = T.templates
T.metamethods.__getmethod = function(self, methodname)
local fnlike = self.methods[methodname] or self.staticmethods[methodname]
if not fnlike and terralib.ismacro(self.metamethods.__methodmissing) then
fnlike = terralib.internalmacro(function(ctx, tree, ...)
return self.metamethods.__methodmissing:run(ctx, tree, methodname, ...)
end)
end
return fnlike
end
T.metamethods.__methodmissing = macro(function(name, obj, ...)
local args = terralib.newlist({...})
local types = args:map(function(t) return t.tree.type end)
types:insert(1, &T)
local method = T.templates[name]
local func = method(unpack(types))
return `[func](&obj, [args])
end)
end
)
return {
Base = Base,
AbstractBase = AbstractBase
}