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
|
---@class vm
local vm = require 'vm.vm'
---@class parser.object
---@field _generic vm.generic
---@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)
end
return newName
end
if source.type == 'doc.type' then
local newType = {
type = source.type,
start = source.start,
finish = source.finish,
parent = source.parent,
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' then
---@cast nd vm.global
result:merge(nd)
else
---@cast nd -vm.global
local clonedObject = cloneObject(nd, resolved)
if clonedObject then
local clonedNode = vm.compileNode(clonedObject)
result:merge(clonedNode)
end
end
end
return result
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
|