diff options
Diffstat (limited to 'script/vm')
-rw-r--r-- | script/vm/init.lua | 2 | ||||
-rw-r--r-- | script/vm/node/class.lua (renamed from script/vm/object/class.lua) | 5 | ||||
-rw-r--r-- | script/vm/node/compiler.lua | 56 | ||||
-rw-r--r-- | script/vm/node/global.lua | 36 | ||||
-rw-r--r-- | script/vm/node/init.lua (renamed from script/vm/compiler.lua) | 15 | ||||
-rw-r--r-- | script/vm/object/init.lua | 0 | ||||
-rw-r--r-- | script/vm/state.lua | 40 |
7 files changed, 142 insertions, 12 deletions
diff --git a/script/vm/init.lua b/script/vm/init.lua index 3a42fb9c..f0bbb032 100644 --- a/script/vm/init.lua +++ b/script/vm/init.lua @@ -1,5 +1,5 @@ local vm = require 'vm.vm' -require 'vm.compiler' +require 'vm.node' require 'vm.getGlobals' require 'vm.getDocs' require 'vm.getLibrary' diff --git a/script/vm/object/class.lua b/script/vm/node/class.lua index 2e6e6094..ee8b1ca8 100644 --- a/script/vm/object/class.lua +++ b/script/vm/node/class.lua @@ -1,8 +1,9 @@ ----@class vm.object.class +---@class vm.node.class local mt = {} mt.__index = mt +mt.type = 'class' ----@return vm.object.class +---@return vm.node.class return function () local class = setmetatable({ }, mt) diff --git a/script/vm/node/compiler.lua b/script/vm/node/compiler.lua new file mode 100644 index 00000000..2663291c --- /dev/null +++ b/script/vm/node/compiler.lua @@ -0,0 +1,56 @@ +local guide = require 'guide' +local util = require 'utility' +local state = require 'vm.state' + +---@class parser.guide.object +---@field _compiledGlobals boolean +---@field _initedNodes boolean +---@field _compiled any + +---@class vm.node.compiler +local m = {} + +---@class vm.node.unknown +m.UNKNOWN = { type = 'unknown' } + +local compilerMap = util.switch() + : case 'setglobal' + : call(function (uri, source) + state.declareGlobal(source[1], uri, source) + end) + : call(function (uri, source) + local global = state.getGlobal(source[1]) + global:addGet(uri, source) + end) + +---@param uri uri +---@param source parser.guide.object +function m.compileNode(uri, source) + if source._compiled then + return + end + source._compiled = m.UNKNOWN + local compiler = compilerMap[source.type] + if compiler then + compiler(uri, source) + end +end + +---编译全局变量的node +---@param root parser.guide.object +function m.compileGlobals(root) + if root._initedNodes then + return + end + if root._compiledGlobals then + return + end + root._compiledGlobals = true + local uri = guide.getUri(root) + local env = guide.getENV(root) + for _, ref in ipairs(env.refs) do + m.compileNode(uri, ref) + end +end + +return m diff --git a/script/vm/node/global.lua b/script/vm/node/global.lua new file mode 100644 index 00000000..07fff2d3 --- /dev/null +++ b/script/vm/node/global.lua @@ -0,0 +1,36 @@ +local util = require 'utility' + +---@class vm.node.global +---@field links table<uri, { gets: table, sets: table }> +local mt = {} +mt.__index = mt +mt.type = 'global' +mt.name = '' + +function mt:addSet(uri, source) + local link = self.links[uri] + link.sets[#link.sets+1] = source +end + +function mt:addGet(uri, source) + local link = self.links[uri] + link.gets[#link.gets+1] = source +end + +function mt:dropUri(uri) + self.links[uri] = nil +end + +---@return vm.node.global +return function (name) + local global = setmetatable({ + name = name, + links = util.defaultTable(function () + return { + sets = {}, + gets = {}, + } + end), + }, mt) + return global +end diff --git a/script/vm/compiler.lua b/script/vm/node/init.lua index 51fc5962..524dab4e 100644 --- a/script/vm/compiler.lua +++ b/script/vm/node/init.lua @@ -1,12 +1,11 @@ -local files = require 'files' - ----@class vm.compiler -local m = {} +local files = require 'files' +local compiler = require 'vm.node.compiler' +local vmState = require 'vm.state' for uri in files.eachFile() do local state = files.getState(uri) if state then - --m.compileGlobalNodes(state.ast) + compiler.compileGlobals(state.ast) end end @@ -14,12 +13,10 @@ files.watch(function (ev, uri) if ev == 'update' then local state = files.getState(uri) if state then - --m.compileGlobalNodes(state.ast) + compiler.compileGlobals(state.ast) end end if ev == 'remove' then - --collector:dropUri(uri) + vmState.dropUri(uri) end end) - -return m diff --git a/script/vm/object/init.lua b/script/vm/object/init.lua deleted file mode 100644 index e69de29b..00000000 --- a/script/vm/object/init.lua +++ /dev/null diff --git a/script/vm/state.lua b/script/vm/state.lua new file mode 100644 index 00000000..ba0b6665 --- /dev/null +++ b/script/vm/state.lua @@ -0,0 +1,40 @@ +local util = require 'utility' +local guide = require 'parser.guide' +local global = require 'vm.node.global' + +---@class vm.state +local m = {} +---@type table<string, vm.node.global> +m.globals = util.defaultTable(global) +---@type table<uri, { globals: table }> +m.subscriptions = util.defaultTable(function () + return { + globals = {}, + } +end) + +---@return vm.node.global +function m.declareGlobal(name, uri, source) + m.subscriptions[uri].globals[name] = true + local node = m.globals[name] + node:addSet(uri, source) + return node +end + +---@return vm.node.global +function m.getGlobal(name, uri) + if uri then + m.subscriptions[uri].globals[name] = true + end + return m.globals[name] +end + +function m.dropUri(uri) + local subscription = m.subscriptions[uri] + m.subscriptions[uri] = nil + for name in pairs(subscription) do + m.globals[name]:dropUri(uri) + end +end + +return m |