summaryrefslogtreecommitdiff
path: root/server/src/matcher/vm.lua
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/matcher/vm.lua')
-rw-r--r--server/src/matcher/vm.lua126
1 files changed, 87 insertions, 39 deletions
diff --git a/server/src/matcher/vm.lua b/server/src/matcher/vm.lua
index 5c4736c9..18e1ddd3 100644
--- a/server/src/matcher/vm.lua
+++ b/server/src/matcher/vm.lua
@@ -68,9 +68,27 @@ function mt:createTable(source)
return tbl
end
+function mt:coverValue(target, source)
+ for k in pairs(target) do
+ target[k] = nil
+ end
+ for k, v in pairs(source) do
+ target[k] = v
+ end
+end
+
function mt:setValue(var, value)
assert(not value or value.type ~= 'list')
- var.value = value or self:createNil(var)
+ if var.value then
+ if var.value.type == 'nil' then
+ -- 允许覆盖nil
+ if value.type ~= 'nil' then
+ self:coverValue(var.value, value)
+ end
+ end
+ else
+ var.value = value or self:createNil(var)
+ end
return value
end
@@ -110,6 +128,7 @@ function mt:createFunction(exp, object)
returns = {
type = 'list',
},
+ args = {},
}
if not exp then
@@ -127,14 +146,17 @@ function mt:createFunction(exp, object)
return
end
if arg.type == 'name' then
- self:createLocal(arg[1], arg)
+ local var = self:createLocal(arg[1], arg)
+ func.args[#func.args+1] = var
elseif arg.type == '...' then
- self:createDots(arg)
+ local dots = self:createDots(arg)
+ func.args[#func.args+1] = dots
stop = true
end
end)
if object then
- self:createLocal('self', object)
+ local var = self:createLocal('self', object)
+ table.insert(func.args, 1, var)
end
self:doActions(exp)
@@ -166,31 +188,32 @@ function mt:call(func, values)
if func.used then
return self:getFunctionReturns(func)
end
-
func.used = true
- if func.args then
- for i, var in ipairs(func.args) do
- if var then
- if var.type == 'dots' then
- local list = {
- type = 'list',
- }
- if values then
- for n = i, #values do
- list[n-i+1] = values[n]
- end
- self:setValue(var, list)
- else
- self:setValue(var, nil)
+ if not func.args then
+ return self:getFunctionReturns(func)
+ end
+
+ for i, var in ipairs(func.args) do
+ if var then
+ if var.type == 'dots' then
+ local list = {
+ type = 'list',
+ }
+ if values then
+ for n = i, #values do
+ list[n-i+1] = values[n]
end
- break
+ self:setValue(var, list)
else
- if values then
- self:setValue(var, values[i])
- else
- self:setValue(var, nil)
- end
+ self:setValue(var, nil)
+ end
+ break
+ else
+ if values then
+ self:setValue(var, values[i])
+ else
+ self:setValue(var, nil)
end
end
end
@@ -203,9 +226,8 @@ function mt:getCurrentFunction()
return self.chunk.func
end
-function mt:setFunctionReturn(index, value)
- local func = self:getCurrentFunction()
- func.returns[index] = value
+function mt:setFunctionReturn(func, index, value)
+ func.returns[index] = value or self:createNil()
end
function mt:getFunctionReturns(func)
@@ -257,25 +279,47 @@ function mt:createNil(source)
}
end
-function mt:setLib(obj, lib)
- obj.lib = lib
+function mt:createCustom(tp, source)
+ return {
+ type = tp,
+ source = source or DefaultSource,
+ }
+end
+
+function mt:getLibValue(lib)
local tp = lib.type
if not tp then
return
end
+ local value
if tp == 'table' then
- self:setValue(obj, self:createTable())
+ value = self:createTable()
elseif tp == 'function' then
- self:setValue(obj, self:createFunction()) -- TODO
+ value = self:createFunction()
+ if lib.returns then
+ for i, rtn in ipairs(lib.returns) do
+ self:setFunctionReturn(value, i, self:getLibValue(rtn))
+ end
+ end
+ if lib.args then
+ local values = {}
+ for i, arg in ipairs(lib.args) do
+ values[i] = self:getLibValue(arg) or self:createNil()
+ end
+ self:call(value, values)
+ end
elseif tp == 'string' then
- self:setValue(obj, self:createString(lib.value))
+ value = self:createString(lib.value)
elseif tp == 'boolean' then
- self:setValue(obj, self:createBoolean(lib.value))
+ value = self:createBoolean(lib.value)
elseif tp == 'number' then
- self:setValue(obj, self:createNumber(lib.value))
+ value = self:createNumber(lib.value)
elseif tp == 'integer' then
- self:setValue(obj, self:createInteger(lib.value))
+ value = self:createInteger(lib.value)
+ else
+ value = self:createCustom(tp)
end
+ return value
end
function mt:getName(name, source)
@@ -473,7 +517,7 @@ end
function mt:doReturn(action)
for i, exp in ipairs(action) do
local value = self:getExp(exp)
- self:setFunctionReturn(i, value)
+ self:setFunctionReturn(self:getCurrentFunction(), i, value)
end
end
@@ -663,13 +707,17 @@ function mt:createEnvironment()
for name, info in pairs(library.global) do
local field = self:createField(pValue, name)
if info.lib then
- self:setLib(field, info.lib)
+ local value = self:getLibValue(info.lib)
+ self:setValue(field, value)
+ value.lib = info.lib
end
if info.child then
local fValue = self:getValue(field)
for fname, flib in pairs(info.child) do
local ffield = self:createField(fValue, fname)
- self:setLib(ffield, flib)
+ local value = self:getLibValue(flib)
+ self:setValue(ffield, value)
+ value.lib = flib
end
end
end