summaryrefslogtreecommitdiff
path: root/script/vm/node/compiler.lua
diff options
context:
space:
mode:
Diffstat (limited to 'script/vm/node/compiler.lua')
-rw-r--r--script/vm/node/compiler.lua81
1 files changed, 64 insertions, 17 deletions
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