cuelang.org/go@v0.13.0/internal/core/adt/context.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 "reflect" 20 "regexp" 21 22 "github.com/cockroachdb/apd/v3" 23 "golang.org/x/text/encoding/unicode" 24 25 "cuelang.org/go/cue/ast" 26 "cuelang.org/go/cue/errors" 27 "cuelang.org/go/cue/stats" 28 "cuelang.org/go/cue/token" 29 "cuelang.org/go/internal" 30 "cuelang.org/go/internal/cuedebug" 31 ) 32 33 // Runtime defines an interface for low-level representation conversion and 34 // lookup. 35 type Runtime interface { 36 // StringIndexer allows for converting string labels to and from a 37 // canonical numeric representation. 38 StringIndexer 39 40 // LoadImport loads a unique Vertex associated with a given import path. It 41 // returns nil if no import for this package could be found. 42 LoadImport(importPath string) *Vertex 43 44 // StoreType associates a CUE expression with a Go type. 45 StoreType(t reflect.Type, src ast.Expr, expr Expr) 46 47 // LoadType retrieves a previously stored CUE expression for a given Go 48 // type if available. 49 LoadType(t reflect.Type) (src ast.Expr, expr Expr, ok bool) 50 51 // ConfigureOpCtx configures the [*OpContext] with details such as 52 // evaluator version, debug options etc. 53 ConfigureOpCtx(ctx *OpContext) 54 } 55 56 type Config struct { 57 Runtime 58 Format func(Runtime, Node) string 59 } 60 61 // New creates an operation context. 62 func New(v *Vertex, cfg *Config) *OpContext { 63 if cfg.Runtime == nil { 64 panic("nil Runtime") 65 } 66 67 ctx := &OpContext{ 68 Runtime: cfg.Runtime, 69 Format: cfg.Format, 70 vertex: v, 71 taskContext: schedConfig, 72 } 73 cfg.Runtime.ConfigureOpCtx(ctx) 74 ctx.stats.EvalVersion = ctx.Version 75 if v != nil { 76 ctx.e = &Environment{Up: nil, Vertex: v} 77 } 78 return ctx 79 } 80 81 // See also: [unreachableForDev] 82 func (c *OpContext) isDevVersion() bool { 83 if c.Version == internal.EvalVersionUnset { 84 panic("OpContext was not provided with an evaluator version") 85 } 86 return c.Version == internal.DevVersion 87 } 88 89 // An OpContext implements CUE's unification operation. It only 90 // operates on values that are created with the Runtime with which an OpContext 91 // is associated. An OpContext is not goroutine safe and only one goroutine may 92 // use an OpContext at a time. 93 type OpContext struct { 94 Runtime 95 Format func(Runtime, Node) string 96 97 cuedebug.Config 98 Version internal.EvaluatorVersion // Copied from Runtime 99 TopoSort bool // Copied from Runtime 100 101 taskContext 102 103 nest int 104 105 nextDefID defID // used in typocheck.go 106 107 stats stats.Counts 108 freeListNode *nodeContext 109 110 e *Environment 111 ci CloseInfo 112 src ast.Node 113 errs *Bottom 114 positions []Node // keep track of error positions 115 116 // vertex is used to determine the path location in case of error. Turning 117 // this into a stack could also allow determining the cyclic path for 118 // structural cycle errors. 119 vertex *Vertex 120 121 // list of vertices that need to be finalized. 122 // TODO: remove this again once we have a proper way of detecting references 123 // across optional boundaries in hasAncestorV3. We can probably do this 124 // with an optional depth counter. 125 toFinalize []*Vertex 126 127 // These fields are used associate scratch fields for computing closedness 128 // of a Vertex. These fields could have been included in StructInfo (like 129 // Tomabechi's unification algorithm), but we opted for an indirection to 130 // allow concurrent unification. 131 // 132 // TODO(perf): have two generations: one for each pass of the closedness 133 // algorithm, so that the results of the first pass can be reused for all 134 // features of a node. 135 generation int 136 closed map[*closeInfo]*closeStats 137 todo *closeStats 138 139 // evalDepth indicates the current depth of evaluation. It is used to 140 // detect structural cycles and their severity.s 141 evalDepth int 142 143 // optionalMark indicates the evalDepth at which the last optional field, 144 // pattern constraint or other construct that may contain errors was 145 // encountered. A value of 0 indicates we are not within such field. 146 optionalMark int 147 148 // holdID is a unique identifier for the current "hole", a choice of 149 // disjunct to be made when processing disjunctions. 150 holeID int 151 152 // inDisjunct indicates that non-monotonic checks should be skipped. 153 // This is used if we want to do some extra work to eliminate disjunctions 154 // early. The result of unification should be thrown away if this check is 155 // used. 156 // 157 // TODO: replace this with a mechanism to determine the correct set (per 158 // conjunct) of StructInfos to include in closedness checking. 159 inDisjunct int 160 161 // inConstaint overrides inDisjunct as field matching should always be 162 // enabled. 163 inConstraint int 164 165 // inDetached indicates that inline structs evaluated in the current context 166 // should never be shared. This is the case, for instance, with the source 167 // for the for clause in a comprehension. 168 inDetached int 169 170 // inValidator defines whether full evaluation need to be enforced, for 171 // instance when comparing against bottom. 172 inValidator int 173 174 // The current call is a validator. A builtin may return a boolean false 175 // along with an error message describing a validation error. If the latter 176 // is wrapped in an internal.ValidationError, it will only be interpreted 177 // as an error if this is true. 178 // TODO: strictly separate validators and functions. 179 IsValidator bool 180 181 overlays []overlayFrame 182 183 // ==== Debugging ==== 184 logID int // sequence number for log messages 185 186 // ErrorGraphs contains an analysis, represented as a Mermaid graph, for 187 // each node that has an error. 188 ErrorGraphs map[string]string 189 190 currentDisjunctionID int // sequence number for call to processDisjunctions 191 192 disjunctStack []disjunctInfo // stack of disjunct IDs 193 194 reqSetsBuf reqSets // reuse a reqSets slice 195 196 // altPath, if non-empty, provides an alternative path for errors. This is 197 // necessary to get the right path for incomplete errors in the presence of 198 // structure sharing. 199 altPath []*Vertex // stack of selectors 200 } 201 202 func (c *OpContext) CloseInfo() CloseInfo { return c.ci } 203 func (c *OpContext) UpdateCloseInfo(ci CloseInfo) { c.ci = ci } 204 205 func (n *nodeContext) skipNonMonotonicChecks() bool { 206 if n.ctx.inConstraint > 0 { 207 return false 208 } 209 return n.ctx.inDisjunct > 0 210 } 211 212 func (c *OpContext) Pos() token.Pos { 213 if c.src == nil { 214 return token.NoPos 215 } 216 return c.src.Pos() 217 } 218 219 func (c *OpContext) Source() ast.Node { 220 return c.src 221 } 222 223 // NewContext creates an operation context. 224 func NewContext(r Runtime, v *Vertex) *OpContext { 225 return New(v, &Config{Runtime: r}) 226 } 227 228 func (c *OpContext) pos() token.Pos { 229 if c.src == nil { 230 return token.NoPos 231 } 232 return c.src.Pos() 233 } 234 235 func (c *OpContext) spawn(node *Vertex) *Environment { 236 return spawn(c.e, node) 237 } 238 239 func spawn(env *Environment, node *Vertex) *Environment { 240 return &Environment{ 241 Up: env, 242 Vertex: node, 243 } 244 } 245 246 func (c *OpContext) Env(upCount int32) *Environment { 247 return c.e.up(c, upCount) 248 } 249 250 func (c *OpContext) relNode(upCount int32) *Vertex { 251 e := c.e.up(c, upCount) 252 c.unify(e.Vertex, oldOnly(partial)) 253 return e.Vertex 254 } 255 256 func (c *OpContext) relLabel(upCount int32) Feature { 257 // locate current label. 258 e := c.e.up(c, upCount) 259 return e.DynamicLabel 260 } 261 262 func (c *OpContext) concreteIsPossible(op Op, x Expr) bool { 263 if !AssertConcreteIsPossible(op, x) { 264 // No need to take position of expression. 265 c.AddErr(c.NewPosf(token.NoPos, 266 "invalid operand %s ('%s' requires concrete value)", x, op)) 267 return false 268 } 269 return true 270 } 271 272 // Assert that the given expression can evaluate to a concrete value. 273 func AssertConcreteIsPossible(op Op, x Expr) bool { 274 switch v := x.(type) { 275 case *Bottom: 276 case *BoundExpr: 277 return false 278 case Value: 279 return v.Concreteness() == Concrete 280 } 281 return true 282 } 283 284 // HasErr reports whether any error was reported, including whether value 285 // was incomplete. 286 func (c *OpContext) HasErr() bool { 287 return c.errs != nil 288 } 289 290 func (c *OpContext) Err() *Bottom { 291 b := c.errs 292 c.errs = nil 293 return b 294 } 295 296 func (c *OpContext) addErrf(code ErrorCode, pos token.Pos, msg string, args ...interface{}) { 297 err := c.NewPosf(pos, msg, args...) 298 c.addErr(code, err) 299 } 300 301 func (c *OpContext) addErr(code ErrorCode, err errors.Error) { 302 c.AddBottom(&Bottom{ 303 Code: code, 304 Err: err, 305 Node: c.vertex, 306 }) 307 } 308 309 // AddBottom records an error in OpContext. 310 func (c *OpContext) AddBottom(b *Bottom) { 311 c.errs = CombineErrors(c.src, c.errs, b) 312 } 313 314 // AddErr records an error in OpContext. It returns errors collected so far. 315 func (c *OpContext) AddErr(err errors.Error) *Bottom { 316 if err != nil { 317 c.AddBottom(&Bottom{ 318 Err: err, 319 Node: c.vertex, 320 }) 321 } 322 return c.errs 323 } 324 325 // NewErrf creates a *Bottom value and returns it. The returned uses the 326 // current source as the point of origin of the error. 327 func (c *OpContext) NewErrf(format string, args ...interface{}) *Bottom { 328 // TODO: consider renaming ot NewBottomf: this is now confusing as we also 329 // have Newf. 330 err := c.Newf(format, args...) 331 return &Bottom{ 332 Src: c.src, 333 Err: err, 334 Code: EvalError, 335 Node: c.vertex, 336 } 337 } 338 339 // AddErrf records an error in OpContext. It returns errors collected so far. 340 func (c *OpContext) AddErrf(format string, args ...interface{}) *Bottom { 341 return c.AddErr(c.Newf(format, args...)) 342 } 343 344 type frame struct { 345 env *Environment 346 err *Bottom 347 src ast.Node 348 ci CloseInfo 349 } 350 351 func (c *OpContext) PushState(env *Environment, src ast.Node) (saved frame) { 352 saved.env = c.e 353 saved.err = c.errs 354 saved.src = c.src 355 saved.ci = c.ci 356 357 c.errs = nil 358 if src != nil { 359 c.src = src 360 } 361 c.e = env 362 363 return saved 364 } 365 366 func (c *OpContext) PushConjunct(x Conjunct) (saved frame) { 367 src := x.Expr().Source() 368 369 saved.env = c.e 370 saved.err = c.errs 371 saved.src = c.src 372 saved.ci = c.ci 373 374 c.errs = nil 375 if src != nil { 376 c.src = src 377 } 378 c.e = x.Env 379 c.ci = x.CloseInfo 380 381 return saved 382 } 383 384 func (c *OpContext) PopState(s frame) *Bottom { 385 err := c.errs 386 c.e = s.env 387 c.errs = s.err 388 c.src = s.src 389 c.ci = s.ci 390 return err 391 } 392 393 // PushArc signals c that arc v is currently being processed for the purpose 394 // of error reporting. PopArc should be called with the returned value once 395 // processing of v is completed. 396 func (c *OpContext) PushArc(v *Vertex) (saved *Vertex) { 397 c.vertex, saved = v, c.vertex 398 return saved 399 } 400 func (c *OpContext) PushArcAndLabel(v *Vertex) (saved *Vertex) { 401 402 c.vertex, saved = v, c.vertex 403 c.altPath = append(c.altPath, v) 404 return saved 405 } 406 407 // PopArc signals completion of processing the current arc. 408 func (c *OpContext) PopArc(saved *Vertex) { 409 c.vertex = saved 410 } 411 412 func (c *OpContext) PopArcAndLabel(saved *Vertex) { 413 c.vertex = saved 414 c.altPath = c.altPath[:len(c.altPath)-1] 415 } 416 417 // Resolve finds a node in the tree. 418 // 419 // Should only be used to insert Conjuncts. TODO: perhaps only return Conjuncts 420 // and error. 421 func (c *OpContext) Resolve(x Conjunct, r Resolver) (*Vertex, *Bottom) { 422 return c.resolveState(x, r, final(finalized, allKnown)) 423 } 424 425 func (c *OpContext) resolveState(x Conjunct, r Resolver, state combinedFlags) (*Vertex, *Bottom) { 426 s := c.PushConjunct(x) 427 428 arc := r.resolve(c, state) 429 430 err := c.PopState(s) 431 if err != nil { 432 return nil, err 433 } 434 435 if arc.ChildErrors != nil && arc.ChildErrors.Code == StructuralCycleError { 436 return nil, arc.ChildErrors 437 } 438 439 // Dereference any vertices that do not contribute to more knownledge about 440 // the node. 441 arc = arc.DerefNonRooted() 442 443 return arc, err 444 } 445 446 // Lookup looks up r in env without further resolving the value. 447 func (c *OpContext) Lookup(env *Environment, r Resolver) (*Vertex, *Bottom) { 448 s := c.PushState(env, r.Source()) 449 450 arc := r.resolve(c, oldOnly(partial)) 451 452 err := c.PopState(s) 453 454 if arc != nil && !c.isDevVersion() { 455 // TODO(deref): lookup should probably not use DerefValue, but 456 // rather only dereference disjunctions. 457 arc = arc.DerefValue() 458 } 459 460 return arc, err 461 } 462 463 // Validate calls validates value for the given validator. 464 // 465 // TODO(errors): return boolean instead: only the caller has enough information 466 // to generate a proper error message. 467 func (c *OpContext) Validate(check Conjunct, value Value) *Bottom { 468 // TODO: use a position stack to push both values. 469 470 // TODO(evalv3): move to PushConjunct once the migration is complete. 471 // Using PushConjunct also saves and restores the error, which may be 472 // impactful, so we want to do this in a separate commit. 473 // saved := c.PushConjunct(check) 474 475 src := c.src 476 ci := c.ci 477 env := c.e 478 c.src = check.Source() 479 c.ci = check.CloseInfo 480 c.e = check.Env 481 482 err := check.x.(Validator).validate(c, value) 483 484 c.src = src 485 c.ci = ci 486 c.e = env 487 488 return err 489 } 490 491 // concrete returns the concrete value of x after evaluating it. 492 // msg is used to mention the context in which an error occurred, if any. 493 func (c *OpContext) concrete(env *Environment, x Expr, msg interface{}) (result Value, complete bool) { 494 s := c.PushState(env, x.Source()) 495 496 state := require(partial, concreteKnown) 497 w := c.evalState(x, state) 498 _ = c.PopState(s) 499 500 w, ok := c.getDefault(w) 501 if !ok { 502 return w, false 503 } 504 v := Unwrap(w) 505 506 complete = w != nil 507 if !IsConcrete(v) { 508 complete = false 509 b := c.NewErrf("non-concrete value %v in operand to %s", w, msg) 510 b.Code = IncompleteError 511 v = b 512 } 513 514 return v, complete 515 } 516 517 // getDefault resolves a disjunction to a single value. If there is no default 518 // value, or if there is more than one default value, it reports an "incomplete" 519 // error and return false. In all other cases it will return true, even if 520 // v is already an error. v may be nil, in which case it will also return nil. 521 func (c *OpContext) getDefault(v Value) (result Value, ok bool) { 522 var d *Disjunction 523 switch x := v.(type) { 524 default: 525 return v, true 526 527 case *Vertex: 528 // TODO: return vertex if not disjunction. 529 switch t := x.BaseValue.(type) { 530 case *Disjunction: 531 d = t 532 533 case *Vertex: 534 return c.getDefault(t) 535 536 default: 537 return x, true 538 } 539 540 case *Disjunction: 541 d = x 542 } 543 544 if d.NumDefaults != 1 { 545 c.addErrf(IncompleteError, c.pos(), 546 "unresolved disjunction %v (type %s)", d, d.Kind()) 547 return nil, false 548 } 549 return c.getDefault(d.Values[0]) 550 } 551 552 // Evaluate evaluates an expression within the given environment and indicates 553 // whether the result is complete. It will always return a non-nil result. 554 func (c *OpContext) Evaluate(env *Environment, x Expr) (result Value, complete bool) { 555 s := c.PushState(env, x.Source()) 556 557 val := c.evalState(x, final(partial, concreteKnown)) 558 559 complete = true 560 561 if err, _ := val.(*Bottom); err != nil && err.IsIncomplete() { 562 complete = false 563 } 564 if val == nil { 565 complete = false 566 // TODO ENSURE THIS DOESN"T HAPPEN> 567 val = &Bottom{ 568 Code: IncompleteError, 569 Err: c.Newf("UNANTICIPATED ERROR"), 570 Node: env.Vertex, 571 } 572 573 } 574 575 _ = c.PopState(s) 576 577 if !complete || val == nil { 578 return val, false 579 } 580 581 return val, true 582 } 583 584 // EvaluateKeepState does an evaluate, but leaves any errors and cycle info 585 // within the context. 586 func (c *OpContext) EvaluateKeepState(x Expr) (result Value) { 587 src := c.src 588 c.src = x.Source() 589 590 result, ci := c.evalStateCI(x, final(partial, concreteKnown)) 591 592 c.src = src 593 c.ci = ci 594 595 return result 596 } 597 598 func (c *OpContext) evaluateRec(v Conjunct, state combinedFlags) Value { 599 x := v.Expr() 600 s := c.PushConjunct(v) 601 602 val := c.evalState(x, state) 603 if val == nil { 604 // Be defensive: this never happens, but just in case. 605 Assertf(c, false, "nil return value: unspecified error") 606 val = &Bottom{ 607 Code: IncompleteError, 608 Err: c.Newf("UNANTICIPATED ERROR"), 609 Node: c.vertex, 610 } 611 } 612 _ = c.PopState(s) 613 614 return val 615 } 616 617 // value evaluates expression v within the current environment. The result may 618 // be nil if the result is incomplete. value leaves errors untouched to that 619 // they can be collected by the caller. 620 func (c *OpContext) value(x Expr, state combinedFlags) (result Value) { 621 v := c.evalState(x, state) 622 623 v, _ = c.getDefault(v) 624 v = Unwrap(v) 625 return v 626 } 627 628 func (c *OpContext) evalState(v Expr, state combinedFlags) (result Value) { 629 result, _ = c.evalStateCI(v, state) 630 return result 631 } 632 633 func (c *OpContext) evalStateCI(v Expr, state combinedFlags) (result Value, ci CloseInfo) { 634 savedSrc := c.src 635 c.src = v.Source() 636 err := c.errs 637 c.errs = nil 638 // Save the old CloseInfo and restore after evaluate to avoid detecting 639 // spurious cycles. 640 saved := c.ci 641 642 defer func() { 643 c.errs = CombineErrors(c.src, c.errs, err) 644 645 if v, ok := result.(*Vertex); ok { 646 if b := v.Bottom(); b != nil { 647 switch b.Code { 648 case IncompleteError: 649 case CycleError: 650 if state.vertexStatus() == partial || c.isDevVersion() { 651 break 652 } 653 fallthrough 654 default: 655 result = b 656 } 657 } 658 } 659 660 // TODO: remove this when we handle errors more principally. 661 if b, ok := result.(*Bottom); ok { 662 result = c.wrapCycleError(c.src, b) 663 if c.errs != result { 664 c.errs = CombineErrors(c.src, c.errs, result) 665 } 666 } 667 if c.errs != nil { 668 result = c.errs 669 } 670 c.src = savedSrc 671 672 // TODO(evalv3): this c.ci should be passed to the caller who may need 673 // it to continue cycle detection for partially evaluated values. 674 // Either this or we must prove that this is covered by structural cycle 675 // detection. 676 c.ci = saved 677 }() 678 679 switch x := v.(type) { 680 case Value: 681 return x, c.ci 682 683 case Evaluator: 684 v := x.evaluate(c, state) 685 return v, c.ci 686 687 case Resolver: 688 arc := x.resolve(c, state) 689 if c.HasErr() { 690 return nil, c.ci 691 } 692 if arc == nil { 693 return nil, c.ci 694 } 695 orig := arc 696 // TODO(deref): what is the right level of dereferencing here? 697 // DerefValue seems to work too. 698 arc = arc.DerefNonShared() 699 700 // TODO: consider moving this after markCycle, depending on how we 701 // implement markCycle, or whether we need it at all. 702 // TODO: is this indirect necessary? 703 // arc = arc.Indirect() 704 705 n := arc.state 706 if c.isDevVersion() { 707 n = arc.getState(c) 708 if n != nil { 709 c.ci, _ = n.detectCycleV3(arc, nil, x, c.ci) 710 } 711 } else { 712 if n != nil { 713 c.ci, _ = n.markCycle(arc, nil, x, c.ci) 714 } 715 } 716 717 if !c.isDevVersion() { 718 c.ci.Inline = true 719 } 720 721 if c.isDevVersion() { 722 if s := arc.getState(c); s != nil { 723 origNeeds := state.conditions() 724 needs := origNeeds | arcTypeKnown 725 runMode := state.runMode() 726 727 switch runMode { 728 case finalize: 729 arc.unify(c, needs, attemptOnly, true) // to set scalar 730 arc.state.freeze(needs) 731 case attemptOnly: 732 arc.unify(c, needs, attemptOnly, true) // to set scalar 733 734 case yield: 735 arc.unify(c, needs, runMode, true) // to set scalar 736 737 evaluating := arc.status == evaluating 738 739 // We cannot resolve a value that represents an unresolved 740 // disjunction. 741 if evaluating && orig != arc && arc.IsDisjunct { 742 task := c.current() 743 if origNeeds == scalarKnown && !orig.state.meets(scalarKnown) { 744 orig.state.defaultAttemptInCycle = task.node.node 745 task.waitFor(&orig.state.scheduler, needs) 746 s.yield() 747 panic("unreachable") 748 } 749 err := c.Newf("unresolved disjunction: %v", x) 750 b := &Bottom{Code: CycleError, Err: err} 751 return b, c.ci 752 } 753 754 hasCycleBreakingValue := s.hasFieldValue || 755 !isCyclePlaceholder(arc.BaseValue) 756 757 if evaluating && !hasCycleBreakingValue { 758 err := c.Newf("cycle with field: %v", x) 759 b := &Bottom{Code: CycleError, Err: err} 760 c.AddBottom(b) 761 break 762 } 763 764 v := c.evaluate(arc, x, state) 765 766 return v, c.ci 767 } 768 } 769 } 770 v := c.evaluate(arc, x, state) 771 772 return v, c.ci 773 774 default: 775 // This can only happen, really, if v == nil, which is not allowed. 776 panic(fmt.Sprintf("unexpected Expr type %T", v)) 777 } 778 } 779 780 // wrapCycleError converts the sentinel cycleError in a concrete one with 781 // position information. 782 func (c *OpContext) wrapCycleError(src ast.Node, b *Bottom) *Bottom { 783 if src != nil && 784 b.Code == CycleError && 785 len(errors.Positions(b.Err)) == 0 { 786 bb := *b 787 bb.Err = errors.Wrapf(b.Err, src.Pos(), "") 788 b = &bb 789 } 790 return b 791 } 792 793 // unifyNode returns a possibly partially evaluated node value. 794 // 795 // TODO: maybe return *Vertex, *Bottom 796 func (c *OpContext) unifyNode(expr Expr, state combinedFlags) (result Value) { 797 savedSrc := c.src 798 c.src = expr.Source() 799 err := c.errs 800 c.errs = nil 801 802 defer func() { 803 c.errs = CombineErrors(c.src, c.errs, err) 804 805 if v, ok := result.(*Vertex); ok { 806 if b := v.Bottom(); b != nil && !b.IsIncomplete() { 807 result = b 808 } 809 } 810 811 // TODO: remove this when we handle errors more principally. 812 if b, ok := result.(*Bottom); ok { 813 if c.src != nil && 814 b.Code == CycleError && 815 b.Err.Position() == token.NoPos && 816 len(b.Err.InputPositions()) == 0 { 817 bb := *b 818 bb.Err = errors.Wrapf(b.Err, c.src.Pos(), "") 819 result = &bb 820 } 821 c.errs = CombineErrors(c.src, c.errs, result) 822 } 823 if c.errs != nil { 824 result = c.errs 825 } 826 c.src = savedSrc 827 }() 828 829 var v *Vertex 830 831 switch x := expr.(type) { 832 case Value: 833 return x 834 835 case Evaluator: 836 return x.evaluate(c, state) 837 838 case Resolver: 839 v = x.resolve(c, state) 840 841 default: 842 // This can only happen, really, if v == nil, which is not allowed. 843 panic(fmt.Sprintf("unexpected Expr type %T", expr)) 844 } 845 846 if c.HasErr() { 847 return nil 848 } 849 if v == nil { 850 return nil 851 } 852 v = v.DerefValue() 853 854 // TODO: consider moving this after markCycle, depending on how we 855 // implement markCycle, or whether we need it at all. 856 // TODO: is this indirect necessary? 857 // v = v.Indirect() 858 859 if c.isDevVersion() { 860 if n := v.getState(c); n != nil { 861 // A lookup counts as new structure. See the commend in Section 862 // "Lookups in inline cycles" in cycle.go. 863 if !c.ci.IsCyclic || v.Label.IsLet() { 864 // TODO: fix! Setting this when we are not structure sharing can 865 // cause some hangs. We are conservative and not set this in 866 // this case, with the potential that some configurations will 867 // break. It is probably related to let. 868 n.hasNonCycle = true 869 } 870 871 // Always yield to not get spurious errors. 872 n.process(arcTypeKnown, yield) 873 // It is possible that the node is only midway through 874 // evaluating a disjunction. In this case, we want to ensure 875 // that disjunctions are finalized, so that disjunction shows 876 // up in BaseValue. 877 if len(n.disjuncts) > 0 { 878 n.node.unify(c, arcTypeKnown, yield, false) 879 } 880 } 881 } else { 882 if v.isUndefined() || state.vertexStatus() > v.Status() { 883 c.unify(v, state) 884 } 885 } 886 887 return v 888 } 889 890 func (c *OpContext) lookup(x *Vertex, pos token.Pos, l Feature, flags combinedFlags) *Vertex { 891 if c.isDevVersion() { 892 return x.lookup(c, pos, l, flags) 893 } 894 895 state := flags.vertexStatus() 896 897 if l == InvalidLabel || x == nil { 898 // TODO: is it possible to have an invalid label here? Maybe through the 899 // API? 900 return &Vertex{} 901 } 902 903 // var kind Kind 904 // if x.BaseValue != nil { 905 // kind = x.BaseValue.Kind() 906 // } 907 908 switch x.BaseValue.(type) { 909 case *StructMarker: 910 if l.Typ() == IntLabel { 911 c.addErrf(0, pos, "invalid struct selector %v (type int)", l) 912 return nil 913 } 914 915 case *ListMarker: 916 switch { 917 case l.Typ() == IntLabel: 918 switch { 919 case l.Index() < 0: 920 c.addErrf(0, pos, "invalid list index %v (index must be non-negative)", l) 921 return nil 922 case l.Index() > len(x.Arcs): 923 c.addErrf(0, pos, "invalid list index %v (out of bounds)", l) 924 return nil 925 } 926 927 case l.IsDef(), l.IsHidden(), l.IsLet(): 928 929 default: 930 c.addErrf(0, pos, "invalid list index %v (type string)", l) 931 return nil 932 } 933 934 case nil: 935 // c.addErrf(IncompleteError, pos, "incomplete value %s", x) 936 // return nil 937 938 case *Bottom: 939 940 default: 941 kind := x.BaseValue.Kind() 942 if kind&(ListKind|StructKind) != 0 { 943 // c.addErrf(IncompleteError, pos, 944 // "cannot look up %s in incomplete type %s (type %s)", 945 // l, x.Source(), kind) 946 // return nil 947 } else if !l.IsDef() && !l.IsHidden() && !l.IsLet() { 948 c.addErrf(0, pos, 949 "invalid selector %v for value of type %s", l, kind) 950 return nil 951 } 952 } 953 954 a := x.Lookup(l) 955 956 var hasCycle bool 957 958 if a != nil { 959 // Ensure that a's status is at least of the required level. Otherwise, 960 // ensure that any remaining unprocessed conjuncts are processed by 961 // calling c.Unify(a, Partial). The ensures that need to rely on 962 // hasAllConjuncts, but that are finalized too early, get conjuncts 963 // processed beforehand. 964 if state > a.status { 965 c.unify(a, deprecated(c, state)) 966 } else if a.state != nil { 967 c.unify(a, deprecated(c, partial)) 968 } 969 970 // TODO(refRequired): see comment in unify.go:Vertex.lookup near the 971 // namesake TODO. 972 if a.ArcType == ArcOptional { 973 code := IncompleteError 974 if hasCycle { 975 code = CycleError 976 } 977 label := l.SelectorString(c.Runtime) 978 c.AddBottom(&Bottom{ 979 Code: code, 980 Permanent: x.status >= conjuncts, 981 Err: c.NewPosf(pos, 982 "cannot reference optional field: %s", label), 983 Node: x, 984 }) 985 } 986 } else { 987 if x.state != nil { 988 x.state.assertInitialized() 989 990 for _, e := range x.state.exprs { 991 if isCyclePlaceholder(e.err) { 992 hasCycle = true 993 } 994 } 995 } 996 code := IncompleteError 997 // As long as we have incomplete information, we cannot mark the 998 // inability to look up a field as "final", as it may resolve down the 999 // line. 1000 permanent := x.status >= conjuncts 1001 if m, _ := x.BaseValue.(*ListMarker); m != nil && !m.IsOpen { 1002 permanent = true 1003 } 1004 if (state > partial || permanent) && !x.Accept(c, l) { 1005 code = 0 1006 } else if hasCycle { 1007 code = CycleError 1008 } 1009 // TODO: if the struct was a literal struct, we can also treat it as 1010 // closed and make this a permanent error. 1011 label := l.SelectorString(c.Runtime) 1012 1013 // TODO(errors): add path reference and make message 1014 // "undefined field %s in %s" 1015 var err *ValueError 1016 switch { 1017 case isCyclePlaceholder(x.BaseValue): 1018 err = c.NewPosf(pos, "cycle error referencing %s", label) 1019 permanent = false 1020 case l.IsInt(): 1021 err = c.NewPosf(pos, "index out of range [%d] with length %d", 1022 l.Index(), len(x.Elems())) 1023 default: 1024 err = c.NewPosf(pos, "undefined field: %s", label) 1025 } 1026 c.AddBottom(&Bottom{ 1027 Code: code, 1028 Permanent: permanent, 1029 Err: err, 1030 Node: x, 1031 }) 1032 } 1033 return a 1034 } 1035 1036 func (c *OpContext) undefinedFieldError(v *Vertex, code ErrorCode) { 1037 label := v.Label.SelectorString(c) 1038 c.addErrf(code, c.pos(), "undefined field: %s", label) 1039 } 1040 1041 func (c *OpContext) Label(src Expr, x Value) Feature { 1042 return LabelFromValue(c, src, x) 1043 } 1044 1045 func (c *OpContext) typeError(v Value, k Kind) { 1046 if isError(v) { 1047 return 1048 } 1049 if !IsConcrete(v) && v.Kind()&k != 0 { 1050 c.addErrf(IncompleteError, pos(v), "incomplete %s: %s", k, v) 1051 } else { 1052 c.AddErrf("cannot use %s (type %s) as type %s", v, v.Kind(), k) 1053 } 1054 } 1055 1056 func (c *OpContext) typeErrorAs(v Value, k Kind, as interface{}) { 1057 if as == nil { 1058 c.typeError(v, k) 1059 return 1060 } 1061 if isError(v) { 1062 return 1063 } 1064 if !IsConcrete(v) && v.Kind()&k != 0 { 1065 c.addErrf(IncompleteError, pos(v), 1066 "incomplete %s in %v: %s", k, as, v) 1067 } else { 1068 c.AddErrf("cannot use %s (type %s) as type %s in %v", v, v.Kind(), k, as) 1069 } 1070 } 1071 1072 var emptyNode = &Vertex{} 1073 1074 func pos(x Node) token.Pos { 1075 if x.Source() == nil { 1076 return token.NoPos 1077 } 1078 return x.Source().Pos() 1079 } 1080 1081 // node is called by SelectorExpr.resolve and IndexExpr.resolve. 1082 func (c *OpContext) node(orig Node, x Expr, scalar bool, state combinedFlags) *Vertex { 1083 // Do not treat inline structs as closed by default if within a schema. 1084 // See comment at top of scheduleVertexConjuncts. 1085 if _, ok := x.(Resolver); !ok { 1086 saved := c.ci.FromDef 1087 c.ci.FromDef = false 1088 defer func() { c.ci.FromDef = saved }() 1089 } 1090 1091 // TODO: always get the vertex. This allows a whole bunch of trickery 1092 // down the line. 1093 v := c.unifyNode(x, state) 1094 1095 v, ok := c.getDefault(v) 1096 if !ok { 1097 // Error already generated by getDefault. 1098 return emptyNode 1099 } 1100 1101 // The two if blocks below are rather subtle. If we have an error of 1102 // the sentinel value cycle, we have earlier determined that the cycle is 1103 // allowed and that it can be ignored here. Any other CycleError is an 1104 // annotated cycle error that could be taken as is. 1105 // TODO: do something simpler. 1106 if scalar { 1107 if w := Unwrap(v); !isCyclePlaceholder(w) { 1108 v = w 1109 } 1110 } 1111 1112 node, ok := v.(*Vertex) 1113 if ok && !isCyclePlaceholder(node.BaseValue) { 1114 v = node.Value() 1115 } 1116 1117 switch nv := v.(type) { 1118 case nil: 1119 c.addErrf(IncompleteError, pos(x), 1120 "%s undefined (%s is incomplete)", orig, x) 1121 return emptyNode 1122 1123 case *Bottom: 1124 // TODO: this is a bit messy. In some cases errors are already added 1125 // and in some cases not. Not a huge deal, as errors will be uniqued 1126 // down the line, but could be better. 1127 c.AddBottom(nv) 1128 return emptyNode 1129 1130 case *Vertex: 1131 if node == nil { 1132 panic("unexpected markers with nil node") 1133 } 1134 // Needed for package dep: dep does partial evaluation of expressions 1135 // while traversing values. Not evaluating the node here could lead 1136 // to a lookup in an unevaluated node, resulting in erroneously failing 1137 // lookups. 1138 if c.isDevVersion() && nv.nonRooted { 1139 nv.CompleteArcsOnly(c) 1140 } 1141 default: 1142 if kind := v.Kind(); kind&StructKind != 0 { 1143 c.addErrf(IncompleteError, pos(x), 1144 "%s undefined as %s is incomplete (type %s)", orig, x, kind) 1145 return emptyNode 1146 1147 } else if !ok { 1148 c.addErrf(0, pos(x), // TODO(error): better message. 1149 "invalid operand %s (found %s, want list or struct)", 1150 x.Source(), v.Kind()) 1151 return emptyNode 1152 } 1153 } 1154 1155 return node 1156 } 1157 1158 // Elems returns the evaluated elements of a list. 1159 func (c *OpContext) Elems(v Value) []*Vertex { 1160 list := c.list(v) 1161 list.Finalize(c) 1162 return list.Elems() 1163 } 1164 1165 // RawElems returns the elements of the list without evaluating them. 1166 func (c *OpContext) RawElems(v Value) []*Vertex { 1167 list := c.list(v) 1168 return list.Elems() 1169 } 1170 1171 func (c *OpContext) list(v Value) *Vertex { 1172 if v != nil { 1173 if a, ok := c.getDefault(v); ok { 1174 v = a 1175 } 1176 } 1177 x, ok := v.(*Vertex) 1178 if !ok || !x.IsList() { 1179 c.typeError(v, ListKind) 1180 return emptyNode 1181 } 1182 return x 1183 } 1184 1185 func (c *OpContext) scalar(v Value) Value { 1186 v = Unwrap(v) 1187 switch v.(type) { 1188 case *Null, *Bool, *Num, *String, *Bytes: 1189 default: 1190 c.typeError(v, ScalarKinds) 1191 } 1192 return v 1193 } 1194 1195 var zero = &Num{K: NumberKind} 1196 1197 func (c *OpContext) Num(v Value, as interface{}) *Num { 1198 v = Unwrap(v) 1199 if isError(v) { 1200 return zero 1201 } 1202 x, ok := v.(*Num) 1203 if !ok { 1204 c.typeErrorAs(v, NumberKind, as) 1205 return zero 1206 } 1207 return x 1208 } 1209 1210 func (c *OpContext) Int64(v Value) int64 { 1211 v = Unwrap(v) 1212 if isError(v) { 1213 return 0 1214 } 1215 x, ok := v.(*Num) 1216 if !ok { 1217 c.typeError(v, IntKind) 1218 return 0 1219 } 1220 i, err := x.X.Int64() 1221 if err != nil { 1222 c.AddErrf("number is not an int64: %v", err) 1223 return 0 1224 } 1225 return i 1226 } 1227 1228 func (c *OpContext) uint64(v Value, as string) uint64 { 1229 v = Unwrap(v) 1230 if isError(v) { 1231 return 0 1232 } 1233 x, ok := v.(*Num) 1234 if !ok { 1235 c.typeErrorAs(v, IntKind, as) 1236 return 0 1237 } 1238 if x.X.Negative { 1239 // TODO: improve message 1240 c.AddErrf("cannot convert negative number to uint64") 1241 return 0 1242 } 1243 if !x.X.Coeff.IsUint64() { 1244 // TODO: improve message 1245 c.AddErrf("cannot convert number %s to uint64", &x.X) 1246 return 0 1247 } 1248 return x.X.Coeff.Uint64() 1249 } 1250 1251 func (c *OpContext) BoolValue(v Value) bool { 1252 return c.boolValue(v, nil) 1253 } 1254 1255 func (c *OpContext) boolValue(v Value, as interface{}) bool { 1256 v = Unwrap(v) 1257 if isError(v) { 1258 return false 1259 } 1260 x, ok := v.(*Bool) 1261 if !ok { 1262 c.typeErrorAs(v, BoolKind, as) 1263 return false 1264 } 1265 return x.B 1266 } 1267 1268 func (c *OpContext) StringValue(v Value) string { 1269 return c.stringValue(v, nil) 1270 } 1271 1272 // ToBytes returns the bytes value of a scalar value. 1273 func (c *OpContext) ToBytes(v Value) []byte { 1274 if x, ok := v.(*Bytes); ok { 1275 return x.B 1276 } 1277 return []byte(c.ToString(v)) 1278 } 1279 1280 // ToString returns the string value of a scalar value. 1281 func (c *OpContext) ToString(v Value) string { 1282 return c.toStringValue(v, StringKind|NumberKind|BytesKind|BoolKind, nil) 1283 1284 } 1285 1286 func (c *OpContext) stringValue(v Value, as interface{}) string { 1287 return c.toStringValue(v, StringKind, as) 1288 } 1289 1290 func (c *OpContext) toStringValue(v Value, k Kind, as interface{}) string { 1291 v = Unwrap(v) 1292 if isError(v) { 1293 return "" 1294 } 1295 if v.Kind()&k == 0 { 1296 if as == nil { 1297 c.typeError(v, k) 1298 } else { 1299 c.typeErrorAs(v, k, as) 1300 } 1301 return "" 1302 } 1303 switch x := v.(type) { 1304 case *String: 1305 return x.Str 1306 1307 case *Bytes: 1308 return bytesToString(x.B) 1309 1310 case *Num: 1311 return x.X.String() 1312 1313 case *Bool: 1314 if x.B { 1315 return "true" 1316 } 1317 return "false" 1318 1319 default: 1320 c.addErrf(IncompleteError, c.pos(), 1321 "non-concrete value %s (type %s)", v, v.Kind()) 1322 } 1323 return "" 1324 } 1325 1326 func bytesToString(b []byte) string { 1327 b, _ = unicode.UTF8.NewDecoder().Bytes(b) 1328 return string(b) 1329 } 1330 1331 func (c *OpContext) bytesValue(v Value, as interface{}) []byte { 1332 v = Unwrap(v) 1333 if isError(v) { 1334 return nil 1335 } 1336 x, ok := v.(*Bytes) 1337 if !ok { 1338 c.typeErrorAs(v, BytesKind, as) 1339 return nil 1340 } 1341 return x.B 1342 } 1343 1344 var matchNone = regexp.MustCompile("^$") 1345 1346 func (c *OpContext) regexp(v Value) *regexp.Regexp { 1347 v = Unwrap(v) 1348 if isError(v) { 1349 return matchNone 1350 } 1351 switch x := v.(type) { 1352 case *String: 1353 if x.RE != nil { 1354 return x.RE 1355 } 1356 // TODO: synchronization 1357 p, err := regexp.Compile(x.Str) 1358 if err != nil { 1359 // FatalError? How to cache error 1360 c.AddErrf("invalid regexp: %s", err) 1361 x.RE = matchNone 1362 } else { 1363 x.RE = p 1364 } 1365 return x.RE 1366 1367 case *Bytes: 1368 if x.RE != nil { 1369 return x.RE 1370 } 1371 // TODO: synchronization 1372 p, err := regexp.Compile(string(x.B)) 1373 if err != nil { 1374 c.AddErrf("invalid regexp: %s", err) 1375 x.RE = matchNone 1376 } else { 1377 x.RE = p 1378 } 1379 return x.RE 1380 1381 default: 1382 c.typeError(v, StringKind|BytesKind) 1383 return matchNone 1384 } 1385 } 1386 1387 // newNum creates a new number of the given kind. It reports an error value 1388 // instead if any error occurred. 1389 func (c *OpContext) newNum(d *apd.Decimal, k Kind, sources ...Node) Value { 1390 if c.HasErr() { 1391 return c.Err() 1392 } 1393 return &Num{Src: c.src, X: *d, K: k} 1394 } 1395 1396 func (c *OpContext) NewInt64(n int64, sources ...Node) Value { 1397 if c.HasErr() { 1398 return c.Err() 1399 } 1400 d := apd.New(n, 0) 1401 return &Num{Src: c.src, X: *d, K: IntKind} 1402 } 1403 1404 func (c *OpContext) NewString(s string) Value { 1405 if c.HasErr() { 1406 return c.Err() 1407 } 1408 return &String{Src: c.src, Str: s} 1409 } 1410 1411 func (c *OpContext) newBytes(b []byte) Value { 1412 if c.HasErr() { 1413 return c.Err() 1414 } 1415 return &Bytes{Src: c.src, B: b} 1416 } 1417 1418 func (c *OpContext) newBool(b bool) Value { 1419 if c.HasErr() { 1420 return c.Err() 1421 } 1422 return &Bool{Src: c.src, B: b} 1423 } 1424 1425 func (c *OpContext) newList(src ast.Node, parent *Vertex) *Vertex { 1426 return c.newInlineVertex(parent, &ListMarker{}) 1427 } 1428 1429 // Str reports a debug string of x. 1430 func (c *OpContext) Str(x Node) string { 1431 if c.Format == nil { 1432 return fmt.Sprintf("%T", x) 1433 } 1434 return c.Format(c.Runtime, x) 1435 } 1436 1437 // NewList returns a new list for the given values. 1438 func (c *OpContext) NewList(values ...Value) *Vertex { 1439 // TODO: consider making this a literal list instead. 1440 list := &ListLit{} 1441 v := c.newInlineVertex(nil, nil, Conjunct{Env: nil, x: list}) 1442 1443 for _, x := range values { 1444 list.Elems = append(list.Elems, x) 1445 } 1446 v.Finalize(c) 1447 return v 1448 }