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
|
local nodeMgr = require 'vm.node'
---@class parser.object
---@field _generic vm.generic
---@class vm.generic
---@field sign vm.sign
---@field proto vm.node
local mt = {}
mt.__index = mt
mt.type = 'generic'
---@param node vm.node
---@param resolved? table<string, vm.node>
---@return vm.node
local function cloneObject(node, resolved)
if not resolved then
return node
end
if node.type == 'doc.generic.name' then
local key = node[1]
return resolved[key] or node
end
if node.type == 'doc.type' then
local newType = {
type = node.type,
start = node.start,
finish = node.finish,
parent = node.parent,
types = {},
}
for i, typeUnit in ipairs(node.types) do
local newObj = cloneObject(typeUnit, resolved)
newObj.parent = newType
newType.types[i] = newObj
end
return newType
end
if node.type == 'doc.type.arg' then
local newArg = {
type = node.type,
start = node.start,
finish = node.finish,
parent = node.parent,
name = node.name,
extends = cloneObject(node.extends, resolved)
}
newArg.name.parent = newArg
newArg.extends.parent = newArg
return newArg
end
if node.type == 'doc.type.array' then
local newArray = {
type = node.type,
start = node.start,
finish = node.finish,
parent = node.parent,
node = cloneObject(node.node, resolved),
}
newArray.node.parent = newArray
return newArray
end
if node.type == 'doc.type.table' then
local newTable = {
type = node.type,
start = node.start,
finish = node.finish,
parent = node.parent,
fields = {},
}
for i, field in ipairs(node.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),
}
newField.name.parent = newField
newField.extends.parent = newField
newTable.fields[i] = newField
end
return newTable
end
if node.type == 'doc.type.function' then
local newDocFunc = {
type = node.type,
start = node.start,
finish = node.finish,
parent = node.parent,
args = {},
returns = {},
}
for i, arg in ipairs(node.args) do
local newObj = cloneObject(arg, resolved)
newObj.parent = newDocFunc
newObj.optional = arg.optional
newDocFunc.args[i] = newObj
end
for i, ret in ipairs(node.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 node
end
---@param argNodes vm.node[]
---@return parser.object
function mt:resolve(argNodes)
local resolved = self.sign:resolve(argNodes)
local newProto = cloneObject(self.proto, resolved)
return newProto
end
function mt:eachNode()
local nodes = {}
for n in nodeMgr.eachNode(self.proto) do
nodes[#nodes+1] = n
end
local i = 0
return function ()
i = i + 1
return nodes[i], self
end
end
---@param proto vm.node
---@param sign vm.sign
return function (proto, sign)
local compiler = require 'vm.compiler'
local generic = setmetatable({
sign = sign,
proto = compiler.compileNode(proto),
}, mt)
return generic
end
|