From 47843b727a9d2c2d3cd545d7aa495f44ce11d55a Mon Sep 17 00:00:00 2001 From: Manuel Simon Hirsig Date: Fri, 9 Sep 2016 02:18:52 +0200 Subject: [PATCH] module refactoring --- aux-addon.lua | 10 +-- core/cache.lua | 2 +- libs/module.lua | 135 ++++++++++++++++++++++------------------- tabs/search/filter.lua | 6 +- util/core.lua | 12 ++-- util/filter.lua | 2 +- 6 files changed, 89 insertions(+), 78 deletions(-) diff --git a/aux-addon.lua b/aux-addon.lua index eb16ce9..cee012f 100644 --- a/aux-addon.lua +++ b/aux-addon.lua @@ -2,17 +2,17 @@ --aux_character_settings = {} do local modules = {} - local mt = {__metatable=false, __index=function(_, key) return modules[key].I end, __newindex=error} + local mt = {__metatable=false, __index=function(_, key) return modules[key]._I end, __newindex=error} aux = function(name) if not modules[name] then (function() - modules[name] = module and M + modules[name] = module and _E import (green_t) private.aux = setmetatable(t, mt) private.p.set = function(v) inspect(nil, v) end end)() end - modules[name].import (modules.core.I) + modules[name].import (modules.core._I) modules[name].private() setfenv(2, modules[name]) end @@ -52,7 +52,7 @@ do for _, f in handlers2 do f() end print('v' .. version .. ' loaded.') else - M[event]() + _E[event]() end end) end @@ -61,7 +61,7 @@ tab_info = t do for _, info in temp-A(temp-A('search_tab', 'Search'), temp-A('post_tab', 'Post'), temp-A('auctions_tab', 'Auctions'), temp-A('bids_tab', 'Bids')) do local tab = T('name', info[2]) - local env = (function() _G.aux(info[1]) return M end)() + local env = (function() _G.aux(info[1]) return _E end)() function env.private.OPEN.set(f) tab.OPEN = f end function env.private.CLOSE.set(f) tab.CLOSE = f end function env.private.USE_ITEM.set(f) tab.USE_ITEM = f end diff --git a/core/cache.lua b/core/cache.lua index cf997e7..4cafebc 100644 --- a/core/cache.lua +++ b/core/cache.lua @@ -28,7 +28,7 @@ function LOAD() event_listener('NEW_AUCTION_UPDATE', function() for info in present(info.auction_sell_item()) do for item_id in present(item_id(info.name)) do - _G.aux_merchant_sell[M.item_id(info.name)] = info.vendor_price / (aux.info.max_item_charges(item_id) or info.count) + _G.aux_merchant_sell[_E.item_id(info.name)] = info.vendor_price / (aux.info.max_item_charges(item_id) or info.count) end end end) diff --git a/libs/module.lua b/libs/module.lua index 052a3a9..870cb91 100644 --- a/libs/module.lua +++ b/libs/module.lua @@ -1,97 +1,108 @@ if module then return end -local setfenv, getmetatable, setmetatable, type, unpack, next, _G = setfenv, getmetatable, setmetatable, type, unpack, next, getfenv(0) +local setfenv, setmetatable, unpack, _G = setfenv, setmetatable, unpack, getfenv(0) -local PUBLIC, PRIVATE = 1, 2 -local CALL, INDEX, NEWINDEX = 1, 2, 3 +local PRIVATE, FIELD, PUBLIC, ACCESSOR, MUTATOR = 0, 0, 1, 2, 4 +local PUBLIC_FIELD, PUBLIC_ACCESSOR, PUBLIC_MUTATOR = PUBLIC+FIELD, PUBLIC+ACCESSOR, PUBLIC+MUTATOR local function error(msg, ...) return _G.error(format(msg or '', unpack(arg)) .. '\n' .. debugstack(), 0) end local function import_error() error('Import error.') end local function declaration_error() error('Declaration error.') end local function collision_error(key) error('"%s" already exists.', key) end -local function nil_error(key) if key then error('"%s" is nil.', key) else error('Callee is nil') end end local nop, id = function() end, function(v) return v end -local function prototype() local eq = function() return true end - return setmetatable({ __metatable=false, __eq=eq }, { __metatable=false, __eq=eq, __call=function(self, t) return setmetatable(t, self) end }) +local interface_eq = function() return true end +local interface_mt, environment_mt, declarator_mt = { __metatable=false, __eq=interface_eq }, { __metatable=false }, { __metatable=false } +local INTERFACE = setmetatable({}, { __eq=interface_eq }) + +local __ = {} + +function interface_mt:__index(k) self=__[self] + return self[PUBLIC_FIELD][k] +end +function interface_mt:__newindex(k, v) self=__[self] + self[PUBLIC_MUTATOR][k](v) end -local INTERFACE, ENVIRONMENT, DECLARATOR = prototype(), prototype(), prototype() - -local state = {} - -function INTERFACE:__index(key) self=state[self] - if self.access[key] == PUBLIC then return self[CALL][key] or (self[INDEX][key] or nop)() end +function environment_mt:__index(k) self=__[self] + return self[FIELD][k] end -function INTERFACE:__newindex(key, value) self=state[self] - if self.access[key] == PUBLIC then (self[NEWINDEX][key] or nop)(value) end +function environment_mt:__newindex(k, v) self=__[self] + local mutator = self[MUTATOR][k] + if mutator then + mutator(v) + elseif not self.defined[k] or collision_error(k) then + self.declarator[k] = v + end end -function ENVIRONMENT:__index(key) self=state[self] - local f = self[CALL][key]; if f then return f end - local getter = self[INDEX][key]; if getter then return getter() end - return _G[key] or self.declarator[key] -end -function ENVIRONMENT:__newindex(key, value) self=state[self] - if self.access[key] then (self[NEWINDEX][key] or collision_error(key))(value) else self.declarator[key] = value end -end -ENVIRONMENT.__call = nop -- TODO - do - local ACCESS, EVENT = { public=PUBLIC, private=PRIVATE }, { call=CALL, get=INDEX, set=NEWINDEX } - local function declare(self, access, name, handlers) - self.access[name] = (not self.access[name] or collision_error(name)) and access or self.default_access or declaration_error() - for event, handler in handlers do local handler = handler - self[event][name] = type(handler) == 'function' and handler or (event == INDEX and function() return handler end or declaration_error()) - end - end - function DECLARATOR:__index(key) self=state[self]; local name, access = self.declaration_name, self.declaration_access - if ACCESS[key] and (not access or declaration_error() and not name or nil_error(name)) then - self.declaration_access = ACCESS[key] - elseif not name or nil_error(name) then - self.declaration_name = (type(key) == 'string' or access and declaration_error() or nil_error(name)) and key + local ACCESS, META = { public=PUBLIC, private=PRIVATE }, { get=ACCESSOR, set=MUTATOR } + function declarator_mt:__index(k) self=__[self] + if not self.declaration_access then + self.declaration_access = ACCESS[k] or declaration_error() + elseif not self.declaration_meta or declaration_error() then + self.declaration_meta = META[k] + self.declaration_modifiers[k] = true end return self.declarator end - function DECLARATOR:__newindex(key, value) self=state[self]; local name, access = self.declaration_name, self.declaration_access - if name then declare(self, access, name, { [EVENT[key] or nil_error(name)]=value }) - elseif access or self.default_access then declare(self, access, key, { [type(value) == 'function' and CALL or INDEX]=value }) - else _G[key] = (_G[key] == nil or _G.error(nil)) and value end -- G.error(nil) TODO silent error? - self.declaration_access, self.declaration_name = nil, nil + function declarator_mt:__newindex(k, v) self=__[self] + local access, meta = self.declaration_access, self.declaration_meta or FIELD + if v ~= self.interface then + self.defined[k] = true + self[meta], self[access+meta] = v, v -- TODO performance assignment vs conditional + elseif _G[k] ~= nil or error(nil) then + _G[k] = v + end + self.declaration_access, self.declaration_meta = nil, nil end - function DECLARATOR:__call(v) self=state[self]; local name, access = self.declaration_name, self.declaration_access - if name then - if type(v) ~= 'table' or getmetatable(v) ~= nil then (access and declaration_error() or nil_error)(name) end - local f, getter, setter; f, getter, setter, v.call, v.get, v.set = v.call, v.get, v.set, nil, nil, nil - if next(v) or f ~= nil and getter ~= nil then (access and declaration_error() or nil_error)(name) end - declare(self, access, name, { [CALL]=f, [INDEX]=getter, [NEWINDEX]=setter }) - elseif access or nil_error() then self.default_access = access end - self.declaration_access, self.declaration_name = nil, nil + function declarator_mt:__call() + self.default_access = (not self.declaration_meta or declaration_error()) and self.declaration_access end - DECLARATOR.__tostring = function() return 'nil table' end end local function import(self, interface) - local module = (interface == INTERFACE or import_error()) and state[interface] - for k, v in module.access do - if v == PUBLIC and not self.access[k] then - self.access[k], self[CALL][k], self[INDEX][k], self[NEWINDEX][k] = PRIVATE, module[CALL][k], module[INDEX][k], module[NEWINDEX][k] + local module = (interface == INTERFACE or import_error()) and __[interface] + for k, v in module[PUBLIC_FIELD] do + if not self.defined[k] then + self.defined[k], self[FIELD][k] = true, v + end + end + for k, v in module[PUBLIC_ACCESSOR] do + if not self.defined[k] then + self.defined[k], self[ACCESSOR][k] = true, v + end + end + for k, v in module[PUBLIC_MUTATOR] do + if not self.defined[k] then + self.defined[k], self[MUTATOR][k] = true, v end end end -local mt = {}; setmetatable(_G, mt) +local nop_mt = { __index=nop } +local mt = { __metatable=false } function mt:__index(key) if key ~= 'module' then return end - local interface, environment, declarator = INTERFACE {}, ENVIRONMENT {}, DECLARATOR {} + local interface, environment, declarator = setmetatable({}, interface_mt), setmetatable({}, environment_mt), setmetatable({}, declarator_mt) + local accessors, public_accessors = setmetatable({}, { __index=_G }), {} self = { - access = { _G=PRIVATE, I=PRIVATE, M=PRIVATE, public=PRIVATE, private=PRIVATE, import=PRIVATE, _=PRIVATE, error=PRIVATE, nop=PRIVATE, id=PRIVATE }, - [CALL] = { _G=_G, I=interface, M=environment, import=function(interface) import(self, interface) end, error=error, nop=nop, id=id }, - [INDEX] = { public=function() return declarator.public end, private=function() return declarator.private end }, - [NEWINDEX] = { _=nop }, + defined = { _G=true, _I=true, _E=true, public=true, private=true, import=true, _=true, error=true, nop=true, id=true }, + [FIELD] = setmetatable( + { _G=_G, _I=interface, _E=environment, import=function(interface) import(self, interface) end, error=error, nop=nop, id=id }, + {__index=function(_, key) return accessors[key]() end } + ), + [ACCESSOR] = setmetatable({ public=function() return declarator.public end, private=function() return declarator.private end }, nop_mt), + [MUTATOR] = setmetatable({}, nop_mt), + [PUBLIC_FIELD] = setmetatable({}, {__index=function(_, key) return public_accessors[key]() end}), + [PUBLIC_ACCESSOR] = setmetatable({}, nop_mt), + [PUBLIC_MUTATOR] = setmetatable({}, nop_mt), + interface = interface, declarator = declarator, } - state[interface], state[environment], state[declarator] = self, self, self + __[interface], __[environment], __[declarator] = self, self, self setfenv(2, environment) return interface -end \ No newline at end of file +end +setmetatable(_G, mt) \ No newline at end of file diff --git a/tabs/search/filter.lua b/tabs/search/filter.lua index 631b852..6d71f9b 100644 --- a/tabs/search/filter.lua +++ b/tabs/search/filter.lua @@ -73,7 +73,7 @@ function update_form() if blizzard_query.exact then for key in temp-S('class', 'subclass', 'slot', 'quality') do - M[key .. '_dropdown'].button:Disable() + _E[key .. '_dropdown'].button:Disable() end else class_dropdown.button:Enable() @@ -81,9 +81,9 @@ function update_form() end for key in temp-S('min_level', 'max_level') do if blizzard_query.exact then - M[key .. '_input']:Disable() + _E[key .. '_input']:Disable() else - M[key .. '_input']:Enable() + _E[key .. '_input']:Enable() end end if blizzard_query.exact then diff --git a/util/core.lua b/util/core.lua index 1d54126..0612c4f 100644 --- a/util/core.lua +++ b/util/core.lua @@ -26,7 +26,7 @@ aux 'core' -- -- end -- local function instantiate(methods, getters, setters, init, arg) -- local interface = setmetatable({}, mt) --- local self = {I=interface}; init(self, unpack(arg)) +-- local self = {_I=interface}; init(self, unpack(arg)) -- state[interface] = {class={methods=methods, getters=getters, setters=setters}, self=self} -- return interface -- end @@ -81,7 +81,7 @@ do for i = 1, 9 do local key = '_' .. i public[key] = t - formal_parameters[M[key]] = i + formal_parameters[_E[key]] = i end local function helper(f, arg1, arg2) local params = t @@ -98,7 +98,7 @@ do if type(body) == 'function' then local arg1 = arg return function(...) return helper(body, arg1, arg) end - else + else -- TODO memoization -- body = gsub(body, '_([ab])', function(char) return '_' .. end) -- local lambda = loadstring('return function(_1,_2,_3,_4,_5,_6,_7,_8,_9)' .. body .. ' end') local lambda = loadstring('return ' .. body) or loadstring(body) or error() @@ -129,7 +129,7 @@ do end function public.copy(t) - local copy = M.t + local copy = _E.t for k, v in t do copy[k] = v end table.setn(copy, getn(t)) return setmetatable(copy, getmetatable(t)) @@ -146,13 +146,13 @@ function public.key(value, t) end function public.keys(t) - local keys = M.t + local keys = _E.t for k in t do tinsert(keys, k) end return keys end function public.values(t) - local values = M.t + local values = _E.t for _, v in t do tinsert(values, v) end return values end diff --git a/util/filter.lua b/util/filter.lua index 42e17a5..131978f 100644 --- a/util/filter.lua +++ b/util/filter.lua @@ -354,7 +354,7 @@ function public.query(filter_string) blizzard_query = blizzard_query(filter), validator = validator(filter), prettified = prettified_filter_string(filter), - }, M.suggestions(filter) + }, _E.suggestions(filter) end function public.queries(filter_string)