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'
local compiler = require 'vm.compiler'
local globalMgr = require 'vm.global-manager'
---@class vm.type-manager
local m = {}
---@param child vm.node
---@param parent vm.node
---@return boolean
function m.isSubType(child, parent, mark)
if type(parent) == 'string' then
parent = globalMgr.getGlobal('type', parent)
end
if type(child) == 'string' then
child = globalMgr.getGlobal('type', child)
end
if parent.type == 'global' and parent.cate == 'type' and parent.name == 'any' then
return true
end
if child.type == 'doc.type' then
for _, typeUnit in ipairs(child.types) do
if not m.isSubType(typeUnit, parent) then
return false
end
end
return true
end
if child.type == 'doc.type.name' then
child = globalMgr.getGlobal('type', child[1])
end
if child.type == 'global' and child.cate == 'type' then
if parent.type == 'doc.type' then
for _, typeUnit in ipairs(parent.types) do
if m.isSubType(child, typeUnit) then
return true
end
end
end
if parent.type == 'doc.type.name' then
parent = globalMgr.getGlobal('type', parent[1])
end
if parent.type == 'global' and parent.cate == 'type' then
if parent.name == child.name then
return true
end
mark = mark or {}
if mark[child.name] then
return false
end
mark[child.name] = true
for _, set in ipairs(child:getSets()) do
if set.type == 'doc.class' and set.extends then
for _, ext in ipairs(set.extends) do
if m.isSubType(globalMgr.getGlobal('type', ext[1]), parent, mark) then
return true
end
end
end
end
end
end
return false
end
---@param tnode vm.node
---@param knode vm.node
function m.getTableValue(tnode, knode)
local result
for tn in nodeMgr.eachNode(tnode) do
if tn.type == 'doc.type.table' then
for _, field in ipairs(tn.fields) do
if m.isSubType(field.name, knode) then
result = nodeMgr.mergeNode(result, compiler.compileNode(field.extends))
end
end
end
if tn.type == 'doc.type.array' then
if m.isSubType(globalMgr.getGlobal('type', 'integer'), knode) then
result = nodeMgr.mergeNode(result, compiler.compileNode(tn.node))
end
end
if tn.type == 'table' then
for _, field in ipairs(tn) do
if field.type == 'tableindex' then
result = nodeMgr.mergeNode(result, compiler.compileNode(field.value))
end
if field.type == 'tablefield' then
result = nodeMgr.mergeNode(result, compiler.compileNode(field.value))
end
if field.type == 'tableexp' then
result = nodeMgr.mergeNode(result, compiler.compileNode(field.value))
end
end
end
end
return result
end
---@param tnode vm.node
---@param vnode vm.node
function m.getTableKey(tnode, vnode)
local result
for tn in nodeMgr.eachNode(tnode) do
if tn.type == 'doc.type.table' then
for _, field in ipairs(tn.fields) do
if m.isSubType(field.extends, vnode) then
result = nodeMgr.mergeNode(result, compiler.compileNode(field.name))
end
end
end
if tn.type == 'doc.type.array' then
if m.isSubType(tn.node, vnode) then
result = nodeMgr.mergeNode(result, globalMgr.getGlobal('type', 'integer'))
end
end
if tn.type == 'table' then
for _, field in ipairs(tn) do
if field.type == 'tableindex' then
result = nodeMgr.mergeNode(result, compiler.compileNode(field.index))
end
if field.type == 'tablefield' then
result = nodeMgr.mergeNode(result, globalMgr.getGlobal('type', 'string'))
end
if field.type == 'tableexp' then
result = nodeMgr.mergeNode(result, globalMgr.getGlobal('type', 'integer'))
end
end
end
end
return result
end
return m
|