diff options
-rw-r--r-- | script/vm/getDef.lua | 2 | ||||
-rw-r--r-- | script/vm/node/compiler.lua | 81 | ||||
-rw-r--r-- | script/vm/state.lua | 5 | ||||
-rw-r--r-- | test/definition/table.lua | 9 |
4 files changed, 77 insertions, 20 deletions
diff --git a/script/vm/getDef.lua b/script/vm/getDef.lua index a303f5f7..735a817e 100644 --- a/script/vm/getDef.lua +++ b/script/vm/getDef.lua @@ -89,7 +89,7 @@ local nodeMap;nodeMap = util.switch() : case 'getfield' : case 'setfield' : call(function (source, pushResult) - local node = compiler.compileNode(guide.getUri(source.node), source.node) + local node = compiler.compileNode(source.node) if not node then return end diff --git a/script/vm/node/compiler.lua b/script/vm/node/compiler.lua index fefe4fb0..a9b77920 100644 --- a/script/vm/node/compiler.lua +++ b/script/vm/node/compiler.lua @@ -2,6 +2,7 @@ local guide = require 'parser.guide' local util = require 'utility' local state = require 'vm.state' local union = require 'vm.node.union' +local localID = require 'vm.local-id' ---@class parser.object ---@field _compiledNodes boolean @@ -55,11 +56,11 @@ local function getReturnOfFunction(func, index) } end) end - return m.compileNode(guide.getUri(func), func._returns[index]) + return m.compileNode(func._returns[index]) end local function getReturn(func, index) - local node = m.compileNode(guide.getUri(func), func) + local node = m.compileNode(func) if not node then return end @@ -77,63 +78,109 @@ local valueMap = util.switch() : case 'number' : case 'string' : case 'function' - : call(function (uri, source, value) - state.declareLiteral(uri, value) + : call(function (source, value) + state.declareLiteral(value) m.setNode(source, value) end) : case 'call' - : call(function (uri, source, value) + : call(function (source, value) m.setNode(source, getReturn(value.node, 1)) end) : getMap() -local function compileValue(uri, source, value) +local function compileValue(source, value) if not value then return end local f = valueMap[value.type] if f then - f(uri, source, value) + f(source, value) + end +end + +local function compileByLocalID(source) + local sources = localID.getSources(source) + if not sources then + return + end + for _, src in ipairs(sources) do + if src.value then + compileValue(source, src.value) + end + end +end + +local searchFieldMap = util.switch() + : case 'table' + : call(function (node, key, pushResult) + for _, field in ipairs(node) do + if field.type == 'tablefield' + or field.type == 'tableindex' then + if guide.getKeyName(field) == key then + pushResult(field) + end + end + end + end) + : getMap() + +local function compileByParentNode(source) + local parentNode = m.compileNode(source.node) + if not parentNode then + return + end + local key = guide.getKeyName(source) + for node in m.eachNode(parentNode) do + local f = searchFieldMap[node.type] + if f then + f(node, key, function (field) + compileValue(source, field.value) + end) + end end end local compilerMap = util.switch() : case 'local' - : call(function (uri, source) - compileValue(uri, source, source.value) + : call(function (source) + compileValue(source, source.value) if source.ref then for _, ref in ipairs(source.ref) do if ref.type == 'setlocal' then - compileValue(uri, source, ref.value) + compileValue(source, ref.value) end end end end) : case 'getlocal' - : call(function (uri, source) - m.setNode(source, m.compileNode(uri, source.node)) + : call(function (source) + m.setNode(source, m.compileNode(source.node)) end) : case 'setfield' + : call(function (source) + compileByLocalID(source) + end) : case 'getfield' - : call(function (uri, source) + : call(function (source) + compileByLocalID(source) + compileByParentNode(source) end) : case 'function.return' - : call(function (uri, source) + : call(function (source) end) : getMap() ----@param uri uri ---@param source parser.object ---@return vm.node -function m.compileNode(uri, source) +function m.compileNode(source) if source._node then return source._node end source._node = false local compiler = compilerMap[source.type] if compiler then - compiler(uri, source) + compiler(source) end state.subscribeLiteral(source, source._node) return source._node diff --git a/script/vm/state.lua b/script/vm/state.lua index 83ce6084..b0689384 100644 --- a/script/vm/state.lua +++ b/script/vm/state.lua @@ -1,6 +1,7 @@ local util = require 'utility' local files = require 'files' local globalNode = require 'vm.global-node' +local guide = require 'parser.guide' ---@class vm.state local m = {} @@ -13,13 +14,13 @@ end) ---@type table<parser.object, boolean> m.allLiterals = {} ----@param uri uri ---@param source parser.object -function m.declareLiteral(uri, source) +function m.declareLiteral(source) if m.allLiterals[source] then return end m.allLiterals[source] = true + local uri = guide.getUri(source) local literals = m.literals[uri] literals[#literals+1] = source end diff --git a/test/definition/table.lua b/test/definition/table.lua index 0fb76191..47cb13ea 100644 --- a/test/definition/table.lua +++ b/test/definition/table.lua @@ -151,6 +151,15 @@ print(x.y.<?z?>) ]] TEST [[ +local x = { + y = { + <!z!> = 1 + } +} +print(x.y.<?z?>) +]] + +TEST [[ local function f() local t = {} t.field1 = { |