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 var err error_
164 err.code = InvalidInitCycle
165 err.errorf(obj, "initialization cycle for %s", obj.Name())
166
167 for i := len(cycle) - 1; i >= 0; i-- {
168 err.errorf(obj, "%s refers to", obj.Name())
169 obj = cycle[i]
170 }
171
172 err.errorf(obj, "%s", obj.Name())
173 check.report(&err)
174 }
175
176
177
178
179
180
181
182
183 type dependency interface {
184 Object
185 isDependency()
186 }
187
188
189
190
191
192 type graphNode struct {
193 obj dependency
194 pred, succ nodeSet
195 index int
196 ndeps int
197 }
198
199
200
201 func (n *graphNode) cost() int {
202 return len(n.pred) * len(n.succ)
203 }
204
205 type nodeSet map[*graphNode]bool
206
207 func (s *nodeSet) add(p *graphNode) {
208 if *s == nil {
209 *s = make(nodeSet)
210 }
211 (*s)[p] = true
212 }
213
214
215
216
217 func dependencyGraph(objMap map[Object]*declInfo) []*graphNode {
218
219 M := make(map[dependency]*graphNode)
220 for obj := range objMap {
221
222 if obj, _ := obj.(dependency); obj != nil {
223 M[obj] = &graphNode{obj: obj}
224 }
225 }
226
227
228
229
230 for obj, n := range M {
231
232 for d := range objMap[obj].deps {
233
234 if d, _ := d.(dependency); d != nil {
235 d := M[d]
236 n.succ.add(d)
237 d.pred.add(n)
238 }
239 }
240 }
241
242 var G, funcG []*graphNode
243 for _, n := range M {
244 if _, ok := n.obj.(*Func); ok {
245 funcG = append(funcG, n)
246 } else {
247 G = append(G, n)
248 }
249 }
250
251
252
253
254
255
256
257
258
259
260
261 sort.Slice(funcG, func(i, j int) bool {
262 return funcG[i].cost() < funcG[j].cost()
263 })
264 for _, n := range funcG {
265
266
267 for p := range n.pred {
268
269 if p != n {
270
271
272 for s := range n.succ {
273
274 if s != n {
275 p.succ.add(s)
276 s.pred.add(p)
277 }
278 }
279 delete(p.succ, n)
280 }
281 }
282 for s := range n.succ {
283 delete(s.pred, n)
284 }
285 }
286
287
288 for i, n := range G {
289 n.index = i
290 n.ndeps = len(n.succ)
291 }
292
293 return G
294 }
295
296
297
298
299
300
301 type nodeQueue []*graphNode
302
303 func (a nodeQueue) Len() int { return len(a) }
304
305 func (a nodeQueue) Swap(i, j int) {
306 x, y := a[i], a[j]
307 a[i], a[j] = y, x
308 x.index, y.index = j, i
309 }
310
311 func (a nodeQueue) Less(i, j int) bool {
312 x, y := a[i], a[j]
313
314
315 return x.ndeps < y.ndeps || x.ndeps == y.ndeps && x.obj.order() < y.obj.order()
316 }
317
318 func (a *nodeQueue) Push(x interface{}) {
319 panic("unreachable")
320 }
321
322 func (a *nodeQueue) Pop() interface{} {
323 n := len(*a)
324 x := (*a)[n-1]
325 x.index = -1
326 *a = (*a)[:n-1]
327 return x
328 }
329
View as plain text