summaryrefslogtreecommitdiff
path: root/server/src
diff options
context:
space:
mode:
Diffstat (limited to 'server/src')
-rw-r--r--server/src/core/value.lua43
-rw-r--r--server/src/core/vm.lua42
2 files changed, 58 insertions, 27 deletions
diff --git a/server/src/core/value.lua b/server/src/core/value.lua
index 632f6cd4..5aa374ad 100644
--- a/server/src/core/value.lua
+++ b/server/src/core/value.lua
@@ -3,9 +3,8 @@ local DefaultSource = { start = 0, finish = 0 }
local mt = {}
mt.__index = mt
mt.type = 'value'
-mt._type = 'any'
-function mt:setValue(source, value)
+function mt:setValue(value)
self._value = value
end
@@ -13,17 +12,34 @@ function mt:getValue()
return self._value
end
-function mt:inference(tp)
+function mt:inference(tp, rate)
if tp == '...' then
error('Value type cant be ...')
end
- if self._type == 'any' and tp ~= 'nil' then
- self._type = tp
+ if not tp or tp == 'any' then
+ return
+ end
+ if not self._type then
+ self._type = {}
+ end
+ if not self._type[tp] or rate > self._type[tp] then
+ self._type[tp] = rate
end
end
function mt:getType()
- return self._type
+ if not self._type then
+ return 'nil'
+ end
+ local mRate = 0.0
+ local mType
+ for tp, rate in pairs(self._type) do
+ if rate > mRate then
+ mRate = rate
+ mType = tp
+ end
+ end
+ return mType or 'any'
end
function mt:createField(name, source)
@@ -42,7 +58,7 @@ function mt:createField(name, source)
end
self._child[uri][name] = field
- self:inference('table')
+ self:inference('table', 0.5)
return field
end
@@ -135,15 +151,18 @@ return function (tp, source, value)
error('Value type cant be ...')
end
-- TODO lib里的多类型
- if type(tp) == 'table' then
- tp = tp[1]
- end
local self = setmetatable({
source = source or DefaultSource,
- _type = tp,
}, mt)
if value ~= nil then
- self:setValue(source, value)
+ self:setValue(value)
+ end
+ if type(tp) == 'table' then
+ for i = 1, #tp do
+ self:inference(tp[i], 0.9)
+ end
+ else
+ self:inference(tp, 1.0)
end
return self
end
diff --git a/server/src/core/vm.lua b/server/src/core/vm.lua
index 219c5be1..68ef0efb 100644
--- a/server/src/core/vm.lua
+++ b/server/src/core/vm.lua
@@ -631,20 +631,23 @@ function mt:callDoFile(func, values)
end
function mt:call(func, values, source)
- func:inference('function')
+ func:inference('function', 0.9)
local lib = func.lib
if lib then
if lib.args then
for i, arg in ipairs(lib.args) do
- -- TODO 反向推测调用参数的类型
+ local value = values[i]
+ if value and arg.type ~= '...' then
+ value:inference(arg.type, 1.0)
+ end
end
end
if lib.returns then
for i, rtn in ipairs(lib.returns) do
if rtn.type == '...' then
- self:getFunctionReturns(func, i):inference('any')
+ self:getFunctionReturns(func, i):inference('any', 0.0)
else
- self:getFunctionReturns(func, i):inference(rtn.type or 'any')
+ self:getFunctionReturns(func, i):inference(rtn.type or 'any', 1.0)
end
end
end
@@ -1029,8 +1032,10 @@ function mt:getBinary(exp)
or op == '<'
or op == '>'
then
- v1:inference('number')
- v2:inference('number')
+ v1:inference('number', 0.9)
+ v2:inference('number', 0.9)
+ v1:inference('string', 0.1)
+ v2:inference('string', 0.1)
return self:createValue('boolean')
elseif op == '~='
or op == '=='
@@ -1042,8 +1047,12 @@ function mt:getBinary(exp)
or op == '<<'
or op == '>>'
then
- v1:inference('integer')
- v2:inference('integer')
+ v1:inference('integer', 0.9)
+ v2:inference('integer', 0.9)
+ v1:inference('number', 0.9)
+ v2:inference('number', 0.9)
+ v1:inference('string', 0.1)
+ v2:inference('string', 0.1)
if math.type(v1:getValue()) == 'integer' and math.type(v2:getValue()) == 'integer' then
if op == '|' then
return self:createValue('integer', v1:getValue() | v2:getValue())
@@ -1059,8 +1068,10 @@ function mt:getBinary(exp)
end
return self:createValue('integer')
elseif op == '..' then
- v1:inference('string')
- v2:inference('string')
+ v1:inference('string', 0.9)
+ v2:inference('string', 0.9)
+ v1:inference('number', 0.1)
+ v2:inference('number', 0.1)
if type(v1:getValue()) == 'string' and type(v2:getValue()) == 'string' then
return self:createValue('string', nil, v1:getValue() .. v2:getValue())
end
@@ -1073,8 +1084,8 @@ function mt:getBinary(exp)
or op == '%'
or op == '//'
then
- v1:inference('number')
- v2:inference('number')
+ v1:inference('number', 0.9)
+ v2:inference('number', 0.9)
if type(v1:getValue()) == 'number' and type(v2:getValue()) == 'number' then
if op == '+' then
return self:createValue('number', nil, v1:getValue() + v2:getValue())
@@ -1111,19 +1122,20 @@ function mt:getUnary(exp)
if op == 'not' then
return self:createValue('boolean')
elseif op == '#' then
- v1:inference('table')
+ v1:inference('table', 0.9)
+ v1:inference('string', 0.9)
if type(v1:getValue()) == 'string' then
return self:createValue('integer', nil, #v1:getValue())
end
return self:createValue('integer')
elseif op == '-' then
- v1:inference('number')
+ v1:inference('number', 0.9)
if type(v1:getValue()) == 'number' then
return self:createValue('number', nil, -v1:getValue())
end
return self:createValue('number')
elseif op == '~' then
- v1:inference('integer')
+ v1:inference('integer', 0.9)
if math.type(v1:getValue()) == 'integer' then
return self:createValue('integer', nil, ~v1:getValue())
end