diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2022-12-15 16:46:59 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2022-12-15 16:46:59 +0800 |
commit | 244a19d365d8b3d3881492e08fefa9847bd11a2f (patch) | |
tree | b71dfe508b14015690a824be3d0f7f57ff1fba16 | |
parent | 0ab880ea3e3ef74c91dc56e449b4b7d60d654d8f (diff) | |
download | lua-language-server-244a19d365d8b3d3881492e08fefa9847bd11a2f.zip |
add supports for merging with `ifblock`
-rw-r--r-- | script/vm/node.lua | 7 | ||||
-rw-r--r-- | script/vm/tracer.lua | 81 |
2 files changed, 68 insertions, 20 deletions
diff --git a/script/vm/node.lua b/script/vm/node.lua index 2e408128..d0fd5ffb 100644 --- a/script/vm/node.lua +++ b/script/vm/node.lua @@ -188,9 +188,6 @@ end ---@return vm.node function mt:setFalsy() - if self.optional == false then - self.optional = nil - end local hasBoolean for index = #self, 1, -1 do local c = self[index] @@ -229,6 +226,10 @@ function mt:setFalsy() if hasBoolean then self:merge(vm.declareGlobal('type', 'false')) end + if self.optional then + self.optional = nil + self:merge(vm.declareGlobal('type', 'nil')) + end return self end diff --git a/script/vm/tracer.lua b/script/vm/tracer.lua index 065a52da..0c5b6939 100644 --- a/script/vm/tracer.lua +++ b/script/vm/tracer.lua @@ -35,11 +35,12 @@ end ---@param mark table function mt:collectBlock(obj, mark) while true do - obj = obj.parent - if mark[obj] then + local block = guide.getParentBlock(obj) + if not block then return end - if not guide.isBlockType(obj) then + obj = block + if mark[obj] then return end if obj == self.main then @@ -63,6 +64,9 @@ function mt:collectLocal() self.assigns[#self.assigns+1] = obj self:collectBlock(obj, mark) end + if obj.type == 'getlocal' then + self:collectBlock(obj, mark) + end end local casts = self:getCasts() @@ -112,10 +116,31 @@ function mt:narrow(source) end if source.type == 'getlocal' then - node = node:copy():setTruthy() - return node + node = node:copy() + node:setTruthy() end + return node +end + +---@param source parser.object +---@return vm.node? +function mt:calcGet(source) + local parent = source.parent + if parent.type == 'filter' then + return self:calcGet(parent) + end + if parent.type == 'ifblock' then + local parentBlock = guide.getParentBlock(parent.parent) + if parentBlock then + local lastAssign = self:getLastAssign(parentBlock, parent.start) + local node = self:getNode(lastAssign or parentBlock) + return node + end + end + if parent.type == 'unary' then + return self:calcGet(parent) + end return nil end @@ -135,19 +160,10 @@ function mt:calcNode(source) local node = self:getNode(lastAssign) return node end - local parent = source.parent - while true do - if parent.type == 'filter' - or parent.type == 'unary' - or parent.type == 'ifblock' - or parent.type == 'elseifblock' then - parent = parent.parent - else - break - end + local node = self:calcGet(source) + if node then + return node end - local node = self:getNode(parent) - return node end if source.type == 'setlocal' then if source.node ~= self.source then @@ -180,6 +196,37 @@ function mt:calcNode(source) return node end end + if source.type == 'if' then + local parentBlock = guide.getParentBlock(source) + if not parentBlock then + return nil + end + local lastAssign = self:getLastAssign(parentBlock, source.start) + local outNode = self:getNode(lastAssign or source.parent) or vm.createNode() + for _, block in ipairs(source) do + local blockNode = self:getNode(block) + if not blockNode then + goto CONTINUE + end + if block.hasReturn + or block.hasError + or block.hasBreak then + outNode:removeNode(blockNode) + goto CONTINUE + end + local blockAssign = self:getLastAssign(block, block.finish) + if not blockAssign then + goto CONTINUE + end + local blockAssignNode = self:getNode(blockAssign) + if not blockAssignNode then + goto CONTINUE + end + outNode:removeNode(blockNode) + outNode:merge(blockAssignNode) + ::CONTINUE:: + end + end if source.type == 'unary' then if source.op.type == 'not' then local node = self:getNode(source[1]) |