196 lines
6.3 KiB
Lua
Executable File
196 lines
6.3 KiB
Lua
Executable File
--------------------------------------------------------------------------------
|
|
---------------------- ## ##### ##### ###### -----------------------
|
|
---------------------- ## ## ## ## ## ## ## -----------------------
|
|
---------------------- ## ## ## ## ## ###### -----------------------
|
|
---------------------- ## ## ## ## ## ## -----------------------
|
|
---------------------- ###### ##### ##### ## -----------------------
|
|
---------------------- -----------------------
|
|
----------------------- Lua Object-Oriented Programming ------------------------
|
|
--------------------------------------------------------------------------------
|
|
-- Project: LOOP - Lua Object-Oriented Programming --
|
|
-- Release: 2.3 beta --
|
|
-- Title : Component Model with Wrapping Container --
|
|
-- Author : Renato Maia <maia@inf.puc-rio.br> --
|
|
--------------------------------------------------------------------------------
|
|
-- Exported API: --
|
|
-- Template --
|
|
-- factoryof(component) --
|
|
-- templateof(factory|component) --
|
|
-- ports(template) --
|
|
-- segmentof(portname, component) --
|
|
--------------------------------------------------------------------------------
|
|
|
|
local error = error
|
|
local pairs = pairs
|
|
local rawget = rawget
|
|
local select = select
|
|
local type = type
|
|
|
|
local oo = require "loop.cached"
|
|
local base = require "loop.component.base"
|
|
|
|
module "loop.component.wrapped"
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
local impl, obj
|
|
local function method(_, ...) return impl(obj, ...) end
|
|
function delegate(value, delegatee)
|
|
if type(value) == "function" then
|
|
impl, obj = value, delegatee
|
|
return method
|
|
end
|
|
return value
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
local ExternalState = oo.class()
|
|
|
|
function ExternalState:__index(name)
|
|
self = self.__container
|
|
local state = self.__state
|
|
local port, manager = state[name], self[name]
|
|
if port and manager then
|
|
return rawget(manager, "__external") or manager
|
|
else
|
|
component = state.__component
|
|
return delegate(port or component[name], component)
|
|
end
|
|
end
|
|
|
|
function ExternalState:__newindex(name, value)
|
|
self = self.__container
|
|
local state = self.__state
|
|
local manager = self[name]
|
|
if manager and manager.__bind then
|
|
manager:__bind(value)
|
|
elseif manager ~= nil then
|
|
state[name] = value
|
|
else
|
|
state.__component[name] = value
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
BaseTemplate = oo.class({}, base.BaseTemplate)
|
|
|
|
function BaseTemplate:__container(segments)
|
|
local container = {
|
|
__state = segments,
|
|
__internal = segments,
|
|
}
|
|
container.__external = ExternalState{ __container = container }
|
|
return container
|
|
end
|
|
|
|
function BaseTemplate:__build(segments)
|
|
local container = self:__container(segments)
|
|
local state = container.__state
|
|
local context = container.__internal
|
|
for port, class in oo.allmembers(oo.classof(self)) do
|
|
if port:find("^%a[%w_]*$") then
|
|
container[port] = class(state, port, context)
|
|
end
|
|
end
|
|
state.__reference = container.__external
|
|
for port in pairs(self) do
|
|
if port == 1
|
|
then self:__setcontext(segments.__component, context)
|
|
else self:__setcontext(segments[port], context)
|
|
end
|
|
end
|
|
return container.__external
|
|
end
|
|
|
|
function Template(template, ...)
|
|
return oo.class(template, BaseTemplate, ...)
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
function factoryof(component)
|
|
local container = component.__container
|
|
return base.factoryof(container and container.__state or component)
|
|
end
|
|
|
|
function templateof(factory)
|
|
if not oo.instanceof(factory, BaseTemplate) then
|
|
factory = factoryof(factory)
|
|
end
|
|
return oo.classof(factory)
|
|
end
|
|
|
|
function ports(template)
|
|
if not oo.subclassof(template, BaseTemplate) then
|
|
template = templateof(template)
|
|
end
|
|
return base.ports(template)
|
|
end
|
|
|
|
function segmentof(comp, port)
|
|
return comp.__container.__state[port]
|
|
end
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
function addport(comp, name, port, class)
|
|
local container = comp.__container
|
|
if container then
|
|
local context = container.__internal
|
|
local state = container.__state
|
|
local factory = state.__factory
|
|
if class then
|
|
local comp = state.__component or state
|
|
state[name] = class(comp[name], comp)
|
|
end
|
|
container[name] = port(state, name, context, factory)
|
|
factory:__setcontext(state[name], context)
|
|
else
|
|
error("bad argument #1 to 'addport' (component expected, got "..type(comp)..")")
|
|
end
|
|
end
|
|
|
|
function removeport(comp, name)
|
|
local container = comp.__container
|
|
if container then
|
|
local state = container.__state
|
|
container[name] = nil
|
|
state[name] = nil
|
|
else
|
|
error("bad argument #1 to 'removeport' (component expected, got "..type(comp)..")")
|
|
end
|
|
end
|
|
|
|
--[[----------------------------------------------------------------------------
|
|
MyCompTemplate = comp.Template{
|
|
[<portname>] = <PortClass>,
|
|
[<portname>] = <PortClass>,
|
|
[<portname>] = <PortClass>,
|
|
}
|
|
|
|
MyContainer = Container{
|
|
__external = Handler{ <container> },
|
|
__internal = {
|
|
<componentimpl>,
|
|
[<portname>] = <portimpl>,
|
|
[<portname>] = <portimpl>,
|
|
[<portname>] = <portimpl>,
|
|
},
|
|
[<portname>] = <portmanager>,
|
|
[<portname>] = <portmanager>,
|
|
[<portname>] = <portmanager>,
|
|
}
|
|
|
|
EMPTY Internal Self | EMPTY Internal Self
|
|
Facet nil wrapper | Facet nil false
|
|
Receptacle nil wrapper | Receptacle nil false
|
|
Multiple multiple wrapper | Multiple multiple false
|
|
|
|
|
FILLED Internal Self | FILLED Internal Self
|
|
Facet port wrapper | Facet port false
|
|
Receptacle wrapper wrapper | Receptacle port false
|
|
Multiple multiple wrapper | Multiple multiple false
|
|
----------------------------------------------------------------------------]]--
|