cuelang.org/go@v0.13.0/internal/core/adt/eval.go (about) 1 // Copyright 2021 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. 20 package adt 21 22 // TODO: 23 // - result should be nodeContext: this allows optionals info to be extracted 24 // and computed. 25 // 26 27 import ( 28 "fmt" 29 30 "cuelang.org/go/cue/ast" 31 "cuelang.org/go/cue/errors" 32 "cuelang.org/go/cue/stats" 33 "cuelang.org/go/cue/token" 34 ) 35 36 // TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO 37 // 38 // - Reuse work from previous cycles. For instance, if we can guarantee that a 39 // value is always correct for partial results, we can just process the arcs 40 // going from Partial to Finalized, without having to reevaluate the value. 41 // 42 // - Test closedness far more thoroughly. 43 // 44 45 func (c *OpContext) Stats() *stats.Counts { 46 return &c.stats 47 } 48 49 // TODO: Note: NewContext takes essentially a cue.Value. By making this 50 // type more central, we can perhaps avoid context creation. 51 52 // func NewContext(r Runtime, v *Vertex) *OpContext { 53 // e := NewUnifier(r) 54 // return e.NewContext(v) 55 // } 56 57 var incompleteSentinel = &Bottom{ 58 Code: IncompleteError, 59 Err: errors.Newf(token.NoPos, "incomplete"), 60 } 61 62 // evaluate returns the evaluated value associated with v. It may return a 63 // partial result. That is, if v was not yet unified, it may return a 64 // concrete value that must be the result assuming the configuration has no 65 // errors. 66 // 67 // This semantics allows CUE to break reference cycles in a straightforward 68 // manner. 69 // 70 // Vertex v must still be evaluated at some point to catch the underlying 71 // error. 72 // 73 // TODO: return *Vertex 74 func (c *OpContext) evaluate(v *Vertex, r Resolver, state combinedFlags) Value { 75 if v.isUndefined() { 76 // Use node itself to allow for cycle detection. 77 c.unify(v, state) 78 79 if v.ArcType == ArcPending { 80 if v.status == evaluating { 81 for ; v.Parent != nil && v.ArcType == ArcPending; v = v.Parent { 82 } 83 err := c.Newf("cycle with field %v", r) 84 b := &Bottom{ 85 Code: CycleError, 86 Err: err, 87 Node: v, 88 } 89 v.setValue(c, v.status, b) 90 return b 91 // TODO: use this instead, as is usual for incomplete errors, 92 // and also move this block one scope up to also apply to 93 // defined arcs. In both cases, though, doing so results in 94 // some errors to be misclassified as evaluation error. 95 // c.AddBottom(b) 96 // return nil 97 } 98 c.undefinedFieldError(v, IncompleteError) 99 return nil 100 } 101 } 102 103 if n := v.state; n != nil { 104 n.assertInitialized() 105 106 if n.errs != nil && !n.errs.IsIncomplete() { 107 return n.errs 108 } 109 if n.scalar != nil && isCyclePlaceholder(v.BaseValue) { 110 return n.scalar 111 } 112 } 113 114 switch x := v.BaseValue.(type) { 115 case *Bottom: 116 if x.IsIncomplete() { 117 c.AddBottom(x) 118 return nil 119 } 120 return x 121 122 case nil: 123 if v.state != nil { 124 switch x := v.state.getValidators(finalized).(type) { 125 case Value: 126 return x 127 default: 128 w := *v 129 w.BaseValue = x 130 return &w 131 } 132 } 133 // This may happen if the evaluator is invoked outside of regular 134 // evaluation, such as in dependency analysis. 135 return nil 136 } 137 138 if v.status < finalized && v.state != nil && !c.isDevVersion() { 139 // TODO: errors are slightly better if we always add addNotify, but 140 // in this case it is less likely to cause a performance penalty. 141 // See https://cuelang.org/issue/661. It may be possible to 142 // relax this again once we have proper tests to prevent regressions of 143 // that issue. 144 if !v.state.done() || v.state.errs != nil { 145 v.state.addNotify(c.vertex) 146 } 147 } 148 149 return v 150 } 151 152 // unify unifies values of a Vertex to and stores the result in the Vertex. If 153 // unify was called on v before it returns the cached results. 154 // state can be used to indicate to which extent processing should continue. 155 // state == finalized means it is evaluated to completion. See vertexStatus 156 // for more details. 157 func (c *OpContext) unify(v *Vertex, flags combinedFlags) { 158 if c.isDevVersion() { 159 requires, mode := flags.conditions(), flags.runMode() 160 v.unify(c, requires, mode, true) 161 return 162 } 163 164 // defer c.PopVertex(c.PushVertex(v)) 165 if c.LogEval > 0 { 166 c.nest++ 167 c.Logf(v, "Unify") 168 defer func() { 169 c.Logf(v, "END Unify") 170 c.nest-- 171 }() 172 } 173 174 // Ensure a node will always have a nodeContext after calling Unify if it is 175 // not yet Finalized. 176 n := v.getNodeContext(c, 1) 177 defer v.freeNode(n) 178 179 state := flags.vertexStatus() 180 181 // TODO(cycle): verify this happens in all cases when we need it. 182 if n != nil && v.Parent != nil && v.Parent.state != nil { 183 n.depth = v.Parent.state.depth + 1 184 } 185 186 if state <= v.Status() && 187 state == partial && 188 v.isDefined() && 189 n != nil && n.scalar != nil { 190 return 191 } 192 193 switch v.Status() { 194 case evaluating: 195 n.insertConjuncts(state) 196 return 197 198 case evaluatingArcs: 199 Assertf(c, v.status > unprocessed, "unexpected status %d", v.status) 200 return 201 202 case 0: 203 if v.Label.IsDef() { 204 v.ClosedRecursive = true 205 } 206 207 if v.Parent != nil { 208 if v.Parent.ClosedRecursive { 209 v.ClosedRecursive = true 210 } 211 } 212 213 defer c.PopArc(c.PushArc(v)) 214 215 v.updateStatus(evaluating) 216 217 if p := v.Parent; p != nil && p.state != nil && v.Label.IsString() { 218 for _, s := range p.state.node.Structs { 219 if s.Disable { 220 continue 221 } 222 s.MatchAndInsert(n.ctx, v) 223 } 224 } 225 226 c.stats.Unifications++ 227 228 // Set the cache to a cycle error to ensure a cyclic reference will result 229 // in an error if applicable. A cyclic error may be ignored for 230 // non-expression references. The cycle error may also be removed as soon 231 // as there is evidence what a correct value must be, but before all 232 // validation has taken place. 233 // 234 // TODO(cycle): having a more recursive algorithm would make this 235 // special cycle handling unnecessary. 236 v.BaseValue = cycle 237 238 if c.HasErr() { 239 n.addBottom(c.errs) 240 } 241 242 // NOTE: safeguard against accidentally entering the 'unprocessed' state 243 // twice. 244 n.conjuncts = n.conjuncts[:0] 245 246 for i, c := range v.Conjuncts { 247 n.addConjunction(c, i) 248 } 249 if n.insertConjuncts(state) { 250 n.maybeSetCache() 251 v.updateStatus(partial) 252 return 253 } 254 255 fallthrough 256 257 case partial, conjuncts: 258 // TODO: remove this optimization or make it correct. 259 // No need to do further processing when we have errors and all values 260 // have been considered. 261 // TODO: is checkClosed really still necessary here? 262 if v.status == conjuncts && (n.hasErr() || !n.checkClosed(state)) { 263 if err := n.getErr(); err != nil { 264 b, _ := v.BaseValue.(*Bottom) 265 v.BaseValue = CombineErrors(nil, b, err) 266 } 267 break 268 } 269 270 defer c.PopArc(c.PushArc(v)) 271 272 n.insertConjuncts(state) 273 274 v.status = evaluating 275 276 // Use maybeSetCache for cycle breaking 277 for n.maybeSetCache(); n.expandOne(partial); n.maybeSetCache() { 278 } 279 280 n.doNotify() 281 282 if !n.done() { 283 switch { 284 case state < conjuncts: 285 n.node.updateStatus(partial) 286 return 287 288 case state == conjuncts: 289 if err := n.incompleteErrors(true); err != nil && err.Code < CycleError { 290 n.node.AddErr(c, err) 291 } else { 292 n.node.updateStatus(partial) 293 } 294 return 295 } 296 } 297 298 // Disjunctions should always be finalized. If there are nested 299 // disjunctions the last one should be finalized. 300 disState := state 301 if len(n.disjunctions) > 0 && disState != finalized { 302 disState = finalized 303 } 304 n.expandDisjuncts(disState, n, maybeDefault, false, true) 305 306 n.finalizeDisjuncts() 307 308 switch len(n.disjuncts) { 309 case 0: 310 case 1: 311 x := n.disjuncts[0].result 312 x.state = nil 313 x.cyclicReferences = n.node.cyclicReferences 314 *v = x 315 316 default: 317 d := n.createDisjunct() 318 v.BaseValue = d 319 // The conjuncts will have too much information. Better have no 320 // information than incorrect information. 321 for _, d := range d.Values { 322 d, ok := d.(*Vertex) 323 if !ok { 324 continue 325 } 326 // We clear the conjuncts for now. As these disjuncts are for API 327 // use only, we will fill them out when necessary (using Defaults). 328 d.Conjuncts = nil 329 330 // TODO: use a more principled form of dereferencing. For instance, 331 // disjuncts could already be assumed to be the given Vertex, and 332 // the main vertex could be dereferenced during evaluation. 333 for _, a := range d.Arcs { 334 for _, x := range a.Conjuncts { 335 // All the environments for embedded structs need to be 336 // dereferenced. 337 for env := x.Env; env != nil && env.Vertex == v; env = env.Up { 338 env.Vertex = d 339 } 340 } 341 } 342 } 343 v.Arcs = nil 344 v.ChildErrors = nil 345 // v.Structs = nil // TODO: should we keep or discard the Structs? 346 // TODO: how to represent closedness information? Do we need it? 347 } 348 349 // If the state has changed, it is because a disjunct has been run, or 350 // because a single disjunct has replaced it. Restore the old state as 351 // to not confuse memory management. 352 v.state = n 353 354 // We don't do this in postDisjuncts, as it should only be done after 355 // completing all disjunctions. 356 if !n.done() { 357 if err := n.incompleteErrors(true); err != nil { 358 b := n.node.Bottom() 359 if b != err { 360 err = CombineErrors(n.ctx.src, b, err) 361 } 362 n.node.BaseValue = err 363 } 364 } 365 366 assertStructuralCycle(n) 367 368 if state != finalized { 369 return 370 } 371 372 if v.BaseValue == nil { 373 v.BaseValue = n.getValidators(finalized) 374 } 375 376 // Free memory here? 377 v.updateStatus(finalized) 378 379 case finalized: 380 } 381 } 382 383 // insertConjuncts inserts conjuncts previously not inserted. 384 func (n *nodeContext) insertConjuncts(state vertexStatus) bool { 385 unreachableForDev(n.ctx) 386 387 // Exit early if we have a concrete value and only need partial results. 388 if state == partial { 389 for n.conjunctsPartialPos < len(n.conjuncts) { 390 c := &n.conjuncts[n.conjunctsPartialPos] 391 n.conjunctsPartialPos++ 392 if c.done { 393 continue 394 } 395 if v, ok := c.C.Elem().(Value); ok && IsConcrete(v) { 396 c.done = true 397 n.addValueConjunct(c.C.Env, v, c.C.CloseInfo) 398 } 399 } 400 if n.scalar != nil && n.node.isDefined() { 401 return true 402 } 403 } 404 for n.conjunctsPos < len(n.conjuncts) { 405 nInfos := len(n.node.Structs) 406 p := &n.conjuncts[n.conjunctsPos] 407 n.conjunctsPos++ 408 if p.done { 409 continue 410 } 411 412 // Initially request a Partial state to allow cyclic references to 413 // resolve more naturally first. This results in better error messages 414 // and less operations. 415 n.addExprConjunct(p.C, partial) 416 p.done = true 417 418 // Record the OptionalTypes for all structs that were inferred by this 419 // Conjunct. This information can be used by algorithms such as trim. 420 for i := nInfos; i < len(n.node.Structs); i++ { 421 n.node.Conjuncts[p.index].CloseInfo.FieldTypes |= n.node.Structs[i].types 422 } 423 } 424 return false 425 } 426 427 // finalizeDisjuncts: incomplete errors are kept around and not removed early. 428 // This call filters the incomplete errors and removes them 429 // 430 // This also collects all errors of empty disjunctions. These cannot be 431 // collected during the finalization state of individual disjuncts. Care should 432 // be taken to only call this after all disjuncts have been finalized. 433 func (n *nodeContext) finalizeDisjuncts() { 434 a := n.disjuncts 435 if len(a) == 0 { 436 return 437 } 438 k := 0 439 for i, d := range a { 440 switch d.finalDone() { 441 case true: 442 a[k], a[i] = d, a[k] 443 k++ 444 default: 445 if err := d.incompleteErrors(true); err != nil { 446 n.disjunctErrs = append(n.disjunctErrs, err) 447 } 448 } 449 d.free() 450 } 451 if k == 0 { 452 n.makeError() 453 } 454 n.disjuncts = a[:k] 455 } 456 457 func (n *nodeContext) doNotify() { 458 if n.errs == nil || len(n.notify) == 0 { 459 return 460 } 461 for _, rec := range n.notify { 462 v := rec.v 463 if v.state == nil { 464 if b := v.Bottom(); b != nil { 465 v.BaseValue = CombineErrors(nil, b, n.errs) 466 } else { 467 v.BaseValue = n.errs 468 } 469 } else { 470 v.state.addBottom(n.errs) 471 } 472 } 473 n.notify = n.notify[:0] 474 } 475 476 func (n *nodeContext) postDisjunct(state vertexStatus) { 477 ctx := n.ctx 478 unreachableForDev(ctx) 479 480 for { 481 // Use maybeSetCache for cycle breaking 482 for n.maybeSetCache(); n.expandOne(state); n.maybeSetCache() { 483 } 484 485 if !n.addLists(oldOnly(state)) { 486 break 487 } 488 } 489 490 if n.aStruct != nil { 491 n.updateNodeType(StructKind, n.aStruct, n.aStructID) 492 } 493 494 if len(n.selfComprehensions) > 0 { 495 // Up to here all comprehensions with sources other than this node will 496 // have had a chance to run. We can now run self-referencing 497 // comprehensions with the restriction that they cannot add new arcs. 498 // 499 // Note: we should only set this in case of self-referential 500 // comprehensions. A comprehension in a parent node may still add 501 // arcs to this node, even if it has reached AllConjunctsDone status, 502 // as long as any evaluation did not rely on its specific set of arcs. 503 // Example: 504 // 505 // a: { 506 // b: _env: c: 1 507 // 508 // // Using dynamic field ("b") prevents the evaluation of the 509 // // comprehension to be pushed down to env: and instead evaluates 510 // // it before b is completed. Even though b needs to reach state 511 // // AllConjunctsDone before evaluating b._env, it is still okay 512 // // to add arcs to b after this evaluation: only the set of arcs 513 // // in b._env needs to be frozen after that. 514 // for k2, v2 in b._env { 515 // ("b"): env: (k2): v2 516 // } 517 // } 518 n.node.LockArcs = true 519 520 n.injectSelfComprehensions(state) 521 } 522 523 for n.expandOne(state) { 524 } 525 526 switch err := n.getErr(); { 527 case err != nil: 528 if err.Code < IncompleteError && n.node.ArcType == ArcPending { 529 n.node.ArcType = ArcMember 530 } 531 n.node.BaseValue = err 532 n.errs = nil 533 534 default: 535 if isCyclePlaceholder(n.node.BaseValue) { 536 if !n.done() { 537 n.node.BaseValue = n.incompleteErrors(true) 538 } else { 539 n.node.BaseValue = nil 540 } 541 } 542 // TODO: this ideally should be done here. However, doing so causes 543 // a somewhat more aggressive cutoff in disjunction cycles, which cause 544 // some incompatibilities. Fix in another CL. 545 // 546 // else if !n.done() { 547 // n.expandOne() 548 // if err := n.incompleteErrors(); err != nil { 549 // n.node.BaseValue = err 550 // } 551 // } 552 553 // We are no longer evaluating. 554 555 n.validateValue(state) 556 557 v := n.node.Value() 558 559 // TODO(perf): only delay processing of actual non-monotonic checks. 560 skip := n.skipNonMonotonicChecks() 561 if v != nil && IsConcrete(v) && !skip { 562 for _, v := range n.checks { 563 // TODO(errors): make Validate return bottom and generate 564 // optimized conflict message. Also track and inject IDs 565 // to determine origin location.s 566 if b := ctx.Validate(v, n.node); b != nil { 567 n.addBottom(b) 568 } 569 } 570 } 571 572 if v == nil { 573 break 574 } 575 576 switch { 577 case v.Kind() == ListKind: 578 for _, a := range n.node.Arcs { 579 if a.Label.Typ() == StringLabel && a.IsDefined(ctx) { 580 n.addErr(ctx.Newf("list may not have regular fields")) 581 // TODO(errors): add positions for list and arc definitions. 582 583 } 584 } 585 586 // case !isStruct(n.node) && v.Kind() != BottomKind: 587 // for _, a := range n.node.Arcs { 588 // if a.Label.IsRegular() { 589 // n.addErr(errors.Newf(token.NoPos, 590 // // TODO(errors): add positions of non-struct values and arcs. 591 // "cannot combine scalar values with arcs")) 592 // } 593 // } 594 } 595 } 596 597 n.completeArcs(state) 598 } 599 600 // validateValue checks collected bound validators and checks them against 601 // the current value. If there is no value, it sets the current value 602 // to these validators itself. 603 // 604 // Before it does this, it also checks whether n is of another incompatible 605 // type, like struct. This prevents validators from being inadvertently set. 606 // TODO(evalv3): optimize this function for new implementation. 607 func (n *nodeContext) validateValue(state vertexStatus) { 608 ctx := n.ctx 609 610 // Either set to Conjunction or error. 611 // TODO: verify and simplify the below code to determine whether 612 // something is a struct. 613 markStruct := false 614 if n.aStruct != nil { 615 markStruct = true 616 } else if len(n.node.Structs) > 0 { 617 // TODO: do something more principled here. 618 // Here we collect evidence that a value is a struct. If a struct has 619 // an embedding, it may evaluate to an embedded scalar value, in which 620 // case it is not a struct. Right now this is tracked at the node level, 621 // but it really should be at the struct level. For instance: 622 // 623 // A: matchN(1, [>10]) 624 // A: { 625 // if true {c: 1} 626 // } 627 // 628 // Here A is marked as Top by matchN. The other struct also has an 629 // embedding (the comprehension), and thus does not force it either. 630 // So the resulting kind is top, not struct. 631 // As an approximation, we at least mark the node as a struct if it has 632 // any regular fields. 633 markStruct = n.kind&StructKind != 0 && !n.hasTop 634 for _, a := range n.node.Arcs { 635 // TODO(spec): we generally allow optional fields alongside embedded 636 // scalars. We probably should not. Either way this is not entirely 637 // accurate, as a Pending arc may still be optional. We should 638 // collect the arcType noted in adt.Comprehension in a nodeContext 639 // as well so that we know what the potential arc of this node may 640 // be. 641 // 642 // TODO(evalv3): even better would be to ensure that all 643 // comprehensions are done before calling this. 644 if a.Label.IsRegular() && a.ArcType != ArcOptional { 645 markStruct = true 646 break 647 } 648 } 649 } 650 v := n.node.DerefValue().Value() 651 if n.node.BaseValue == nil && markStruct { 652 n.node.BaseValue = &StructMarker{} 653 v = n.node 654 } 655 if v != nil && IsConcrete(v) { 656 // Also check when we already have errors as we may find more 657 // serious errors and would like to know about all errors anyway. 658 659 if n.lowerBound != nil { 660 c := MakeRootConjunct(nil, n.lowerBound) 661 if b := ctx.Validate(c, v); b != nil { 662 // TODO(errors): make Validate return boolean and generate 663 // optimized conflict message. Also track and inject IDs 664 // to determine origin location.s 665 if e, _ := b.Err.(*ValueError); e != nil { 666 e.AddPosition(n.lowerBound) 667 e.AddPosition(v) 668 } 669 n.addBottom(b) 670 } 671 } 672 if n.upperBound != nil { 673 c := MakeRootConjunct(nil, n.upperBound) 674 if b := ctx.Validate(c, v); b != nil { 675 // TODO(errors): make Validate return boolean and generate 676 // optimized conflict message. Also track and inject IDs 677 // to determine origin location.s 678 if e, _ := b.Err.(*ValueError); e != nil { 679 e.AddPosition(n.upperBound) 680 e.AddPosition(v) 681 } 682 n.addBottom(b) 683 } 684 } 685 686 } else if state == finalized { 687 n.node.BaseValue = n.getValidators(finalized) 688 } 689 } 690 691 // incompleteErrors reports all errors from uncompleted conjuncts. 692 // If final is true, errors are permanent and reported to parents. 693 func (n *nodeContext) incompleteErrors(final bool) *Bottom { 694 unreachableForDev(n.ctx) 695 696 // collect incomplete errors. 697 var err *Bottom // n.incomplete 698 for _, d := range n.dynamicFields { 699 err = CombineErrors(nil, err, d.err) 700 } 701 for _, c := range n.comprehensions { 702 if c.err == nil { 703 continue 704 } 705 err = CombineErrors(nil, err, c.err) 706 707 // TODO: use this code once possible. 708 // 709 // Add comprehension to ensure incomplete error is inserted. This 710 // ensures that the error is reported in the Vertex where the 711 // comprehension was defined, and not just in the node below. This, in 712 // turn, is necessary to support certain logic, like export, that 713 // expects to be able to detect an "incomplete" error at the first level 714 // where it is necessary. 715 // if c.node.status != Finalized { 716 // n := c.node.getNodeContext(n.ctx) 717 // n.comprehensions = append(n.comprehensions, c) 718 // } else { 719 // n.node.AddErr(n.ctx, err) 720 // } 721 // n := d.node.getNodeContext(ctx) 722 // n.addBottom(err) 723 if final && c.vertex != nil && c.vertex.status != finalized { 724 c.vertex.state.assertInitialized() 725 c.vertex.state.addBottom(err) 726 c.vertex = nil 727 } 728 } 729 for _, c := range n.selfComprehensions { 730 if c.err == nil { 731 continue 732 } 733 734 err = CombineErrors(nil, err, c.err) 735 736 // TODO: use this code once possible. 737 // 738 // Add comprehension to ensure incomplete error is inserted. This 739 // ensures that the error is reported in the Vertex where the 740 // comprehension was defined, and not just in the node below. This, in 741 // turn, is necessary to support certain logic, like export, that 742 // expects to be able to detect an "incomplete" error at the first level 743 // where it is necessary. 744 // if c.node.status != Finalized { 745 // n := c.node.getNodeContext(n.ctx) 746 // n.comprehensions = append(n.comprehensions, c) 747 // } else { 748 // n.node.AddErr(n.ctx, err) 749 // } 750 // n := d.node.getNodeContext(ctx) 751 // n.addBottom(err) 752 if c.vertex != nil && c.vertex.status != finalized { 753 c.vertex.state.addBottom(err) 754 c.vertex = nil 755 } 756 } 757 for _, x := range n.exprs { 758 err = CombineErrors(nil, err, x.err) 759 } 760 if err == nil { 761 // safeguard. 762 err = incompleteSentinel 763 } 764 if err.Code < IncompleteError { 765 n.node.ArcType = ArcMember 766 } 767 return err 768 } 769 770 // TODO(perf): ideally we should always perform a closedness check if 771 // state is Finalized. This is currently not possible when computing a 772 // partial disjunction as the closedness information is not yet 773 // complete, possibly leading to a disjunct to be rejected prematurely. 774 // It is probably possible to fix this if we could add StructInfo 775 // structures demarked per conjunct. 776 // 777 // In practice this should not be a problem: when disjuncts originate 778 // from the same disjunct, they will have the same StructInfos, and thus 779 // Equal is able to equate them even in the presence of optional field. 780 // In general, combining any limited set of disjuncts will soon reach 781 // a fixed point where duplicate elements can be eliminated this way. 782 // 783 // Note that not checking closedness is irrelevant for disjunctions of 784 // scalars. This means it also doesn't hurt performance where structs 785 // have a discriminator field (e.g. Kubernetes). We should take care, 786 // though, that any potential performance issues are eliminated for 787 // Protobuf-like oneOf fields. 788 func (n *nodeContext) checkClosed(state vertexStatus) bool { 789 unreachableForDev(n.ctx) 790 791 ignore := state != finalized || n.skipNonMonotonicChecks() 792 793 v := n.node 794 if !v.Label.IsInt() && v.Parent != nil && !ignore && v.ArcType <= ArcRequired { 795 ctx := n.ctx 796 // Visit arcs recursively to validate and compute error. 797 if _, err := verifyArc2(ctx, v.Label, v, v.ClosedRecursive); err != nil { 798 // Record error in child node to allow recording multiple 799 // conflicts at the appropriate place, to allow valid fields to 800 // be represented normally and, most importantly, to avoid 801 // recursive processing of a disallowed field. 802 v.SetValue(ctx, err) 803 return false 804 } 805 } 806 return true 807 } 808 809 func (n *nodeContext) completeArcs(state vertexStatus) { 810 unreachableForDev(n.ctx) 811 812 if n.node.hasAllConjuncts || n.node.Parent == nil { 813 n.node.setParentDone() 814 } 815 816 // At this point, if this arc is of type arcVoid, it means that the value 817 // may still be modified by child arcs. So in this case we must now process 818 // all arcs to be sure we get the correct result. 819 // For other cases we terminate early as this results in considerably 820 // better error messages. 821 if state <= conjuncts && 822 // Is allowed to go one step back. See Vertex.UpdateStatus. 823 n.node.status <= state+1 && 824 (!n.node.hasPendingArc || n.node.ArcType == ArcMember) { 825 826 n.node.updateStatus(conjuncts) 827 return 828 } 829 830 n.node.updateStatus(evaluatingArcs) 831 832 ctx := n.ctx 833 834 if !assertStructuralCycle(n) { 835 k := 0 836 // Visit arcs recursively to validate and compute error. 837 for _, a := range n.node.Arcs { 838 // Call UpdateStatus here to be absolutely sure the status is set 839 // correctly and that we are not regressing. 840 n.node.updateStatus(evaluatingArcs) 841 842 wasVoid := a.ArcType == ArcPending 843 844 ctx.unify(a, oldOnly(finalized)) 845 846 if a.ArcType == ArcPending { 847 continue 848 } 849 850 // Errors are allowed in let fields. Handle errors and failure to 851 // complete accordingly. 852 if !a.Label.IsLet() && a.ArcType <= ArcRequired { 853 // Don't set the state to Finalized if the child arcs are not done. 854 if state == finalized && a.status < finalized { 855 state = conjuncts 856 } 857 858 if err := a.Bottom(); err != nil { 859 n.AddChildError(err) 860 } 861 } 862 863 // If a structural cycle is detected, Arcs is cleared to avoid 864 // going into an infinite loop. If this is the case, we can bail 865 // from this loop. 866 if len(n.node.Arcs) == 0 { 867 goto postChecks 868 } 869 n.node.Arcs[k] = a 870 k++ 871 872 switch { 873 case a.ArcType > ArcRequired, !a.Label.IsString(): 874 case n.kind&StructKind == 0: 875 if !n.node.IsErr() { 876 n.reportFieldMismatch(pos(a.Value()), nil, a.Label, n.node.Value()) 877 } 878 case !wasVoid: 879 case n.kind == TopKind: 880 // Theoretically it may be possible that a "void" arc references 881 // this top value where it really should have been a struct. One 882 // way to solve this is to have two passes over the arcs, where 883 // the first pass additionally analyzes whether comprehensions 884 // will yield values and "un-voids" an arc ahead of the rest. 885 // 886 // At this moment, though, I fail to see a possibility to create 887 // faulty CUE using this mechanism, though. At most error 888 // messages are a bit unintuitive. This may change once we have 889 // functionality to reflect on types. 890 if !n.node.IsErr() { 891 n.node.BaseValue = &StructMarker{} 892 n.kind = StructKind 893 } 894 } 895 } 896 n.node.Arcs = n.node.Arcs[:k] 897 898 postChecks: 899 for _, c := range n.postChecks { 900 f := ctx.PushState(c.env, c.expr.Source()) 901 902 // TODO(errors): make Validate return bottom and generate 903 // optimized conflict message. Also track and inject IDs 904 // to determine origin location.s 905 v := ctx.evalState(c.expr, oldOnly(finalized)) 906 v, _ = ctx.getDefault(v) 907 v = Unwrap(v) 908 909 switch _, isError := v.(*Bottom); { 910 case isError == c.expectError: 911 default: 912 n.node.AddErr(ctx, &Bottom{ 913 Src: c.expr.Source(), 914 Code: CycleError, 915 Node: n.node, 916 Err: ctx.NewPosf(pos(c.expr), 917 "circular dependency in evaluation of conditionals: %v changed after evaluation", 918 ctx.Str(c.expr)), 919 }) 920 } 921 922 ctx.PopState(f) 923 } 924 } 925 926 if err := n.getErr(); err != nil { 927 n.errs = nil 928 if b, _ := n.node.BaseValue.(*Bottom); b != nil { 929 err = CombineErrors(nil, b, err) 930 } 931 n.node.BaseValue = err 932 } 933 934 b, hasErr := n.node.BaseValue.(*Bottom) 935 if !hasErr && b != cycle { 936 n.checkClosed(state) 937 } 938 939 // Strip struct literals that were not initialized and are not part 940 // of the output. 941 // 942 // TODO(perf): we could keep track if any such structs exist and only 943 // do this removal if there is a change of shrinking the list. 944 k := 0 945 for _, s := range n.node.Structs { 946 if s.initialized { 947 n.node.Structs[k] = s 948 k++ 949 } 950 } 951 n.node.Structs = n.node.Structs[:k] 952 953 n.node.updateStatus(finalized) 954 } 955 956 // TODO: this is now a sentinel. Use a user-facing error that traces where 957 // the cycle originates. 958 var cycle = &Bottom{ 959 Err: errors.Newf(token.NoPos, "cycle error"), 960 Code: CycleError, 961 } 962 963 func isCyclePlaceholder(v BaseValue) bool { 964 // TODO: do not mark cycle in BaseValue. 965 if a, _ := v.(*Vertex); a != nil { 966 v = a.DerefValue().BaseValue 967 } 968 return v == cycle 969 } 970 971 func (n *nodeContext) createDisjunct() *Disjunction { 972 a := make([]Value, len(n.disjuncts)) 973 p := 0 974 hasDefaults := false 975 for i, x := range n.disjuncts { 976 v := new(Vertex) 977 *v = x.result 978 v.state = nil 979 switch x.defaultMode { 980 case isDefault: 981 a[i] = a[p] 982 a[p] = v 983 p++ 984 hasDefaults = true 985 986 case notDefault: 987 hasDefaults = true 988 fallthrough 989 case maybeDefault: 990 a[i] = v 991 } 992 } 993 // TODO: disambiguate based on concrete values. 994 // TODO: consider not storing defaults. 995 // if p > 0 { 996 // a = a[:p] 997 // } 998 return &Disjunction{ 999 Values: a, 1000 NumDefaults: p, 1001 HasDefaults: hasDefaults, 1002 } 1003 } 1004 1005 type arcKey struct { 1006 arc *Vertex 1007 id CloseInfo 1008 } 1009 1010 // A nodeContext is used to collate all conjuncts of a value to facilitate 1011 // unification. Conceptually order of unification does not matter. However, 1012 // order has relevance when performing checks of non-monotic properties. Such 1013 // checks should only be performed once the full value is known. 1014 type nodeContext struct { 1015 nextFree *nodeContext 1016 refCount int 1017 1018 // Keep node out of the nodeContextState to make them more accessible 1019 // for source-level debuggers. 1020 node *Vertex 1021 1022 // parent keeps track of the parent Vertex in which a Vertex is being 1023 // evaluated. This is to keep track of the full path in error messages. 1024 parent *Vertex 1025 1026 // underlying is the original Vertex that this node overlays. It should be 1027 // set for all Vertex values that were cloned. 1028 underlying *Vertex 1029 1030 nodeContextState 1031 1032 scheduler 1033 1034 // Below are slices that need to be managed when cloning and reclaiming 1035 // nodeContexts for reuse. We want to ensure that, instead of setting 1036 // slices to nil, we truncate the existing buffers so that they do not 1037 // need to be reallocated upon reuse of the nodeContext. 1038 1039 arcMap []arcKey // not copied for cloning 1040 1041 // vertexMap is used to map vertices in disjunctions. 1042 vertexMap vertexMap 1043 1044 // notify is used to communicate errors in cyclic dependencies. 1045 // TODO: also use this to communicate increasingly more concrete values. 1046 notify []receiver 1047 1048 // sharedIDs contains all the CloseInfos that are involved in a shared node. 1049 // There can be more than one if the same Vertex is shared multiple times. 1050 // It is important to keep track of each instance as we need to insert each 1051 // of them separately in case a Vertex is "unshared" to ensure that 1052 // closedness information is correctly computed in such cases. 1053 sharedIDs []CloseInfo 1054 1055 // Conjuncts holds a reference to the Vertex Arcs that still need 1056 // processing. It does NOT need to be copied. 1057 conjuncts []conjunct 1058 cyclicConjuncts []cyclicConjunct 1059 1060 dynamicFields []envDynamic 1061 comprehensions []envYield 1062 selfComprehensions []envYield // comprehensions iterating over own struct. 1063 1064 // Expression conjuncts 1065 lists []envList 1066 vLists []*Vertex 1067 exprs []envExpr 1068 1069 // These fields are used to track type checking. 1070 reqDefIDs []refInfo 1071 replaceIDs []replaceID 1072 conjunctInfo []conjunctInfo 1073 reqSets reqSets 1074 1075 // Checks is a list of conjuncts, as we need to preserve the context in 1076 // which it was evaluated. The conjunct is always a validator (and thus 1077 // a Value). We need to keep track of the CloseInfo, however, to be able 1078 // to catch cycles when evaluating BuiltinValidators. 1079 // TODO: introduce ValueConjunct to get better compile time type checking. 1080 checks []Conjunct 1081 1082 postChecks []envCheck // Check non-monotonic constraints, among other things. 1083 1084 // Disjunction handling 1085 disjunctions []envDisjunct 1086 1087 // usedDefault indicates the for each of possibly multiple parent 1088 // disjunctions whether it is unified with a default disjunct or not. 1089 // This is then later used to determine whether a disjunction should 1090 // be treated as a marked disjunction. 1091 usedDefault []defaultInfo 1092 1093 // disjuncts holds disjuncts that evaluated to a non-bottom value. 1094 // TODO: come up with a better name. 1095 disjuncts []*nodeContext 1096 buffer []*nodeContext 1097 disjunctErrs []*Bottom 1098 1099 // hasDisjunction marks wither any disjunct was added. It is listed here 1100 // instead of in nodeContextState as it should be cleared when a disjunction 1101 // is split off. TODO: find something more principled. 1102 hasDisjunction bool 1103 1104 // snapshot holds the last value of the vertex before calling postDisjunct. 1105 snapshot Vertex 1106 1107 // Result holds the last evaluated value of the vertex after calling 1108 // postDisjunct. 1109 result Vertex 1110 } 1111 1112 type conjunct struct { 1113 C Conjunct 1114 1115 // done marks that this conjunct has been inserted. This prevents a 1116 // conjunct from being processed more than once, for instance, when 1117 // insertConjuncts is called more than once for the same node. 1118 done bool 1119 index int // index of the original conjunct in Vertex.Conjuncts 1120 } 1121 1122 type nodeContextState struct { 1123 // isInitialized indicates whether conjuncts have been inserted in the node. 1124 // Use node.isInitialized() to more generally check whether conjuncts have 1125 // been processed. 1126 isInitialized bool 1127 1128 // toComplete marks whether completeNodeTasks needs to be called on this 1129 // node after a corresponding task has been completed. 1130 toComplete bool 1131 1132 // isCompleting > 0 indicates whether a call to completeNodeTasks is in 1133 // progress. 1134 isCompleting int 1135 1136 // runMode keeps track of what runMode a disjunct should run as. This is 1137 // relevant for nested disjunctions, like the 2|3 in (1 | (2|3)) & (1 | 2), 1138 // where the nested disjunction should _not_ be considered as final, as 1139 // there is still a disjunction at a higher level to be processed. 1140 runMode runMode 1141 1142 // evalDept is a number that is assigned when evaluating arcs and is set to 1143 // detect structural cycles. This value may be temporarily altered when a 1144 // node descends into evaluating a value that may be an error (pattern 1145 // constraints, optional fields, etc.). A non-zero value always indicates 1146 // that there are cyclic references, though. 1147 evalDepth int 1148 1149 // State info 1150 1151 hasTop bool 1152 hasAnyCyclicConjunct bool // has conjunct with structural cycle 1153 hasAncestorCycle bool // has conjunct with structural cycle to an ancestor 1154 hasNonCycle bool // has material conjuncts without structural cycle 1155 hasNonCyclic bool // has non-cyclic conjuncts at start of field processing 1156 1157 // These simulate the old closeContext logic. TODO: perhaps remove. 1158 hasStruct bool // this node has a struct conjunct 1159 hasOpenValidator bool // this node has an open validator 1160 isDef bool // this node is a definition 1161 1162 dropParentRequirements bool // used for typo checking 1163 computedCloseInfo bool // used for typo checking 1164 1165 isShared bool // set if we are currently structure sharing 1166 noSharing bool // set if structure sharing is not allowed 1167 shared Conjunct // the original conjunct that led to sharing 1168 shareCycleType CyclicType // keeps track of the cycle type of shared nodes 1169 origBaseValue BaseValue // the BaseValue that structure sharing replaces 1170 shareDecremented bool // counters of sharedIDs have been decremented 1171 1172 depth int32 1173 defaultMode defaultMode // cumulative default mode 1174 origDefaultMode defaultMode // default mode of the original disjunct 1175 1176 // has a value filled out before the node splits into a disjunction. Aside 1177 // from detecting a self-reference cycle when there is otherwise just an 1178 // other error, this field is not needed. It greatly helps, however, to 1179 // improve the error messages. 1180 hasFieldValue bool 1181 1182 // defaultAttemptInCycle indicates that a value relies on the default value 1183 // and that it will be an error to remove the default value from the 1184 // disjunction. It is set to the referring Vertex. Consider for instance: 1185 // 1186 // a: 1 - b 1187 // b: 1 - a 1188 // a: *0 | 1 1189 // b: *0 | 1 1190 // 1191 // versus 1192 // 1193 // a: 1 - b 1194 // b: 1 - a 1195 // a: *1 | 0 1196 // b: *0 | 1 1197 // 1198 // In both cases there are multiple solutions to the configuration. In the 1199 // first case there is an ambiguity: if we start with evaluating 'a' and 1200 // pick the default for 'b', we end up with a value of '1' for 'a'. If, 1201 // conversely, we start evaluating 'b' and pick the default for 'a', we end 1202 // up with {a: 0, b: 0}. In the seconds case, however, we do _will_ get the 1203 // same answer regardless of order. 1204 // 1205 // In general, we will allow expressions on cyclic paths to be resolved if 1206 // in all cases the default value is taken. In order to do that, we do not 1207 // allow a default value to be removed from a disjunction if such value is 1208 // depended on. 1209 // 1210 // For completeness, note that CUE will NOT solve a solution, even if there 1211 // is only one solution. Consider for instance: 1212 // 1213 // a: 0 | 1 1214 // a: b + 1 1215 // b: c - 1 1216 // c: a - 1 1217 // c: 1 | 2 1218 // 1219 // There the only consistent solution is {a: 1, b: 0, c: 1}. CUE, however, 1220 // will not attempt this solve this as, in general, such solving would be NP 1221 // complete. 1222 // 1223 // NOTE(evalv4): note that this would be easier if we got rid of default 1224 // values and had pre-selected overridable values instead. 1225 defaultAttemptInCycle *Vertex 1226 1227 // Value info 1228 1229 kind Kind 1230 kindExpr Expr // expr that adjust last value (for error reporting) 1231 kindID CloseInfo // for error tracing 1232 1233 // Current value (may be under construction) 1234 scalar Value // TODO: use Value in node. 1235 scalarID CloseInfo 1236 1237 aStruct Expr 1238 aStructID CloseInfo 1239 1240 // List fields 1241 listIsClosed bool 1242 maxListLen int 1243 maxNode Expr 1244 1245 lowerBound *BoundValue // > or >= 1246 upperBound *BoundValue // < or <= 1247 errs *Bottom 1248 1249 // Slice positions 1250 1251 // conjunctsPos is an index into conjuncts indicating the next conjunct 1252 // to process. This is used to avoids processing a conjunct twice in some 1253 // cases where there is an evaluation cycle. 1254 conjunctsPos int 1255 // conjunctsPartialPos is like conjunctsPos, but for the 'partial' phase 1256 // of processing where conjuncts are only processed as concrete scalars. 1257 conjunctsPartialPos int 1258 } 1259 1260 // A receiver receives notifications. 1261 // cc is used for V3 and is nil in V2. 1262 // v is equal to cc.src._cc in V3. 1263 type receiver struct { 1264 v *Vertex 1265 } 1266 1267 // Logf substitutes args in format. Arguments of type Feature, Value, and Expr 1268 // are printed in human-friendly formats. The printed string is prefixed and 1269 // indented with the path associated with the current nodeContext. 1270 func (n *nodeContext) Logf(format string, args ...interface{}) { 1271 n.ctx.Logf(n.node, format, args...) 1272 } 1273 1274 type defaultInfo struct { 1275 // parentMode indicates whether this values was used as a default value, 1276 // based on the parent mode. 1277 parentMode defaultMode 1278 1279 // The result of default evaluation for a nested disjunction. 1280 nestedMode defaultMode 1281 1282 origMode defaultMode 1283 } 1284 1285 func (n *nodeContext) addNotify(v *Vertex) { 1286 unreachableForDev(n.ctx) 1287 1288 if v != nil && !n.node.hasAllConjuncts { 1289 n.notify = append(n.notify, receiver{v}) 1290 } 1291 } 1292 1293 func (n *nodeContext) clone() *nodeContext { 1294 d := n.ctx.newNodeContext(n.node) 1295 1296 d.refCount++ 1297 1298 d.ctx = n.ctx 1299 d.node = n.node 1300 1301 d.nodeContextState = n.nodeContextState 1302 1303 d.arcMap = append(d.arcMap, n.arcMap...) 1304 d.notify = append(d.notify, n.notify...) 1305 d.sharedIDs = append(d.sharedIDs, n.sharedIDs...) 1306 1307 n.scheduler.cloneInto(&d.scheduler) 1308 1309 d.conjuncts = append(d.conjuncts, n.conjuncts...) 1310 d.cyclicConjuncts = append(d.cyclicConjuncts, n.cyclicConjuncts...) 1311 d.dynamicFields = append(d.dynamicFields, n.dynamicFields...) 1312 d.comprehensions = append(d.comprehensions, n.comprehensions...) 1313 d.selfComprehensions = append(d.selfComprehensions, n.selfComprehensions...) 1314 d.lists = append(d.lists, n.lists...) 1315 d.vLists = append(d.vLists, n.vLists...) 1316 d.exprs = append(d.exprs, n.exprs...) 1317 1318 d.reqDefIDs = append(d.reqDefIDs, n.reqDefIDs...) 1319 d.replaceIDs = append(d.replaceIDs, n.replaceIDs...) 1320 d.conjunctInfo = append(d.conjunctInfo, n.conjunctInfo...) 1321 d.reqSets = append(d.reqSets, n.reqSets...) 1322 1323 d.checks = append(d.checks, n.checks...) 1324 d.postChecks = append(d.postChecks, n.postChecks...) 1325 1326 d.usedDefault = append(d.usedDefault, n.usedDefault...) 1327 1328 // Do not clone other disjunction-related slices, like disjuncts and buffer: 1329 // disjunction slices are managed by disjunction processing directly. 1330 1331 return d 1332 } 1333 1334 func (c *OpContext) newNodeContext(node *Vertex) *nodeContext { 1335 if n := c.freeListNode; n != nil { 1336 c.stats.Reused++ 1337 c.freeListNode = n.nextFree 1338 1339 *n = nodeContext{ 1340 scheduler: scheduler{ctx: c}, 1341 node: node, 1342 nodeContextState: nodeContextState{ 1343 kind: TopKind, 1344 }, 1345 arcMap: n.arcMap[:0], 1346 conjuncts: n.conjuncts[:0], 1347 cyclicConjuncts: n.cyclicConjuncts[:0], 1348 notify: n.notify[:0], 1349 sharedIDs: n.sharedIDs[:0], 1350 checks: n.checks[:0], 1351 postChecks: n.postChecks[:0], 1352 dynamicFields: n.dynamicFields[:0], 1353 comprehensions: n.comprehensions[:0], 1354 selfComprehensions: n.selfComprehensions[:0], 1355 lists: n.lists[:0], 1356 vLists: n.vLists[:0], 1357 exprs: n.exprs[:0], 1358 reqDefIDs: n.reqDefIDs[:0], 1359 replaceIDs: n.replaceIDs[:0], 1360 conjunctInfo: n.conjunctInfo[:0], 1361 reqSets: n.reqSets[:0], 1362 disjunctions: n.disjunctions[:0], 1363 usedDefault: n.usedDefault[:0], 1364 disjunctErrs: n.disjunctErrs[:0], 1365 disjuncts: n.disjuncts[:0], 1366 buffer: n.buffer[:0], 1367 } 1368 n.scheduler.clear() 1369 n.scheduler.node = n 1370 n.underlying = node 1371 1372 return n 1373 } 1374 c.stats.Allocs++ 1375 1376 n := &nodeContext{ 1377 scheduler: scheduler{ 1378 ctx: c, 1379 }, 1380 node: node, 1381 1382 nodeContextState: nodeContextState{kind: TopKind}, 1383 } 1384 n.scheduler.node = n 1385 n.underlying = node 1386 return n 1387 } 1388 1389 func (v *Vertex) getNodeContext(c *OpContext, ref int) *nodeContext { 1390 unreachableForDev(c) 1391 1392 if v.state == nil { 1393 if v.status == finalized { 1394 return nil 1395 } 1396 v.state = c.newNodeContext(v) 1397 } else if v.state.node != v { 1398 panic("getNodeContext: nodeContext out of sync") 1399 } 1400 v.state.refCount += ref 1401 return v.state 1402 } 1403 1404 func (v *Vertex) freeNode(n *nodeContext) { 1405 if n == nil { 1406 return 1407 } 1408 if n.node != v { 1409 panic("freeNode: unpaired free") 1410 } 1411 if v.state != nil && v.state != n { 1412 panic("freeNode: nodeContext out of sync") 1413 } 1414 if n.refCount--; n.refCount == 0 { 1415 if v.status == finalized { 1416 v.freeNodeState() 1417 } else { 1418 n.ctx.stats.Retained++ 1419 } 1420 } 1421 } 1422 1423 func (v *Vertex) freeNodeState() { 1424 if v.state == nil { 1425 return 1426 } 1427 state := v.state 1428 v.state = nil 1429 1430 state.ctx.freeNodeContext(state) 1431 } 1432 1433 func (n *nodeContext) free() { 1434 if n.refCount--; n.refCount == 0 { 1435 n.ctx.freeNodeContext(n) 1436 } 1437 } 1438 1439 func (c *OpContext) freeNodeContext(n *nodeContext) { 1440 c.stats.Freed++ 1441 n.nextFree = c.freeListNode 1442 c.freeListNode = n 1443 n.node = nil 1444 n.refCount = 0 1445 n.scheduler.clear() 1446 } 1447 1448 // TODO(perf): return a dedicated ConflictError that can track original 1449 // positions on demand. 1450 func (n *nodeContext) reportConflict( 1451 v1, v2 Node, 1452 k1, k2 Kind, 1453 ids ...CloseInfo) { 1454 1455 ctx := n.ctx 1456 1457 var err *ValueError 1458 if k1 == k2 { 1459 err = ctx.NewPosf(token.NoPos, "conflicting values %s and %s", v1, v2) 1460 } else { 1461 err = ctx.NewPosf(token.NoPos, 1462 "conflicting values %s and %s (mismatched types %s and %s)", 1463 v1, v2, k1, k2) 1464 } 1465 1466 err.AddPosition(v1) 1467 err.AddPosition(v2) 1468 for _, id := range ids { 1469 err.AddClosedPositions(id) 1470 } 1471 1472 n.addErr(err) 1473 } 1474 1475 // reportFieldMismatch reports the mixture of regular fields with non-struct 1476 // values. Either s or f needs to be given. 1477 func (n *nodeContext) reportFieldMismatch( 1478 p token.Pos, 1479 s *StructLit, 1480 f Feature, 1481 scalar Expr, 1482 id ...CloseInfo) { 1483 1484 ctx := n.ctx 1485 1486 if f == InvalidLabel { 1487 for _, a := range s.Decls { 1488 if x, ok := a.(*Field); ok && x.Label.IsRegular() { 1489 f = x.Label 1490 p = pos(x) 1491 break 1492 } 1493 } 1494 if f == InvalidLabel { 1495 n.reportConflict(scalar, s, n.kind, StructKind, id...) 1496 return 1497 } 1498 } 1499 1500 err := ctx.NewPosf(p, "cannot combine regular field %q with %v", f, scalar) 1501 1502 if s != nil { 1503 err.AddPosition(s) 1504 } 1505 1506 for _, ci := range id { 1507 err.AddClosedPositions(ci) 1508 } 1509 1510 n.addErr(err) 1511 } 1512 1513 func (n *nodeContext) updateNodeType(k Kind, v Expr, id CloseInfo) bool { 1514 n.updateConjunctInfo(k, id, 0) 1515 1516 ctx := n.ctx 1517 kind := n.kind & k 1518 1519 switch { 1520 case n.kind == BottomKind, 1521 k == BottomKind: 1522 return false 1523 1524 case kind != BottomKind: 1525 1526 // TODO: we could consider changing the reporting for structs, but this 1527 // makes only sense in case they are for embeddings. Otherwise the type 1528 // of a struct is more relevant for the failure. 1529 // case k == StructKind: 1530 // s, _ := v.(*StructLit) 1531 // n.reportFieldMismatch(token.NoPos, s, 0, n.kindExpr, id, n.kindID) 1532 1533 case n.kindExpr != nil: 1534 n.reportConflict(n.kindExpr, v, n.kind, k, n.kindID, id) 1535 1536 default: 1537 n.addErr(ctx.Newf( 1538 "conflicting value %s (mismatched types %s and %s)", 1539 v, n.kind, k)) 1540 } 1541 1542 if n.kind != kind || n.kindExpr == nil { 1543 n.kindExpr = v 1544 } 1545 n.kind = kind 1546 return kind != BottomKind 1547 } 1548 1549 func (n *nodeContext) done() bool { 1550 // TODO(v0.7): verify that done() is checking for the right conditions in 1551 // the new evaluator implementation. 1552 return len(n.dynamicFields) == 0 && 1553 len(n.comprehensions) == 0 && 1554 len(n.exprs) == 0 1555 } 1556 1557 // finalDone is like done, but allows for cycle errors, which can be ignored 1558 // as they essentially indicate a = a & _. 1559 func (n *nodeContext) finalDone() bool { 1560 // TODO(v0.7): update for new evaluator? 1561 for _, x := range n.exprs { 1562 if x.err.Code != CycleError { 1563 return false 1564 } 1565 } 1566 return len(n.dynamicFields) == 0 && 1567 len(n.comprehensions) == 0 && 1568 len(n.selfComprehensions) == 0 1569 } 1570 1571 // hasErr is used to determine if an evaluation path, for instance a single 1572 // path after expanding all disjunctions, has an error. 1573 func (n *nodeContext) hasErr() bool { 1574 n.assertInitialized() 1575 1576 if n.node.ChildErrors != nil { 1577 return true 1578 } 1579 if n.node.Status() > evaluating && n.node.IsErr() { 1580 return true 1581 } 1582 return n.ctx.HasErr() || n.errs != nil 1583 } 1584 1585 func (n *nodeContext) getErr() *Bottom { 1586 n.assertInitialized() 1587 1588 n.errs = CombineErrors(nil, n.errs, n.ctx.Err()) 1589 return n.errs 1590 } 1591 1592 // getValidators sets the vertex' Value in case there was no concrete value. 1593 func (n *nodeContext) getValidators(state vertexStatus) BaseValue { 1594 n.assertInitialized() 1595 1596 ctx := n.ctx 1597 1598 a := []Value{} 1599 // if n.node.Value != nil { 1600 // a = append(a, n.node.Value) 1601 // } 1602 kind := TopKind 1603 if n.lowerBound != nil { 1604 a = append(a, n.lowerBound) 1605 kind &= n.lowerBound.Kind() 1606 } 1607 if n.upperBound != nil { 1608 a = append(a, n.upperBound) 1609 kind &= n.upperBound.Kind() 1610 } 1611 for _, c := range n.checks { 1612 // Drop !=x if x is out of bounds with another bound. 1613 if b, _ := c.x.(*BoundValue); b != nil && b.Op == NotEqualOp { 1614 if n.upperBound != nil && 1615 SimplifyBounds(ctx, n.kind, n.upperBound, b) != nil { 1616 continue 1617 } 1618 if n.lowerBound != nil && 1619 SimplifyBounds(ctx, n.kind, n.lowerBound, b) != nil { 1620 continue 1621 } 1622 } 1623 v := c.x.(Value) 1624 a = append(a, v) 1625 kind &= v.Kind() 1626 } 1627 1628 if kind&^n.kind != 0 { 1629 a = append(a, &BasicType{ 1630 Src: n.kindExpr.Source(), // TODO:Is this always a BasicType? 1631 K: n.kind, 1632 }) 1633 } 1634 1635 var v BaseValue 1636 switch len(a) { 1637 case 0: 1638 // Src is the combined input. 1639 if state >= conjuncts || n.kind&^CompositeKind == 0 { 1640 v = &BasicType{K: n.kind} 1641 } 1642 1643 case 1: 1644 v = a[0] 1645 1646 default: 1647 v = &Conjunction{Values: a} 1648 } 1649 1650 return v 1651 } 1652 1653 // TODO: this function can probably go as this is now handled in the nodeContext. 1654 func (n *nodeContext) maybeSetCache() { 1655 // Set BaseValue to scalar, but only if it was not set before. Most notably, 1656 // errors should not be discarded. 1657 _, isErr := n.node.BaseValue.(*Bottom) 1658 if n.scalar != nil && (!isErr || isCyclePlaceholder(n.node.BaseValue)) { 1659 n.node.BaseValue = n.scalar 1660 } 1661 // NOTE: this is now handled by associating the nodeContext 1662 // if n.errs != nil { 1663 // n.node.SetValue(n.ctx, Partial, n.errs) 1664 // } 1665 } 1666 1667 type envExpr struct { 1668 c Conjunct 1669 err *Bottom 1670 } 1671 1672 type envDynamic struct { 1673 env *Environment 1674 field *DynamicField 1675 id CloseInfo 1676 err *Bottom 1677 } 1678 1679 type envList struct { 1680 env *Environment 1681 list *ListLit 1682 n int64 // recorded length after evaluator 1683 elipsis *Ellipsis 1684 id CloseInfo 1685 ignore bool // has a self-referencing comprehension and is postponed 1686 self bool // was added as a postponed self-referencing comprehension 1687 } 1688 1689 type envCheck struct { 1690 env *Environment 1691 expr Expr 1692 expectError bool 1693 } 1694 1695 func (n *nodeContext) addBottom(b *Bottom) { 1696 n.assertInitialized() 1697 1698 n.errs = CombineErrors(nil, n.errs, b) 1699 // TODO(errors): consider doing this 1700 // n.kindExpr = n.errs 1701 // n.kind = 0 1702 } 1703 1704 func (n *nodeContext) addErr(err errors.Error) { 1705 n.assertInitialized() 1706 1707 if err != nil { 1708 n.addBottom(&Bottom{ 1709 Err: err, 1710 Node: n.node, 1711 }) 1712 } 1713 } 1714 1715 // addExprConjuncts will attempt to evaluate an Expr and insert the value 1716 // into the nodeContext if successful or queue it for later evaluation if it is 1717 // incomplete or is not value. 1718 func (n *nodeContext) addExprConjunct(v Conjunct, state vertexStatus) { 1719 unreachableForDev(n.ctx) 1720 1721 env := v.Env 1722 id := v.CloseInfo 1723 1724 switch x := v.Elem().(type) { 1725 case *Vertex: 1726 if x.IsData() { 1727 n.addValueConjunct(env, x, id) 1728 } else { 1729 n.addVertexConjuncts(v, x, true) 1730 } 1731 1732 case Value: 1733 n.addValueConjunct(env, x, id) 1734 1735 case *BinaryExpr: 1736 if x.Op == AndOp { 1737 n.addExprConjunct(MakeConjunct(env, x.X, id), state) 1738 n.addExprConjunct(MakeConjunct(env, x.Y, id), state) 1739 return 1740 } else { 1741 n.evalExpr(v, state) 1742 } 1743 1744 case *StructLit: 1745 n.addStruct(env, x, id) 1746 1747 case *ListLit: 1748 childEnv := &Environment{ 1749 Up: env, 1750 Vertex: n.node, 1751 } 1752 n.lists = append(n.lists, envList{env: childEnv, list: x, id: id}) 1753 1754 case *DisjunctionExpr: 1755 n.addDisjunction(env, x, id) 1756 1757 case *Comprehension: 1758 // always a partial comprehension. 1759 n.insertComprehension(env, x, id) 1760 return 1761 1762 default: 1763 // Must be Resolver or Evaluator. 1764 n.evalExpr(v, state) 1765 } 1766 n.ctx.stats.Conjuncts++ 1767 } 1768 1769 // evalExpr is only called by addExprConjunct. If an error occurs, it records 1770 // the error in n and returns nil. 1771 func (n *nodeContext) evalExpr(v Conjunct, state vertexStatus) { 1772 unreachableForDev(n.ctx) 1773 1774 // Require an Environment. 1775 ctx := n.ctx 1776 1777 closeID := v.CloseInfo 1778 1779 switch x := v.Expr().(type) { 1780 case Resolver: 1781 // We elevate a field evaluated to the Conjuncts state to Finalized 1782 // later. For now we allow partial evaluation so that we can break 1783 // cycles and postpone incomplete evaluations until more information is 1784 // available down the line. 1785 if state == finalized { 1786 state = conjuncts 1787 } 1788 arc, err := ctx.resolveState(v, x, oldOnly(state)) 1789 if err != nil && (!err.IsIncomplete() || err.Permanent) { 1790 n.addBottom(err) 1791 break 1792 } 1793 if arc == nil { 1794 n.exprs = append(n.exprs, envExpr{v, err}) 1795 break 1796 } 1797 1798 // We complete the evaluation. Some optimizations will only work when an 1799 // arc is already finalized. So this ensures that such optimizations get 1800 // triggered more often. 1801 // 1802 // NOTE(let finalization): aside from being an optimization, this also 1803 // ensures that let arcs that are not contained as fields of arcs, but 1804 // rather are held in the cash, are finalized. This, in turn, is 1805 // necessary to trigger the notification mechanism, where appropriate. 1806 // 1807 // A node should not Finalize itself as it may erase the state object 1808 // which is still assumed to be present down the line 1809 // (see https://cuelang.org/issues/2171). 1810 if arc.status == conjuncts && arc != n.node && arc.hasAllConjuncts { 1811 arc.Finalize(ctx) 1812 } 1813 1814 ci, skip := n.markCycle(arc, v.Env, x, v.CloseInfo) 1815 if skip { 1816 return 1817 } 1818 v.CloseInfo = ci 1819 1820 n.addVertexConjuncts(v, arc, false) 1821 1822 case Evaluator: 1823 // Interpolation, UnaryExpr, BinaryExpr, CallExpr 1824 // Could be unify? 1825 val := ctx.evaluateRec(v, oldOnly(partial)) 1826 if b, ok := val.(*Bottom); ok && 1827 b.IsIncomplete() { 1828 n.exprs = append(n.exprs, envExpr{v, b}) 1829 break 1830 } 1831 1832 if v, ok := val.(*Vertex); ok { 1833 // Handle generated disjunctions (as in the 'or' builtin). 1834 // These come as a Vertex, but should not be added as a value. 1835 b, ok := v.BaseValue.(*Bottom) 1836 if ok && b.IsIncomplete() && len(v.Conjuncts) > 0 { 1837 for _, c := range v.Conjuncts { 1838 c.CloseInfo = closeID 1839 n.addExprConjunct(c, state) 1840 } 1841 break 1842 } 1843 } 1844 1845 // TODO: also to through normal Vertex handling here. At the moment 1846 // addValueConjunct handles StructMarker.NeedsClose, as this is always 1847 // only needed when evaluation an Evaluator, and not a Resolver. 1848 // The two code paths should ideally be merged once this separate 1849 // mechanism is eliminated. 1850 // 1851 // if arc, ok := val.(*Vertex); ok && !arc.IsData() { 1852 // n.addVertexConjuncts(v.Env, closeID, v.Expr(), arc) 1853 // break 1854 // } 1855 1856 // TODO: insert in vertex as well 1857 n.addValueConjunct(v.Env, val, closeID) 1858 1859 default: 1860 panic(fmt.Sprintf("unknown expression of type %T", x)) 1861 } 1862 } 1863 1864 func (n *nodeContext) addVertexConjuncts(c Conjunct, arc *Vertex, inline bool) { 1865 unreachableForDev(n.ctx) 1866 1867 closeInfo := c.CloseInfo 1868 1869 // We need to ensure that each arc is only unified once (or at least) a 1870 // bounded time, witch each conjunct. Comprehensions, for instance, may 1871 // distribute a value across many values that get unified back into the 1872 // same value. If such a value is a disjunction, than a disjunction of N 1873 // disjuncts will result in a factor N more unifications for each 1874 // occurrence of such value, resulting in exponential running time. This 1875 // is especially common values that are used as a type. 1876 // 1877 // However, unification is idempotent, so each such conjunct only needs 1878 // to be unified once. This cache checks for this and prevents an 1879 // exponential blowup in such case. 1880 // 1881 // TODO(perf): this cache ensures the conjuncts of an arc at most once 1882 // per ID. However, we really need to add the conjuncts of an arc only 1883 // once total, and then add the close information once per close ID 1884 // (pointer can probably be shared). Aside from being more performant, 1885 // this is probably the best way to guarantee that conjunctions are 1886 // linear in this case. 1887 1888 ckey := closeInfo 1889 ckey.Refs = nil 1890 ckey.Inline = false 1891 key := arcKey{arc, ckey} 1892 for _, k := range n.arcMap { 1893 if key == k { 1894 return 1895 } 1896 } 1897 n.arcMap = append(n.arcMap, key) 1898 1899 status := arc.status 1900 1901 switch status { 1902 case evaluating: 1903 // Reference cycle detected. We have reached a fixed point and 1904 // adding conjuncts at this point will not change the value. Also, 1905 // continuing to pursue this value will result in an infinite loop. 1906 1907 // TODO: add a mechanism so that the computation will only have to 1908 // be done once? 1909 1910 if arc == n.node { 1911 // TODO: we could use node sharing here. This may avoid an 1912 // exponential blowup during evaluation, like is possible with 1913 // YAML. 1914 return 1915 } 1916 1917 case evaluatingArcs: 1918 // There is a structural cycle, but values may be processed nonetheless 1919 // if there is a non-cyclic conjunct. See cycle.go. 1920 } 1921 1922 // Performance: the following if check filters cases that are not strictly 1923 // necessary for correct functioning. Not updating the closeInfo may cause 1924 // some position information to be lost for top-level positions of merges 1925 // resulting form APIs. These tend to be fairly uninteresting. 1926 // At the same time, this optimization may prevent considerable slowdown 1927 // in case an API does many calls to Unify. 1928 x := c.Expr() 1929 if !inline || arc.IsClosedStruct() || arc.IsClosedList() { 1930 isDef, _ := IsDef(x) 1931 closeInfo = closeInfo.SpawnRef(arc, isDef, x) 1932 } 1933 1934 if arc.status == unprocessed && !inline { 1935 // This is a rare condition, but can happen in certain 1936 // evaluation orders. Unfortunately, adding this breaks 1937 // resolution of cyclic mutually referring disjunctions. But it 1938 // is necessary to prevent lookups in unevaluated structs. 1939 // TODO(cycles): this can probably most easily be fixed with a 1940 // having a more recursive implementation. 1941 n.ctx.unify(arc, oldOnly(partial)) 1942 } 1943 1944 // Don't add conjuncts if a node is referring to itself. 1945 if n.node == arc { 1946 return 1947 } 1948 1949 if arc.state != nil { 1950 arc.state.addNotify(n.node) 1951 } 1952 1953 for _, c := range arc.Conjuncts { 1954 // Note that we are resetting the tree here. We hereby assume that 1955 // closedness conflicts resulting from unifying the referenced arc were 1956 // already caught there and that we can ignore further errors here. 1957 c.CloseInfo = closeInfo 1958 n.addExprConjunct(c, partial) 1959 } 1960 } 1961 1962 func (n *nodeContext) addValueConjunct(env *Environment, v Value, id CloseInfo) { 1963 n.updateCyclicStatus(id) 1964 1965 ctx := n.ctx 1966 1967 if x, ok := v.(*Vertex); ok { 1968 if m, ok := x.BaseValue.(*StructMarker); ok { 1969 n.aStruct = x 1970 n.aStructID = id 1971 if m.NeedClose { 1972 id.IsClosed = true 1973 } 1974 } 1975 1976 if !x.IsData() { 1977 // TODO: this really shouldn't happen anymore. 1978 if isComplexStruct(ctx, x) { 1979 // This really shouldn't happen, but just in case. 1980 n.addVertexConjuncts(MakeConjunct(env, x, id), x, true) 1981 return 1982 } 1983 1984 for _, c := range x.Conjuncts { 1985 c.CloseInfo = id 1986 n.addExprConjunct(c, partial) // TODO: Pass from eval 1987 } 1988 return 1989 } 1990 1991 // TODO: evaluate value? 1992 switch v := x.BaseValue.(type) { 1993 default: 1994 panic(fmt.Sprintf("invalid type %T", x.BaseValue)) 1995 1996 case *ListMarker: 1997 n.vLists = append(n.vLists, x) 1998 return 1999 2000 case *StructMarker: 2001 2002 case Value: 2003 n.addValueConjunct(env, v, id) 2004 } 2005 2006 if len(x.Arcs) == 0 { 2007 return 2008 } 2009 2010 s := &StructLit{} 2011 2012 // Keep ordering of Go struct for topological sort. 2013 n.node.AddStruct(s, env, id) 2014 n.node.Structs = append(n.node.Structs, x.Structs...) 2015 2016 for _, a := range x.Arcs { 2017 if !a.definitelyExists() { 2018 continue 2019 } 2020 // TODO(errors): report error when this is a regular field. 2021 c := MakeConjunct(nil, a, id) 2022 n.insertField(a.Label, a.ArcType, c) 2023 s.MarkField(a.Label) 2024 } 2025 return 2026 } 2027 2028 switch b := v.(type) { 2029 case *Bottom: 2030 if b == NoShareSentinel { 2031 return 2032 } 2033 n.addBottom(b) 2034 return 2035 case *Builtin: 2036 if v := b.BareValidator(); v != nil { 2037 n.addValueConjunct(env, v, id) 2038 return 2039 } 2040 } 2041 2042 if !n.updateNodeType(v.Kind(), v, id) { 2043 return 2044 } 2045 2046 switch x := v.(type) { 2047 case *Disjunction: 2048 n.addDisjunctionValue(env, x, id) 2049 2050 case *Conjunction: 2051 for _, x := range x.Values { 2052 n.addValueConjunct(env, x, id) 2053 } 2054 2055 case *Top: 2056 n.hasTop = true 2057 2058 case *BasicType: 2059 // handled above 2060 2061 case *BoundValue: 2062 switch x.Op { 2063 case LessThanOp, LessEqualOp: 2064 if y := n.upperBound; y != nil { 2065 v := SimplifyBounds(ctx, n.kind, x, y) 2066 if err := valueError(v); err != nil { 2067 err.AddPosition(v) 2068 err.AddPosition(n.upperBound) 2069 err.AddClosedPositions(id) 2070 } 2071 n.upperBound = nil 2072 n.addValueConjunct(env, v, id) 2073 return 2074 } 2075 n.upperBound = x 2076 2077 case GreaterThanOp, GreaterEqualOp: 2078 if y := n.lowerBound; y != nil { 2079 v := SimplifyBounds(ctx, n.kind, x, y) 2080 if err := valueError(v); err != nil { 2081 err.AddPosition(v) 2082 err.AddPosition(n.lowerBound) 2083 err.AddClosedPositions(id) 2084 } 2085 n.lowerBound = nil 2086 n.addValueConjunct(env, v, id) 2087 return 2088 } 2089 n.lowerBound = x 2090 2091 case EqualOp, NotEqualOp, MatchOp, NotMatchOp: 2092 // This check serves as simplifier, but also to remove duplicates. 2093 k := 0 2094 match := false 2095 cx := MakeConjunct(env, x, id) 2096 for _, c := range n.checks { 2097 if y, ok := c.x.(*BoundValue); ok { 2098 switch z := SimplifyBounds(ctx, n.kind, x, y); { 2099 case z == y: 2100 match = true 2101 case z == x: 2102 continue 2103 } 2104 } 2105 n.checks[k] = c 2106 k++ 2107 } 2108 n.checks = n.checks[:k] 2109 if !match { 2110 n.checks = append(n.checks, cx) 2111 } 2112 return 2113 } 2114 2115 case Validator: 2116 // This check serves as simplifier, but also to remove duplicates. 2117 cx := MakeConjunct(env, x, id) 2118 for i, y := range n.checks { 2119 if b, ok := SimplifyValidator(ctx, cx, y); ok { 2120 n.checks[i] = b 2121 return 2122 } 2123 } 2124 n.updateNodeType(x.Kind(), x, id) 2125 n.checks = append(n.checks, cx) 2126 // TODO(validatorType): see namesake TODO in conjunct.go. 2127 k := x.Kind() 2128 if k == TopKind { 2129 n.hasTop = true 2130 } 2131 n.updateNodeType(k, x, id) 2132 2133 case *Vertex: 2134 // handled above. 2135 2136 case Value: // *NullLit, *BoolLit, *NumLit, *StringLit, *BytesLit, *Builtin 2137 if y := n.scalar; y != nil { 2138 if b, ok := BinOp(ctx, EqualOp, x, y).(*Bool); !ok || !b.B { 2139 n.reportConflict(x, y, x.Kind(), y.Kind(), n.scalarID, id) 2140 } 2141 // TODO: do we need to explicitly add again? 2142 // n.scalar = nil 2143 // n.addValueConjunct(c, BinOp(c, EqualOp, x, y)) 2144 break 2145 } 2146 n.scalar = x 2147 n.scalarID = id 2148 if n.node.status >= conjuncts { 2149 n.node.BaseValue = x 2150 } 2151 2152 default: 2153 panic(fmt.Sprintf("unknown value type %T", x)) 2154 } 2155 2156 if n.lowerBound != nil && n.upperBound != nil { 2157 if u := SimplifyBounds(ctx, n.kind, n.lowerBound, n.upperBound); u != nil { 2158 if err := valueError(u); err != nil { 2159 err.AddPosition(n.lowerBound) 2160 err.AddPosition(n.upperBound) 2161 err.AddClosedPositions(id) 2162 } 2163 n.lowerBound = nil 2164 n.upperBound = nil 2165 n.addValueConjunct(env, u, id) 2166 } 2167 } 2168 } 2169 2170 func valueError(v Value) *ValueError { 2171 if v == nil { 2172 return nil 2173 } 2174 b, _ := v.(*Bottom) 2175 if b == nil { 2176 return nil 2177 } 2178 err, _ := b.Err.(*ValueError) 2179 if err == nil { 2180 return nil 2181 } 2182 return err 2183 } 2184 2185 // addStruct collates the declarations of a struct. 2186 // 2187 // addStruct fulfills two additional pivotal functions: 2188 // 1. Implement vertex unification (this happens through De Bruijn indices 2189 // combined with proper set up of Environments). 2190 // 2. Implied closedness for definitions. 2191 func (n *nodeContext) addStruct( 2192 env *Environment, 2193 s *StructLit, 2194 closeInfo CloseInfo) { 2195 2196 n.updateCyclicStatus(closeInfo) 2197 2198 // NOTE: This is a crucial point in the code: 2199 // Unification dereferencing happens here. The child nodes are set to 2200 // an Environment linked to the current node. Together with the De Bruijn 2201 // indices, this determines to which Vertex a reference resolves. 2202 2203 childEnv := &Environment{ 2204 Up: env, 2205 Vertex: n.node, 2206 } 2207 2208 s.Init(n.ctx) 2209 2210 if s.HasEmbed && !s.IsFile() { 2211 closeInfo = closeInfo.SpawnGroup(nil) 2212 } 2213 2214 parent := n.node.AddStruct(s, childEnv, closeInfo) 2215 closeInfo.IsClosed = false 2216 2217 parent.Disable = true // disable until processing is done. 2218 2219 for _, d := range s.Decls { 2220 switch x := d.(type) { 2221 case *Field: 2222 if x.Label.IsString() && x.ArcType == ArcMember { 2223 n.aStruct = s 2224 n.aStructID = closeInfo 2225 } 2226 n.insertField(x.Label, x.ArcType, MakeConjunct(childEnv, x, closeInfo)) 2227 2228 case *LetField: 2229 arc := n.insertField(x.Label, ArcMember, MakeConjunct(childEnv, x, closeInfo)) 2230 if x.IsMulti { 2231 arc.MultiLet = x.IsMulti 2232 } 2233 2234 case *DynamicField: 2235 n.aStruct = s 2236 n.aStructID = closeInfo 2237 n.dynamicFields = append(n.dynamicFields, envDynamic{childEnv, x, closeInfo, nil}) 2238 2239 case *Comprehension: 2240 n.insertComprehension(childEnv, x, closeInfo) 2241 2242 case Expr: 2243 // add embedding to optional 2244 2245 // TODO(perf): only do this if addExprConjunct below will result in 2246 // a fieldSet. Otherwise the entry will just be removed next. 2247 id := closeInfo.SpawnEmbed(x) 2248 2249 c := MakeConjunct(childEnv, x, id) 2250 n.addExprConjunct(c, partial) 2251 2252 case *BulkOptionalField, *Ellipsis: 2253 // Nothing to do here. Note that the presence of these fields do not 2254 // excluded embedded scalars: only when they match actual fields 2255 // does it exclude those. 2256 2257 default: 2258 panic("unreachable") 2259 } 2260 } 2261 2262 if !s.HasEmbed { 2263 n.aStruct = s 2264 n.aStructID = closeInfo 2265 } 2266 2267 parent.Disable = false 2268 2269 } 2270 2271 // TODO(perf): if an arc is the only arc with that label added to a Vertex, and 2272 // if there are no conjuncts of optional fields to be added, then the arc could 2273 // be added as is until any of these conditions change. This would allow 2274 // structure sharing in many cases. One should be careful, however, to 2275 // recursively track arcs of previously unified evaluated vertices ot make this 2276 // optimization meaningful. 2277 // 2278 // An alternative approach to avoid evaluating optional arcs (if we take that 2279 // route) is to not recursively evaluate those arcs, even for Finalize. This is 2280 // possible as it is not necessary to evaluate optional arcs to evaluate 2281 // disjunctions. 2282 func (n *nodeContext) insertField(f Feature, mode ArcType, x Conjunct) *Vertex { 2283 ctx := n.ctx 2284 if ctx.isDevVersion() { 2285 return n.insertArc(f, mode, x, x.CloseInfo, true) 2286 } 2287 2288 arc, isNew := n.node.GetArc(ctx, f, mode) 2289 if f.IsLet() && !isNew { 2290 arc.MultiLet = true 2291 return arc 2292 } 2293 if arc.hasConjunct(x) { 2294 return arc 2295 } 2296 2297 switch { 2298 case arc.state != nil: 2299 arc.state.addConjunctDynamic(x) 2300 2301 case arc.IsUnprocessed() || arc.status != finalized: 2302 arc.addConjunctUnchecked(x) 2303 2304 default: 2305 n.addBottom(&Bottom{ 2306 Code: IncompleteError, 2307 Node: n.node, 2308 Err: ctx.NewPosf(pos(x.Field()), 2309 "cannot add field %s: was already used", 2310 f.SelectorString(ctx)), 2311 }) 2312 } 2313 return arc 2314 } 2315 2316 func (n *nodeContext) insertFieldUnchecked(f Feature, mode ArcType, x Conjunct) *Vertex { 2317 ctx := n.ctx 2318 if ctx.isDevVersion() { 2319 return n.insertArc(f, mode, x, x.CloseInfo, false) 2320 } 2321 2322 arc, isNew := n.node.GetArc(ctx, f, mode) 2323 if f.IsLet() && !isNew { 2324 arc.MultiLet = true 2325 return arc 2326 } 2327 arc.addConjunctUnchecked(x) 2328 return arc 2329 } 2330 2331 // expandOne adds dynamic fields to a node until a fixed point is reached. 2332 // On each iteration, dynamic fields that cannot resolve due to incomplete 2333 // values are skipped. They will be retried on the next iteration until no 2334 // progress can be made. Note that a dynamic field may add more dynamic fields. 2335 // 2336 // forClauses are processed after all other clauses. A struct may be referenced 2337 // before it is complete, meaning that fields added by other forms of injection 2338 // may influence the result of a for clause _after_ it has already been 2339 // processed. We could instead detect such insertion and feed it to the 2340 // ForClause to generate another entry or have the for clause be recomputed. 2341 // This seems to be too complicated and lead to iffy edge cases. 2342 // TODO(errors): detect when a field is added to a struct that is already used 2343 // in a for clause. 2344 func (n *nodeContext) expandOne(state vertexStatus) (done bool) { 2345 unreachableForDev(n.ctx) 2346 2347 // Don't expand incomplete expressions if we detected a cycle. 2348 if n.done() || (n.hasAnyCyclicConjunct && !n.hasNonCycle) { 2349 return false 2350 } 2351 2352 var progress bool 2353 2354 if progress = n.injectDynamic(); progress { 2355 return true 2356 } 2357 2358 if progress = n.injectComprehensions(state); progress { 2359 return true 2360 } 2361 2362 // Do expressions after comprehensions, as comprehensions can never 2363 // refer to embedded scalars, whereas expressions may refer to generated 2364 // fields if we were to allow attributes to be defined alongside 2365 // scalars. 2366 exprs := n.exprs 2367 n.exprs = n.exprs[:0] 2368 for _, x := range exprs { 2369 n.addExprConjunct(x.c, state) 2370 2371 // collect and or 2372 } 2373 if len(n.exprs) < len(exprs) { 2374 return true 2375 } 2376 2377 // No progress, report error later if needed: unification with 2378 // disjuncts may resolve this later on. 2379 return false 2380 } 2381 2382 // injectDynamic evaluates and inserts dynamic declarations. 2383 func (n *nodeContext) injectDynamic() (progress bool) { 2384 unreachableForDev(n.ctx) 2385 2386 ctx := n.ctx 2387 k := 0 2388 2389 a := n.dynamicFields 2390 for _, d := range n.dynamicFields { 2391 var f Feature 2392 x := d.field.Key 2393 // Push state to capture and remove errors. 2394 s := ctx.PushState(d.env, x.Source()) 2395 v := ctx.evalState(x, oldOnly(finalized)) 2396 b := ctx.PopState(s) 2397 2398 if b != nil && b.IsIncomplete() { 2399 d.err, _ = v.(*Bottom) 2400 a[k] = d 2401 k++ 2402 continue 2403 } 2404 if b, _ := v.(*Bottom); b != nil { 2405 n.addValueConjunct(nil, b, d.id) 2406 continue 2407 } 2408 f = ctx.Label(d.field.Key, v) 2409 if f.IsInt() { 2410 n.addErr(ctx.NewPosf(pos(d.field.Key), "integer fields not supported")) 2411 } 2412 n.insertField(f, d.field.ArcType, MakeConjunct(d.env, d.field, d.id)) 2413 } 2414 2415 progress = k < len(n.dynamicFields) 2416 2417 n.dynamicFields = a[:k] 2418 2419 return progress 2420 } 2421 2422 // addLists evaluates the queued list conjuncts and inserts its arcs into the 2423 // Vertex. 2424 // 2425 // TODO: association arrays: 2426 // If an association array marker was present in a struct, create a struct node 2427 // instead of a list node. In either case, a node may only have list fields 2428 // or struct fields and not both. 2429 // 2430 // addLists should be run after the fixpoint expansion: 2431 // - it enforces that comprehensions may not refer to the list itself 2432 // - there may be no other fields within the list. 2433 // 2434 // TODO(embeddedScalars): for embedded scalars, there should be another pass 2435 // of evaluation expressions after expanding lists. 2436 func (n *nodeContext) addLists(state combinedFlags) (progress bool) { 2437 if len(n.lists) == 0 && len(n.vLists) == 0 { 2438 return false 2439 } 2440 2441 var oneOfTheLists Expr 2442 var anID CloseInfo 2443 2444 isOpen := true 2445 max := 0 2446 var maxNode Expr 2447 2448 if m, ok := n.node.BaseValue.(*ListMarker); ok { 2449 isOpen = m.IsOpen 2450 max = len(n.node.Arcs) 2451 } 2452 2453 c := n.ctx 2454 2455 for _, l := range n.vLists { 2456 // XXX: set hasNonCycle if appropriate. 2457 2458 oneOfTheLists = l 2459 2460 elems := l.Elems() 2461 isClosed := l.IsClosedList() 2462 2463 switch { 2464 case len(elems) < max: 2465 if isClosed { 2466 n.invalidListLength(len(elems), max, l, maxNode) 2467 continue 2468 } 2469 2470 case len(elems) > max: 2471 if !isOpen { 2472 n.invalidListLength(max, len(elems), maxNode, l) 2473 continue 2474 } 2475 isOpen = !isClosed 2476 max = len(elems) 2477 maxNode = l 2478 2479 case isClosed: 2480 isOpen = false 2481 maxNode = l 2482 } 2483 2484 for _, a := range elems { 2485 if a.Conjuncts == nil { 2486 n.insertField(a.Label, ArcMember, MakeRootConjunct(nil, a)) 2487 continue 2488 } 2489 for _, c := range a.Conjuncts { 2490 n.insertField(a.Label, ArcMember, c) 2491 } 2492 } 2493 } 2494 2495 outer: 2496 // updateCyclicStatus may grow the list of values, so we cannot use range. 2497 for i := 0; i < len(n.lists); i++ { 2498 l := n.lists[i] 2499 2500 n.updateCyclicStatus(l.id) 2501 2502 if l.self { 2503 n.node.LockArcs = true 2504 } 2505 2506 index := int64(0) 2507 hasComprehension := false 2508 for j, elem := range l.list.Elems { 2509 switch x := elem.(type) { 2510 case *Comprehension: 2511 err := c.yield(nil, l.env, x, state, func(e *Environment) { 2512 label, err := MakeLabel(x.Source(), index, IntLabel) 2513 n.addErr(err) 2514 index++ 2515 c := MakeConjunct(e, x.Value, l.id) 2516 n.insertField(label, ArcMember, c) 2517 }) 2518 hasComprehension = true 2519 if err != nil { 2520 if err.ForCycle && !l.self { 2521 // The list has a comprehension that refers to the list 2522 // itself. This means we should postpone evaluating this 2523 // list until all other lists have been evaluated. 2524 n.lists[i].ignore = true 2525 l.self = true 2526 n.lists = append(n.lists, l) 2527 } else { 2528 n.addBottom(err) 2529 } 2530 continue outer 2531 } 2532 2533 case *Ellipsis: 2534 if j != len(l.list.Elems)-1 { 2535 n.addErr(c.Newf("ellipsis must be last element in list")) 2536 } 2537 2538 n.lists[i].elipsis = x 2539 2540 default: 2541 label, err := MakeLabel(x.Source(), index, IntLabel) 2542 n.addErr(err) 2543 index++ // TODO: don't use insertField. 2544 n.insertField(label, ArcMember, MakeConjunct(l.env, x, l.id)) 2545 } 2546 2547 // Terminate early in case of runaway comprehension. 2548 if !isOpen && int(index) > max { 2549 n.invalidListLength(max, len(l.list.Elems), maxNode, l.list) 2550 continue outer 2551 } 2552 } 2553 2554 oneOfTheLists = l.list 2555 anID = l.id 2556 2557 switch closed := n.lists[i].elipsis == nil; { 2558 case int(index) < max: 2559 if closed { 2560 n.invalidListLength(int(index), max, l.list, maxNode) 2561 continue 2562 } 2563 2564 case int(index) > max, 2565 closed && isOpen, 2566 (!closed == isOpen) && !hasComprehension: 2567 max = int(index) 2568 maxNode = l.list 2569 isOpen = !closed 2570 } 2571 2572 n.lists[i].n = index 2573 } 2574 2575 // add additionalItem values to list and construct optionals. 2576 elems := n.node.Elems() 2577 for _, l := range n.vLists { 2578 if !l.IsClosedList() { 2579 continue 2580 } 2581 2582 newElems := l.Elems() 2583 if len(newElems) >= len(elems) { 2584 continue // error generated earlier, if applicable. 2585 } 2586 2587 for _, arc := range elems[len(newElems):] { 2588 l.MatchAndInsert(c, arc) 2589 } 2590 } 2591 2592 for _, l := range n.lists { 2593 if l.elipsis == nil || l.ignore { 2594 continue 2595 } 2596 2597 s := l.list.info 2598 if s == nil { 2599 s = &StructLit{Decls: []Decl{l.elipsis}} 2600 s.Init(n.ctx) 2601 l.list.info = s 2602 } 2603 info := n.node.AddStruct(s, l.env, l.id) 2604 2605 for _, arc := range elems[l.n:] { 2606 info.MatchAndInsert(c, arc) 2607 } 2608 } 2609 2610 sources := []ast.Expr{} 2611 // Add conjuncts for additional items. 2612 for _, l := range n.lists { 2613 if l.elipsis == nil || l.ignore { 2614 continue 2615 } 2616 if src, _ := l.elipsis.Source().(ast.Expr); src != nil { 2617 sources = append(sources, src) 2618 } 2619 } 2620 2621 if m, ok := n.node.BaseValue.(*ListMarker); !ok { 2622 n.node.setValue(c, partial, &ListMarker{ 2623 Src: ast.NewBinExpr(token.AND, sources...), 2624 IsOpen: isOpen, 2625 }) 2626 } else { 2627 if m.Src != nil { 2628 sources = append(sources, m.Src) 2629 } 2630 m.Src = ast.NewBinExpr(token.AND, sources...) 2631 m.IsOpen = m.IsOpen && isOpen 2632 } 2633 2634 n.lists = n.lists[:0] 2635 n.vLists = n.vLists[:0] 2636 2637 n.updateNodeType(ListKind, oneOfTheLists, anID) 2638 2639 return true 2640 } 2641 2642 func (n *nodeContext) invalidListLength(na, nb int, a, b Expr) { 2643 n.addErr(n.ctx.Newf("incompatible list lengths (%d and %d)", na, nb)) 2644 }