diff options
Diffstat (limited to 'script/vm')
-rw-r--r-- | script/vm/node.lua | 26 | ||||
-rw-r--r-- | script/vm/runner.lua | 58 |
2 files changed, 64 insertions, 20 deletions
diff --git a/script/vm/node.lua b/script/vm/node.lua index 5086f66d..1b3ea45c 100644 --- a/script/vm/node.lua +++ b/script/vm/node.lua @@ -224,6 +224,32 @@ function mt:remove(name) return self end +---@param name string +function mt:narrow(name) + if name ~= 'nil' and self.optional == true then + self.optional = nil + end + for index = #self, 1, -1 do + local c = self[index] + if (c.type == 'global' and c.cate == 'type' and c.name == name) + or (c.type == name) + or (c.type == 'doc.type.integer' and (name == 'number' or name == 'integer')) + or (c.type == 'doc.type.boolean' and name == 'boolean') + or (c.type == 'doc.type.table' and name == 'table') + or (c.type == 'doc.type.array' and name == 'table') + or (c.type == 'doc.type.function' and name == 'function') then + goto CONTINUE + end + table.remove(self, index) + self[c] = nil + ::CONTINUE:: + end + if #self == 0 then + self[#self+1] = vm.getGlobal('type', name) + end + return self +end + ---@param node vm.node function mt:removeNode(node) for _, c in ipairs(node) do diff --git a/script/vm/runner.lua b/script/vm/runner.lua index 2e362871..e6f34656 100644 --- a/script/vm/runner.lua +++ b/script/vm/runner.lua @@ -208,30 +208,48 @@ function mt:_lookInto(action, topNode, outNode) outNode = outNode2 elseif action.op.type == '==' or action.op.type == '~=' then - local loc, checker + local exp, checker for i = 1, 2 do - if action[i].type == 'getlocal' and action[i].node == self._loc then - loc = action[i] - checker = action[3-i] -- Copilot tells me use `3-i` instead of `i%2+1` - elseif action[2].type == 'getlocal' and action[2].node == self._loc then - loc = action[3-i] + if guide.isLiteral(action[i]) then checker = action[i] + exp = action[3-i] -- Copilot tells me use `3-i` instead of `i%2+1` end end - if loc then - self:_fastWard(loc.finish, topNode:copy()) - if guide.isLiteral(checker) then - local checkerNode = vm.compileNode(checker) - if action.op.type == '==' then - topNode = checkerNode - if outNode then - outNode:removeNode(topNode) - end - else - topNode:removeNode(checkerNode) - if outNode then - outNode = checkerNode - end + if not exp then + goto RETURN + end + if exp.type == 'getlocal' + and exp.node == self._loc then + self:_fastWard(exp.finish, topNode:copy()) + local checkerNode = vm.compileNode(checker) + if action.op.type == '==' then + topNode = checkerNode + if outNode then + outNode:removeNode(topNode) + end + else + topNode:removeNode(checkerNode) + if outNode then + outNode = checkerNode + end + end + elseif exp.type == 'call' + and checker.type == 'string' + and exp.node.special == 'type' + and exp.args + and exp.args[1] + and exp.args[1].type == 'getlocal' + and exp.args[1].node == self._loc then + self:_fastWard(exp.finish, topNode:copy()) + if action.op.type == '==' then + topNode:narrow(checker[1]) + if outNode then + outNode:remove(checker[1]) + end + else + topNode:remove(checker[1]) + if outNode then + outNode:narrow(checker[1]) end end end |