blob: 409eda396099df59bbbea9bfb5887c0dd42c2063 [file] [log] [blame]
Marcel van Lohuizen0f935f82020-06-09 09:13:01 +02001// Copyright 2020 CUE Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// Package eval contains the high level CUE evaluation strategy.
16//
17// CUE allows for a significant amount of freedom in order of evaluation due to
18// the commutativity of the unification operation. This package implements one
19// of the possible strategies.
20package eval
21
22// TODO:
23// - result should be nodeContext: this allows optionals info to be extracted
24// and computed.
25//
26
27import (
28 "fmt"
29
30 "cuelang.org/go/cue/ast"
31 "cuelang.org/go/cue/errors"
32 "cuelang.org/go/cue/token"
33 "cuelang.org/go/internal/core/adt"
34 "cuelang.org/go/internal/core/debug"
35)
36
37func Evaluate(r adt.Runtime, v *adt.Vertex) {
38 format := func(n adt.Node) string {
39 return debug.NodeString(r, n, printConfig)
40 }
41 e := New(r)
42 c := adt.New(v, &adt.Config{
43 Runtime: r,
44 Unifier: e,
45 Format: format,
46 })
47 e.Unify(c, v, adt.Finalized)
48}
49
50func New(r adt.Runtime) *Evaluator {
51 return &Evaluator{r: r, index: r}
52}
53
54// TODO: Note: NewContext takes essentially a cue.Value. By making this
55// type more central, we can perhaps avoid context creation.
56
57func NewContext(r adt.Runtime, v *adt.Vertex) *adt.OpContext {
58 e := New(r)
59 return e.NewContext(v)
60}
61
62var printConfig = &debug.Config{Compact: true}
63
64func (e *Evaluator) NewContext(v *adt.Vertex) *adt.OpContext {
65 format := func(n adt.Node) string {
66 return debug.NodeString(e.r, n, printConfig)
67 }
68 return adt.New(v, &adt.Config{
69 Runtime: e.r,
70 Unifier: e,
71 Format: format,
72 })
73}
74
75var structSentinel = &adt.StructMarker{}
76
77var incompleteSentinel = &adt.Bottom{
78 Code: adt.IncompleteError,
79 Err: errors.Newf(token.NoPos, "incomplete"),
80}
81
82type Evaluator struct {
83 r adt.Runtime
84 index adt.StringIndexer
85 closeID uint32
86}
87
88func (e *Evaluator) nextID() uint32 {
89 e.closeID++
90 return e.closeID
91}
92
93func (e *Evaluator) Eval(v *adt.Vertex) errors.Error {
94 if v.Value == nil {
95 ctx := adt.NewContext(e.r, e, v)
96 e.Unify(ctx, v, adt.Finalized)
97 }
98
99 // extract error if needed.
100 return nil
101}
102
103// Evaluate is used to evaluate a sub expression while evaluating a Vertex
104// with Unify. It may or may not return the original Vertex. It may also
105// terminate evaluation early if it has enough evidence that a certain value
106// can be the only value in a valid configuration. This means that an error
107// may go undetected at this point, as long as it is caught later.
108//
109func (e *Evaluator) Evaluate(c *adt.OpContext, v *adt.Vertex) adt.Value {
110 var resultValue adt.Value
111 if v.Value == nil {
112 save := *v
113 // Use node itself to allow for cycle detection.
114 s := e.evalVertex(c, v, adt.Partial)
115
116 if d := s.disjunct; d != nil && len(d.Values) > 1 && d.NumDefaults != 1 {
117 v.Value = d
118 v.Arcs = nil
119 v.Structs = nil // TODO: maybe not do this.
120 // The conjuncts will have too much information. Better have no
121 // information than incorrect information.
122 for _, d := range d.Values {
123 d.Conjuncts = nil
124 }
125 }
126
127 resultValue = v.Value
128
129 result := s.result()
130 *v = save
131
132 if result.Value != nil {
133 *v = *result
134 resultValue = result.Value
135 }
136
137 // TODO: this seems unnecessary as long as we have a better way
138 // to handle incomplete, and perhaps referenced. nodes.
139 if c.IsTentative() && isStruct(v) {
140 // TODO(perf): do something more efficient perhaps? This discards
141 // the computed arcs so far. Instead, we could have a separate
142 // marker to accumulate results. As this only happens within
143 // comprehensions, the effect is likely minimal, though.
144 arcs := v.Arcs
145 *v = save
146 return &adt.Vertex{
147 Parent: v.Parent,
148 Value: &adt.StructMarker{},
149 Arcs: arcs,
150 }
151 }
152 // *v = save // DO NOT ADD.
153 err, _ := resultValue.(*adt.Bottom)
154 // BEFORE RESTORING, copy the value to return one
155 // with the temporary arcs.
156 if !s.done() && (err == nil || err.IsIncomplete()) {
157 // Clear values afterwards
158 *v = save
159 }
160 if !s.done() && s.hasDisjunction() {
161 return &adt.Bottom{Code: adt.IncompleteError}
162 }
163 if s.hasResult() {
164 if b, _ := v.Value.(*adt.Bottom); b != nil {
165 *v = save
166 return b
167 }
168 // TODO: Only use result when not a cycle.
169 v = result
170 }
171 // TODO: Store if concrete and fully resolved.
172
173 } else {
174 b, _ := v.Value.(*adt.Bottom)
175 if b != nil {
176 return b
177 }
178 }
179
180 switch v.Value.(type) {
181 case nil:
182 // Error saved in result.
183 return resultValue // incomplete
184
185 case *adt.ListMarker, *adt.StructMarker:
186 return v
187
188 default:
189 return v.Value
190 }
191}
192
193// Unify implements adt.Unifier.
194//
195// May not evaluate the entire value, but just enough to be able to compute.
196//
197// Phase one: record everything concrete
198// Phase two: record incomplete
199// Phase three: record cycle.
200func (e *Evaluator) Unify(c *adt.OpContext, v *adt.Vertex, state adt.VertexStatus) {
201 // defer c.PopVertex(c.PushVertex(v))
202
203 if state <= v.Status()+1 {
204 return
205 }
206
207 if x := v.Value; x != nil {
208 // if state == adt.Partial || x == cycle {
209 // return
210 // }
211 return
212 }
213
214 n := e.evalVertex(c, v, state)
215
216 switch d := n.disjunct; {
217 case d != nil && len(d.Values) == 1:
218 *v = *(d.Values[0])
219
220 case d != nil && len(d.Values) > 0:
221 v.Value = d
222 v.Arcs = nil
223 v.Structs = nil
224 // The conjuncts will have too much information. Better have no
225 // information than incorrect information.
226 for _, d := range d.Values {
227 d.Conjuncts = nil
228 }
229
230 default:
231 if r := n.result(); r.Value != nil {
232 *v = *r
233 }
234 }
235
236 // Else set it to something.
237
238 if v.Value == nil {
239 panic("errer")
240 }
241
242 // Check whether result is done.
243}
244
245// evalVertex computes the vertex results. The state indicates the minimum
246// status to which this vertex should be evaluated. It should be either
247// adt.Finalized or adt.Partial.
248func (e *Evaluator) evalVertex(c *adt.OpContext, v *adt.Vertex, state adt.VertexStatus) *nodeShared {
249 // fmt.Println(debug.NodeString(c.StringIndexer, v, nil))
250 shared := &nodeShared{
251 ctx: c,
252 eval: e,
253 node: v,
254 stack: nil, // silence linter
255 }
256 saved := *v
257
258 for i := 0; ; i++ {
259
260 // Clear any remaining error.
261 if err := c.Err(); err != nil {
262 panic("uncaught error")
263 }
264
265 // Set the cache to a cycle error to ensure a cyclic reference will result
266 // in an error if applicable. A cyclic error may be ignored for
267 // non-expression references. The cycle error may also be removed as soon
268 // as there is evidence what a correct value must be, but before all
269 // validation has taken place.
270 *v = saved
271 v.Value = cycle
272 v.UpdateStatus(adt.Evaluating)
273
274 // If the result is a struct, it needs to be closed if:
275 // 1) this node introduces a definition
276 // 2) this node is a child of a node that introduces a definition,
277 // recursively.
278 // 3) this node embeds a closed struct.
279 needClose := v.Label.IsDef()
280
281 n := &nodeContext{
282 kind: adt.TopKind,
283 nodeShared: shared,
284 needClose: needClose,
285
286 // These get cleared upon proof to the contrary.
287 // isDefault: true,
288 isFinal: true,
289 }
290
291 closeID := uint32(0)
292
293 for _, x := range v.Conjuncts {
294 closeID := closeID
295 // TODO: needed for reentrancy. Investigate usefulness for cycle
296 // detection.
297 if x.Env != nil && x.Env.CloseID != 0 {
298 closeID = x.Env.CloseID
299 }
300 n.addExprConjunct(x, closeID, true)
301 }
302
303 if i == 0 {
304 // Use maybeSetCache for cycle breaking
305 for n.maybeSetCache(); n.expandOne(); n.maybeSetCache() {
306 }
307 if v.Status() > adt.Evaluating && state <= adt.Partial {
308 // We have found a partial result. There may still be errors
309 // down the line which may result from further evaluating this
310 // field, but that will be caught when evaluating this field
311 // for real.
312 shared.setResult(v)
313 return shared
314 }
315 if !n.done() && len(n.disjunctions) > 0 && isEvaluating(v) {
316 // We disallow entering computations of disjunctions with
317 // incomplete data.
318 b := c.NewErrf("incomplete cause disjunction")
319 b.Code = adt.IncompleteError
320 v.SetValue(n.ctx, adt.Finalized, b)
321 shared.setResult(v)
322 return shared
323 }
324 }
325
326 // Handle disjunctions. If there are no disjunctions, this call is
327 // equivalent to calling n.postDisjunct.
328 if n.tryDisjuncts() {
329 if v.Value == nil {
330 v.Value = n.getValidators()
331 }
332
333 break
334 }
335 }
336
337 return shared
338}
339
340func isStruct(v *adt.Vertex) bool {
341 _, ok := v.Value.(*adt.StructMarker)
342 return ok
343}
344
345func (n *nodeContext) postDisjunct() {
346 ctx := n.ctx
347
348 // Use maybeSetCache for cycle breaking
349 for n.maybeSetCache(); n.expandOne(); n.maybeSetCache() {
350 }
351
352 // TODO: preparation for association lists:
353 // We assume that association types may not be created dynamically for now.
354 // So we add lists
355 n.addLists(ctx)
356
357 switch err := n.getErr(); {
358 case err != nil:
359 n.node.Value = err
360 n.errs = nil
361
362 default:
363 if isEvaluating(n.node) {
364 // TODO: this does not yet validate all values.
365
366 if !n.done() { // && !ctx.IsTentative() {
367 // collect incomplete errors.
368 // len(n.ifClauses) == 0 &&
369 // len(n.forClauses) == 0 &&
370 var err *adt.Bottom // n.incomplete
371 // err = n.incomplete
372 for _, d := range n.dynamicFields {
373 x, _ := ctx.Concrete(d.env, d.field.Key, "dynamic field")
374 b, _ := x.(*adt.Bottom)
375 err = adt.CombineErrors(nil, err, b)
376 }
377 for _, c := range n.forClauses {
378 f := func(env *adt.Environment, st *adt.StructLit) {}
379 err = adt.CombineErrors(nil, err, ctx.Yield(c.env, c.yield, f))
380 }
381 for _, x := range n.exprs {
382 x, _ := ctx.Evaluate(x.Env, x.Expr())
383 b, _ := x.(*adt.Bottom)
384 err = adt.CombineErrors(nil, err, b)
385 }
386 if err == nil {
387 // safeguard.
388 err = incompleteSentinel
389 }
390 n.node.Value = err
391 } else {
392 n.node.Value = nil
393 }
394 }
395
396 // We are no longer evaluating.
397 n.node.UpdateStatus(adt.Partial)
398
399 // Either set to Conjunction or error.
400 var v adt.Value = n.node.Value
401 kind := n.kind
402 markStruct := false
403 if n.isStruct {
404 if kind != 0 && kind&adt.StructKind == 0 {
405 n.node.Value = &adt.Bottom{
406 Err: errors.Newf(token.NoPos,
407 "conflicting values struct and %s", n.kind),
408 }
409 }
410 markStruct = true
411 } else if len(n.node.Structs) > 0 {
412 markStruct = kind&adt.StructKind != 0 && !n.hasTop
413 }
414 if v == nil && markStruct {
415 kind = adt.StructKind
416 n.node.Value = &adt.StructMarker{}
417 v = n.node
418 }
419 if v != nil && adt.IsConcrete(v) {
420 if n.scalar != nil {
421 kind = n.scalar.Kind()
422 }
423 if v.Kind()&^kind != 0 {
424 p := token.NoPos
425 if src := v.Source(); src != nil {
426 p = src.Pos()
427 }
428 n.addErr(errors.Newf(p,
429 // TODO(err): position of all value types.
430 "conflicting types",
431 ))
432 }
433 if n.lowerBound != nil {
434 if b := ctx.Validate(n.lowerBound, v); b != nil {
435 n.addBottom(b)
436 }
437 }
438 if n.upperBound != nil {
439 if b := ctx.Validate(n.upperBound, v); b != nil {
440 n.addBottom(b)
441 }
442 }
443 for _, v := range n.checks {
444 if b := ctx.Validate(v, n.node); b != nil {
445 n.addBottom(b)
446 }
447 }
448
449 } else if !ctx.IsTentative() {
450 n.node.Value = n.getValidators()
451 }
452 // else if v == nil {
453 // n.node.Value = incompleteSentinel
454 // }
455
456 if v == nil {
457 break
458 }
459
460 switch {
461 case v.Kind() == adt.ListKind:
462 for _, a := range n.node.Arcs {
463 if a.Label.Typ() == adt.StringLabel {
464 n.addErr(errors.Newf(token.NoPos,
465 // TODO(err): add positions for list and arc definitions.
466 "list may not have regular fields"))
467 }
468 }
469
470 // case !isStruct(n.node) && v.Kind() != adt.BottomKind:
471 // for _, a := range n.node.Arcs {
472 // if a.Label.IsRegular() {
473 // n.addErr(errors.Newf(token.NoPos,
474 // // TODO(err): add positions of non-struct values and arcs.
475 // "cannot combine scalar values with arcs"))
476 // }
477 // }
478 }
479 }
480
481 var c *CloseDef
482 if a, _ := n.node.Closed.(*acceptor); a != nil {
483 c = a.tree
484 n.needClose = n.needClose || a.isClosed
485 }
486
487 updated := updateClosed(c, n.replace)
488 if updated == nil && n.needClose {
489 updated = &CloseDef{}
490 }
491
492 // TODO retrieve from env.
493
494 if err := n.getErr(); err != nil {
495 if b, _ := n.node.Value.(*adt.Bottom); b != nil {
496 err = adt.CombineErrors(nil, b, err)
497 }
498 n.node.Value = err
499 // TODO: add return: if evaluation of arcs is important it can be done
500 // later. Logically we're done.
501 }
502
503 m := &acceptor{
504 tree: updated,
505 fields: n.optionals,
506 isClosed: n.needClose,
507 openList: n.openList,
508 isList: n.node.IsList(),
509 }
510 if updated != nil || len(n.optionals) > 0 {
511 n.node.Closed = m
512 }
513
514 // Visit arcs recursively to validate and compute error.
515 for _, a := range n.node.Arcs {
516 if updated != nil {
517 a.Closed = m
518 }
519 if updated != nil && m.isClosed {
520 if err := m.verifyArcAllowed(n.ctx, a.Label); err != nil {
521 n.node.Value = err
522 }
523 // TODO: use continue to not process already failed fields,
524 // or at least don't record recursive error.
525 // continue
526 }
527 // Call UpdateStatus here to be absolutely sure the status is set
528 // correctly and that we are not regressing.
529 n.node.UpdateStatus(adt.EvaluatingArcs)
530 n.eval.Unify(ctx, a, adt.Finalized)
531 if err, _ := a.Value.(*adt.Bottom); err != nil {
532 n.node.AddChildError(err)
533 }
534 }
535
536 n.node.UpdateStatus(adt.Finalized)
537}
538
539// TODO: this is now a sentinel. Use a user-facing error that traces where
540// the cycle originates.
541var cycle = &adt.Bottom{
542 Err: errors.Newf(token.NoPos, "cycle error"),
543 Code: adt.CycleError,
544}
545
546func isEvaluating(v *adt.Vertex) bool {
547 isCycle := v.Status() == adt.Evaluating
548 if isCycle != (v.Value == cycle) {
549 panic(fmt.Sprintf("cycle data of sync %d vs %#v", v.Status(), v.Value))
550 }
551 return isCycle
552}
553
554type nodeShared struct {
555 eval *Evaluator
556 ctx *adt.OpContext
557 sub []*adt.Environment // Environment cache
558 node *adt.Vertex
559
560 // Disjunction handling
561 disjunct *adt.Disjunction
562 resultNode *nodeContext
563 result_ adt.Vertex
564 stack []int
565}
566
567func (n *nodeShared) result() *adt.Vertex {
568 return &n.result_
569}
570
571func (n *nodeShared) setResult(v *adt.Vertex) {
572 n.result_ = *v
573}
574
575func (n *nodeShared) hasResult() bool {
576 return n.resultNode != nil //|| n.hasResult_
577 // return n.resultNode != nil || n.hasResult_
578}
579
580func (n *nodeShared) done() bool {
581 // if d := n.disjunct; d == nil || len(n.disjunct.Values) == 0 {
582 // return false
583 // }
584 if n.resultNode == nil {
585 return false
586 }
587 return n.resultNode.done()
588}
589
590func (n *nodeShared) hasDisjunction() bool {
591 if n.resultNode == nil {
592 return false
593 }
594 return len(n.resultNode.disjunctions) > 0
595}
596
597func (n *nodeShared) isDefault() bool {
598 if n.resultNode == nil {
599 return false
600 }
601 return n.resultNode.defaultMode == isDefault
602}
603
604// A nodeContext is used to collate all conjuncts of a value to facilitate
605// unification. Conceptually order of unification does not matter. However,
606// order has relevance when performing checks of non-monotic properities. Such
607// checks should only be performed once the full value is known.
608type nodeContext struct {
609 *nodeShared
610
611 // TODO:
612 // filter *adt.Vertex a subset of composite with concrete fields for
613 // bloom-like filtering of disjuncts. We should first verify, however,
614 // whether some breath-first search gives sufficient performance, as this
615 // should already ensure a quick-fail for struct disjunctions with
616 // discriminators.
617
618 // Current value (may be under construction)
619 scalar adt.Value // TODO: use Value in node.
620
621 // Concrete conjuncts
622 kind adt.Kind
623 lowerBound *adt.BoundValue // > or >=
624 upperBound *adt.BoundValue // < or <=
625 checks []adt.Validator // BuiltinValidator, other bound values.
626 errs *adt.Bottom
627 incomplete *adt.Bottom
628
629 // Struct information
630 dynamicFields []envDynamic
631 ifClauses []envYield
632 forClauses []envYield
633 optionals []fieldSet // env + field
634 // NeedClose:
635 // - node starts definition
636 // - embeds a definition
637 // - parent node is closing
638 needClose bool
639 openList bool
640 isStruct bool
641 hasTop bool
642 newClose *CloseDef
643 // closeID uint32 // from parent, or if not exist, new if introducing a def.
644 replace map[uint32]*CloseDef
645
646 // Expression conjuncts
647 lists []envList
648 vLists []*adt.Vertex
649 exprs []conjunct
650
651 // Disjunction handling
652 disjunctions []envDisjunct
653 defaultMode defaultMode
654 isFinal bool
655}
656
657func (n *nodeContext) done() bool {
658 return len(n.dynamicFields) == 0 &&
659 len(n.ifClauses) == 0 &&
660 len(n.forClauses) == 0 &&
661 len(n.exprs) == 0
662}
663
664// hasErr is used to determine if an evaluation path, for instance a single
665// path after expanding all disjunctions, has an error.
666func (n *nodeContext) hasErr() bool {
667 if n.node.ChildErrors != nil {
668 return true
669 }
670 if n.node.Status() > adt.Evaluating && n.node.IsErr() {
671 return true
672 }
673 return n.ctx.HasErr() || n.errs != nil
674}
675
676func (n *nodeContext) getErr() *adt.Bottom {
677 n.errs = adt.CombineErrors(nil, n.errs, n.ctx.Err())
678 return n.errs
679}
680
681// getValidators sets the vertex' Value in case there was no concrete value.
682func (n *nodeContext) getValidators() adt.Value {
683 ctx := n.ctx
684
685 a := []adt.Value{}
686 // if n.node.Value != nil {
687 // a = append(a, n.node.Value)
688 // }
689 kind := adt.TopKind
690 if n.lowerBound != nil {
691 a = append(a, n.lowerBound)
692 kind &= n.lowerBound.Kind()
693 }
694 if n.upperBound != nil {
695 a = append(a, n.upperBound)
696 kind &= n.upperBound.Kind()
697 }
698 for _, c := range n.checks {
699 // Drop !=x if x is out of bounds with another bound.
700 if b, _ := c.(*adt.BoundValue); b != nil && b.Op == adt.NotEqualOp {
701 if n.upperBound != nil &&
702 adt.SimplifyBounds(ctx, n.kind, n.upperBound, b) != nil {
703 continue
704 }
705 if n.lowerBound != nil &&
706 adt.SimplifyBounds(ctx, n.kind, n.lowerBound, b) != nil {
707 continue
708 }
709 }
710 a = append(a, c)
711 kind &= c.Kind()
712 }
713 if kind&^n.kind != 0 {
714 a = append(a, &adt.BasicType{K: n.kind})
715 }
716
717 var v adt.Value
718 switch len(a) {
719 case 0:
720 // Src is the combined input.
721 v = &adt.BasicType{K: n.kind}
722
723 // TODO: Change to isStruct?
724 if len(n.node.Structs) > 0 {
725 // n.isStruct = true
726 v = structSentinel
727
728 }
729
730 case 1:
731 v = a[0].(adt.Value)
732
733 default:
734 v = &adt.Conjunction{Values: a}
735 }
736
737 return v
738}
739
740func (n *nodeContext) maybeSetCache() {
741 if n.node.Status() > adt.Evaluating { // n.node.Value != nil
742 return
743 }
744 if n.scalar != nil {
745 n.node.SetValue(n.ctx, adt.Partial, n.scalar)
746 }
747 if n.errs != nil {
748 n.node.SetValue(n.ctx, adt.Partial, n.errs)
749 }
750}
751
752type conjunct struct {
753 adt.Conjunct
754 closeID uint32
755 top bool
756}
757
758type envDynamic struct {
759 env *adt.Environment
760 field *adt.DynamicField
761}
762
763type envYield struct {
764 env *adt.Environment
765 yield adt.Yielder
766}
767
768type envList struct {
769 env *adt.Environment
770 list *adt.ListLit
771 n int64 // recorded length after evaluator
772 elipsis *adt.Ellipsis
773}
774
775func (n *nodeContext) addBottom(b *adt.Bottom) {
776 n.errs = adt.CombineErrors(nil, n.errs, b)
777}
778
779func (n *nodeContext) addErr(err errors.Error) {
780 if err != nil {
781 n.errs = adt.CombineErrors(nil, n.errs, &adt.Bottom{
782 Err: err,
783 })
784 }
785}
786
787// addExprConjuncts will attempt to evaluate an adt.Expr and insert the value
788// into the nodeContext if successful or queue it for later evaluation if it is
789// incomplete or is not value.
790func (n *nodeContext) addExprConjunct(v adt.Conjunct, def uint32, top bool) {
791 env := v.Env
792 if env != nil && env.CloseID != def {
793 e := *env
794 e.CloseID = def
795 env = &e
796 }
797 switch x := v.Expr().(type) {
798 case adt.Value:
799 n.addValueConjunct(env, x)
800
801 case *adt.BinaryExpr:
802 if x.Op == adt.AndOp {
803 n.addExprConjunct(adt.MakeConjunct(env, x.X), def, false)
804 n.addExprConjunct(adt.MakeConjunct(env, x.Y), def, false)
805 } else {
806 n.evalExpr(v, def, top)
807 }
808
809 case *adt.StructLit:
810 n.addStruct(env, x, def, top)
811
812 case *adt.ListLit:
813 n.lists = append(n.lists, envList{env: env, list: x})
814
815 case *adt.DisjunctionExpr:
816 if n.disjunctions != nil {
817 _ = n.disjunctions
818 }
819 n.addDisjunction(env, x, def, top)
820
821 default:
822 // Must be Resolver or Evaluator.
823 n.evalExpr(v, def, top)
824 }
825
826 if top {
827 n.updateReplace(v.Env)
828 }
829}
830
831// evalExpr is only called by addExprConjunct.
832func (n *nodeContext) evalExpr(v adt.Conjunct, closeID uint32, top bool) {
833 // Require an Environment.
834 ctx := n.ctx
835
836 switch x := v.Expr().(type) {
837 case adt.Resolver:
838 arc, err := ctx.Resolve(v.Env, x)
839 if err != nil {
840 if err.IsIncomplete() {
841 n.incomplete = adt.CombineErrors(nil, n.incomplete, err)
842 } else {
843 n.addBottom(err)
844 break
845 }
846 }
847 if arc == nil {
848 n.exprs = append(n.exprs, conjunct{v, closeID, top})
849 break
850 }
851
852 // If this is a cycle error, we have reached a fixed point and adding
853 // conjuncts at this point will not change the value. Also, continuing
854 // to pursue this value will result in an infinite loop.
855 //
856 // TODO: add a mechanism so that the computation will only have to be
857 // one once?
858 if isEvaluating(arc) {
859 break
860 }
861
862 // TODO: detect structural cycles here. A structural cycle can occur
863 // if it is not a reference cycle, but refers to a parent. node.
864 // This should only be allowed if it is unified with a finite structure.
865
866 if arc.Label.IsDef() {
867 n.insertClosed(arc)
868 } else {
869 for _, a := range arc.Conjuncts {
870 n.addExprConjunct(a, closeID, top)
871 }
872 }
873
874 case adt.Evaluator:
875 // adt.Interpolation, adt.UnaryExpr, adt.BinaryExpr, adt.CallExpr
876 val, complete := ctx.Evaluate(v.Env, v.Expr())
877 if !complete {
878 n.exprs = append(n.exprs, conjunct{v, closeID, top})
879 break
880 }
881
882 if v, ok := val.(*adt.Vertex); ok {
883 // Handle generated disjunctions (as in the 'or' builtin).
884 // These come as a Vertex, but should not be added as a value.
885 b, ok := v.Value.(*adt.Bottom)
886 if ok && b.IsIncomplete() && len(v.Conjuncts) > 0 {
887 for _, c := range v.Conjuncts {
888 n.addExprConjunct(c, closeID, top)
889 }
890 break
891 }
892 }
893
894 // TODO: insert in vertex as well
895 n.addValueConjunct(v.Env, val)
896
897 default:
898 panic(fmt.Sprintf("unknown expression of type %T", x))
899 }
900}
901
902func (n *nodeContext) insertClosed(arc *adt.Vertex) {
903 id := n.eval.nextID()
904 n.needClose = true
905
906 current := n.newClose
907 n.newClose = nil
908
909 for _, a := range arc.Conjuncts {
910 n.addExprConjunct(a, id, false)
911 }
912
913 current, n.newClose = n.newClose, current
914
915 if current == nil {
916 current = &CloseDef{ID: id}
917 }
918 n.addAnd(current)
919}
920
921func (n *nodeContext) addValueConjunct(env *adt.Environment, v adt.Value) {
922 if x, ok := v.(*adt.Vertex); ok {
923 needClose := false
924 if isStruct(x) {
925 n.isStruct = true
926 // TODO: find better way to mark as struct.
927 // For instance, we may want to add a faux
928 // Structlit for topological sort.
929 // return
930
931 if x.IsClosed(n.ctx) {
932 needClose = true
933 }
934
935 n.node.AddStructs(x.Structs...)
936 }
937
938 if len(x.Conjuncts) > 0 {
939 if needClose {
940 n.insertClosed(x)
941 return
942 }
943 for _, c := range x.Conjuncts {
944 n.addExprConjunct(c, 0, false) // Pass from eval
945 }
946 return
947 }
948
949 if x.IsList() {
950 n.vLists = append(n.vLists, x)
951 return
952 }
953
954 // TODO: evaluate value?
955 switch v := x.Value.(type) {
956 case *adt.ListMarker:
957 panic("unreachable")
958
959 case *adt.StructMarker:
960 for _, a := range x.Arcs {
961 // TODO, insert here as
962 n.insertField(a.Label, adt.MakeConjunct(nil, a))
963 // sub, _ := n.node.GetArc(a.Label)
964 // sub.Add(a)
965 }
966
967 default:
968 n.addValueConjunct(env, v)
969
970 for _, a := range x.Arcs {
971 // TODO, insert here as
972 n.insertField(a.Label, adt.MakeConjunct(nil, a))
973 // sub, _ := n.node.GetArc(a.Label)
974 // sub.Add(a)
975 }
976 }
977
978 return
979 // TODO: Use the Closer to close other fields as well?
980 }
981
982 if b, ok := v.(*adt.Bottom); ok {
983 n.addBottom(b)
984 return
985 }
986
987 ctx := n.ctx
988 kind := n.kind & v.Kind()
989 if kind == adt.BottomKind {
990 // TODO: how to get other conflicting values?
991 n.addErr(errors.Newf(token.NoPos,
992 "invalid value %s (mismatched types %s and %s)",
993 ctx.Str(v), v.Kind(), n.kind))
994 return
995 }
996 n.kind = kind
997
998 switch x := v.(type) {
999 case *adt.Disjunction:
1000 n.addDisjunctionValue(env, x, 0, true)
1001
1002 case *adt.Conjunction:
1003 for _, x := range x.Values {
1004 n.addValueConjunct(env, x)
1005 }
1006
1007 case *adt.Top:
1008 n.hasTop = true
1009 // TODO: Is this correct. Needed for elipsis, but not sure for others.
1010 n.optionals = append(n.optionals, fieldSet{env: env, isOpen: true})
1011
1012 case *adt.BasicType:
1013
1014 case *adt.BoundValue:
1015 switch x.Op {
1016 case adt.LessThanOp, adt.LessEqualOp:
1017 if y := n.upperBound; y != nil {
1018 n.upperBound = nil
1019 n.addValueConjunct(env, adt.SimplifyBounds(ctx, n.kind, x, y))
1020 return
1021 }
1022 n.upperBound = x
1023
1024 case adt.GreaterThanOp, adt.GreaterEqualOp:
1025 if y := n.lowerBound; y != nil {
1026 n.lowerBound = nil
1027 n.addValueConjunct(env, adt.SimplifyBounds(ctx, n.kind, x, y))
1028 return
1029 }
1030 n.lowerBound = x
1031
1032 case adt.EqualOp, adt.NotEqualOp, adt.MatchOp, adt.NotMatchOp:
1033 n.checks = append(n.checks, x)
1034 return
1035 }
1036
1037 case adt.Validator:
1038 n.checks = append(n.checks, x)
1039
1040 case *adt.Vertex:
1041 // handled above.
1042
1043 case adt.Value: // *NullLit, *BoolLit, *NumLit, *StringLit, *BytesLit
1044 if y := n.scalar; y != nil {
1045 if b, ok := adt.BinOp(ctx, adt.EqualOp, x, y).(*adt.Bool); !ok || !b.B {
1046 n.addErr(errors.Newf(ctx.Pos(), "incompatible values %s and %s", ctx.Str(x), ctx.Str(y)))
1047 }
1048 // TODO: do we need to explicitly add again?
1049 // n.scalar = nil
1050 // n.addValueConjunct(c, adt.BinOp(c, adt.EqualOp, x, y))
1051 break
1052 }
1053 n.scalar = x
1054
1055 default:
1056 panic(fmt.Sprintf("unknown value type %T", x))
1057 }
1058
1059 if n.lowerBound != nil && n.upperBound != nil {
1060 if u := adt.SimplifyBounds(ctx, n.kind, n.lowerBound, n.upperBound); u != nil {
1061 n.lowerBound = nil
1062 n.upperBound = nil
1063 n.addValueConjunct(env, u)
1064 }
1065 }
1066}
1067
1068// addStruct collates the declarations of a struct.
1069//
1070// addStruct fulfills two additional pivotal functions:
Oleg Kovalovbdb45b32020-07-22 14:47:38 +02001071// 1) Implement vertex unification (this happens through De Bruijn indices
Marcel van Lohuizen0f935f82020-06-09 09:13:01 +02001072// combined with proper set up of Environments).
1073// 2) Implied closedness for definitions.
1074//
1075func (n *nodeContext) addStruct(
1076 env *adt.Environment,
1077 s *adt.StructLit,
1078 newDef uint32,
1079 top bool) {
1080
1081 ctx := n.ctx
1082 n.node.AddStructs(s)
1083
1084 // Inherit closeID from environment, unless this is a new definition.
1085 closeID := newDef
1086 if closeID == 0 && env != nil {
1087 closeID = env.CloseID
1088 }
1089
1090 // NOTE: This is a crucial point in the code:
1091 // Unification derferencing happens here. The child nodes are set to
1092 // an Environment linked to the current node. Together with the De Bruijn
1093 // indices, this determines to which Vertex a reference resolves.
1094
1095 // TODO(perf): consider using environment cache:
1096 // var childEnv *adt.Environment
1097 // for _, s := range n.nodeCache.sub {
1098 // if s.Up == env {
1099 // childEnv = s
1100 // }
1101 // }
1102 childEnv := &adt.Environment{
1103 Up: env,
1104 Vertex: n.node,
1105 CloseID: closeID,
1106 }
1107
1108 var hasOther, hasBulk adt.Node
1109
1110 opt := fieldSet{env: childEnv}
1111
1112 for _, d := range s.Decls {
1113 switch x := d.(type) {
1114 case *adt.Field:
1115 opt.MarkField(ctx, x)
1116 // handle in next iteration.
1117
1118 case *adt.OptionalField:
1119 opt.AddOptional(ctx, x)
1120
1121 case *adt.DynamicField:
1122 hasOther = x
1123 n.dynamicFields = append(n.dynamicFields, envDynamic{childEnv, x})
1124 opt.AddDynamic(ctx, childEnv, x)
1125
1126 case *adt.ForClause:
1127 hasOther = x
1128 n.forClauses = append(n.forClauses, envYield{childEnv, x})
1129
1130 case adt.Yielder:
1131 hasOther = x
1132 n.ifClauses = append(n.ifClauses, envYield{childEnv, x})
1133
1134 case adt.Expr:
1135 // push and opo embedding type.
1136 id := n.eval.nextID()
1137
1138 current := n.newClose
1139 n.newClose = nil
1140
1141 hasOther = x
1142 n.addExprConjunct(adt.MakeConjunct(childEnv, x), id, false)
1143
1144 current, n.newClose = n.newClose, current
1145
1146 if current == nil {
1147 current = &CloseDef{ID: id} // TODO: isClosed?
1148 } else {
1149 // n.needClose = true
1150 }
1151 n.addOr(closeID, current)
1152
1153 case *adt.BulkOptionalField:
1154 hasBulk = x
1155 opt.AddBulk(ctx, x)
1156
1157 case *adt.Ellipsis:
1158 hasBulk = x
1159 opt.AddEllipsis(ctx, x)
1160
1161 default:
1162 panic("unreachable")
1163 }
1164 }
1165
1166 if hasBulk != nil && hasOther != nil {
1167 n.addErr(errors.Newf(token.NoPos, "cannot mix bulk optional fields with dynamic fields, embeddings, or comprehensions within the same struct"))
1168 }
1169
1170 // Apply existing fields
1171 for _, arc := range n.node.Arcs {
1172 // Reuse adt.Acceptor interface.
1173 opt.MatchAndInsert(ctx, arc)
1174 }
1175
1176 n.optionals = append(n.optionals, opt)
1177
1178 for _, d := range s.Decls {
1179 switch x := d.(type) {
1180 case *adt.Field:
1181 n.insertField(x.Label, adt.MakeConjunct(childEnv, x))
1182 }
1183 }
1184}
1185
1186func (n *nodeContext) insertField(f adt.Feature, x adt.Conjunct) *adt.Vertex {
1187 ctx := n.ctx
1188 arc, isNew := n.node.GetArc(f)
1189
1190 if f.IsString() {
1191 n.isStruct = true
1192 }
1193
1194 // TODO: disallow adding conjuncts when cache set?
1195 arc.AddConjunct(x)
1196
1197 if isNew {
1198 for _, o := range n.optionals {
1199 o.MatchAndInsert(ctx, arc)
1200 }
1201 }
1202 return arc
1203}
1204
1205// expandOne adds dynamic fields to a node until a fixed point is reached.
1206// On each iteration, dynamic fields that cannot resolve due to incomplete
1207// values are skipped. They will be retried on the next iteration until no
1208// progress can be made. Note that a dynamic field may add more dynamic fields.
1209//
1210// forClauses are processed after all other clauses. A struct may be referenced
1211// before it is complete, meaning that fields added by other forms of injection
1212// may influence the result of a for clause _after_ it has already been
1213// processed. We could instead detect such insertion and feed it to the
1214// ForClause to generate another entry or have the for clause be recomputed.
1215// This seems to be too complicated and lead to iffy edge cases.
1216// TODO(error): detect when a field is added to a struct that is already used
1217// in a for clause.
1218func (n *nodeContext) expandOne() (done bool) {
1219 if n.done() {
1220 return false
1221 }
1222
1223 var progress bool
1224
1225 if progress = n.injectDynamic(); progress {
1226 return true
1227 }
1228
1229 if n.ifClauses, progress = n.injectEmbedded(n.ifClauses); progress {
1230 return true
1231 }
1232
1233 if n.forClauses, progress = n.injectEmbedded(n.forClauses); progress {
1234 return true
1235 }
1236
1237 // Do expressions after comprehensions, as comprehensions can never
1238 // refer to embedded scalars, whereas expressions may refer to generated
1239 // fields if we were to allow attributes to be defined alongside
1240 // scalars.
1241 exprs := n.exprs
1242 n.exprs = n.exprs[:0]
1243 for _, x := range exprs {
1244 n.addExprConjunct(x.Conjunct, x.closeID, x.top)
1245
1246 // collect and and or
1247 }
1248 if len(n.exprs) < len(exprs) {
1249 return true
1250 }
1251
1252 // No progress, report error later if needed: unification with
1253 // disjuncts may resolve this later later on.
1254 return false
1255}
1256
1257// injectDynamic evaluates and inserts dynamic declarations.
1258func (n *nodeContext) injectDynamic() (progress bool) {
1259 ctx := n.ctx
1260 k := 0
1261
1262 a := n.dynamicFields
1263 for _, d := range n.dynamicFields {
1264 var f adt.Feature
1265 v, complete := ctx.Evaluate(d.env, d.field.Key)
1266 if !complete {
1267 a[k] = d
1268 k++
1269 continue
1270 }
1271 if b, _ := v.(*adt.Bottom); b != nil {
1272 n.addValueConjunct(nil, b)
1273 continue
1274 }
1275 f = ctx.Label(v)
1276 n.insertField(f, adt.MakeConjunct(d.env, d.field))
1277 }
1278
1279 progress = k < len(n.dynamicFields)
1280
1281 n.dynamicFields = a[:k]
1282
1283 return progress
1284}
1285
1286// injectEmbedded evaluates and inserts embeddings. It first evaluates all
1287// embeddings before inserting the results to ensure that the order of
1288// evaluation does not matter.
1289func (n *nodeContext) injectEmbedded(all []envYield) (a []envYield, progress bool) {
1290 ctx := n.ctx
1291 type envStruct struct {
1292 env *adt.Environment
1293 s *adt.StructLit
1294 }
1295 var sa []envStruct
1296 f := func(env *adt.Environment, st *adt.StructLit) {
1297 sa = append(sa, envStruct{env, st})
1298 }
1299
1300 k := 0
1301 for _, d := range all {
1302 sa = sa[:0]
1303
1304 if err := ctx.Yield(d.env, d.yield, f); err != nil {
1305 if err.IsIncomplete() {
1306 all[k] = d
1307 k++
1308 } else {
1309 // continue to collect other errors.
1310 n.addBottom(err)
1311 }
1312 continue
1313 }
1314
1315 for _, st := range sa {
1316 n.addStruct(st.env, st.s, 0, true)
1317 }
1318 }
1319
1320 return all[:k], k < len(all)
1321}
1322
1323// addLists
1324//
1325// TODO: association arrays:
1326// If an association array marker was present in a struct, create a struct node
1327// instead of a list node. In either case, a node may only have list fields
1328// or struct fields and not both.
1329//
1330// addLists should be run after the fixpoint expansion:
1331// - it enforces that comprehensions may not refer to the list itself
1332// - there may be no other fields within the list.
1333//
1334// TODO(embeddedScalars): for embedded scalars, there should be another pass
1335// of evaluation expressions after expanding lists.
1336func (n *nodeContext) addLists(c *adt.OpContext) {
1337 if len(n.lists) == 0 && len(n.vLists) == 0 {
1338 return
1339 }
1340
1341 for _, a := range n.node.Arcs {
1342 if t := a.Label.Typ(); t == adt.StringLabel {
1343 n.addErr(errors.Newf(token.NoPos, "conflicting types list and struct"))
1344 }
1345 }
1346
1347 // fmt.Println(len(n.lists), "ELNE")
1348
1349 isOpen := true
1350 max := 0
1351 var maxNode adt.Expr
1352
1353 for _, l := range n.vLists {
1354 elems := l.Elems()
1355 isClosed := l.IsClosed(c)
1356
1357 switch {
1358 case len(elems) < max:
1359 if isClosed {
1360 n.invalidListLength(len(elems), max, l, maxNode)
1361 continue
1362 }
1363
1364 case len(elems) > max:
1365 if !isOpen {
1366 n.invalidListLength(max, len(elems), maxNode, l)
1367 continue
1368 }
1369 isOpen = !isClosed
1370 max = len(elems)
1371 maxNode = l
1372
1373 case isClosed:
1374 isOpen = false
1375 maxNode = l
1376 }
1377
1378 for _, a := range elems {
1379 if a.Conjuncts == nil {
1380 n.insertField(a.Label, adt.MakeConjunct(nil, a.Value))
1381 continue
1382 }
1383 for _, c := range a.Conjuncts {
1384 n.insertField(a.Label, c)
1385 }
1386 }
1387 }
1388
1389outer:
1390 for i, l := range n.lists {
1391 index := int64(0)
1392 hasComprehension := false
1393 for j, elem := range l.list.Elems {
1394 switch x := elem.(type) {
1395 case adt.Yielder:
1396 err := c.Yield(l.env, x, func(e *adt.Environment, st *adt.StructLit) {
1397 label, err := adt.MakeLabel(x.Source(), index, adt.IntLabel)
1398 n.addErr(err)
1399 index++
1400 n.insertField(label, adt.MakeConjunct(e, st))
1401 })
1402 hasComprehension = true
1403 if err.IsIncomplete() {
1404
1405 }
1406
1407 case *adt.Ellipsis:
1408 if j != len(l.list.Elems)-1 {
1409 n.addErr(errors.Newf(token.NoPos,
1410 "ellipsis must be last element in list"))
1411 }
1412
1413 n.lists[i].elipsis = x
1414
1415 default:
1416 label, err := adt.MakeLabel(x.Source(), index, adt.IntLabel)
1417 n.addErr(err)
1418 index++ // TODO: don't use insertField.
1419 n.insertField(label, adt.MakeConjunct(l.env, x))
1420 }
1421
1422 // Terminate early n case of runaway comprehension.
1423 if !isOpen && int(index) > max {
1424 n.invalidListLength(max, int(index), maxNode, l.list)
1425 continue outer
1426 }
1427 }
1428
1429 switch closed := n.lists[i].elipsis == nil; {
1430 case int(index) < max:
1431 if closed {
1432 n.invalidListLength(int(index), max, l.list, maxNode)
1433 continue
1434 }
1435
1436 case int(index) > max,
1437 closed && isOpen,
1438 (!closed == isOpen) && !hasComprehension:
1439 max = int(index)
1440 maxNode = l.list
1441 isOpen = !closed
1442 }
1443
1444 n.lists[i].n = index
1445 }
1446
1447 // add additionalItem values to list and construct optionals.
1448 elems := n.node.Elems()
1449 for _, l := range n.vLists {
1450 a, _ := l.Closed.(*acceptor)
1451 if a == nil {
1452 continue
1453 }
1454
1455 newElems := l.Elems()
1456 if len(newElems) >= len(elems) {
1457 continue // error generated earlier, if applicable.
1458 }
1459
1460 n.optionals = append(n.optionals, a.fields...)
1461
1462 for _, arc := range elems[len(newElems):] {
1463 l.MatchAndInsert(c, arc)
1464 }
1465 }
1466
1467 for _, l := range n.lists {
1468 if l.elipsis == nil {
1469 continue
1470 }
1471
1472 f := fieldSet{env: l.env}
1473 f.AddEllipsis(c, l.elipsis)
1474
1475 n.optionals = append(n.optionals, f)
1476
1477 for _, arc := range elems[l.n:] {
1478 f.MatchAndInsert(c, arc)
1479 }
1480 }
1481
1482 sources := []ast.Expr{}
1483 // Add conjuncts for additional items.
1484 for _, l := range n.lists {
1485 if l.elipsis == nil {
1486 continue
1487 }
1488 if src, _ := l.elipsis.Source().(ast.Expr); src != nil {
1489 sources = append(sources, src)
1490 }
1491 }
1492
1493 n.openList = isOpen
1494
1495 n.node.SetValue(c, adt.Partial, &adt.ListMarker{
1496 Src: ast.NewBinExpr(token.AND, sources...),
1497 IsOpen: isOpen,
1498 })
1499}
1500
1501func (n *nodeContext) invalidListLength(na, nb int, a, b adt.Expr) {
1502 n.addErr(errors.Newf(n.ctx.Pos(),
1503 "incompatible list lengths (%d and %d)", na, nb))
1504}