LuPPC/src/lua/core/component.lua

125 lines
3.1 KiB
Lua

local component = {}
local api = {}
local components = {}
component.api = api
component.components = components
local componentCallback = {
__call = function(self, ...) return components[self.address].rawproxy[self.name](...) end,
__tostring = function(self) return (components[self.address] ~= nil and components[self.address].doc[self.name] ~= nil) and components[self.address].doc[self.name] or "function" end
}
function component.prepare()
print("Assembling initial component tree")
end
function api.register(address, ctype, proxy, doc)
checkArg(2, ctype, "string")
checkArg(3, proxy, "table")
if type(address) ~= "string" then
address = random.uuid()
end
if components[address] ~= nil then
return nil, "component already at address"
end
components[address] = {address = address, type = ctype, doc = doc or {}}
components[address].rawproxy = proxy
components[address].proxy = {}
for k,v in pairs(proxy) do
if type(v) == "function" then
components[address].proxy = setmetatable({name=k,address=address}, componentCallback)
else
components[address].proxy = v
end
end
computer.pushSignal("component_added", address, ctype)
return true
end
function api.unregister(address)
checkArg(1, address, "string")
if components[address] == nil then
return nil, "no component at address"
end
local ctype = components[address].type
components[address] = nil
computer.pushSignal("component_removed", address, ctype)
return true
end
function api.doc(address, method)
checkArg(1, address, "string")
checkArg(2, method, "string")
if not components[address] then
error("No such component")
end
return components[address].doc[method]
end
function api.invoke(address, method, ...)
checkArg(1, address, "string")
checkArg(2, method, "string")
if not components[address] then
error("No such component")
end
if not components[address].rawproxy[method] then
error("No such method")
end
return components[address].rawproxy[method](...)
end
function api.list(filter, exact)
checkArg(1, filter, "string", "nil")
local list = {}
for addr, c in pairs(components) do
if not filter or ((exact and c.type or c.type:sub(1, #filter)) == filter) then
list[addr] = c.type
end
end
local key = nil
return setmetatable(list, {__call=function()
key = next(list, key)
if key then
return key, list[key]
end
end})
end
function api.methods(address)
checkArg(1, address, "string")
if not components[address] then
return nil, "No such component"
end
local list = {}
for k, v in pairs(components[address].rawproxy) do
if type(v) == "function" then
list[k] = true
end
end
return list
end
function api.fields(address)
checkArg(1, address, "string")
if not components[address] then
return nil, "No such component"
end
local list = {}
for k, v in pairs(components[address].rawproxy) do
if type(v) ~= "function" then
list[k] = true
end
end
return list
end
function api.proxy(address)
if not components[address] then
return nil, "No such component"
end
return components[address].proxy
end
return component