diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2018-12-11 20:12:04 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2018-12-11 20:12:04 +0800 |
commit | febe2ee50eb8f13063e0e2f04bd40bbf38073a30 (patch) | |
tree | 90bf9dc348c38a03ab9ad38b21d6810ffe5c668e /server | |
parent | 30406bb8db6c33b7da92734da41a7eec884a73c6 (diff) | |
download | lua-language-server-febe2ee50eb8f13063e0e2f04bd40bbf38073a30.zip |
更新vm
Diffstat (limited to 'server')
-rw-r--r-- | server/src/matcher/definition.lua | 12 | ||||
-rw-r--r-- | server/src/matcher/vm.lua | 132 |
2 files changed, 74 insertions, 70 deletions
diff --git a/server/src/matcher/definition.lua b/server/src/matcher/definition.lua index 57e4b237..e8cfe4c0 100644 --- a/server/src/matcher/definition.lua +++ b/server/src/matcher/definition.lua @@ -10,11 +10,21 @@ local function parseResult(result) end end elseif tp == 'field' then + local mark = {} for _, info in ipairs(result.object) do - if info.type == 'set' then + if info.type == 'set' and not mark[info.source] then + mark[info.source] = true positions[#positions+1] = {info.source.start, info.source.finish} end end + if result.object.value then + for _, info in ipairs(result.object.value) do + if info.type == 'set' and not mark[info.source] then + mark[info.source] = true + positions[#positions+1] = {info.source.start, info.source.finish} + end + end + end elseif tp == 'label' then for _, info in ipairs(result.object) do if info.type == 'set' then diff --git a/server/src/matcher/vm.lua b/server/src/matcher/vm.lua index e09cfe54..f090d502 100644 --- a/server/src/matcher/vm.lua +++ b/server/src/matcher/vm.lua @@ -16,8 +16,6 @@ function mt:createLocal(key, source, value) self.results.locals[#self.results.locals+1] = loc self:addInfo(loc, 'local', source) - - local value = value or self:createValue('nil', source) self:setValue(loc, value, source) return loc end @@ -89,35 +87,58 @@ function mt:buildTable(source) return tbl end -function mt:coverValue(target, source) - local child = target.child - for k in pairs(target) do - target[k] = nil +function mt:mergeValue(a, b, mark) + if not mark then + mark = {} end - for k, v in pairs(source) do - target[k] = v + if mark[a] or mark[b] then + return end - if child then - if not target.child then - target.child = {} - end - for k, v in pairs(child) do - if target.child[k] == nil then - target.child[k] = v - end + mark[a] = true + mark[b] = true + for i, info in ipairs(a) do + a[i] = nil + b[#b+1] = info + end + self:mergeChild(a, b, mark) + for k in pairs(a) do + a[k] = nil + end + for k, v in pairs(b) do + a[k] = v + end +end + +function mt:mergeChild(a, b, mark) + if not a.child and not b.child then + return + end + if not mark then + mark = {} + end + local child = a.child or {} + local other = b.child or {} + a.child = nil + b.child = nil + for k, v in pairs(other) do + if child[k] then + self:mergeValue(v.value, child[k].value, mark) + else + child[k] = v end end + a.child = child + b.child = child end function mt:setValue(var, value, source) assert(not value or value.type ~= 'list') - value = value or self:createValue('nil', var) + value = value or self:createValue('nil', source) if var.value then - if var.value.type == 'nil' then - -- 允许覆盖nil - if value.type ~= 'nil' then - self:coverValue(var.value, value) - end + if value.type == 'nil' then + self:mergeChild(var.value, value) + else + self:mergeValue(var.value, value) end value = var.value else @@ -125,6 +146,7 @@ function mt:setValue(var, value, source) end if source and source.start then self:addInfo(var, 'set', source) + self:addInfo(value, 'set', source) end return value end @@ -250,17 +272,28 @@ function mt:setFunctionArgs(func, values) end end -function mt:callSetMetaTable(values) - values[1].metatable = values[2] - self:setFunctionReturn(self:getCurrentFunction(), 1, values[1]) - self.metas[#self.metas+1] = values[1] +function mt:checkMetaIndex(value, meta) + local index = self:getField(meta, '__index') + if not index then + return + end + local indexValue = self:getValue(index) + -- TODO 支持function + self:mergeChild(value, indexValue) +end + +function mt:callSetMetaTable(func, values) + self:setFunctionReturn(func, 1, values[1]) + + -- 检查 __index + self:checkMetaIndex(values[1], values[2]) end function mt:call(func, values) local lib = func.lib if lib and lib.special then if lib.special == 'setmetatable' then - self:callSetMetaTable(values) + self:callSetMetaTable(func, values) end end @@ -585,7 +618,7 @@ function mt:doLocal(action) if values then value = table.remove(values, 1) end - local var = self:createLocal(key[1], key, value) + self:createLocal(key[1], key, value) end) end @@ -742,7 +775,7 @@ function mt:createEnvironment() local field = self:createField(pValue, name) if info.lib then local value = self:getLibValue(info.lib) - self:setValue(field, value) + value = self:setValue(field, value) value.lib = info.lib end if info.child then @@ -750,48 +783,13 @@ function mt:createEnvironment() for fname, flib in pairs(info.child) do local ffield = self:createField(fValue, fname) local value = self:getLibValue(flib) - self:setValue(ffield, value) + value = self:setValue(ffield, value) value.lib = flib end end end end -function mt:mergeChild(a, b) - if not a.child and not b.child then - return - end - local child = a.child or {} - a.child = nil - b.child = nil - for k, v in pairs(b.child or {}) do - if child[k] then - self:coverValue(v, child[k]) - else - child[k] = v - end - end - a.child = child - b.child = child -end - -function mt:checkMetaIndex(value, meta) - local index = self:getField(meta, '__index') - if not index then - return - end - local indexValue = self:getValue(index) - -- TODO 支持function - self:mergeChild(value, indexValue) -end - -function mt:checkMeta() - for _, value in ipairs(self.metas) do - local meta = value.metatable - self:checkMetaIndex(value, meta) - end -end - local function compile(ast) local vm = setmetatable({ scope = env { @@ -806,7 +804,6 @@ local function compile(ast) labels = {}, funcs = {}, }, - metas = {}, }, mt) -- 创建初始环境 @@ -815,9 +812,6 @@ local function compile(ast) -- 执行代码 vm:doActions(ast) - -- 后处理meta - vm:checkMeta() - return vm end |