From 6aa19b14e48d5c81af0cda08362a975392a45565 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=80=E8=90=8C=E5=B0=8F=E6=B1=90?= Date: Mon, 10 Dec 2018 11:56:04 +0800 Subject: =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E4=B8=80=E4=BA=9B=E8=BF=90=E7=AE=97?= =?UTF-8?q?=E7=AC=A6=E6=9D=A5=E6=8E=A8=E5=AF=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/src/matcher/compile.lua | 18 ++++-- server/src/matcher/type_inference.lua | 111 +++++++++++++++++++++++++++++++--- 2 files changed, 117 insertions(+), 12 deletions(-) (limited to 'server/src/matcher') diff --git a/server/src/matcher/compile.lua b/server/src/matcher/compile.lua index de9f914b..53da49e0 100644 --- a/server/src/matcher/compile.lua +++ b/server/src/matcher/compile.lua @@ -242,12 +242,20 @@ function mt:searchSimple(simple) end function mt:searchBinary(exp) - self:searchExp(exp[1]) - self:searchExp(exp[2]) + return { + type = 'binary', + op = exp.op, + [1] = self:searchExp(exp[1]), + [2] = self:searchExp(exp[2]), + } end function mt:searchUnary(exp) - self:searchExp(exp[1]) + return { + type = 'unary', + op = exp.op, + [1] = self:searchExp(exp[1]), + } end function mt:searchTable(exp) @@ -309,9 +317,9 @@ function mt:searchExp(exp) elseif tp == 'simple' then return self:searchSimple(exp) elseif tp == 'binary' then - self:searchBinary(exp) + return self:searchBinary(exp) elseif tp == 'unary' then - self:searchUnary(exp) + return self:searchUnary(exp) elseif tp == '...' then self:checkDots(exp) elseif tp == 'function' then diff --git a/server/src/matcher/type_inference.lua b/server/src/matcher/type_inference.lua index e689c482..19205413 100644 --- a/server/src/matcher/type_inference.lua +++ b/server/src/matcher/type_inference.lua @@ -1,6 +1,77 @@ local mt = {} mt.__index = mt +function mt:setType(obj, type) + if not obj then + return + end + if not obj.group then + obj.group = { + type = type, + } + end + obj.valuetype = type +end + +function mt:getType(obj) + if not obj then + return nil + end + if obj.valuetype then + return obj.valuetype + end + if obj.group then + return obj.group.type + end + return nil +end + +function mt:getUnaryType(obj) + if obj.op == 'not' then + return 'boolean' + elseif obj.op == '#' then + return 'integer' + elseif obj.op == '-' then + return 'number' + elseif obj.op == '~' then + return 'integer' + end + return nil +end + +function mt:getBinaryType(obj) + if obj.op == 'or' + or obj.op == 'and' + or obj.op == '<=' + or obj.op == '>=' + or obj.op == '<' + or obj.op == '>' + or obj.op == '~=' + or obj.op == '==' + then + return 'boolean' + elseif obj.op == '|' + or obj.op == '~' + or obj.op == '&' + or obj.op == '<<' + or obj.op == '>>' + or obj.op == '//' + then + return 'integer' + elseif obj.op == '..' then + return 'string' + elseif obj.op == '+' + or obj.op == '-' + or obj.op == '*' + or obj.op == '/' + or obj.op == '^' + or obj.op == '%' + then + return 'number' + end + return nil +end + function mt:searchGroup(group) if not group then return @@ -14,6 +85,22 @@ function mt:searchGroup(group) return end end + for obj in pairs(group) do + -- TODO 搜索metatable + if obj.type == 'unary' then + local type = self:getUnaryType(obj) + if type then + group.type = type + return + end + elseif obj.type == 'binary' then + local type = self:getBinaryType(obj) + if type then + group.type = type + return + end + end + end group.type = false end @@ -24,16 +111,13 @@ function mt:searchVar(var) if self.lock[var] then return end - if not var.group and next(var.childs) then - var.valuetype = 'table' - var.group = { - type = 'table', - } - return - end self.lock[var] = true self:searchGroup(var.group) self.lock[var] = nil + if not self:getType(var) and next(var.childs) then + self:setType(var, 'table') + return + end end function mt:searchVars(vars) @@ -42,9 +126,22 @@ function mt:searchVars(vars) end end +function mt:searchCall(call) + if not self:getType(call.func) then + self:setType(call.func, 'function') + end +end + +function mt:searchCalls(calls) + for _, call in ipairs(calls) do + self:searchCall(call) + end +end + return function (results) local session = setmetatable({ lock = {}, }, mt) session:searchVars(results.vars) + session:searchCalls(results.calls) end -- cgit v1.2.3