diff options
Diffstat (limited to 'script-beta/vm')
-rw-r--r-- | script-beta/vm/eachDef.lua | 40 | ||||
-rw-r--r-- | script-beta/vm/eachField.lua | 45 | ||||
-rw-r--r-- | script-beta/vm/eachRef.lua | 39 | ||||
-rw-r--r-- | script-beta/vm/getClass.lua | 62 | ||||
-rw-r--r-- | script-beta/vm/getDocs.lua | 175 | ||||
-rw-r--r-- | script-beta/vm/getGlobals.lua | 192 | ||||
-rw-r--r-- | script-beta/vm/getInfer.lua | 96 | ||||
-rw-r--r-- | script-beta/vm/getLibrary.lua | 32 | ||||
-rw-r--r-- | script-beta/vm/getLinks.lua | 61 | ||||
-rw-r--r-- | script-beta/vm/getMeta.lua | 52 | ||||
-rw-r--r-- | script-beta/vm/guideInterface.lua | 106 | ||||
-rw-r--r-- | script-beta/vm/init.lua | 13 | ||||
-rw-r--r-- | script-beta/vm/vm.lua | 167 |
13 files changed, 0 insertions, 1080 deletions
diff --git a/script-beta/vm/eachDef.lua b/script-beta/vm/eachDef.lua deleted file mode 100644 index 5ff58889..00000000 --- a/script-beta/vm/eachDef.lua +++ /dev/null @@ -1,40 +0,0 @@ -local vm = require 'vm.vm' -local guide = require 'parser.guide' -local files = require 'files' -local util = require 'utility' -local await = require 'await' - -local function eachDef(source, deep) - local results = {} - local lock = vm.lock('eachDef', source) - if not lock then - return results - end - - await.delay() - - local clock = os.clock() - local myResults, count = guide.requestDefinition(source, vm.interface, deep) - if DEVELOP and os.clock() - clock > 0.1 then - log.warn('requestDefinition', count, os.clock() - clock, guide.getUri(source), util.dump(source, { deep = 1 })) - end - vm.mergeResults(results, myResults) - - lock() - - return results -end - -function vm.getDefs(source, deep) - if guide.isGlobal(source) then - local key = guide.getKeyName(source) - return vm.getGlobalSets(key) - else - local cache = vm.getCache('eachDef')[source] - or eachDef(source, deep) - if deep then - vm.getCache('eachDef')[source] = cache - end - return cache - end -end diff --git a/script-beta/vm/eachField.lua b/script-beta/vm/eachField.lua deleted file mode 100644 index ce0e3928..00000000 --- a/script-beta/vm/eachField.lua +++ /dev/null @@ -1,45 +0,0 @@ -local vm = require 'vm.vm' -local guide = require 'parser.guide' -local await = require 'await' - -local function eachField(source, deep) - local unlock = vm.lock('eachField', source) - if not unlock then - return {} - end - - while source.type == 'paren' do - source = source.exp - if not source then - return {} - end - end - - await.delay() - local results = guide.requestFields(source, vm.interface, deep) - - unlock() - return results -end - -function vm.getFields(source, deep) - if source.special == '_G' then - return vm.getGlobals '*' - end - if guide.isGlobal(source) then - local name = guide.getKeyName(source) - local cache = vm.getCache('eachFieldOfGlobal')[name] - or vm.getCache('eachField')[source] - or eachField(source, 'deep') - vm.getCache('eachFieldOfGlobal')[name] = cache - vm.getCache('eachField')[source] = cache - return cache - else - local cache = vm.getCache('eachField')[source] - or eachField(source, deep) - if deep then - vm.getCache('eachField')[source] = cache - end - return cache - end -end diff --git a/script-beta/vm/eachRef.lua b/script-beta/vm/eachRef.lua deleted file mode 100644 index 4e735abf..00000000 --- a/script-beta/vm/eachRef.lua +++ /dev/null @@ -1,39 +0,0 @@ -local vm = require 'vm.vm' -local guide = require 'parser.guide' -local util = require 'utility' -local await = require 'await' - -local function getRefs(source, deep) - local results = {} - local lock = vm.lock('eachRef', source) - if not lock then - return results - end - - await.delay() - - local clock = os.clock() - local myResults, count = guide.requestReference(source, vm.interface, deep) - if DEVELOP and os.clock() - clock > 0.1 then - log.warn('requestReference', count, os.clock() - clock, guide.getUri(source), util.dump(source, { deep = 1 })) - end - vm.mergeResults(results, myResults) - - lock() - - return results -end - -function vm.getRefs(source, deep) - if guide.isGlobal(source) then - local key = guide.getKeyName(source) - return vm.getGlobals(key) - else - local cache = vm.getCache('eachRef')[source] - or getRefs(source, deep) - if deep then - vm.getCache('eachRef')[source] = cache - end - return cache - end -end diff --git a/script-beta/vm/getClass.lua b/script-beta/vm/getClass.lua deleted file mode 100644 index a8bd7e40..00000000 --- a/script-beta/vm/getClass.lua +++ /dev/null @@ -1,62 +0,0 @@ -local vm = require 'vm.vm' -local guide = require 'parser.guide' - -local function lookUpDocClass(source) - local infers = vm.getInfers(source, 'deep') - for _, infer in ipairs(infers) do - if infer.source.type == 'doc.class' - or infer.source.type == 'doc.type' then - return infer.type - end - end -end - -local function getClass(source, classes, depth, deep) - local docClass = lookUpDocClass(source) - if docClass then - classes[#classes+1] = docClass - return - end - if depth > 3 then - return - end - local value = guide.getObjectValue(source) or source - if not deep then - if value and value.type == 'string' then - classes[#classes+1] = value[1] - end - else - for _, src in ipairs(vm.getFields(value)) do - local key = vm.getKeyName(src) - if not key then - goto CONTINUE - end - local lkey = key:lower() - if lkey == 's|type' - or lkey == 's|__name' - or lkey == 's|name' - or lkey == 's|class' then - local value = guide.getObjectValue(src) - if value and value.type == 'string' then - classes[#classes+1] = value[1] - end - end - ::CONTINUE:: - end - end - if #classes ~= 0 then - return - end - vm.eachMeta(source, function (mt) - getClass(mt, classes, depth + 1, deep) - end) -end - -function vm.getClass(source, deep) - local classes = {} - getClass(source, classes, 1, deep) - if #classes == 0 then - return nil - end - return guide.mergeTypes(classes) -end diff --git a/script-beta/vm/getDocs.lua b/script-beta/vm/getDocs.lua deleted file mode 100644 index c06efc11..00000000 --- a/script-beta/vm/getDocs.lua +++ /dev/null @@ -1,175 +0,0 @@ -local files = require 'files' -local util = require 'utility' -local guide = require 'parser.guide' -local vm = require 'vm.vm' -local config = require 'config' - -local function getTypesOfFile(uri) - local types = {} - local ast = files.getAst(uri) - if not ast or not ast.ast.docs then - return types - end - guide.eachSource(ast.ast.docs, function (src) - if src.type == 'doc.type.name' - or src.type == 'doc.class.name' - or src.type == 'doc.extends.name' - or src.type == 'doc.alias.name' then - local name = src[1] - if name then - if not types[name] then - types[name] = {} - end - types[name][#types[name]+1] = src - end - end - end) - return types -end - -local function getDocTypes(name) - local results = {} - for uri in files.eachFile() do - local cache = files.getCache(uri) - cache.classes = cache.classes or getTypesOfFile(uri) - if name == '*' then - for _, sources in util.sortPairs(cache.classes) do - for _, source in ipairs(sources) do - results[#results+1] = source - end - end - else - if cache.classes[name] then - for _, source in ipairs(cache.classes[name]) do - results[#results+1] = source - end - end - end - end - return results -end - -function vm.getDocEnums(doc, mark, results) - mark = mark or {} - if mark[doc] then - return nil - end - mark[doc] = true - results = results or {} - for _, enum in ipairs(doc.enums) do - results[#results+1] = enum - end - for _, resume in ipairs(doc.resumes) do - results[#results+1] = resume - end - for _, unit in ipairs(doc.types) do - if unit.type == 'doc.type.name' then - for _, other in ipairs(vm.getDocTypes(unit[1])) do - if other.type == 'doc.alias.name' then - vm.getDocEnums(other.parent.extends, mark, results) - end - end - end - end - return results -end - -function vm.getDocTypes(name) - local cache = vm.getCache('getDocTypes')[name] - if cache ~= nil then - return cache - end - cache = getDocTypes(name) - vm.getCache('getDocTypes')[name] = cache - return cache -end - -function vm.isMetaFile(uri) - local status = files.getAst(uri) - if not status then - return false - end - local cache = files.getCache(uri) - if cache.isMeta ~= nil then - return cache.isMeta - end - cache.isMeta = false - if not status.ast.docs then - return false - end - for _, doc in ipairs(status.ast.docs) do - if doc.type == 'doc.meta' then - cache.isMeta = true - return true - end - end - return false -end - -function vm.getValidVersions(doc) - if doc.type ~= 'doc.version' then - return - end - local valids = { - ['Lua 5.1'] = false, - ['Lua 5.2'] = false, - ['Lua 5.3'] = false, - ['Lua 5.4'] = false, - ['LuaJIT'] = false, - } - for _, version in ipairs(doc.versions) do - if version.ge and type(version.version) == 'number' then - for ver in pairs(valids) do - local verNumber = tonumber(ver:sub(-3)) - if verNumber and verNumber >= version.version then - valids[ver] = true - end - end - elseif version.le and type(version.version) == 'number' then - for ver in pairs(valids) do - local verNumber = tonumber(ver:sub(-3)) - if verNumber and verNumber <= version.version then - valids[ver] = true - end - end - elseif type(version.version) == 'number' then - valids[('Lua %.1f'):format(version.version)] = true - elseif 'JIT' == version.version then - valids['LuaJIT'] = true - end - end - if valids['Lua 5.1'] then - valids['LuaJIT'] = true - end - return valids -end - -local function isDeprecated(value) - if not value.bindDocs then - return false - end - for _, doc in ipairs(value.bindDocs) do - if doc.type == 'doc.deprecated' then - return true - elseif doc.type == 'doc.version' then - local valids = vm.getValidVersions(doc) - if not valids[config.config.runtime.version] then - return true - end - end - end - return false -end - -function vm.isDeprecated(value) - local defs = vm.getDefs(value, 'deep') - if #defs == 0 then - return false - end - for _, def in ipairs(defs) do - if not isDeprecated(def) then - return false - end - end - return true -end diff --git a/script-beta/vm/getGlobals.lua b/script-beta/vm/getGlobals.lua deleted file mode 100644 index 83d6a5e6..00000000 --- a/script-beta/vm/getGlobals.lua +++ /dev/null @@ -1,192 +0,0 @@ -local guide = require 'parser.guide' -local vm = require 'vm.vm' -local files = require 'files' -local util = require 'utility' -local config = require 'config' - -local function getGlobalsOfFile(uri) - local cache = files.getCache(uri) - if cache.globals then - return cache.globals - end - local globals = {} - cache.globals = globals - local ast = files.getAst(uri) - if not ast then - return globals - end - local results = guide.findGlobals(ast.ast) - local mark = {} - for _, res in ipairs(results) do - if mark[res] then - goto CONTINUE - end - mark[res] = true - local name = guide.getSimpleName(res) - if name then - if not globals[name] then - globals[name] = {} - end - globals[name][#globals[name]+1] = res - end - ::CONTINUE:: - end - return globals -end - -local function getGlobalSetsOfFile(uri) - local cache = files.getCache(uri) - if cache.globalSets then - return cache.globalSets - end - local globals = {} - cache.globalSets = globals - local ast = files.getAst(uri) - if not ast then - return globals - end - local results = guide.findGlobals(ast.ast) - local mark = {} - for _, res in ipairs(results) do - if mark[res] then - goto CONTINUE - end - mark[res] = true - if vm.isSet(res) then - local name = guide.getSimpleName(res) - if name then - if not globals[name] then - globals[name] = {} - end - globals[name][#globals[name]+1] = res - end - end - ::CONTINUE:: - end - return globals -end - -local function getGlobals(name) - local results = {} - for uri in files.eachFile() do - local globals = getGlobalsOfFile(uri) - if name == '*' then - for _, sources in util.sortPairs(globals) do - for _, source in ipairs(sources) do - results[#results+1] = source - end - end - else - if globals[name] then - for _, source in ipairs(globals[name]) do - results[#results+1] = source - end - end - end - end - return results -end - -local function getGlobalSets(name) - local results = {} - for uri in files.eachFile() do - local globals = getGlobalSetsOfFile(uri) - if name == '*' then - for _, sources in util.sortPairs(globals) do - for _, source in ipairs(sources) do - results[#results+1] = source - end - end - else - if globals[name] then - for _, source in ipairs(globals[name]) do - results[#results+1] = source - end - end - end - end - return results -end - -local function fastGetAnyGlobals() - local results = {} - local mark = {} - for uri in files.eachFile() do - --local globalSets = getGlobalsOfFile(uri) - --for destName, sources in util.sortPairs(globalSets) do - -- if not mark[destName] then - -- mark[destName] = true - -- results[#results+1] = sources[1] - -- end - --end - local globals = getGlobalsOfFile(uri) - for destName, sources in util.sortPairs(globals) do - if not mark[destName] then - mark[destName] = true - results[#results+1] = sources[1] - end - end - end - return results -end - -local function fastGetAnyGlobalSets() - local results = {} - local mark = {} - for uri in files.eachFile() do - local globals = getGlobalSetsOfFile(uri) - for destName, sources in util.sortPairs(globals) do - if not mark[destName] then - mark[destName] = true - results[#results+1] = sources[1] - end - end - end - return results -end - -function vm.getGlobals(key) - if key == '*' and config.config.intelliSense.fastGlobal then - local cache = vm.getCache('fastGetAnyGlobals')[key] - if cache ~= nil then - return cache - end - cache = fastGetAnyGlobals() - vm.getCache('fastGetAnyGlobals')[key] = cache - return cache - else - local cache = vm.getCache('getGlobals')[key] - if cache ~= nil then - return cache - end - cache = getGlobals(key) - vm.getCache('getGlobals')[key] = cache - return cache - end -end - -function vm.getGlobalSets(key) - if key == '*' and config.config.intelliSense.fastGlobal then - local cache = vm.getCache('fastGetAnyGlobalSets')[key] - if cache ~= nil then - return cache - end - cache = fastGetAnyGlobalSets() - vm.getCache('fastGetAnyGlobalSets')[key] = cache - return cache - end - local cache = vm.getCache('getGlobalSets')[key] - if cache ~= nil then - return cache - end - cache = getGlobalSets(key) - vm.getCache('getGlobalSets')[key] = cache - return cache -end - -files.watch(function (ev, uri) - if ev == 'update' then - getGlobalsOfFile(uri) - getGlobalSetsOfFile(uri) - end -end) diff --git a/script-beta/vm/getInfer.lua b/script-beta/vm/getInfer.lua deleted file mode 100644 index 5272c389..00000000 --- a/script-beta/vm/getInfer.lua +++ /dev/null @@ -1,96 +0,0 @@ -local vm = require 'vm.vm' -local guide = require 'parser.guide' -local util = require 'utility' -local await = require 'await' - -NIL = setmetatable({'<nil>'}, { __tostring = function () return 'nil' end }) - ---- 是否包含某种类型 -function vm.hasType(source, type, deep) - local defs = vm.getDefs(source, deep) - for i = 1, #defs do - local def = defs[i] - local value = guide.getObjectValue(def) or def - if value.type == type then - return true - end - end - return false -end - ---- 是否包含某种类型 -function vm.hasInferType(source, type, deep) - local infers = vm.getInfers(source, deep) - for i = 1, #infers do - local infer = infers[i] - if infer.type == type then - return true - end - end - return false -end - -function vm.getInferType(source, deep) - local infers = vm.getInfers(source, deep) - return guide.viewInferType(infers) -end - -function vm.getInferLiteral(source, deep) - local infers = vm.getInfers(source, deep) - local literals = {} - local mark = {} - for _, infer in ipairs(infers) do - local value = infer.value - if value and not mark[value] then - mark[value] = true - literals[#literals+1] = util.viewLiteral(value) - end - end - if #literals == 0 then - return nil - end - table.sort(literals) - return table.concat(literals, '|') -end - -local function getInfers(source, deep) - local results = {} - local lock = vm.lock('getInfers', source) - if not lock then - return results - end - - await.delay() - - local clock = os.clock() - local myResults, count = guide.requestInfer(source, vm.interface, deep) - if DEVELOP and os.clock() - clock > 0.1 then - log.warn('requestInfer', count, os.clock() - clock, guide.getUri(source), util.dump(source, { deep = 1 })) - end - vm.mergeResults(results, myResults) - - lock() - - return results -end - ---- 获取对象的值 ---- 会尝试穿透函数调用 -function vm.getInfers(source, deep) - if guide.isGlobal(source) then - local name = guide.getKeyName(source) - local cache = vm.getCache('getInfersOfGlobal')[name] - or vm.getCache('getInfers')[source] - or getInfers(source, 'deep') - vm.getCache('getInfersOfGlobal')[name] = cache - vm.getCache('getInfers')[source] = cache - return cache - else - local cache = vm.getCache('getInfers')[source] - or getInfers(source, deep) - if deep then - vm.getCache('getInfers')[source] = cache - end - return cache - end -end diff --git a/script-beta/vm/getLibrary.lua b/script-beta/vm/getLibrary.lua deleted file mode 100644 index 5803a73b..00000000 --- a/script-beta/vm/getLibrary.lua +++ /dev/null @@ -1,32 +0,0 @@ -local vm = require 'vm.vm' - -function vm.getLibraryName(source, deep) - local defs = vm.getDefs(source, deep) - for _, def in ipairs(defs) do - if def.special then - return def.special - end - end - return nil -end - -local globalLibraryNames = { - 'arg', 'assert', 'collectgarbage', 'dofile', '_G', 'getfenv', - 'getmetatable', 'ipairs', 'load', 'loadfile', 'loadstring', - 'module', 'next', 'pairs', 'pcall', 'print', 'rawequal', - 'rawget', 'rawlen', 'rawset', 'select', 'setfenv', - 'setmetatable', 'tonumber', 'tostring', 'type', '_VERSION', - 'warn', 'xpcall', 'require', 'unpack', 'bit32', 'coroutine', - 'debug', 'io', 'math', 'os', 'package', 'string', 'table', - 'utf8', -} -local globalLibraryNamesMap -function vm.isGlobalLibraryName(name) - if not globalLibraryNamesMap then - globalLibraryNamesMap = {} - for _, v in ipairs(globalLibraryNames) do - globalLibraryNamesMap[v] = true - end - end - return globalLibraryNamesMap[name] or false -end diff --git a/script-beta/vm/getLinks.lua b/script-beta/vm/getLinks.lua deleted file mode 100644 index 0bb1c6ff..00000000 --- a/script-beta/vm/getLinks.lua +++ /dev/null @@ -1,61 +0,0 @@ -local guide = require 'parser.guide' -local vm = require 'vm.vm' -local files = require 'files' - -local function getFileLinks(uri) - local ws = require 'workspace' - local links = {} - local ast = files.getAst(uri) - if not ast then - return links - end - guide.eachSpecialOf(ast.ast, 'require', function (source) - local call = source.parent - if not call or call.type ~= 'call' then - return - end - local args = call.args - if not args[1] or args[1].type ~= 'string' then - return - end - local uris = ws.findUrisByRequirePath(args[1][1]) - for _, u in ipairs(uris) do - u = files.asKey(u) - if not links[u] then - links[u] = {} - end - links[u][#links[u]+1] = call - end - end) - return links -end - -local function getLinksTo(uri) - uri = files.asKey(uri) - local links = {} - for u in files.eachFile() do - local ls = vm.getFileLinks(u) - if ls[uri] then - for _, l in ipairs(ls[uri]) do - links[#links+1] = l - end - end - end - return links -end - -function vm.getLinksTo(uri) - local cache = vm.getCache('getLinksTo')[uri] - if cache ~= nil then - return cache - end - cache = getLinksTo(uri) - vm.getCache('getLinksTo')[uri] = cache - return cache -end - -function vm.getFileLinks(uri) - local cache = files.getCache(uri) - cache.links = cache.links or getFileLinks(uri) - return cache.links -end diff --git a/script-beta/vm/getMeta.lua b/script-beta/vm/getMeta.lua deleted file mode 100644 index aebef1a7..00000000 --- a/script-beta/vm/getMeta.lua +++ /dev/null @@ -1,52 +0,0 @@ -local vm = require 'vm.vm' - -local function eachMetaOfArg1(source, callback) - local node, index = vm.getArgInfo(source) - local special = vm.getSpecial(node) - if special == 'setmetatable' and index == 1 then - local mt = node.next.args[2] - if mt then - callback(mt) - end - end -end - -local function eachMetaOfRecv(source, callback) - if not source or source.type ~= 'select' then - return - end - if source.index ~= 1 then - return - end - local call = source.vararg - if not call or call.type ~= 'call' then - return - end - local special = vm.getSpecial(call.node) - if special ~= 'setmetatable' then - return - end - local mt = call.args[2] - if mt then - callback(mt) - end -end - -function vm.eachMetaValue(source, callback) - vm.eachMeta(source, function (mt) - for _, src in ipairs(vm.getFields(mt)) do - if vm.getKeyName(src) == 's|__index' then - if src.value then - for _, valueSrc in ipairs(vm.getFields(src.value)) do - callback(valueSrc) - end - end - end - end - end) -end - -function vm.eachMeta(source, callback) - eachMetaOfArg1(source, callback) - eachMetaOfRecv(source.value, callback) -end diff --git a/script-beta/vm/guideInterface.lua b/script-beta/vm/guideInterface.lua deleted file mode 100644 index e646def8..00000000 --- a/script-beta/vm/guideInterface.lua +++ /dev/null @@ -1,106 +0,0 @@ -local vm = require 'vm.vm' -local files = require 'files' -local ws = require 'workspace' -local guide = require 'parser.guide' -local await = require 'await' -local config = require 'config' - -local m = {} - -function m.searchFileReturn(results, ast, index) - local returns = ast.returns - if not returns then - return - end - for _, ret in ipairs(returns) do - local exp = ret[index] - if exp then - vm.mergeResults(results, { exp }) - end - end -end - -function m.require(args, index) - local reqName = args[1] and args[1][1] - if not reqName then - return nil - end - local results = {} - local myUri = guide.getUri(args[1]) - local uris = ws.findUrisByRequirePath(reqName) - for _, uri in ipairs(uris) do - if not files.eq(myUri, uri) then - local ast = files.getAst(uri) - if ast then - m.searchFileReturn(results, ast.ast, index) - end - end - end - - return results -end - -function m.dofile(args, index) - local reqName = args[1] and args[1][1] - if not reqName then - return - end - local results = {} - local myUri = guide.getUri(args[1]) - local uris = ws.findUrisByFilePath(reqName) - for _, uri in ipairs(uris) do - if not files.eq(myUri, uri) then - local ast = files.getAst(uri) - if ast then - m.searchFileReturn(results, ast.ast, index) - end - end - end - return results -end - -vm.interface = {} - --- 向前寻找引用的层数限制,一般情况下都为0 --- 在自动完成/漂浮提示等情况时设置为5(需要清空缓存) --- 在查找引用时设置为10(需要清空缓存) -vm.interface.searchLevel = 0 - -function vm.interface.call(func, args, index) - if func.special == 'require' and index == 1 then - await.delay() - return m.require(args, index) - end - if func.special == 'dofile' then - await.delay() - return m.dofile(args, index) - end -end - -function vm.interface.global(name) - await.delay() - return vm.getGlobals(name) -end - -function vm.interface.docType(name) - await.delay() - return vm.getDocTypes(name) -end - -function vm.interface.link(uri) - await.delay() - return vm.getLinksTo(uri) -end - -function vm.interface.index(obj) - return nil -end - -function vm.interface.cache() - await.delay() - return vm.getCache('cache') -end - -function vm.interface.getSearchDepth() - return config.config.intelliSense.searchDepth -end diff --git a/script-beta/vm/init.lua b/script-beta/vm/init.lua deleted file mode 100644 index b9e8e147..00000000 --- a/script-beta/vm/init.lua +++ /dev/null @@ -1,13 +0,0 @@ -local vm = require 'vm.vm' -require 'vm.getGlobals' -require 'vm.getDocs' -require 'vm.getLibrary' -require 'vm.getInfer' -require 'vm.getClass' -require 'vm.getMeta' -require 'vm.eachField' -require 'vm.eachDef' -require 'vm.eachRef' -require 'vm.getLinks' -require 'vm.guideInterface' -return vm diff --git a/script-beta/vm/vm.lua b/script-beta/vm/vm.lua deleted file mode 100644 index e942d55e..00000000 --- a/script-beta/vm/vm.lua +++ /dev/null @@ -1,167 +0,0 @@ -local guide = require 'parser.guide' -local util = require 'utility' -local files = require 'files' -local timer = require 'timer' - -local setmetatable = setmetatable -local assert = assert -local require = require -local type = type -local running = coroutine.running -local ipairs = ipairs -local log = log -local xpcall = xpcall -local mathHuge = math.huge -local collectgarbage = collectgarbage - -_ENV = nil - ----@class vm -local m = {} - -function m.lock(tp, source) - local co = running() - local master = m.locked[co] - if not master then - master = {} - m.locked[co] = master - end - if not master[tp] then - master[tp] = {} - end - if master[tp][source] then - return nil - end - master[tp][source] = true - return function () - master[tp][source] = nil - end -end - -function m.isSet(src) - local tp = src.type - if tp == 'setglobal' - or tp == 'local' - or tp == 'setlocal' - or tp == 'setfield' - or tp == 'setmethod' - or tp == 'setindex' - or tp == 'tablefield' - or tp == 'tableindex' then - return true - end - if tp == 'call' then - local special = m.getSpecial(src.node) - if special == 'rawset' then - return true - end - end - return false -end - -function m.isGet(src) - local tp = src.type - if tp == 'getglobal' - or tp == 'getlocal' - or tp == 'getfield' - or tp == 'getmethod' - or tp == 'getindex' then - return true - end - if tp == 'call' then - local special = m.getSpecial(src.node) - if special == 'rawget' then - return true - end - end - return false -end - -function m.getArgInfo(source) - local callargs = source.parent - if not callargs or callargs.type ~= 'callargs' then - return nil - end - local call = callargs.parent - if not call or call.type ~= 'call' then - return nil - end - for i = 1, #callargs do - if callargs[i] == source then - return call.node, i - end - end - return nil -end - -function m.getSpecial(source) - if not source then - return nil - end - return source.special -end - -function m.getKeyName(source) - if not source then - return nil - end - if source.type == 'call' then - local special = m.getSpecial(source.node) - if special == 'rawset' - or special == 'rawget' then - return guide.getKeyNameOfLiteral(source.args[2]) - end - end - return guide.getKeyName(source) -end - -function m.mergeResults(a, b) - for _, r in ipairs(b) do - if not a[r] then - a[r] = true - a[#a+1] = r - end - end - return a -end - -m.cacheTracker = setmetatable({}, { __mode = 'kv' }) - -function m.flushCache() - if m.cache then - m.cache.dead = true - end - m.cacheVersion = files.globalVersion - m.cache = {} - m.cacheActiveTime = mathHuge - m.locked = setmetatable({}, { __mode = 'k' }) - m.cacheTracker[m.cache] = true -end - -function m.getCache(name) - if m.cacheVersion ~= files.globalVersion then - m.flushCache() - end - m.cacheActiveTime = timer.clock() - if not m.cache[name] then - m.cache[name] = {} - end - return m.cache[name] -end - -local function init() - m.flushCache() - - -- 可以在一段时间不活动后清空缓存,不过目前看起来没有必要 - --timer.loop(1, function () - -- if timer.clock() - m.cacheActiveTime > 10.0 then - -- log.info('Flush cache: Inactive') - -- m.flushCache() - -- collectgarbage() - -- end - --end) -end - -xpcall(init, log.error) - -return m |