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