summaryrefslogtreecommitdiff
path: root/script/vm/node/compiler.lua
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2022-02-16 16:24:13 +0800
committer最萌小汐 <sumneko@hotmail.com>2022-02-16 16:24:13 +0800
commiteaa677572486a8c8fa1a140b2dcbbff18b09d7d5 (patch)
treeb9f7024e20895655c6db3593e05b417c2fb1975b /script/vm/node/compiler.lua
parent4e5ede23db35012ce0f2d9ec9a9425375f4f5062 (diff)
downloadlua-language-server-eaa677572486a8c8fa1a140b2dcbbff18b09d7d5.zip
update
Diffstat (limited to 'script/vm/node/compiler.lua')
-rw-r--r--script/vm/node/compiler.lua71
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