1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
|
---@class vm
local vm = require 'vm.vm'
---@class parser.object
---@field package _generic vm.generic
---@field package _resolved vm.node
---@class vm.generic
---@field sign vm.sign
---@field proto vm.object
local mt = {}
mt.__index = mt
mt.type = 'generic'
---@param source vm.object?
---@param resolved? table<string, vm.node>
---@return vm.object?
local function cloneObject(source, resolved)
if not resolved or not source then
return source
end
if source.type == 'doc.generic.name' then
local key = source[1]
local newName = {
type = source.type,
start = source.start,
finish = source.finish,
parent = source.parent,
[1] = source[1],
}
if resolved[key] then
vm.setNode(newName, resolved[key], true)
newName._resolved = resolved[key]
end
return newName
end
if source.type == 'doc.type' then
local newType = {
type = source.type,
start = source.start,
finish = source.finish,
parent = source.parent,
optional = source.optional,
types = {},
}
for i, typeUnit in ipairs(source.types) do
local newObj = cloneObject(typeUnit, resolved)
newType.types[i] = newObj
end
return newType
end
if source.type == 'doc.type.arg' then
local newArg = {
type = source.type,
start = source.start,
finish = source.finish,
parent = source.parent,
name = source.name,
extends = cloneObject(source.extends, resolved)
}
return newArg
end
if source.type == 'doc.type.array' then
local newArray = {
type = source.type,
start = source.start,
finish = source.finish,
parent = source.parent,
node = cloneObject(source.node, resolved),
}
return newArray
end
if source.type == 'doc.type.table' then
local newTable = {
type = source.type,
start = source.start,
finish = source.finish,
parent = source.parent,
fields = {},
}
for i, field in ipairs(source.fields) do
local newField = {
type = field.type,
start = field.start,
finish = field.finish,
parent = newTable,
name = cloneObject(field.name, resolved),
extends = cloneObject(field.extends, resolved),
}
newTable.fields[i] = newField
end
return newTable
end
if source.type == 'doc.type.function' then
local newDocFunc = {
type = source.type,
start = source.start,
finish = source.finish,
parent = source.parent,
args = {},
returns = {},
}
for i, arg in ipairs(source.args) do
local newObj = cloneObject(arg, resolved)
newObj.optional = arg.optional
newDocFunc.args[i] = newObj
end
for i, ret in ipairs(source.returns) do
local newObj = cloneObject(ret, resolved)
newObj.parent = newDocFunc
newObj.optional = ret.optional
newDocFunc.returns[i] = cloneObject(ret, resolved)
end
return newDocFunc
end
return source
end
---@param uri uri
---@param args parser.object
---@return vm.node
function mt:resolve(uri, args)
local resolved = self.sign:resolve(uri, args)
local protoNode = vm.compileNode(self.proto)
local result = vm.createNode()
for nd in protoNode:eachObject() do
if nd.type == 'global' or nd.type == 'variable' then
---@cast nd vm.global | vm.variable
result:merge(nd)
else
---@cast nd -vm.global, -vm.variable
local clonedObject = cloneObject(nd, resolved)
if clonedObject then
local clonedNode = vm.compileNode(clonedObject)
result:merge(clonedNode)
end
end
end
return result
end
---@param source parser.object
---@return vm.node?
function vm.getGenericResolved(source)
if source.type ~= 'doc.generic.name' then
return nil
end
return source._resolved
end
---@param source parser.object
---@param generic vm.generic
function vm.setGeneric(source, generic)
source._generic = generic
end
---@param source parser.object
---@return vm.generic?
function vm.getGeneric(source)
return source._generic
end
---@param proto vm.object
---@param sign vm.sign
---@return vm.generic
function vm.createGeneric(proto, sign)
local generic = setmetatable({
sign = sign,
proto = proto,
}, mt)
return generic
end
|