1
2
3
4
5 package types2
6
7 import (
8 "container/heap"
9 "fmt"
10 . "internal/types/errors"
11 "sort"
12 )
13
14
15 func (check *Checker) initOrder() {
16
17
18 check.Info.InitOrder = check.Info.InitOrder[:0]
19
20
21
22 pq := nodeQueue(dependencyGraph(check.objMap))
23 heap.Init(&pq)
24
25 const debug = false
26 if debug {
27 fmt.Printf("Computing initialization order for %s\n\n", check.pkg)
28 fmt.Println("Object dependency graph:")
29 for obj, d := range check.objMap {
30
31 if obj, _ := obj.(dependency); obj != nil {
32 if len(d.deps) > 0 {
33 fmt.Printf("\t%s depends on\n", obj.Name())
34 for dep := range d.deps {
35 fmt.Printf("\t\t%s\n", dep.Name())
36 }
37 } else {
38 fmt.Printf("\t%s has no dependencies\n", obj.Name())
39 }
40 }
41 }
42 fmt.Println()
43
44 fmt.Println("Transposed object dependency graph (functions eliminated):")
45 for _, n := range pq {
46 fmt.Printf("\t%s depends on %d nodes\n", n.obj.Name(), n.ndeps)
47 for p := range n.pred {
48 fmt.Printf("\t\t%s is dependent\n", p.obj.Name())
49 }
50 }
51 fmt.Println()
52
53 fmt.Println("Processing nodes:")
54 }
55
56
57
58
59
60
61
62 emitted := make(map[*declInfo]bool)
63 for len(pq) > 0 {
64
65 n := heap.Pop(&pq).(*graphNode)
66
67 if debug {
68 fmt.Printf("\t%s (src pos %d) depends on %d nodes now\n",
69 n.obj.Name(), n.obj.order(), n.ndeps)
70 }
71
72
73 if n.ndeps > 0 {
74 cycle := findPath(check.objMap, n.obj, n.obj, make(map[Object]bool))
75
76
77
78
79
80
81
82
83 if cycle != nil {
84 check.reportCycle(cycle)
85 }
86
87
88
89 }
90
91
92
93 for p := range n.pred {
94 p.ndeps--
95 heap.Fix(&pq, p.index)
96 }
97
98
99 v, _ := n.obj.(*Var)
100 info := check.objMap[v]
101 if v == nil || !info.hasInitializer() {
102 continue
103 }
104
105
106
107
108
109 if emitted[info] {
110 continue
111 }
112 emitted[info] = true
113
114 infoLhs := info.lhs
115 if infoLhs == nil {
116 infoLhs = []*Var{v}
117 }
118 init := &Initializer{infoLhs, info.init}
119 check.Info.InitOrder = append(check.Info.InitOrder, init)
120 }
121
122 if debug {
123 fmt.Println()
124 fmt.Println("Initialization order:")
125 for _, init := range check.Info.InitOrder {
126 fmt.Printf("\t%s\n", init)
127 }
128 fmt.Println()
129 }
130 }
131
132
133
134
135 func findPath(objMap map[Object]*declInfo, from, to Object, seen map[Object]bool) []Object {
136 if seen[from] {
137 return nil
138 }
139 seen[from] = true
140
141 for d := range objMap[from].deps {
142 if d == to {
143 return []Object{d}
144 }
145 if P := findPath(objMap, d, to, seen); P != nil {
146 return append(P, d)
147 }
148 }
149
150 return nil
151 }
152
153
154 func (check *Checker) reportCycle(cycle []Object) {
155 obj := cycle[0]
156
157
158 if len(cycle) == 1 {
159 check.errorf(obj, InvalidInitCycle, "initialization cycle: %s refers to itself", obj.Name())
160 return
161 }
162
163 err := check.newError(InvalidInitCycle)
164 err.addf(obj, "initialization cycle for %s", obj.Name())
165
166 for i := len(cycle) - 1; i >= 0; i-- {
167 err.addf(obj, "%s refers to", obj.Name())
168 obj = cycle[i]
169 }
170
171 err.addf(obj, "%s", obj.Name())
172 err.report()
173 }
174
175
176
177
178
179
180
181
182 type dependency interface {
183 Object
184 isDependency()
185 }
186
187
188
189
190
191 type graphNode struct {
192 obj dependency
193 pred, succ nodeSet
194 index int
195 ndeps int
196 }
197
198
199
200 func (n *graphNode) cost() int {
201 return len(n.pred) * len(n.succ)
202 }
203
204 type nodeSet map[*graphNode]bool
205
206 func (s *nodeSet) add(p *graphNode) {
207 if *s == nil {
208 *s = make(nodeSet)
209 }
210 (*s)[p] = true
211 }
212
213
214
215
216 func dependencyGraph(objMap map[Object]*declInfo) []*graphNode {
217
218 M := make(map[dependency]*graphNode)
219 for obj := range objMap {
220
221 if obj, _ := obj.(dependency); obj != nil {
222 M[obj] = &graphNode{obj: obj}
223 }
224 }
225
226
227
228
229 for obj, n := range M {
230
231 for d := range objMap[obj].deps {
232
233 if d, _ := d.(dependency); d != nil {
234 d := M[d]
235 n.succ.add(d)
236 d.pred.add(n)
237 }
238 }
239 }
240
241 var G, funcG []*graphNode
242 for _, n := range M {
243 if _, ok := n.obj.(*Func); ok {
244 funcG = append(funcG, n)
245 } else {
246 G = append(G, n)
247 }
248 }
249
250
251
252
253
254
255
256
257
258
259
260 sort.Slice(funcG, func(i, j int) bool {
261 return funcG[i].cost() < funcG[j].cost()
262 })
263 for _, n := range funcG {
264
265
266 for p := range n.pred {
267
268 if p != n {
269
270
271 for s := range n.succ {
272
273 if s != n {
274 p.succ.add(s)
275 s.pred.add(p)
276 }
277 }
278 delete(p.succ, n)
279 }
280 }
281 for s := range n.succ {
282 delete(s.pred, n)
283 }
284 }
285
286
287 for i, n := range G {
288 n.index = i
289 n.ndeps = len(n.succ)
290 }
291
292 return G
293 }
294
295
296
297
298
299
300 type nodeQueue []*graphNode
301
302 func (a nodeQueue) Len() int { return len(a) }
303
304 func (a nodeQueue) Swap(i, j int) {
305 x, y := a[i], a[j]
306 a[i], a[j] = y, x
307 x.index, y.index = j, i
308 }
309
310 func (a nodeQueue) Less(i, j int) bool {
311 x, y := a[i], a[j]
312
313
314 _, xConst := x.obj.(*Const)
315 _, yConst := y.obj.(*Const)
316 if xConst != yConst {
317 return xConst
318 }
319
320
321
322 return x.ndeps < y.ndeps || x.ndeps == y.ndeps && x.obj.order() < y.obj.order()
323 }
324
325 func (a *nodeQueue) Push(x any) {
326 panic("unreachable")
327 }
328
329 func (a *nodeQueue) Pop() any {
330 n := len(*a)
331 x := (*a)[n-1]
332 x.index = -1
333 *a = (*a)[:n-1]
334 return x
335 }
336
View as plain text