1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package adt
16
17 import (
18 "cuelang.org/go/cue/errors"
19 "cuelang.org/go/cue/token"
20 )
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
85 type envDisjunct struct {
86 env *Environment
87 cloneID CloseInfo
88 expr *DisjunctionExpr
89 value *Disjunction
90 hasDefaults bool
91
92
93
94
95
96 parentDefaultUsed bool
97 childDefaultUsed bool
98 }
99
100 func (n *nodeContext) addDisjunction(env *Environment, x *DisjunctionExpr, cloneID CloseInfo) {
101
102
103 numDefaults := 0
104 for _, v := range x.Values {
105 isDef := v.Default
106 if isDef {
107 numDefaults++
108 }
109 }
110
111 n.disjunctions = append(n.disjunctions,
112 envDisjunct{env, cloneID, x, nil, numDefaults > 0, false, false})
113 }
114
115 func (n *nodeContext) addDisjunctionValue(env *Environment, x *Disjunction, cloneID CloseInfo) {
116 n.disjunctions = append(n.disjunctions,
117 envDisjunct{env, cloneID, nil, x, x.HasDefaults, false, false})
118
119 }
120
121 func (n *nodeContext) expandDisjuncts(
122 state vertexStatus,
123 parent *nodeContext,
124 parentMode defaultMode,
125 recursive, last bool) {
126
127 unreachableForDev(n.ctx)
128
129 n.ctx.stats.Disjuncts++
130
131
132
133
134
135
136 var refNode *RefNode
137
138 node := n.node
139 defer func() {
140 n.node = node
141 }()
142
143 for n.expandOne(partial) {
144 }
145
146
147
148
149 if recursive || len(n.disjunctions) > 0 {
150 n.snapshot = clone(*n.node)
151 } else {
152 n.snapshot = *n.node
153 }
154
155 defaultOffset := len(n.usedDefault)
156
157 switch {
158 default:
159 m := *n
160 n.postDisjunct(state)
161
162 switch {
163 case n.hasErr():
164
165
166
167
168 x := n.node
169 err, ok := x.BaseValue.(*Bottom)
170 if !ok {
171 err = n.getErr()
172 }
173 if err == nil {
174
175
176
177 err = x.ChildErrors
178 }
179 if err != nil {
180 parent.disjunctErrs = append(parent.disjunctErrs, err)
181 }
182 if recursive {
183 n.free()
184 }
185 return
186 }
187
188 if recursive {
189 *n = m
190 n.result = *n.node
191 n.node = &n.result
192 n.disjuncts = append(n.disjuncts, n)
193 }
194 if n.node.BaseValue == nil {
195 n.node.BaseValue = n.getValidators(state)
196 }
197
198 n.usedDefault = append(n.usedDefault, defaultInfo{
199 parentMode: parentMode,
200 nestedMode: parentMode,
201 origMode: parentMode,
202 })
203
204 case len(n.disjunctions) > 0:
205
206
207 state = finalized
208
209 n.disjuncts = append(n.disjuncts, n)
210
211 n.refCount++
212 defer n.free()
213
214 for i, d := range n.disjunctions {
215 a := n.disjuncts
216 n.disjuncts = n.buffer[:0]
217 n.buffer = a[:0]
218
219 last := i+1 == len(n.disjunctions)
220 skipNonMonotonicChecks := i+1 < len(n.disjunctions)
221 if skipNonMonotonicChecks {
222 n.ctx.inDisjunct++
223 }
224
225 for _, dn := range a {
226 switch {
227 case d.expr != nil:
228 for _, v := range d.expr.Values {
229 cn := dn.clone()
230 *cn.node = clone(dn.snapshot)
231 cn.node.state = cn
232
233 c := MakeConjunct(d.env, v.Val, d.cloneID)
234 cn.addExprConjunct(c, state)
235
236 newMode := mode(d.hasDefaults, v.Default)
237
238 cn.expandDisjuncts(state, n, newMode, true, last)
239
240
241
242
243
244
245 for r := n.node.cyclicReferences; r != nil; r = r.Next {
246 s := *r
247 s.Next = refNode
248 refNode = &s
249 }
250 }
251
252 case d.value != nil:
253 for i, v := range d.value.Values {
254 cn := dn.clone()
255 *cn.node = clone(dn.snapshot)
256 cn.node.state = cn
257
258 cn.addValueConjunct(d.env, v, d.cloneID)
259
260 newMode := mode(d.hasDefaults, i < d.value.NumDefaults)
261
262 cn.expandDisjuncts(state, n, newMode, true, last)
263
264
265 for r := n.node.cyclicReferences; r != nil; r = r.Next {
266 s := *r
267 s.Next = refNode
268 refNode = &s
269 }
270 }
271 }
272 }
273
274 if skipNonMonotonicChecks {
275 n.ctx.inDisjunct--
276 }
277
278 if len(n.disjuncts) == 0 {
279 n.makeError()
280 }
281
282 if recursive || i > 0 {
283 for _, x := range a {
284 x.free()
285 }
286 }
287
288 if len(n.disjuncts) == 0 {
289 break
290 }
291 }
292
293
294
295 for _, d := range n.disjuncts {
296 for i, info := range d.usedDefault[defaultOffset:] {
297 if info.parentMode == isDefault {
298 n.disjunctions[i].parentDefaultUsed = true
299 }
300 if info.origMode == isDefault {
301 n.disjunctions[i].childDefaultUsed = true
302 }
303 }
304 }
305
306
307
308
309
310
311
312
313
314 for _, d := range n.disjuncts {
315 m := maybeDefault
316 orig := maybeDefault
317 for i, info := range d.usedDefault[defaultOffset:] {
318 parent := info.parentMode
319
320 used := n.disjunctions[i].parentDefaultUsed
321 childUsed := n.disjunctions[i].childDefaultUsed
322 hasDefaults := n.disjunctions[i].hasDefaults
323
324 orig = combineDefault(orig, info.parentMode)
325 orig = combineDefault(orig, info.nestedMode)
326
327 switch {
328 case childUsed:
329
330
331
332
333
334
335
336
337
338
339 m = combineDefault(m, info.parentMode)
340 m = combineDefault(m, info.origMode)
341
342 case !hasDefaults, used:
343 m = combineDefault(m, info.parentMode)
344 m = combineDefault(m, info.nestedMode)
345
346 case hasDefaults && !used:
347 Assertf(parent == notDefault, "unexpected default mode")
348 }
349 }
350 d.defaultMode = m
351
352 d.usedDefault = d.usedDefault[:defaultOffset]
353 d.usedDefault = append(d.usedDefault, defaultInfo{
354 parentMode: parentMode,
355 nestedMode: m,
356 origMode: orig,
357 })
358
359 }
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382 }
383
384
385 switch p := parent; {
386 case p != n:
387 p.disjunctErrs = append(p.disjunctErrs, n.disjunctErrs...)
388 n.disjunctErrs = n.disjunctErrs[:0]
389
390 outer:
391 for _, d := range n.disjuncts {
392 for k, v := range p.disjuncts {
393
394
395
396
397 if v.result.status < finalized || d.result.status < finalized {
398 break
399 }
400
401
402 if !d.done() || !v.done() {
403 break
404 }
405 flags := CheckStructural
406 if last {
407 flags |= IgnoreOptional
408 }
409 if Equal(n.ctx, &v.result, &d.result, flags) {
410 m := maybeDefault
411 for _, u := range d.usedDefault {
412 m = combineDefault(m, u.nestedMode)
413 }
414 if m == isDefault {
415 p.disjuncts[k] = d
416 v.free()
417 } else {
418 d.free()
419 }
420 continue outer
421 }
422 }
423
424 p.disjuncts = append(p.disjuncts, d)
425 }
426
427 n.disjuncts = n.disjuncts[:0]
428 }
429
430
431 for r := refNode; r != nil; {
432 next := r.Next
433 r.Next = parent.node.cyclicReferences
434 parent.node.cyclicReferences = r
435 r = next
436 }
437 }
438
439 func (n *nodeContext) makeError() {
440 code := IncompleteError
441
442 if len(n.disjunctErrs) > 0 {
443 code = EvalError
444 for _, c := range n.disjunctErrs {
445 if c.Code > code {
446 code = c.Code
447 }
448 }
449 }
450
451 b := &Bottom{
452 Code: code,
453 Err: n.disjunctError(),
454 }
455 n.node.SetValue(n.ctx, b)
456 }
457
458 func mode(hasDefault, marked bool) defaultMode {
459 var mode defaultMode
460 switch {
461 case !hasDefault:
462 mode = maybeDefault
463 case marked:
464 mode = isDefault
465 default:
466 mode = notDefault
467 }
468 return mode
469 }
470
471
472
473
474
475
476
477
478
479
480 func clone(v Vertex) Vertex {
481 v.state = nil
482 if a := v.Arcs; len(a) > 0 {
483 v.Arcs = make([]*Vertex, len(a))
484 for i, arc := range a {
485 switch arc.status {
486 case finalized:
487 v.Arcs[i] = arc
488
489 case 0:
490 a := *arc
491 v.Arcs[i] = &a
492
493 a.Conjuncts = make([]Conjunct, len(arc.Conjuncts))
494 copy(a.Conjuncts, arc.Conjuncts)
495
496 default:
497 a := *arc
498 a.state = arc.state.clone()
499 a.state.node = &a
500 a.state.snapshot = clone(a)
501 v.Arcs[i] = &a
502 }
503 }
504 }
505
506 if a := v.Structs; len(a) > 0 {
507 v.Structs = make([]*StructInfo, len(a))
508 copy(v.Structs, a)
509 }
510
511 return v
512 }
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537 type defaultMode int
538
539 const (
540 maybeDefault defaultMode = iota
541 isDefault
542 notDefault
543 )
544
545
546
547
548
549
550
551 func combineDefault(a, b defaultMode) defaultMode {
552 if a > b {
553 return a
554 }
555 return b
556 }
557
558
559
560
561
562 func (n *nodeContext) disjunctError() (errs errors.Error) {
563 ctx := n.ctx
564
565 disjuncts := selectErrors(n.disjunctErrs)
566
567 if disjuncts == nil {
568 errs = ctx.Newf("empty disjunction")
569 } else {
570 disjuncts = errors.Sanitize(disjuncts)
571 k := len(errors.Errors(disjuncts))
572 if k == 1 {
573 return disjuncts
574 }
575
576 errs = ctx.Newf("%d errors in empty disjunction:", k)
577 errs = errors.Append(errs, disjuncts)
578 }
579
580 return errs
581 }
582
583 func selectErrors(a []*Bottom) (errs errors.Error) {
584
585 if len(a) <= 2 {
586 for _, b := range a {
587 errs = errors.Append(errs, b.Err)
588
589 }
590 return errs
591 }
592
593
594 isIncomplete := false
595 k := 0
596 for _, b := range a {
597 if !isIncomplete && b.Code >= IncompleteError {
598 k = 0
599 isIncomplete = true
600 }
601 a[k] = b
602 k++
603 }
604 a = a[:k]
605
606
607 positions := map[token.Pos]bool{}
608
609 add := func(b *Bottom, p token.Pos) bool {
610 if positions[p] {
611 return false
612 }
613 positions[p] = true
614 errs = errors.Append(errs, b.Err)
615 return true
616 }
617
618 for _, b := range a {
619
620 if add(b, b.Err.Position()) {
621 continue
622 }
623 for _, p := range b.Err.InputPositions() {
624 if add(b, p) {
625 break
626 }
627 }
628 }
629
630 return errs
631 }
632
View as plain text