summaryrefslogtreecommitdiff
path: root/script/vm
diff options
context:
space:
mode:
Diffstat (limited to 'script/vm')
-rw-r--r--script/vm/compiler.lua9
-rw-r--r--script/vm/infer.lua48
-rw-r--r--script/vm/node.lua34
-rw-r--r--script/vm/sign.lua2
-rw-r--r--script/vm/value.lua19
5 files changed, 53 insertions, 59 deletions
diff --git a/script/vm/compiler.lua b/script/vm/compiler.lua
index 8126f393..8df28e7b 100644
--- a/script/vm/compiler.lua
+++ b/script/vm/compiler.lua
@@ -455,6 +455,9 @@ local function getReturn(func, index, args)
result:merge(rnode)
end
end
+ if result and returnNode:isOptional() then
+ result:addOptional()
+ end
end
end
end
@@ -1115,6 +1118,9 @@ local compilerSwitch = util.switch()
for _, typeUnit in ipairs(source.types) do
vm.setNode(source, vm.compileNode(typeUnit))
end
+ if source.optional then
+ vm.getNode(source):addOptional()
+ end
end)
: case 'doc.type.integer'
: case 'doc.type.string'
@@ -1220,6 +1226,9 @@ local compilerSwitch = util.switch()
else
vm.setNode(source, globalMgr.getGlobal('type', 'any'))
end
+ if source.optional then
+ vm.getNode(source):addOptional()
+ end
end)
: case 'generic'
: call(function (source)
diff --git a/script/vm/infer.lua b/script/vm/infer.lua
index 2a64ed52..7bb581cf 100644
--- a/script/vm/infer.lua
+++ b/script/vm/infer.lua
@@ -144,20 +144,23 @@ local viewNodeSwitch = util.switch()
local argView = ''
local regView = ''
for i, arg in ipairs(source.args) do
+ local argNode = vm.compileNode(arg)
+ local isOptional = argNode:isOptional()
+ if isOptional then
+ argNode = argNode:copy()
+ argNode:removeOptional()
+ end
args[i] = string.format('%s%s: %s'
, arg.name[1]
- , arg.optional and '?' or ''
- , m.getInfer(arg):view()
+ , isOptional and '?' or ''
+ , m.getInfer(argNode):view()
)
end
if #args > 0 then
argView = table.concat(args, ', ')
end
for i, ret in ipairs(source.returns) do
- rets[i] = string.format('%s%s'
- , m.getInfer(ret):view()
- , ret.optional and '?' or ''
- )
+ rets[i] = m.getInfer(ret):view()
end
if #rets > 0 then
regView = ':' .. table.concat(rets, ', ')
@@ -165,16 +168,21 @@ local viewNodeSwitch = util.switch()
return ('fun(%s)%s'):format(argView, regView)
end)
----@param source parser.object
+---@param source parser.object | vm.node
---@return vm.infer
function m.getInfer(source)
- local node = vm.compileNode(source)
+ local node
+ if source.type == 'vm.node' then
+ node = source
+ else
+ node = vm.compileNode(source)
+ end
if node.lastInfer then
return node.lastInfer
end
local infer = setmetatable({
node = node,
- uri = guide.getUri(source),
+ uri = source.type ~= 'vm.node' and guide.getUri(source),
}, mt)
node.lastInfer = infer
@@ -298,22 +306,26 @@ function mt:view(default, uri)
local max = #array
local limit = config.get(uri or self.uri, 'Lua.hover.enumsLimit')
+ local view
if max > limit then
- local view = string.format('%s...(+%d)'
+ view = string.format('%s...(+%d)'
, table.concat(array, '|', 1, limit)
, max - limit
)
-
- self.cachedView = view
-
- return view
else
- local view = table.concat(array, '|')
-
- self.cachedView = view
+ view = table.concat(array, '|')
+ end
- return view
+ if self.node:isOptional() then
+ if max > 1 then
+ view = '(' .. view .. ')?'
+ else
+ view = view .. '?'
+ end
end
+ self.cachedView = view
+
+ return view
end
function mt:eachView()
diff --git a/script/vm/node.lua b/script/vm/node.lua
index 3145a34d..6ef7c9d5 100644
--- a/script/vm/node.lua
+++ b/script/vm/node.lua
@@ -146,43 +146,30 @@ function mt:getData(k)
end
function mt:addOptional()
- if self:isOptional() then
- return self
- end
self.optional = true
end
function mt:removeOptional()
- if not self:isOptional() then
- return self
- end
- self:_expand()
- for i = #self, 1, -1 do
- local n = self[i]
- if n.type == 'nil'
- or (n.type == 'boolean' and n[1] == false)
- or (n.type == 'doc.type.boolean' and n[1] == false) then
- self[i] = self[#self]
- self[#self] = nil
- end
- end
+ self.optional = false
end
---@return boolean
function mt:isOptional()
- if self.optional ~= nil then
- return self.optional
+ return self.optional == true
+end
+
+---@return boolean
+function mt:isFalsy()
+ if self.optional then
+ return true
end
- self:_expand()
for _, c in ipairs(self) do
if c.type == 'nil'
or (c.type == 'boolean' and c[1] == false)
or (c.type == 'doc.type.boolean' and c[1] == false) then
- self.optional = true
return true
end
end
- self.optional = false
return false
end
@@ -196,6 +183,11 @@ function mt:eachObject()
end
end
+---@return vm.node
+function mt:copy()
+ return vm.createNode(self)
+end
+
---@param source parser.object | vm.generic
---@param node vm.node | vm.object
---@param cover? boolean
diff --git a/script/vm/sign.lua b/script/vm/sign.lua
index 2d45a5a7..257166ce 100644
--- a/script/vm/sign.lua
+++ b/script/vm/sign.lua
@@ -114,7 +114,7 @@ function mt:resolve(uri, args)
local function buildArgNode(argNode, knownTypes)
local newArgNode = vm.createNode()
for n in argNode:eachObject() do
- if argNode:isOptional() and vm.isFalsy(n) then
+ if argNode:isFalsy() then
goto CONTINUE
end
local view = infer.viewObject(n)
diff --git a/script/vm/value.lua b/script/vm/value.lua
index a784be2a..1a2b5722 100644
--- a/script/vm/value.lua
+++ b/script/vm/value.lua
@@ -41,28 +41,9 @@ function vm.test(source)
end
end
----@param source parser.object
----@return boolean
-function vm.isFalsy(source)
- if source.type == 'nil' then
- return true
- end
- if source.type == 'boolean'
- or source.type == 'doc.type.boolean' then
- return source[1] == false
- end
- return false
-end
-
---@param v vm.object
---@return string?
local function getUnique(v)
- if v.type == 'local' then
- return ('loc:%s@%d'):format(guide.getUri(v), v.start)
- end
- if v.type == 'global' then
- return ('%s:%s'):format(v.cate, v.name)
- end
if v.type == 'boolean' then
if v[1] == nil then
return false