1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package dep
17
18 import (
19 "cuelang.org/go/cue/errors"
20 "cuelang.org/go/internal/core/adt"
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 type Config struct {
85
86 Dynamic bool
87
88
89
90 Descend bool
91
92
93
94
95 AllowCycles bool
96
97
98
99
100 Rootless bool
101
102
103
104
105
106
107
108
109 Pkg *adt.ImportReference
110 }
111
112
113 type Dependency struct {
114
115 Node *adt.Vertex
116
117
118 Reference adt.Resolver
119
120 pkg *adt.ImportReference
121
122 top bool
123
124 visitor *visitor
125 }
126
127
128
129 func (d *Dependency) Recurse() {
130 savedAll := d.visitor.all
131 savedTop := d.visitor.top
132 d.visitor.all = d.visitor.recurse
133 d.visitor.top = true
134
135 d.visitor.visitReusingVisitor(d.Node, false)
136
137 d.visitor.all = savedAll
138 d.visitor.top = savedTop
139 }
140
141
142
143 func (d *Dependency) Import() *adt.ImportReference {
144 return d.pkg
145 }
146
147
148
149
150 func (d *Dependency) IsRoot() bool {
151 return d.top
152 }
153
154 func importRef(r adt.Expr) *adt.ImportReference {
155 switch x := r.(type) {
156 case *adt.ImportReference:
157 return x
158 case *adt.SelectorExpr:
159 return importRef(x.X)
160 case *adt.IndexExpr:
161 return importRef(x.X)
162 }
163 return nil
164 }
165
166
167 type VisitFunc func(Dependency) error
168
169 var empty *adt.Vertex
170
171 func init() {
172
173 empty = &adt.Vertex{}
174 empty.ForceDone()
175 }
176
177 var zeroConfig = &Config{}
178
179
180
181 func Visit(cfg *Config, c *adt.OpContext, n *adt.Vertex, f VisitFunc) error {
182 if cfg == nil {
183 cfg = zeroConfig
184 }
185 if c == nil {
186 panic("nil context")
187 }
188 v := visitor{
189 ctxt: c,
190 fn: f,
191 pkg: cfg.Pkg,
192 recurse: cfg.Descend,
193 all: cfg.Descend,
194 top: true,
195 cfgDynamic: cfg.Dynamic,
196 }
197 return v.visitReusingVisitor(n, true)
198 }
199
200
201 func (v *visitor) visitReusingVisitor(n *adt.Vertex, top bool) error {
202 if v.cfgDynamic {
203 if v.marked == nil {
204 v.marked = marked{}
205 }
206 v.marked.markExpr(n)
207
208 v.dynamic(n, top)
209 } else {
210 v.visit(n, top)
211 }
212 return v.err
213 }
214
215 func (v *visitor) visit(n *adt.Vertex, top bool) (err error) {
216 savedNode := v.node
217 savedTop := v.top
218
219 v.node = n
220 v.top = top
221
222 defer func() {
223 v.node = savedNode
224 v.top = savedTop
225
226 switch x := recover(); x {
227 case nil:
228 case aborted:
229 err = v.err
230 default:
231 panic(x)
232 }
233 }()
234
235 for _, x := range n.Conjuncts {
236 v.markExpr(x.Env, x.Elem())
237 }
238
239 return nil
240 }
241
242 var aborted = errors.New("aborted")
243
244 type visitor struct {
245 ctxt *adt.OpContext
246 fn VisitFunc
247 node *adt.Vertex
248 err error
249 pkg *adt.ImportReference
250
251
252
253 recurse bool
254
255
256
257 all bool
258 top bool
259 topRef adt.Resolver
260 pathStack []refEntry
261 numRefs int
262
263
264 cfgDynamic bool
265
266 marked marked
267 }
268
269 type refEntry struct {
270 env *adt.Environment
271 ref adt.Resolver
272 }
273
274
275
276
277
278 func (c *visitor) markExpr(env *adt.Environment, expr adt.Elem) {
279 if expr, ok := expr.(adt.Resolver); ok {
280 c.markResolver(env, expr)
281 return
282 }
283
284 saved := c.topRef
285 c.topRef = nil
286 defer func() { c.topRef = saved }()
287
288 switch x := expr.(type) {
289 case nil:
290 case *adt.BinaryExpr:
291 c.markExpr(env, x.X)
292 c.markExpr(env, x.Y)
293
294 case *adt.UnaryExpr:
295 c.markExpr(env, x.X)
296
297 case *adt.Interpolation:
298 for i := 1; i < len(x.Parts); i += 2 {
299 c.markExpr(env, x.Parts[i])
300 }
301
302 case *adt.BoundExpr:
303 c.markExpr(env, x.Expr)
304
305 case *adt.CallExpr:
306 c.markExpr(env, x.Fun)
307 saved := c.all
308 c.all = true
309 for _, a := range x.Args {
310 c.markExpr(env, a)
311 }
312 c.all = saved
313
314 case *adt.DisjunctionExpr:
315 for _, d := range x.Values {
316 c.markExpr(env, d.Val)
317 }
318
319 case *adt.SliceExpr:
320 c.markExpr(env, x.X)
321 c.markExpr(env, x.Lo)
322 c.markExpr(env, x.Hi)
323 c.markExpr(env, x.Stride)
324
325 case *adt.ListLit:
326 env := &adt.Environment{Up: env, Vertex: empty}
327 for _, e := range x.Elems {
328 switch x := e.(type) {
329 case *adt.Comprehension:
330 c.markComprehension(env, x)
331
332 case adt.Expr:
333 c.markSubExpr(env, x)
334
335 case *adt.Ellipsis:
336 if x.Value != nil {
337 c.markSubExpr(env, x.Value)
338 }
339 }
340 }
341
342 case *adt.StructLit:
343 env := &adt.Environment{Up: env, Vertex: empty}
344 for _, e := range x.Decls {
345 c.markDecl(env, e)
346 }
347
348 case *adt.Comprehension:
349 c.markComprehension(env, x)
350 }
351 }
352
353
354 func (c *visitor) markResolver(env *adt.Environment, r adt.Resolver) {
355
356
357
358 ref, _ := c.ctxt.Resolve(adt.MakeConjunct(env, r, adt.CloseInfo{}), r)
359
360
361
362
363
364
365 if ref != nil {
366 c.reportDependency(env, r, ref)
367 return
368 }
369
370
371
372
373
374
375
376 switch x := r.(type) {
377 case *adt.NodeLink:
378 panic("unreachable")
379
380 case *adt.IndexExpr:
381 c.markExpr(env, x.X)
382 c.markExpr(env, x.Index)
383
384 case *adt.SelectorExpr:
385 c.markExpr(env, x.X)
386 }
387 }
388
389
390
391 func (c *visitor) reportDependency(env *adt.Environment, ref adt.Resolver, v *adt.Vertex) {
392 if v == c.node || v == empty {
393 return
394 }
395
396 reference := ref
397 if c.topRef == nil && len(c.pathStack) == 0 {
398 saved := c.topRef
399 c.topRef = ref
400 defer func() { c.topRef = saved }()
401 }
402
403
404
405
406
407
408 if !c.recurse && len(c.pathStack) == 0 && c.topRef != nil {
409 reference = c.topRef
410 }
411
412 if !v.Rooted() {
413 before := c.numRefs
414 c.markInternalResolvers(env, ref, v)
415
416
417
418 switch _, ok := ref.(*adt.FieldReference); {
419 case !ok:
420
421 return
422 case c.numRefs > before:
423
424
425 return
426 }
427 }
428 if hasLetParent(v) {
429 return
430 }
431
432
433 altRef := reference
434 for i := len(c.pathStack) - 1; i >= 0; i-- {
435 x := c.pathStack[i]
436 var w *adt.Vertex
437
438
439
440 if f := c.feature(x.env, x.ref); f != 0 {
441 w = v.Lookup(f)
442 }
443 if w == nil {
444 break
445 }
446 altRef = x.ref
447 if i == 0 && c.topRef != nil {
448 altRef = c.topRef
449 }
450 v = w
451 }
452
453
454 if p := importRef(ref.(adt.Expr)); p != nil {
455 savedPkg := c.pkg
456 c.pkg = p
457 defer func() { c.pkg = savedPkg }()
458 }
459
460 c.numRefs++
461
462 d := Dependency{
463 Node: v,
464 Reference: altRef,
465 pkg: c.pkg,
466 top: c.top,
467 visitor: c,
468 }
469 if err := c.fn(d); err != nil {
470 c.err = err
471 panic(aborted)
472 }
473 }
474
475
476
477 func hasLetParent(v *adt.Vertex) bool {
478 for ; v != nil; v = v.Parent {
479 if v.Label.IsLet() {
480 return true
481 }
482 }
483 return false
484 }
485
486
487 func (c *visitor) markConjuncts(v *adt.Vertex) {
488 for _, x := range v.Conjuncts {
489
490
491 c.markExpr(x.Env, x.Elem())
492 }
493 }
494
495
496
497
498
499 func (c *visitor) markInternalResolvers(env *adt.Environment, r adt.Resolver, v *adt.Vertex) {
500 if v.Rooted() {
501 panic("node must not be rooted")
502 }
503
504 saved := c.all
505
506
507
508 if c.marked != nil && hasLetParent(v) {
509 for _, x := range v.Conjuncts {
510 c.marked.markExpr(x.Expr())
511 }
512 }
513
514 c.markConjuncts(v)
515
516
517
518 c.all = false
519
520 switch r := r.(type) {
521 case *adt.SelectorExpr:
522 c.evaluateInner(env, r.X, r)
523 case *adt.IndexExpr:
524 c.evaluateInner(env, r.X, r)
525 }
526
527 c.all = saved
528 }
529
530
531
532
533
534 func (c *visitor) evaluateInner(env *adt.Environment, x adt.Expr, r adt.Resolver) {
535 value, _ := c.ctxt.Evaluate(env, x)
536 v, _ := value.(*adt.Vertex)
537 if v == nil {
538 return
539 }
540
541 v.Finalize(c.ctxt)
542
543 saved := len(c.pathStack)
544 c.pathStack = append(c.pathStack, refEntry{env, r})
545 c.markConjuncts(v)
546 c.pathStack = c.pathStack[:saved]
547 }
548
549 func (c *visitor) feature(env *adt.Environment, r adt.Resolver) adt.Feature {
550 switch r := r.(type) {
551 case *adt.SelectorExpr:
552 return r.Sel
553 case *adt.IndexExpr:
554 v, _ := c.ctxt.Evaluate(env, r.Index)
555 v = adt.Unwrap(v)
556 return adt.LabelFromValue(c.ctxt, r.Index, v)
557 default:
558 return adt.InvalidLabel
559 }
560 }
561
562 func (c *visitor) markSubExpr(env *adt.Environment, x adt.Expr) {
563 if c.all {
564 saved := c.top
565 c.top = false
566 c.markExpr(env, x)
567 c.top = saved
568 }
569 }
570
571 func (c *visitor) markDecl(env *adt.Environment, d adt.Decl) {
572 switch x := d.(type) {
573 case *adt.Field:
574 c.markSubExpr(env, x.Value)
575
576 case *adt.BulkOptionalField:
577 c.markExpr(env, x.Filter)
578
579
580 c.markSubExpr(env, x.Value)
581
582 case *adt.DynamicField:
583 c.markExpr(env, x.Key)
584
585
586 c.markSubExpr(env, x.Value)
587
588 case *adt.Comprehension:
589 c.markComprehension(env, x)
590
591 case adt.Expr:
592 c.markExpr(env, x)
593
594 case *adt.Ellipsis:
595 if x.Value != nil {
596 c.markSubExpr(env, x.Value)
597 }
598 }
599 }
600
601 func (c *visitor) markComprehension(env *adt.Environment, y *adt.Comprehension) {
602 env = c.markClauses(env, y.Clauses)
603
604
605
606
607
608
609
610
611
612
613
614
615 if envs := y.Envs(); len(envs) > 0 {
616
617
618
619 env = envs[0]
620 }
621 for i := y.Nest(); i > 0; i-- {
622 env = &adt.Environment{Up: env, Vertex: empty}
623 }
624
625 c.markExpr(env, adt.ToExpr(y.Value))
626 }
627
628 func (c *visitor) markClauses(env *adt.Environment, a []adt.Yielder) *adt.Environment {
629 for _, y := range a {
630 switch x := y.(type) {
631 case *adt.ForClause:
632 c.markExpr(env, x.Src)
633 env = &adt.Environment{Up: env, Vertex: empty}
634
635
636
637 case *adt.LetClause:
638 c.markExpr(env, x.Expr)
639 env = &adt.Environment{Up: env, Vertex: empty}
640
641 case *adt.IfClause:
642 c.markExpr(env, x.Condition)
643
644
645 case *adt.ValueClause:
646 env = &adt.Environment{Up: env, Vertex: empty}
647 }
648 }
649 return env
650 }
651
View as plain text