summaryrefslogtreecommitdiff
path: root/script/emmy/manager.lua
diff options
context:
space:
mode:
Diffstat (limited to 'script/emmy/manager.lua')
-rw-r--r--script/emmy/manager.lua221
1 files changed, 221 insertions, 0 deletions
diff --git a/script/emmy/manager.lua b/script/emmy/manager.lua
new file mode 100644
index 00000000..c80e05df
--- /dev/null
+++ b/script/emmy/manager.lua
@@ -0,0 +1,221 @@
+local listMgr = require 'vm.list'
+local sourceMgr = require 'vm.source'
+local newClass = require 'emmy.class'
+local newType = require 'emmy.type'
+local newTypeUnit = require 'emmy.typeUnit'
+local newAlias = require 'emmy.alias'
+local newParam = require 'emmy.param'
+local newReturn = require 'emmy.return'
+local newField = require 'emmy.field'
+local newGeneric = require 'emmy.generic'
+local newArrayType = require 'emmy.arrayType'
+local newTableType = require 'emmy.tableType'
+local newFuncType = require 'emmy.funcType'
+
+local mt = {}
+mt.__index = mt
+mt.__name = 'emmyMgr'
+
+function mt:flushClass(name)
+ local list = self._class[name]
+ if not list then
+ return
+ end
+ local version = listMgr.getVersion()
+ if version == list.version then
+ return
+ end
+ for srcId in pairs(list) do
+ if not listMgr.get(srcId) then
+ list[srcId] = nil
+ end
+ end
+ if not next(list) then
+ self._class[name] = nil
+ return
+ end
+ list.version = version
+end
+
+function mt:eachClassByName(name, callback)
+ self:flushClass(name)
+ local list = self._class[name]
+ if not list then
+ return
+ end
+ for k, class in pairs(list) do
+ if k ~= 'version' then
+ local res = callback(class)
+ if res ~= nil then
+ return res
+ end
+ end
+ end
+end
+
+function mt:eachClass(...)
+ local n = select('#', ...)
+ if n == 1 then
+ local callback = ...
+ for name in pairs(self._class) do
+ local res = self:eachClassByName(name, callback)
+ if res ~= nil then
+ return res
+ end
+ end
+ else
+ local name, callback = ...
+ return self:eachClassByName(name, callback)
+ end
+end
+
+function mt:getClass(name)
+ self:flushClass(name)
+ local list = self._class[name]
+ local version = listMgr.getVersion()
+ if not list then
+ list = {
+ version = version,
+ }
+ self._class[name] = list
+ end
+ return list
+end
+
+function mt:newClass(name, extends, source)
+ local list = self:getClass(name)
+ list[source.id] = newClass(self, name, extends, source)
+ return list[source.id]
+end
+
+function mt:addClass(source)
+ local className = source[1][1]
+ local extends = source[2] and source[2][1]
+ local class = self:newClass(className, extends, source)
+ return class
+end
+
+function mt:addType(source)
+ local typeObj = newType(self, source)
+ for i, obj in ipairs(source) do
+ local typeUnit = newTypeUnit(self, obj)
+ local className = obj[1]
+ if className then
+ local list = self:getClass(className)
+ list[source.id] = typeUnit
+ end
+ typeUnit:setParent(typeObj)
+ typeObj._childs[i] = typeUnit
+ obj:set('emmy.typeUnit', typeUnit)
+ end
+ return typeObj
+end
+
+function mt:addArrayType(source)
+ local typeObj = self:addType(source)
+ local arrayTypeObj = newArrayType(self, source, typeObj)
+ return arrayTypeObj
+end
+
+function mt:addTableType(source, keyType, valueType)
+ local typeObj = newTableType(self, source, keyType, valueType)
+ return typeObj
+end
+
+function mt:addFunctionType(source)
+ local typeObj = newFuncType(self, source)
+ return typeObj
+end
+
+function mt:addAlias(source, typeObj)
+ local aliasName = source[1][1]
+ local aliasObj = newAlias(self, source)
+ aliasObj:bindType(typeObj)
+ local list = self:getClass(aliasName)
+ list[source.id] = aliasObj
+ for i = 3, #source do
+ aliasObj:addEnum(source[i])
+ end
+ return aliasObj
+end
+
+function mt:addParam(source, bind)
+ local paramObj = newParam(self, source)
+ if bind.type == 'emmy.generic' then
+ paramObj:bindGeneric(bind)
+ else
+ paramObj:bindType(bind)
+ self:eachClass(bind:getType(), function (class)
+ if class.type == 'emmy.alias' then
+ class:eachEnum(function (enum)
+ paramObj:addEnum(enum)
+ end)
+ end
+ end)
+ end
+ for i = 3, #source do
+ paramObj:addEnum(source[i])
+ end
+ paramObj:setOption(source.option)
+ return paramObj
+end
+
+function mt:addReturn(source, bind, name)
+ local returnObj = newReturn(self, source, name)
+ if bind then
+ if bind.type == 'emmy.generic' then
+ returnObj:bindGeneric(bind)
+ else
+ returnObj:bindType(bind)
+ end
+ end
+ return returnObj
+end
+
+function mt:addField(source, typeObj, value)
+ local fieldObj = newField(self, source)
+ fieldObj:bindType(typeObj)
+ fieldObj:bindValue(value)
+ return fieldObj
+end
+
+function mt:addGeneric(defs)
+ local genericObj = newGeneric(self, defs)
+ return genericObj
+end
+
+function mt:remove()
+end
+
+function mt:count()
+ local count = 0
+ for _, list in pairs(self._class) do
+ for k in pairs(list) do
+ if k ~= 'version' then
+ count = count + 1
+ end
+ end
+ end
+ return count
+end
+
+return function ()
+ ---@class emmyMgr
+ local self = setmetatable({
+ _class = {},
+ }, mt)
+
+ local source = sourceMgr.dummy()
+ self:newClass('any', nil, source)
+ self:newClass('string', 'any', source)
+ self:newClass('number', 'any', source)
+ self:newClass('integer', 'number', source)
+ self:newClass('boolean', 'any', source)
+ self:newClass('table', 'any', source)
+ self:newClass('function', 'any', source)
+ self:newClass('nil', 'any', source)
+ self:newClass('userdata', 'any', source)
+ self:newClass('thread', 'any', source)
+
+ return self
+end