diff options
Diffstat (limited to 'script/vm/node/compiler.lua')
-rw-r--r-- | script/vm/node/compiler.lua | 71 |
1 files changed, 57 insertions, 14 deletions
diff --git a/script/vm/node/compiler.lua b/script/vm/node/compiler.lua index db5cd486..2dfd6efd 100644 --- a/script/vm/node/compiler.lua +++ b/script/vm/node/compiler.lua @@ -2,8 +2,7 @@ local guide = require 'parser.guide' local util = require 'utility' local state = require 'vm.state' ----@class parser.guide.object ----@field _compiledGlobal boolean +---@class parser.object ---@field _compiledNodes boolean ---@field _compiled any ---@field _globalID vm.node.global @@ -13,14 +12,21 @@ local m = {} ---@class vm.node.unknown m.UNKNOWN = { type = 'unknown' } +m.GLOBAL_SPLITE = '\x1F' ---@alias vm.node vm.node.unknown | vm.node.global | vm.node.class +---@param ... string +---@return string +function m.getGlobalID(...) + return table.concat({...}, m.GLOBAL_SPLITE) +end + local compilerMap = util.switch() : getMap() ---@param uri uri ----@param source parser.guide.object +---@param source parser.object ---@return vm.node function m.compileNode(uri, source) if source._compiled then @@ -35,6 +41,17 @@ function m.compileNode(uri, source) end local compilerGlobalMap = util.switch() + : case 'local' + : call(function (uri, source) + if source.tag ~= '_ENV' then + return + end + if source.ref then + for _, ref in ipairs(source.ref) do + m.compileGlobalNode(uri, ref) + end + end + end) : case 'setglobal' : call(function (uri, source) local name = guide.getKeyName(source) @@ -46,11 +63,45 @@ local compilerGlobalMap = util.switch() local global = state.getGlobal(name) global:addGet(uri, source) source._globalID = global + + local nxt = source.next + if nxt then + m.compileGlobalNode(uri, nxt) + end + end) + : case 'setfield' + ---@param uri uri + ---@param source parser.object + : call(function (uri, source) + local parent = source.node._globalID + if not parent then + return + end + local name = m.getGlobalID(parent:getName(), guide.getKeyName(source)) + source._globalID = state.declareGlobal(name, uri, source) + end) + : case 'getfield' + ---@param uri uri + ---@param source parser.object + : call(function (uri, source) + local parent = source.node._globalID + if not parent then + return + end + local name = m.getGlobalID(parent:getName(), guide.getKeyName(source)) + local global = state.getGlobal(name) + global:addGet(uri, source) + source._globalID = global + + local nxt = source.next + if nxt then + m.compileGlobalNode(uri, nxt) + end end) : getMap() ---@param uri uri ----@param source parser.guide.object +---@param source parser.object function m.compileGlobalNode(uri, source) if source._globalID ~= nil then return @@ -63,19 +114,11 @@ function m.compileGlobalNode(uri, source) end ---编译全局变量的node ----@param root parser.guide.object +---@param root parser.object function m.compileGlobals(root) - if root._compiledGlobal then - return - end - root._compiledGlobal = true local uri = guide.getUri(root) local env = guide.getENV(root) - if env.ref then - for _, ref in ipairs(env.ref) do - m.compileGlobalNode(uri, ref) - end - end + m.compileGlobalNode(uri, env) end return m |