cuelang.org/go@v0.13.0/internal/core/adt/composite.go (about) 1 // 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 adt 16 17 import ( 18 "fmt" 19 "slices" 20 21 "cuelang.org/go/cue/ast" 22 "cuelang.org/go/cue/errors" 23 "cuelang.org/go/cue/token" 24 "cuelang.org/go/internal" 25 ) 26 27 // TODO: unanswered questions about structural cycles: 28 // 29 // 1. When detecting a structural cycle, should we consider this as: 30 // a) an unevaluated value, 31 // b) an incomplete error (which does not affect parent validity), or 32 // c) a special value. 33 // 34 // Making it an error is the simplest way to ensure reentrancy is disallowed: 35 // without an error it would require an additional mechanism to stop reentrancy 36 // from continuing to process. Even worse, in some cases it may only partially 37 // evaluate, resulting in unexpected results. For this reason, we are taking 38 // approach `b` for now. 39 // 40 // This has some consequences of how disjunctions are treated though. Consider 41 // 42 // list: { 43 // head: _ 44 // tail: list | null 45 // } 46 // 47 // When making it an error, evaluating the above will result in 48 // 49 // list: { 50 // head: _ 51 // tail: null 52 // } 53 // 54 // because list will result in a structural cycle, and thus an error, it will be 55 // stripped from the disjunction. This may or may not be a desirable property. A 56 // nice thing is that it is not required to write `list | *null`. A disadvantage 57 // is that this is perhaps somewhat inexplicit. 58 // 59 // When not making it an error (and simply cease evaluating child arcs upon 60 // cycle detection), the result would be: 61 // 62 // list: { 63 // head: _ 64 // tail: list | null 65 // } 66 // 67 // In other words, an evaluation would result in a cycle and thus an error. 68 // Implementations can recognize such cases by having unevaluated arcs. An 69 // explicit structure cycle marker would probably be less error prone. 70 // 71 // Note that in both cases, a reference to list will still use the original 72 // conjuncts, so the result will be the same for either method in this case. 73 // 74 // 75 // 2. Structural cycle allowance. 76 // 77 // Structural cycle detection disallows reentrancy as well. This means one 78 // cannot use structs for recursive computation. This will probably preclude 79 // evaluation of some configuration. Given that there is no real alternative 80 // yet, we could allow structural cycle detection to be optionally disabled. 81 82 // An Environment links the parent scopes for identifier lookup to a composite 83 // node. Each conjunct that make up node in the tree can be associated with 84 // a different environment (although some conjuncts may share an Environment). 85 type Environment struct { 86 Up *Environment 87 Vertex *Vertex 88 89 // DynamicLabel is only set when instantiating a field from a pattern 90 // constraint. It is used to resolve label references. 91 DynamicLabel Feature 92 93 // TODO(perf): make the following public fields a shareable struct as it 94 // mostly is going to be the same for child nodes. 95 96 // TODO: This can probably move into the nodeContext, making it a map from 97 // conjunct to Value. 98 cache map[cacheKey]Value 99 } 100 101 type cacheKey struct { 102 Expr Expr 103 Arc *Vertex 104 } 105 106 func (e *Environment) up(ctx *OpContext, count int32) *Environment { 107 for i := int32(0); i < count; i++ { 108 e = e.Up 109 ctx.Assertf(ctx.Pos(), e.Vertex != nil, "Environment.up encountered a nil vertex") 110 } 111 return e 112 } 113 114 type ID int32 115 116 // evalCached is used to look up dynamic field pattern constraint expressions. 117 func (e *Environment) evalCached(c *OpContext, x Expr) Value { 118 if v, ok := x.(Value); ok { 119 return v 120 } 121 key := cacheKey{x, nil} 122 v, ok := e.cache[key] 123 if !ok { 124 if e.cache == nil { 125 e.cache = map[cacheKey]Value{} 126 } 127 env, src := c.e, c.src 128 c.e, c.src = e, x.Source() 129 // Save and restore errors to ensure that only relevant errors are 130 // associated with the cash. 131 err := c.errs 132 v = c.evalState(x, require(partial, allKnown)) // TODO: should this be finalized? 133 c.e, c.src = env, src 134 c.errs = err 135 if b, ok := v.(*Bottom); !ok || !b.IsIncomplete() { 136 e.cache[key] = v 137 } 138 } 139 return v 140 } 141 142 // A Vertex is a node in the value tree. It may be a leaf or internal node. 143 // It may have arcs to represent elements of a fully evaluated struct or list. 144 // 145 // For structs, it only contains definitions and concrete fields. 146 // optional fields are dropped. 147 // 148 // It maintains source information such as a list of conjuncts that contributed 149 // to the value. 150 type Vertex struct { 151 // Parent links to a parent Vertex. This parent should only be used to 152 // access the parent's Label field to find the relative location within a 153 // tree. 154 Parent *Vertex 155 156 // State: 157 // eval: nil, BaseValue: nil -- unevaluated 158 // eval: *, BaseValue: nil -- evaluating 159 // eval: *, BaseValue: * -- finalized 160 // 161 state *nodeContext 162 // TODO: move to nodeContext. 163 overlay *Vertex 164 165 // Label is the feature leading to this vertex. 166 Label Feature 167 168 // TODO: move the following fields to nodeContext. 169 170 // status indicates the evaluation progress of this vertex. 171 status vertexStatus 172 173 // hasAllConjuncts indicates that the set of conjuncts is complete. 174 // This is the case if the conjuncts of all its ancestors have been 175 // processed. 176 hasAllConjuncts bool 177 178 // isData indicates that this Vertex is to be interpreted as data: pattern 179 // and additional constraints, as well as optional fields, should be 180 // ignored. 181 isData bool 182 183 // ClosedRecursive indicates whether this Vertex is recursively closed. 184 // This is the case, for instance, if it is a node in a definition or if one 185 // of the conjuncts, or ancestor conjuncts, is a definition. 186 ClosedRecursive bool 187 188 // ClosedNonRecursive indicates that this Vertex has been closed for this 189 // level only. This supports the close builtin. 190 ClosedNonRecursive bool 191 192 // HasEllipsis indicates that this Vertex is open by means of an ellipsis. 193 // TODO: combine this field with Closed once we removed the old evaluator. 194 HasEllipsis bool 195 196 // MultiLet indicates whether multiple let fields were added from 197 // different sources. If true, a LetReference must be resolved using 198 // the per-Environment value cache. 199 MultiLet bool 200 201 // After this is set, no more arcs may be added during evaluation. This is 202 // set, for instance, after a Vertex is used as a source for comprehensions, 203 // or any other operation that relies on the set of arcs being constant. 204 LockArcs bool 205 206 // IsDynamic signifies whether this struct is computed as part of an 207 // expression and not part of the static evaluation tree. 208 // Used for cycle detection. 209 IsDynamic bool 210 211 // IsPatternConstraint indicates that this Vertex is an entry in 212 // Vertex.PatternConstraints. 213 IsPatternConstraint bool 214 215 // nonRooted indicates that this Vertex originates within the context of 216 // a dynamic, or inlined, Vertex (e.g. `{out: ...}.out``). Note that, 217 // through reappropriation, this Vertex may become rooted down the line. 218 // Use the !IsDetached method to determine whether this Vertex became 219 // rooted. 220 nonRooted bool // indicates that there is no path from the root of the tree. 221 222 // anonymous indicates that this Vertex is being computed without an 223 // addressable context, or in other words, a context for which there is 224 // np path from the root of the file. Typically, the only addressable 225 // contexts are fields. Examples of fields that are not addressable are 226 // the for source of comprehensions and let fields or let clauses. 227 anonymous bool 228 229 // hasPendingArc is set if this Vertex has a void arc (e.g. for comprehensions) 230 hasPendingArc bool 231 232 // IsDisjunct indicates this Vertex is a disjunct resulting from a 233 // disjunction evaluation. 234 IsDisjunct bool 235 236 // IsShared is true if BaseValue holds a Vertex of a node of another path. 237 // If a node is shared, the user should be careful with traversal. 238 // The debug printer, for instance, takes extra care not to print in a loop. 239 IsShared bool 240 241 // IsCyclic is true if a node is cyclic, for instance if its value is 242 // a cyclic reference to a shared node or if the value is a conjunction 243 // of which at least one value is cyclic (not yet supported). 244 IsCyclic bool 245 246 // ArcType indicates the level of optionality of this arc. 247 ArcType ArcType 248 249 // cyclicReferences is a linked list of internal references pointing to this 250 // Vertex. This is used to shorten the path of some structural cycles. 251 cyclicReferences *RefNode 252 253 // BaseValue is the value associated with this vertex. For lists and structs 254 // this is a sentinel value indicating its kind. 255 BaseValue BaseValue 256 257 // ChildErrors is the collection of all errors of children. 258 ChildErrors *Bottom 259 260 // The parent of nodes can be followed to determine the path within the 261 // configuration of this node. 262 // Value Value 263 Arcs []*Vertex // arcs are sorted in display order. 264 265 // PatternConstraints are additional constraints that match more nodes. 266 // Constraints that match existing Arcs already have their conjuncts 267 // mixed in. 268 // TODO: either put in StructMarker/ListMarker or integrate with Arcs 269 // so that this pointer is unnecessary. 270 PatternConstraints *Constraints 271 272 // Conjuncts lists the structs that ultimately formed this Composite value. 273 // This includes all selected disjuncts. 274 // 275 // This value may be nil, in which case the Arcs are considered to define 276 // the final value of this Vertex. 277 // 278 // TODO: all access to Conjuncts should go through functions like 279 // VisitLeafConjuncts and VisitAllConjuncts. We should probably make this 280 // an unexported field. 281 Conjuncts ConjunctGroup 282 283 // Structs is a slice of struct literals that contributed to this value. 284 // This information is used to compute the topological sort of arcs. 285 Structs []*StructInfo 286 } 287 288 func deref(v *Vertex) *Vertex { 289 v = v.DerefValue() 290 n := v.state 291 if n != nil { 292 v = n.underlying 293 } 294 if v == nil { 295 panic("unexpected nil underlying with non-nil state") 296 } 297 return v 298 } 299 300 func equalDeref(a, b *Vertex) bool { 301 return deref(a) == deref(b) 302 } 303 304 // newInlineVertex creates a Vertex that is needed for computation, but for 305 // which there is no CUE path defined from the root Vertex. 306 func (ctx *OpContext) newInlineVertex(parent *Vertex, v BaseValue, a ...Conjunct) *Vertex { 307 n := &Vertex{ 308 BaseValue: v, 309 IsDynamic: true, 310 ArcType: ArcMember, 311 Conjuncts: a, 312 } 313 if !ctx.isDevVersion() { 314 n.Parent = parent 315 } 316 if ctx.inDetached > 0 { 317 n.anonymous = true 318 } 319 return n 320 321 } 322 323 // updateArcType updates v.ArcType if t is more restrictive. 324 func (v *Vertex) updateArcType(t ArcType) { 325 if t >= v.ArcType { 326 return 327 } 328 if v.ArcType == ArcNotPresent { 329 return 330 } 331 s := v.state 332 // NOTE: this condition does not occur in V2. 333 if s != nil && v.isFinal() { 334 c := s.ctx 335 if s.scheduler.frozen.meets(arcTypeKnown) { 336 p := token.NoPos 337 if src := c.Source(); src != nil { 338 p = src.Pos() 339 } 340 parent := v.Parent 341 parent.reportFieldCycleError(c, p, v.Label) 342 return 343 } 344 } 345 if v.Parent != nil && v.Parent.ArcType == ArcPending && v.Parent.state != nil && v.Parent.state.ctx.isDevVersion() { 346 // TODO: check that state is always non-nil. 347 v.Parent.state.unshare() 348 } 349 v.ArcType = t 350 } 351 352 // isDefined indicates whether this arc is a "value" field, and not a constraint 353 // or void arc. 354 func (v *Vertex) isDefined() bool { 355 return v.ArcType == ArcMember 356 } 357 358 // IsConstraint reports whether the Vertex is an optional or required field. 359 func (v *Vertex) IsConstraint() bool { 360 return v.ArcType == ArcOptional || v.ArcType == ArcRequired 361 } 362 363 // IsDefined indicates whether this arc is defined meaning it is not a 364 // required or optional constraint and not a "void" arc. 365 // It will evaluate the arc, and thus evaluate any comprehension, to make this 366 // determination. 367 func (v *Vertex) IsDefined(c *OpContext) bool { 368 if v.isDefined() { 369 return true 370 } 371 v.Finalize(c) 372 return v.isDefined() 373 } 374 375 // Rooted reports if it is known there is a path from the root of the tree to 376 // this Vertex. If this returns false, it may still be rooted if the node 377 // originated from an inline struct, but was later reappropriated. 378 func (v *Vertex) Rooted() bool { 379 return !v.nonRooted && !v.Label.IsLet() && !v.IsDynamic 380 } 381 382 // Internal is like !Rooted, but also counts internal let nodes as internal. 383 func (v *Vertex) Internal() bool { 384 return v.nonRooted || v.anonymous || v.IsDynamic 385 } 386 387 // IsDetached reports whether this Vertex does not have a path from the root. 388 func (v *Vertex) IsDetached() bool { 389 // v might have resulted from an inline struct that was subsequently shared. 390 // In this case, it is still rooted. 391 for v != nil { 392 if v.Rooted() { 393 return false 394 } 395 // Already take into account the provisionally assigned parent. 396 if v.state != nil && v.state.parent != nil { 397 v = v.state.parent 398 } else { 399 v = v.Parent 400 } 401 } 402 403 return true 404 } 405 406 // MayAttach reports whether this Vertex may attach to another arc. 407 // The behavior is undefined if IsDetached is true. 408 func (v *Vertex) MayAttach() bool { 409 return !v.Label.IsLet() && !v.anonymous 410 } 411 412 type ArcType uint8 413 414 const ( 415 // ArcMember means that this arc is a normal non-optional field 416 // (including regular, hidden, and definition fields). 417 ArcMember ArcType = iota 418 419 // ArcRequired is like optional, but requires that a field be specified. 420 // Fields are of the form foo!. 421 ArcRequired 422 423 // ArcOptional represents fields of the form foo? and defines constraints 424 // for foo in case it is defined. 425 ArcOptional 426 427 // ArcPending means that it is not known yet whether an arc exists and that 428 // its conjuncts need to be processed to find out. This happens when an arc 429 // is provisionally added as part of a comprehension, but when this 430 // comprehension has not yet yielded any results. 431 // 432 // TODO: make this a separate state so that we can track which arcs still 433 // have unresolved comprehensions. 434 ArcPending 435 436 // ArcNotPresent indicates that this arc is not present and, unlike 437 // ArcPending, needs no further processing. 438 ArcNotPresent 439 440 // TODO: define a type for optional arcs. This will be needed for pulling 441 // in optional fields into the Vertex, which, in turn, is needed for 442 // structure sharing, among other things. 443 // We could also define types for required fields and potentially lets. 444 ) 445 446 func (a ArcType) String() string { 447 switch a { 448 case ArcMember: 449 return "Member" 450 case ArcOptional: 451 return "Optional" 452 case ArcRequired: 453 return "Required" 454 case ArcPending: 455 return "Pending" 456 case ArcNotPresent: 457 return "NotPresent" 458 } 459 return fmt.Sprintf("ArcType(%d)", a) 460 } 461 462 // definitelyExists reports whether an arc is a constraint or member arc. 463 // TODO: we should check that users of this call ensure there are no 464 // ArcPendings. 465 func (v *Vertex) definitelyExists() bool { 466 return v.ArcType < ArcPending 467 } 468 469 // ConstraintFromToken converts a given AST constraint token to the 470 // corresponding ArcType. 471 func ConstraintFromToken(t token.Token) ArcType { 472 switch t { 473 case token.OPTION: 474 return ArcOptional 475 case token.NOT: 476 return ArcRequired 477 } 478 return ArcMember 479 } 480 481 // Token reports the token corresponding to the constraint represented by a, 482 // or token.ILLEGAL otherwise. 483 func (a ArcType) Token() (t token.Token) { 484 switch a { 485 case ArcOptional: 486 t = token.OPTION 487 case ArcRequired: 488 t = token.NOT 489 } 490 return t 491 } 492 493 // Suffix reports the field suffix for the given ArcType if it is a 494 // constraint or the empty string otherwise. 495 func (a ArcType) Suffix() string { 496 switch a { 497 case ArcOptional: 498 return "?" 499 case ArcRequired: 500 return "!" 501 502 // For debugging internal state. This is not CUE syntax. 503 case ArcPending: 504 return "*" 505 case ArcNotPresent: 506 return "-" 507 } 508 return "" 509 } 510 511 func (v *Vertex) Clone() *Vertex { 512 c := *v 513 c.state = nil 514 return &c 515 } 516 517 type StructInfo struct { 518 *StructLit 519 520 Env *Environment 521 522 CloseInfo 523 524 // Embed indicates the struct in which this struct is embedded (originally), 525 // or nil if this is a root structure. 526 // Embed *StructInfo 527 // Context *RefInfo // the location from which this struct originates. 528 Disable bool 529 530 Embedding bool 531 } 532 533 // TODO(perf): this could be much more aggressive for eliminating structs that 534 // are immaterial for closing. 535 func (s *StructInfo) useForAccept() bool { 536 if c := s.closeInfo; c != nil { 537 return !c.noCheck 538 } 539 return true 540 } 541 542 // vertexStatus indicates the evaluation progress of a Vertex. 543 type vertexStatus int8 544 545 //go:generate go run golang.org/x/tools/cmd/stringer -type=vertexStatus 546 547 const ( 548 // unprocessed indicates a Vertex has not been processed before. 549 // Value must be nil. 550 unprocessed vertexStatus = iota 551 552 // evaluating means that the current Vertex is being evaluated. If this is 553 // encountered it indicates a reference cycle. Value must be nil. 554 evaluating 555 556 // partial indicates that the result was only partially evaluated. It will 557 // need to be fully evaluated to get a complete results. 558 // 559 // TODO: this currently requires a renewed computation. Cache the 560 // nodeContext to allow reusing the computations done so far. 561 partial 562 563 // conjuncts is the state reached when all conjuncts have been evaluated, 564 // but without recursively processing arcs. 565 conjuncts 566 567 // evaluatingArcs indicates that the arcs of the Vertex are currently being 568 // evaluated. If this is encountered it indicates a structural cycle. 569 // Value does not have to be nil 570 evaluatingArcs 571 572 // TODO: introduce a "frozen" state. Right now a node may marked and used 573 // as finalized, before all tasks have completed. We should introduce a 574 // frozen state that simply checks that all remaining tasks are idempotent 575 // and errors if they are not. 576 577 // finalized means that this node is fully evaluated and that the results 578 // are save to use without further consideration. 579 finalized 580 ) 581 582 // Wrap creates a Vertex that takes w as a shared value. This allows users 583 // to set different flags for a wrapped Vertex. 584 func (c *OpContext) Wrap(v *Vertex, id CloseInfo) *Vertex { 585 w := c.newInlineVertex(nil, nil, v.Conjuncts...) 586 n := w.getState(c) 587 n.share(makeAnonymousConjunct(nil, v, nil), v, id) 588 return w 589 } 590 591 // Status returns the status of the current node. When reading the status, one 592 // should always use this method over directly reading status field. 593 // 594 // NOTE: this only matters for EvalV3 and beyonds, so a lot of the old code 595 // might still access it directly. 596 func (v *Vertex) Status() vertexStatus { 597 v = v.DerefValue() 598 return v.status 599 } 600 601 // ForceDone prevents v from being evaluated. 602 func (v *Vertex) ForceDone() { 603 v.updateStatus(finalized) 604 } 605 606 // IsUnprocessed reports whether v is unprocessed. 607 func (v *Vertex) IsUnprocessed() bool { 608 return v.Status() == unprocessed 609 } 610 611 func (v *Vertex) updateStatus(s vertexStatus) { 612 if !isCyclePlaceholder(v.BaseValue) { 613 if !v.IsErr() && v.state != nil { 614 Assertf(v.state.ctx, v.Status() <= s+1, "attempt to regress status from %d to %d", v.Status(), s) 615 } 616 } 617 618 if s == finalized && v.BaseValue == nil { 619 // TODO: for debugging. 620 // panic("not finalized") 621 } 622 v.status = s 623 } 624 625 // setParentDone signals v that the conjuncts of all ancestors have been 626 // processed. 627 // If all conjuncts of this node have been set, all arcs will be notified 628 // of this parent being done. 629 // 630 // Note: once a vertex has started evaluation (state != nil), insertField will 631 // cause all conjuncts to be immediately processed. This means that if all 632 // ancestors of this node processed their conjuncts, and if this node has 633 // processed all its conjuncts as well, all nodes that it embedded will have 634 // received all their conjuncts as well, after which this node will have been 635 // notified of these conjuncts. 636 func (v *Vertex) setParentDone() { 637 v.hasAllConjuncts = true 638 // Could set "Conjuncts" flag of arc at this point. 639 if n := v.state; n != nil && len(n.conjuncts) == n.conjunctsPos { 640 for _, a := range v.Arcs { 641 a.setParentDone() 642 } 643 } 644 } 645 646 // VisitLeafConjuncts visits all conjuncts that are leafs of the ConjunctGroup tree. 647 func (v *Vertex) VisitLeafConjuncts(f func(Conjunct) bool) { 648 VisitConjuncts(v.Conjuncts, f) 649 } 650 651 func VisitConjuncts(a []Conjunct, f func(Conjunct) bool) bool { 652 for _, c := range a { 653 switch x := c.x.(type) { 654 case *ConjunctGroup: 655 if !VisitConjuncts(*x, f) { 656 return false 657 } 658 default: 659 if !f(c) { 660 return false 661 } 662 } 663 } 664 return true 665 } 666 667 // VisitAllConjuncts visits all conjuncts of v, including ConjunctGroups. 668 // Note that ConjunctGroups do not have an Environment associated with them. 669 func (v *Vertex) VisitAllConjuncts(f func(c Conjunct, isLeaf bool)) { 670 visitAllConjuncts(v.Conjuncts, f) 671 } 672 673 func visitAllConjuncts(a []Conjunct, f func(c Conjunct, isLeaf bool)) { 674 for _, c := range a { 675 switch x := c.x.(type) { 676 case *ConjunctGroup: 677 f(c, false) 678 visitAllConjuncts(*x, f) 679 default: 680 f(c, true) 681 } 682 } 683 } 684 685 // HasConjuncts reports whether v has any conjuncts. 686 func (v *Vertex) HasConjuncts() bool { 687 return len(v.Conjuncts) > 0 688 } 689 690 // SingleConjunct reports whether there is a single leaf conjunct and returns 1 691 // if so. It will return 0 if there are no conjuncts or 2 if there are more than 692 // 1. 693 // 694 // This is an often-used operation. 695 func (v *Vertex) SingleConjunct() (c Conjunct, count int) { 696 if v == nil { 697 return c, 0 698 } 699 v.VisitLeafConjuncts(func(x Conjunct) bool { 700 c = x 701 if count++; count > 1 { 702 return false 703 } 704 return true 705 }) 706 707 return c, count 708 } 709 710 // ConjunctAt assumes a Vertex represents a top-level Vertex, such as one 711 // representing a file or a let expressions, where all conjuncts appear at the 712 // top level. It may panic if this condition is not met. 713 func (v *Vertex) ConjunctAt(i int) Conjunct { 714 return v.Conjuncts[i] 715 } 716 717 // Value returns the Value of v without definitions if it is a scalar 718 // or itself otherwise. 719 func (v *Vertex) Value() Value { 720 switch x := v.BaseValue.(type) { 721 case nil: 722 return nil 723 case *StructMarker, *ListMarker: 724 return v 725 case Value: 726 // TODO: recursively descend into Vertex? 727 return x 728 default: 729 panic(fmt.Sprintf("unexpected type %T", v.BaseValue)) 730 } 731 } 732 733 // isUndefined reports whether a vertex does not have a useable BaseValue yet. 734 func (v *Vertex) isUndefined() bool { 735 if !v.isDefined() { 736 return true 737 } 738 switch v.BaseValue { 739 case nil, cycle: 740 return true 741 } 742 return false 743 } 744 745 // isFinal reports whether this node may no longer be modified. 746 func (v *Vertex) isFinal() bool { 747 // TODO(deref): the accounting of what is final should be recorded 748 // in the original node. Remove this dereference once the old 749 // evaluator has been removed. 750 return v.Status() == finalized 751 } 752 753 func (x *Vertex) IsConcrete() bool { 754 return x.Concreteness() <= Concrete 755 } 756 757 // IsData reports whether v should be interpreted in data mode. In other words, 758 // it tells whether optional field matching and non-regular fields, like 759 // definitions and hidden fields, should be ignored. 760 func (v *Vertex) IsData() bool { 761 return v.isData || !v.HasConjuncts() 762 } 763 764 // ToDataSingle creates a new Vertex that represents just the regular fields 765 // of this vertex. Arcs are left untouched. 766 // It is used by cue.Eval to convert nodes to data on per-node basis. 767 func (v *Vertex) ToDataSingle() *Vertex { 768 v = v.DerefValue() 769 w := *v 770 w.isData = true 771 w.state = nil 772 w.status = finalized 773 return &w 774 } 775 776 // ToDataAll returns a new v where v and all its descendents contain only 777 // the regular fields. 778 func (v *Vertex) ToDataAll(ctx *OpContext) *Vertex { 779 v.Finalize(ctx) 780 781 arcs := make([]*Vertex, 0, len(v.Arcs)) 782 for _, a := range v.Arcs { 783 if !a.IsDefined(ctx) { 784 continue 785 } 786 if a.Label.IsRegular() { 787 arcs = append(arcs, a.ToDataAll(ctx)) 788 } 789 } 790 w := *v 791 w.state = nil 792 w.status = finalized 793 794 w.BaseValue = toDataAll(ctx, w.BaseValue) 795 w.Arcs = arcs 796 w.isData = true 797 w.Conjuncts = slices.Clone(v.Conjuncts) 798 799 // Converting to dat drops constraints and non-regular fields. This means 800 // that the domain on which they are defined is reduced, which will change 801 // closedness properties. We therefore remove closedness. Note that data, 802 // in general and JSON specifically, is not closed. 803 w.ClosedRecursive = false 804 w.ClosedNonRecursive = false 805 806 // TODO(perf): this is not strictly necessary for evaluation, but it can 807 // hurt performance greatly. Drawback is that it may disable ordering. 808 for _, s := range w.Structs { 809 s.Disable = true 810 } 811 for i, c := range w.Conjuncts { 812 if v, _ := c.x.(Value); v != nil { 813 w.Conjuncts[i].x = toDataAll(ctx, v).(Value) 814 } 815 } 816 return &w 817 } 818 819 func toDataAll(ctx *OpContext, v BaseValue) BaseValue { 820 switch x := v.(type) { 821 default: 822 return x 823 824 case *Vertex: 825 return x.ToDataAll(ctx) 826 827 case *Disjunction: 828 d := *x 829 values := x.Values 830 // Data mode involves taking default values and if there is an 831 // unambiguous default value, we should convert that to data as well. 832 switch x.NumDefaults { 833 case 0: 834 case 1: 835 return toDataAll(ctx, values[0]) 836 default: 837 values = values[:x.NumDefaults] 838 } 839 d.Values = make([]Value, len(values)) 840 for i, v := range values { 841 switch x := v.(type) { 842 case *Vertex: 843 d.Values[i] = x.ToDataAll(ctx) 844 default: 845 d.Values[i] = x 846 } 847 } 848 return &d 849 850 case *Conjunction: 851 c := *x 852 c.Values = make([]Value, len(x.Values)) 853 for i, v := range x.Values { 854 // This case is okay because the source is of type Value. 855 c.Values[i] = toDataAll(ctx, v).(Value) 856 } 857 return &c 858 } 859 } 860 861 // IsFinal reports whether value v can still become more specific, when only 862 // considering regular fields. 863 // 864 // TODO: move this functionality as a method on cue.Value. 865 func IsFinal(v Value) bool { 866 return isFinal(v, false) 867 } 868 869 func isFinal(v Value, isClosed bool) bool { 870 switch x := v.(type) { 871 case *Vertex: 872 closed := isClosed || x.ClosedNonRecursive || x.ClosedRecursive 873 874 // TODO(evalv3): this is for V2 compatibility. Remove once V2 is gone. 875 closed = closed || x.IsClosedList() || x.IsClosedStruct() 876 877 // This also dereferences the value. 878 if v, ok := x.BaseValue.(Value); ok { 879 return isFinal(v, closed) 880 } 881 882 // If it is not closed, it can still become more specific. 883 if !closed { 884 return false 885 } 886 887 for _, a := range x.Arcs { 888 if !a.Label.IsRegular() { 889 continue 890 } 891 if a.ArcType > ArcMember && !a.IsErr() { 892 return false 893 } 894 if !isFinal(a, false) { 895 return false 896 } 897 } 898 return true 899 900 case *Bottom: 901 // Incomplete errors could be resolved by making a struct more specific. 902 return x.Code <= StructuralCycleError 903 904 default: 905 return v.Concreteness() <= Concrete 906 } 907 } 908 909 // func (v *Vertex) IsEvaluating() bool { 910 // return v.Value == cycle 911 // } 912 913 // IsErr is a convenience function to check whether a Vertex represents an 914 // error currently. It does not finalize the value, so it is possible that 915 // v may become erroneous after this call. 916 func (v *Vertex) IsErr() bool { 917 // if v.Status() > Evaluating { 918 return v.Bottom() != nil 919 } 920 921 // Err finalizes v, if it isn't yet, and returns an error if v evaluates to an 922 // error or nil otherwise. 923 func (v *Vertex) Err(c *OpContext) *Bottom { 924 v.Finalize(c) 925 return v.Bottom() 926 } 927 928 // Bottom reports whether v is currently erroneous It does not finalize the 929 // value, so it is possible that v may become erroneous after this call. 930 func (v *Vertex) Bottom() *Bottom { 931 // TODO: should we consider errors recorded in the state? 932 v = v.DerefValue() 933 if b, ok := v.BaseValue.(*Bottom); ok { 934 return b 935 } 936 return nil 937 } 938 939 // func (v *Vertex) Evaluate() 940 941 // Unify unifies two values and returns the result. 942 // 943 // TODO: introduce: Open() wrapper that indicates closedness should be ignored. 944 // 945 // Change Value to Node to allow any kind of type to be passed. 946 func Unify(c *OpContext, a, b Value) *Vertex { 947 v := &Vertex{} 948 949 // We set the parent of the context to be able to detect structural cycles 950 // early enough to error on schemas used for validation. 951 if n := c.vertex; n != nil { 952 v.Parent = n.Parent 953 if c.isDevVersion() { 954 v.Label = n.Label // this doesn't work in V2 955 } 956 } 957 958 addConjuncts(c, v, a) 959 addConjuncts(c, v, b) 960 961 if c.isDevVersion() { 962 s := v.getState(c) 963 // As this is a new node, we should drop all the requirements from 964 // parent nodes, as these will not be aligned with the reinsertion 965 // of the conjuncts. 966 s.dropParentRequirements = true 967 if p := c.vertex; p != nil && p.state != nil && s != nil { 968 s.hasNonCyclic = p.state.hasNonCyclic 969 } 970 } 971 972 v.Finalize(c) 973 974 if c.vertex != nil { 975 v.Label = c.vertex.Label 976 } 977 978 return v 979 } 980 981 func addConjuncts(ctx *OpContext, dst *Vertex, src Value) { 982 closeInfo := ctx.CloseInfo() 983 closeInfo.FromDef = false 984 c := MakeConjunct(nil, src, closeInfo) 985 986 if v, ok := src.(*Vertex); ok { 987 if ctx.Version == internal.EvalV2 { 988 if v.ClosedRecursive { 989 var root CloseInfo 990 c.CloseInfo = root.SpawnRef(v, v.ClosedRecursive, nil) 991 } 992 } else { 993 // By default, all conjuncts in a node are considered to be not 994 // mutually closed. This means that if one of the arguments to Unify 995 // closes, but is acquired to embedding, the closeness information 996 // is disregarded. For instance, for Unify(a, b) where a and b are 997 // 998 // a: {#D, #D: d: f: int} 999 // b: {d: e: 1} 1000 // 1001 // we expect 'e' to be not allowed. 1002 // 1003 // In order to do so, we wrap the outer conjunct in a separate 1004 // scope that will be closed in the presence of closed embeddings 1005 // independently from the other conjuncts. 1006 n := dst.getBareState(ctx) 1007 c.CloseInfo = n.splitScope(c.CloseInfo) 1008 1009 // Even if a node is marked as ClosedRecursive, it may be that this 1010 // is the first node that references a definition. 1011 // We approximate this to see if the path leading up to this 1012 // value is a defintion. This is not fully accurate. We could 1013 // investigate the closedness information contained in the parent. 1014 for p := v; p != nil; p = p.Parent { 1015 if p.Label.IsDef() { 1016 c.CloseInfo.TopDef = true 1017 break 1018 } 1019 } 1020 } 1021 } 1022 1023 dst.AddConjunct(c) 1024 } 1025 1026 func (v *Vertex) Finalize(c *OpContext) { 1027 // Saving and restoring the error context prevents v from panicking in 1028 // case the caller did not handle existing errors in the context. 1029 err := c.errs 1030 c.errs = nil 1031 c.unify(v, final(finalized, allKnown)) 1032 c.errs = err 1033 } 1034 1035 // CompleteArcs ensures the set of arcs has been computed. 1036 func (v *Vertex) CompleteArcs(c *OpContext) { 1037 c.unify(v, final(conjuncts, allKnown)) 1038 } 1039 1040 func (v *Vertex) CompleteArcsOnly(c *OpContext) { 1041 c.unify(v, final(conjuncts, fieldSetKnown)) 1042 } 1043 1044 func (v *Vertex) AddErr(ctx *OpContext, b *Bottom) { 1045 v.SetValue(ctx, CombineErrors(nil, v.Value(), b)) 1046 } 1047 1048 // SetValue sets the value of a node. 1049 func (v *Vertex) SetValue(ctx *OpContext, value BaseValue) *Bottom { 1050 return v.setValue(ctx, finalized, value) 1051 } 1052 1053 func (v *Vertex) setValue(ctx *OpContext, state vertexStatus, value BaseValue) *Bottom { 1054 v.BaseValue = value 1055 // TODO: should not set status here for new evaluator. 1056 v.updateStatus(state) 1057 return nil 1058 } 1059 1060 func (n *nodeContext) setBaseValue(value BaseValue) { 1061 n.node.BaseValue = value 1062 } 1063 1064 // swapBaseValue swaps the BaseValue of a node with the given value and returns 1065 // the previous value. 1066 func (n *nodeContext) swapBaseValue(value BaseValue) (saved BaseValue) { 1067 saved = n.node.BaseValue 1068 n.setBaseValue(value) 1069 return saved 1070 } 1071 1072 // ToVertex wraps v in a new Vertex, if necessary. 1073 func ToVertex(v Value) *Vertex { 1074 switch x := v.(type) { 1075 case *Vertex: 1076 return x 1077 default: 1078 n := &Vertex{ 1079 status: finalized, 1080 BaseValue: x, 1081 } 1082 n.AddConjunct(MakeRootConjunct(nil, v)) 1083 return n 1084 } 1085 } 1086 1087 // Unwrap returns the possibly non-concrete scalar value of v, v itself for 1088 // lists and structs, or nil if v is an undefined type. 1089 func Unwrap(v Value) Value { 1090 x, ok := v.(*Vertex) 1091 if !ok { 1092 return v 1093 } 1094 // TODO(deref): BaseValue is currently overloaded to track cycles as well 1095 // as the actual or dereferenced value. Once the old evaluator can be 1096 // removed, we should use the new cycle tracking mechanism for cycle 1097 // detection and keep BaseValue clean. 1098 x = x.DerefValue() 1099 if n := x.state; n != nil && isCyclePlaceholder(x.BaseValue) { 1100 if n.errs != nil && !n.errs.IsIncomplete() { 1101 return n.errs 1102 } 1103 if n.scalar != nil { 1104 return n.scalar 1105 } 1106 } 1107 return x.Value() 1108 } 1109 1110 // OptionalType is a bit field of the type of optional constraints in use by an 1111 // Acceptor. 1112 type OptionalType int8 1113 1114 const ( 1115 HasField OptionalType = 1 << iota // X: T 1116 HasDynamic // (X): T or "\(X)": T 1117 HasPattern // [X]: T 1118 HasComplexPattern // anything but a basic type 1119 HasAdditional // ...T 1120 IsOpen // Defined for all fields 1121 ) 1122 1123 func (v *Vertex) Kind() Kind { 1124 // This is possible when evaluating comprehensions. It is potentially 1125 // not known at this time what the type is. 1126 switch { 1127 case v.state != nil && v.state.kind == BottomKind: 1128 return BottomKind 1129 case v.BaseValue != nil && !isCyclePlaceholder(v.BaseValue): 1130 return v.BaseValue.Kind() 1131 case v.state != nil: 1132 return v.state.kind 1133 default: 1134 return TopKind 1135 } 1136 } 1137 1138 func (v *Vertex) OptionalTypes() OptionalType { 1139 var mask OptionalType 1140 for _, s := range v.Structs { 1141 mask |= s.OptionalTypes() 1142 } 1143 return mask 1144 } 1145 1146 // IsOptional reports whether a field is explicitly defined as optional, 1147 // as opposed to whether it is allowed by a pattern constraint. 1148 func (v *Vertex) IsOptional(label Feature) bool { 1149 for _, a := range v.Arcs { 1150 if a.Label == label { 1151 return a.IsConstraint() 1152 } 1153 } 1154 return false 1155 } 1156 1157 func (v *Vertex) accepts(ok, required bool) bool { 1158 return ok || (!required && !v.ClosedRecursive) 1159 } 1160 1161 func (v *Vertex) IsClosedStruct() bool { 1162 // TODO: uncomment this. This fixes a bunch of closedness bugs 1163 // in the old and new evaluator. For compability sake, though, we 1164 // keep it as is for now. 1165 // if v.Closed { 1166 // return true 1167 // } 1168 // if v.HasEllipsis { 1169 // return false 1170 // } 1171 switch x := v.BaseValue.(type) { 1172 default: 1173 return false 1174 1175 case *Vertex: 1176 return v.ClosedRecursive && !v.HasEllipsis 1177 1178 case *StructMarker: 1179 if x.NeedClose { 1180 return true 1181 } 1182 1183 case *Disjunction: 1184 } 1185 return isClosed(v) 1186 } 1187 1188 func (v *Vertex) IsClosedList() bool { 1189 if x, ok := v.BaseValue.(*ListMarker); ok { 1190 return !x.IsOpen 1191 } 1192 return false 1193 } 1194 1195 // TODO: return error instead of boolean? (or at least have version that does.) 1196 func (v *Vertex) Accept(ctx *OpContext, f Feature) bool { 1197 // TODO(#543): remove this check. 1198 if f.IsDef() { 1199 return true 1200 } 1201 1202 if f.IsHidden() || f.IsLet() { 1203 return true 1204 } 1205 1206 // TODO(deref): right now a dereferenced value holds all the necessary 1207 // closedness information. In the future we may want to allow sharing nodes 1208 // with different closedness information. In that case, we should reconsider 1209 // the use of this dereference. Consider, for instance: 1210 // 1211 // #a: b // this node is currently not shared, but could be. 1212 // b: {c: 1} 1213 v = v.DerefValue() 1214 if x, ok := v.BaseValue.(*Disjunction); ok { 1215 for _, v := range x.Values { 1216 if x, ok := v.(*Vertex); ok && x.Accept(ctx, f) { 1217 return true 1218 } 1219 } 1220 return false 1221 } 1222 1223 if f.IsInt() { 1224 switch v.BaseValue.(type) { 1225 case *ListMarker: 1226 // TODO(perf): use precomputed length. 1227 if f.Index() < len(v.Elems()) { 1228 return true 1229 } 1230 return !v.IsClosedList() 1231 1232 default: 1233 return v.Kind()&ListKind != 0 1234 } 1235 } 1236 1237 if k := v.Kind(); k&StructKind == 0 && f.IsString() { 1238 // If the value is bottom, we may not really know if this used to 1239 // be a struct. 1240 if k != BottomKind || len(v.Structs) == 0 { 1241 return false 1242 } 1243 } 1244 1245 // TODO: move this check to IsClosedStruct. Right now this causes too many 1246 // changes in the debug output, and it also appears to be not entirely 1247 // correct. 1248 if v.HasEllipsis { 1249 return true 1250 1251 } 1252 1253 if !v.IsClosedStruct() || v.Lookup(f) != nil { 1254 return true 1255 } 1256 1257 // TODO(perf): collect positions in error. 1258 defer ctx.ReleasePositions(ctx.MarkPositions()) 1259 1260 return v.accepts(Accept(ctx, v, f)) 1261 } 1262 1263 // MatchAndInsert finds the conjuncts for optional fields, pattern 1264 // constraints, and additional constraints that match f and inserts them in 1265 // arc. Use f is 0 to match all additional constraints only. 1266 func (v *Vertex) MatchAndInsert(ctx *OpContext, arc *Vertex) { 1267 if !v.Accept(ctx, arc.Label) { 1268 return 1269 } 1270 1271 // Go backwards to simulate old implementation. 1272 if !ctx.isDevVersion() { 1273 for i := len(v.Structs) - 1; i >= 0; i-- { 1274 s := v.Structs[i] 1275 if s.Disable { 1276 continue 1277 } 1278 s.MatchAndInsert(ctx, arc) 1279 } 1280 } 1281 1282 // This is the equivalent for the new implementation. 1283 if pcs := v.PatternConstraints; pcs != nil { 1284 for _, pc := range pcs.Pairs { 1285 if matchPattern(ctx, pc.Pattern, arc.Label) { 1286 for _, c := range pc.Constraint.Conjuncts { 1287 env := *(c.Env) 1288 if arc.Label.Index() < MaxIndex { 1289 env.DynamicLabel = arc.Label 1290 } 1291 c.Env = &env 1292 1293 arc.insertConjunct(ctx, c, c.CloseInfo, ArcMember, true, false) 1294 } 1295 } 1296 } 1297 } 1298 1299 if len(arc.Conjuncts) == 0 && v.HasEllipsis { 1300 // TODO: consider adding an Ellipsis fields to the Constraints struct 1301 // to record the original position of the elllipsis. 1302 c := MakeRootConjunct(nil, &Top{}) 1303 arc.insertConjunct(ctx, c, c.CloseInfo, ArcOptional, false, false) 1304 } 1305 } 1306 func (v *Vertex) IsList() bool { 1307 _, ok := v.BaseValue.(*ListMarker) 1308 return ok 1309 } 1310 1311 // Lookup returns the Arc with label f if it exists or nil otherwise. 1312 func (v *Vertex) Lookup(f Feature) *Vertex { 1313 for _, a := range v.Arcs { 1314 if a.Label == f { 1315 // TODO(P1)/TODO(deref): this indirection should ultimately be 1316 // eliminated: the original node may have useful information (like 1317 // original conjuncts) that are eliminated after indirection. We 1318 // should leave it up to the user of Lookup at what point an 1319 // indirection is necessary. 1320 a = a.DerefValue() 1321 return a 1322 } 1323 } 1324 return nil 1325 } 1326 1327 // LookupRaw returns the Arc with label f if it exists or nil otherwise. 1328 // 1329 // TODO: with the introduction of structure sharing, it is not always correct 1330 // to indirect the arc. At the very least, this discards potential useful 1331 // information. We introduce LookupRaw to avoid having to delete the 1332 // information. Ultimately, this should become Lookup, or better, we should 1333 // have a higher-level API for accessing values. 1334 func (v *Vertex) LookupRaw(f Feature) *Vertex { 1335 for _, a := range v.Arcs { 1336 if a.Label == f { 1337 return a 1338 } 1339 } 1340 return nil 1341 } 1342 1343 // Elems returns the regular elements of a list. 1344 func (v *Vertex) Elems() []*Vertex { 1345 // TODO: add bookkeeping for where list arcs start and end. 1346 a := make([]*Vertex, 0, len(v.Arcs)) 1347 for _, x := range v.Arcs { 1348 if x.Label.IsInt() { 1349 a = append(a, x) 1350 } 1351 } 1352 return a 1353 } 1354 1355 func (v *Vertex) Init(c *OpContext) { 1356 v.getState(c) 1357 } 1358 1359 // GetArc returns a Vertex for the outgoing arc with label f. It creates and 1360 // ads one if it doesn't yet exist. 1361 func (v *Vertex) GetArc(c *OpContext, f Feature, t ArcType) (arc *Vertex, isNew bool) { 1362 arc = v.Lookup(f) 1363 if arc != nil { 1364 arc.updateArcType(t) 1365 return arc, false 1366 } 1367 1368 if c.isDevVersion() { 1369 return nil, false 1370 } 1371 1372 if v.LockArcs { 1373 // TODO(errors): add positions. 1374 if f.IsInt() { 1375 c.addErrf(EvalError, token.NoPos, 1376 "element at index %v not allowed by earlier comprehension or reference cycle", f) 1377 } else { 1378 c.addErrf(EvalError, token.NoPos, 1379 "field %v not allowed by earlier comprehension or reference cycle", f) 1380 } 1381 } 1382 // TODO: consider setting Dynamic here from parent. 1383 arc = &Vertex{ 1384 Parent: v, 1385 Label: f, 1386 ArcType: t, 1387 nonRooted: v.IsDynamic || v.Label.IsLet() || v.nonRooted, 1388 anonymous: v.anonymous || v.Label.IsLet(), 1389 } 1390 v.Arcs = append(v.Arcs, arc) 1391 if t == ArcPending { 1392 v.hasPendingArc = true 1393 } 1394 return arc, true 1395 } 1396 1397 func (v *Vertex) Source() ast.Node { 1398 if v != nil { 1399 if b, ok := v.BaseValue.(Value); ok { 1400 return b.Source() 1401 } 1402 } 1403 return nil 1404 } 1405 1406 // InsertConjunct is a low-level method to insert a conjunct into a Vertex. 1407 // It should only be used by the compiler. It does not consider any logic 1408 // that is necessary if a conjunct is added to a Vertex that is already being 1409 // evaluated. 1410 func (v *Vertex) InsertConjunct(c Conjunct) { 1411 v.Conjuncts = append(v.Conjuncts, c) 1412 } 1413 1414 // InsertConjunctsFrom is a low-level method to insert a conjuncts into a Vertex 1415 // from another Vertex. 1416 func (v *Vertex) InsertConjunctsFrom(w *Vertex) { 1417 v.Conjuncts = append(v.Conjuncts, w.Conjuncts...) 1418 } 1419 1420 // AddConjunct adds the given Conjuncts to v if it doesn't already exist. 1421 func (v *Vertex) AddConjunct(c Conjunct) *Bottom { 1422 if v.BaseValue != nil && !isCyclePlaceholder(v.BaseValue) { 1423 // TODO: investigate why this happens at all. Removing it seems to 1424 // change the order of fields in some cases. 1425 // 1426 // This is likely a bug in the evaluator and should not happen. 1427 return &Bottom{ 1428 Err: errors.Newf(token.NoPos, "cannot add conjunct"), 1429 Node: v, 1430 } 1431 } 1432 if !v.hasConjunct(c) { 1433 v.addConjunctUnchecked(c) 1434 } 1435 return nil 1436 } 1437 1438 func (v *Vertex) hasConjunct(c Conjunct) (added bool) { 1439 switch f := c.x.(type) { 1440 case *BulkOptionalField, *Ellipsis: 1441 case *Field: 1442 v.updateArcType(f.ArcType) 1443 case *DynamicField: 1444 v.updateArcType(f.ArcType) 1445 default: 1446 v.ArcType = ArcMember 1447 } 1448 p, _ := findConjunct(v.Conjuncts, c) 1449 return p >= 0 1450 } 1451 1452 // findConjunct reports the position of c within cs or -1 if it is not found. 1453 // 1454 // NOTE: we are not comparing closeContexts. The intended use of this function 1455 // is only to add to list of conjuncts within a closeContext. 1456 func findConjunct(cs []Conjunct, c Conjunct) (int, Conjunct) { 1457 for i, x := range cs { 1458 // TODO: disregard certain fields from comparison (e.g. Refs)? 1459 if x.CloseInfo.closeInfo == c.CloseInfo.closeInfo && // V2 1460 x.x == c.x && 1461 x.Env.Up == c.Env.Up && x.Env.Vertex == c.Env.Vertex { 1462 return i, x 1463 } 1464 } 1465 return -1, Conjunct{} 1466 } 1467 1468 func (n *nodeContext) addConjunction(c Conjunct, index int) { 1469 unreachableForDev(n.ctx) 1470 1471 // NOTE: This does not split binary expressions for comprehensions. 1472 // TODO: split for comprehensions and rewrap? 1473 if x, ok := c.Elem().(*BinaryExpr); ok && x.Op == AndOp { 1474 c.x = x.X 1475 n.conjuncts = append(n.conjuncts, conjunct{C: c, index: index}) 1476 c.x = x.Y 1477 n.conjuncts = append(n.conjuncts, conjunct{C: c, index: index}) 1478 } else { 1479 n.conjuncts = append(n.conjuncts, conjunct{C: c, index: index}) 1480 } 1481 } 1482 1483 func (v *Vertex) addConjunctUnchecked(c Conjunct) { 1484 index := len(v.Conjuncts) 1485 v.Conjuncts = append(v.Conjuncts, c) 1486 if n := v.state; n != nil && !n.ctx.isDevVersion() { 1487 // TODO(notify): consider this as a central place to send out 1488 // notifications. At the moment this is not necessary, but it may 1489 // be if we move the notification mechanism outside of the path of 1490 // running tasks. 1491 n.addConjunction(c, index) 1492 1493 // TODO: can we remove notifyConjunct here? This method is only 1494 // used if either Unprocessed is 0, in which case there will be no 1495 // notification recipients, or for "pushed down" comprehensions, 1496 // which should also have been added at an earlier point. 1497 n.notifyConjunct(c) 1498 } 1499 } 1500 1501 // addConjunctDynamic adds a conjunct to a vertex and immediately evaluates 1502 // it, whilst doing the same for any vertices on the notify list, recursively. 1503 func (n *nodeContext) addConjunctDynamic(c Conjunct) { 1504 unreachableForDev(n.ctx) 1505 1506 n.node.Conjuncts = append(n.node.Conjuncts, c) 1507 n.addExprConjunct(c, partial) 1508 n.notifyConjunct(c) 1509 1510 } 1511 1512 func (n *nodeContext) notifyConjunct(c Conjunct) { 1513 unreachableForDev(n.ctx) 1514 1515 for _, rec := range n.notify { 1516 arc := rec.v 1517 if !arc.hasConjunct(c) { 1518 if arc.state == nil { 1519 // TODO: continuing here is likely to result in a faulty 1520 // (incomplete) configuration. But this may be okay. The 1521 // CUE_DEBUG=0 flag disables this assertion. 1522 n.ctx.Assertf(n.ctx.pos(), !n.ctx.Strict, "unexpected nil state") 1523 n.ctx.addErrf(0, n.ctx.pos(), "cannot add to field %v", arc.Label) 1524 continue 1525 } 1526 arc.state.addConjunctDynamic(c) 1527 } 1528 } 1529 } 1530 1531 func (v *Vertex) AddStruct(s *StructLit, env *Environment, ci CloseInfo) *StructInfo { 1532 info := StructInfo{ 1533 StructLit: s, 1534 Env: env, 1535 CloseInfo: ci, 1536 } 1537 for _, t := range v.Structs { 1538 if *t == info { // TODO: check for different identity. 1539 return t 1540 } 1541 } 1542 t := &info 1543 v.Structs = append(v.Structs, t) 1544 return t 1545 } 1546 1547 // Path computes the sequence of Features leading from the root to of the 1548 // instance to this Vertex. 1549 // 1550 // NOTE: this is for debugging purposes only. 1551 func (v *Vertex) Path() []Feature { 1552 return appendPath(nil, v) 1553 } 1554 1555 func appendPath(a []Feature, v *Vertex) []Feature { 1556 if v.Parent == nil { 1557 return a 1558 } 1559 a = appendPath(a, v.Parent) 1560 // Skip if the node is a structure-shared node that has been assingned to 1561 // the parent as it's new location: in this case the parent node will 1562 // have the desired label. 1563 if v.Label != 0 && v.Parent.BaseValue != v { 1564 // A Label may be 0 for programmatically inserted nodes. 1565 a = append(a, v.Label) 1566 } 1567 return a 1568 } 1569 1570 // A Conjunct is an Environment-Expr pair. The Environment is the starting 1571 // point for reference lookup for any reference contained in X. 1572 type Conjunct struct { 1573 Env *Environment 1574 x Node 1575 1576 // CloseInfo is a unique number that tracks a group of conjuncts that need 1577 // belong to a single originating definition. 1578 CloseInfo CloseInfo 1579 } 1580 1581 // MakeConjunct creates a conjunct from current Environment and CloseInfo of c. 1582 func (c *OpContext) MakeConjunct(x Expr) Conjunct { 1583 return MakeConjunct(c.e, x, c.ci) 1584 } 1585 1586 // TODO(perf): replace with composite literal if this helps performance. 1587 1588 // MakeRootConjunct creates a conjunct from the given environment and node. 1589 // It panics if x cannot be used as an expression. 1590 func MakeRootConjunct(env *Environment, x Node) Conjunct { 1591 return MakeConjunct(env, x, CloseInfo{}) 1592 } 1593 1594 func MakeConjunct(env *Environment, x Node, id CloseInfo) Conjunct { 1595 if env == nil { 1596 // TODO: better is to pass one. 1597 env = &Environment{} 1598 } 1599 switch x.(type) { 1600 case Elem, interface{ expr() Expr }: 1601 default: 1602 panic(fmt.Sprintf("invalid Node type %T", x)) 1603 } 1604 return Conjunct{env, x, id} 1605 } 1606 1607 func (c *Conjunct) Source() ast.Node { 1608 return c.x.Source() 1609 } 1610 1611 func (c *Conjunct) Field() Node { 1612 switch x := c.x.(type) { 1613 case *Comprehension: 1614 return x.Value 1615 default: 1616 return c.x 1617 } 1618 } 1619 1620 // Elem retrieves the Elem form of the contained conjunct. 1621 // If it is a Field, it will return the field value. 1622 func (c Conjunct) Elem() Elem { 1623 switch x := c.x.(type) { 1624 case interface{ expr() Expr }: 1625 return x.expr() 1626 case Elem: 1627 return x 1628 default: 1629 panic("unreachable") 1630 } 1631 } 1632 1633 // Expr retrieves the expression form of the contained conjunct. If it is a 1634 // field or comprehension, it will return its associated value. This is only to 1635 // be used for syntactic operations where evaluation of the expression is not 1636 // required. To get an expression paired with the correct environment, use 1637 // EnvExpr. 1638 // 1639 // TODO: rename to RawExpr. 1640 func (c *Conjunct) Expr() Expr { 1641 return ToExpr(c.x) 1642 } 1643 1644 // EnvExpr returns the expression form of the contained conjunct alongside an 1645 // Environment in which this expression should be evaluated. 1646 func (c Conjunct) EnvExpr() (*Environment, Expr) { 1647 return EnvExpr(c.Env, c.Elem()) 1648 } 1649 1650 // EnvExpr returns the expression represented by Elem alongside an Environment 1651 // with the necessary adjustments in which the resulting expression can be 1652 // evaluated. 1653 func EnvExpr(env *Environment, elem Elem) (*Environment, Expr) { 1654 for { 1655 switch x := elem.(type) { 1656 case *ConjunctGroup: 1657 if len(*x) == 1 { 1658 c := (*x)[0] 1659 env = c.Env 1660 elem = c.Elem() 1661 continue 1662 } 1663 case *Comprehension: 1664 env = linkChildren(env, x) 1665 c := MakeConjunct(env, x.Value, CloseInfo{}) 1666 elem = c.Elem() 1667 continue 1668 } 1669 break 1670 } 1671 return env, ToExpr(elem) 1672 } 1673 1674 // ToExpr extracts the underlying expression for a Node. If something is already 1675 // an Expr, it will return it as is, if it is a field, it will return its value, 1676 // and for comprehensions it returns the yielded struct. 1677 func ToExpr(n Node) Expr { 1678 for { 1679 switch x := n.(type) { 1680 case *ConjunctGroup: 1681 if len(*x) != 1 { 1682 return x 1683 } 1684 n = (*x)[0].x 1685 case Expr: 1686 return x 1687 case interface{ expr() Expr }: 1688 n = x.expr() 1689 case *Comprehension: 1690 n = x.Value 1691 default: 1692 panic("unreachable") 1693 } 1694 } 1695 }