summaryrefslogtreecommitdiff
path: root/script/vm
diff options
context:
space:
mode:
Diffstat (limited to 'script/vm')
-rw-r--r--script/vm/init.lua2
-rw-r--r--script/vm/node/class.lua (renamed from script/vm/object/class.lua)5
-rw-r--r--script/vm/node/compiler.lua56
-rw-r--r--script/vm/node/global.lua36
-rw-r--r--script/vm/node/init.lua (renamed from script/vm/compiler.lua)15
-rw-r--r--script/vm/object/init.lua0
-rw-r--r--script/vm/state.lua40
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