summaryrefslogtreecommitdiff
path: root/server-beta/src/parser
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2019-09-26 17:47:21 +0800
committer最萌小汐 <sumneko@hotmail.com>2019-09-26 17:47:21 +0800
commit76bf5108d5fb0723d658598c8cc56c8f8fb16127 (patch)
treed5c2853e640c2ea76e45c872c52b0778244d63cd /server-beta/src/parser
parent4958dc910cbe4fd00d263cb320f06ae1ea3bee2f (diff)
downloadlua-language-server-76bf5108d5fb0723d658598c8cc56c8f8fb16127.zip
暂存
Diffstat (limited to 'server-beta/src/parser')
-rw-r--r--server-beta/src/parser/compile.lua126
-rw-r--r--server-beta/src/parser/guide.lua35
2 files changed, 143 insertions, 18 deletions
diff --git a/server-beta/src/parser/compile.lua b/server-beta/src/parser/compile.lua
index 8cfcd7a2..b8abad22 100644
--- a/server-beta/src/parser/compile.lua
+++ b/server-beta/src/parser/compile.lua
@@ -3,7 +3,105 @@ local type = type
_ENV = nil
-local pushError, Root, Compile, CompileBlock, Cache, Block, GoToTag, Version, ENVMode
+local pushError, Root, Compile, CompileBlock, Cache, Block, GoToTag, Version, ENVMode, Value
+
+--[[
+-- value 类右字面量创建,在set get call中传递
+-- obj 用 vref 表标记当前可能的 value 是哪些
+Value
+ type -> 确定类型
+ literal -> 字面量对象
+ tag -> 特殊标记
+ ref -> 值的引用者
+ child -> 值的child
+ func -> 函数对象
+--]]
+
+local function createValue(data)
+ local id = #Value+1
+ Value[id] = data
+ data.ref = {}
+ return id
+end
+
+local function addValue(objID, valueID)
+ local obj = Root[objID]
+ local vref = obj.vref
+ if not vref then
+ vref = {}
+ obj.vref = vref
+ Cache[vref] = {}
+ end
+ local cache = Cache[vref]
+ if cache[valueID] then
+ return
+ end
+ cache[valueID] = true
+ vref[#vref+1] = valueID
+ local valueRef = Value[valueID].ref
+ valueRef[#valueRef+1] = objID
+end
+
+local function getValue(objID)
+ local obj = Root[objID]
+ local vref = obj.vref
+ if vref then
+ return vref
+ end
+ addValue(objID, createValue {})
+ return obj.vref
+end
+
+local function mergeValue(objID1, objID2)
+ local obj1 = Root[objID1]
+ local obj2 = Root[objID2]
+ local vref1 = obj1.vref
+ local vref2 = obj2.vref
+ if not vref2 then
+ return
+ end
+ if not vref1 then
+ vref1 = {}
+ obj1.vref = vref1
+ Cache[vref1] = {}
+ end
+ local cache = Cache[vref1]
+ for i = 1, #vref2 do
+ local valueID = vref2[i]
+ if not cache[valueID] then
+ cache[valueID] = true
+ vref1[#vref1+1] = valueID
+ local valueRef = Value[valueID].ref
+ valueRef[#valueRef+1] = objID1
+ end
+ end
+end
+
+local function setChildValue(objID, keyID, valueID)
+ if not valueID then
+ return
+ end
+ local objVref = getValue(objID)
+ local key = guide.getKeyName(Root[keyID])
+ local valueVref = getValue(valueID)
+ for i = 1, #objVref do
+ local value = Value[objVref[i]]
+ if not value.child then
+ value.child = {}
+ end
+ value.child[key] = valueVref
+ end
+end
+
+local function addLocalRef(nodeID, objID)
+ local node = Root[nodeID]
+ local obj = Root[objID]
+ if not node.ref then
+ node.ref = {}
+ end
+ node.ref[#node.ref+1] = objID
+ obj.node = nodeID
+end
local vmMap = {
['nil'] = function (obj)
@@ -40,13 +138,9 @@ local vmMap = {
else
obj.type = 'getglobal'
if ENVMode == '_ENV' then
- local node = guide.getLocal(Root, obj, '_ENV', obj.start)
+ local node, nodeID = guide.getLocal(Root, obj, '_ENV', obj.start)
if node then
- if not node.ref then
- node.ref = {}
- end
- node.ref[#node.ref+1] = id
- obj.node = Cache[node]
+ addLocalRef(nodeID, id)
end
end
end
@@ -278,13 +372,10 @@ local vmMap = {
else
obj.type = 'setglobal'
if ENVMode == '_ENV' then
- local node = guide.getLocal(Root, obj, '_ENV', obj.start)
+ local node, nodeID = guide.getLocal(Root, obj, '_ENV', obj.start)
if node then
- if not node.ref then
- node.ref = {}
- end
- node.ref[#node.ref+1] = id
- obj.node = Cache[node]
+ addLocalRef(nodeID, id)
+ setChildValue(nodeID, id, obj.value)
end
end
end
@@ -508,13 +599,17 @@ local vmMap = {
Root[#Root+1] = obj
local id = #Root
if ENVMode == '_ENV' then
- Compile({
+ local envID = Compile({
type = 'local',
start = 0,
finish = 0,
effect = 0,
[1] = '_ENV',
}, id)
+ addValue(envID, createValue {
+ type = 'table',
+ tag = '_ENV',
+ })
end
CompileBlock(obj, id)
Block = nil
@@ -633,11 +728,14 @@ return function (self, lua, mode, version)
end
Cache = {}
GoToTag = {}
+ Value = {}
if type(state.ast) == 'table' then
Compile(state.ast)
end
PostCompile()
state.ast = nil
+ state.value = Value
Cache = nil
+ Value = nil
return state
end
diff --git a/server-beta/src/parser/guide.lua b/server-beta/src/parser/guide.lua
index 7925abe2..747d8d4f 100644
--- a/server-beta/src/parser/guide.lua
+++ b/server-beta/src/parser/guide.lua
@@ -129,18 +129,19 @@ function m.getLocal(root, block, name, pos)
goto CONTINUE
end
for i = 1, #locals do
- local loc = root[locals[i]]
+ local locID = locals[i]
+ local loc = root[locID]
if loc.effect > pos then
break
end
if loc[1] == name then
- if not res or res.effect < loc.effect then
- res = loc
+ if not res or root[res].effect < loc.effect then
+ res = locID
end
end
end
if res then
- return res
+ return root[res], res
end
::CONTINUE::
block = m.getParentBlock(root, block)
@@ -286,4 +287,30 @@ function m.lineRange(lines, row)
return line.start + 1, line.finish
end
+function m.getKeyName(obj)
+ if obj.type == 'getglobal' or obj.type == 'setglobal' then
+ return 'string|' .. obj[1]
+ elseif obj.type == 'getfield' or obj.type == 'getglobal' then
+ return 'string|' .. obj[1]
+ end
+end
+
+function m.eachField(value, obj, key, callback)
+ local vref = obj.vref
+ if not vref then
+ return
+ end
+ for x = 1, #vref do
+ local vID = vref[x]
+ local v = value[vID]
+ local child = v.child
+ if child then
+ local refs = child[key]
+ if refs then
+
+ end
+ end
+ end
+end
+
return m