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