github.com/solo-io/cue@v0.4.7/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 "log" 20 "os" 21 "reflect" 22 "regexp" 23 24 "github.com/cockroachdb/apd/v2" 25 "golang.org/x/text/encoding/unicode" 26 27 "github.com/solo-io/cue/cue/ast" 28 "github.com/solo-io/cue/cue/errors" 29 "github.com/solo-io/cue/cue/token" 30 ) 31 32 // Debug sets whether extra aggressive checking should be done. 33 // This should typically default to true for pre-releases and default to 34 // false otherwise. 35 var Debug bool = os.Getenv("CUE_DEBUG") != "0" 36 37 // Verbosity sets the log level. There are currently only two levels: 38 // 39 // 0: no logging 40 // 1: logging 41 var Verbosity int 42 43 // Assert panics if the condition is false. Assert can be used to check for 44 // conditions that are considers to break an internal variant or unexpected 45 // condition, but that nonetheless probably will be handled correctly down the 46 // line. For instance, a faulty condition could lead to to error being caught 47 // down the road, but resulting in an inaccurate error message. In production 48 // code it is better to deal with the bad error message than to panic. 49 // 50 // It is advisable for each use of Assert to document how the error is expected 51 // to be handled down the line. 52 func Assertf(b bool, format string, args ...interface{}) { 53 if Debug && !b { 54 panic(fmt.Sprintf("assertion failed: "+format, args...)) 55 } 56 } 57 58 // Assertf either panics or reports an error to c if the condition is not met. 59 func (c *OpContext) Assertf(pos token.Pos, b bool, format string, args ...interface{}) { 60 if !b { 61 if Debug { 62 panic(fmt.Sprintf("assertion failed: "+format, args...)) 63 } 64 c.addErrf(0, pos, format, args...) 65 } 66 } 67 68 func init() { 69 log.SetFlags(log.Lshortfile) 70 } 71 72 func Logf(format string, args ...interface{}) { 73 if Verbosity == 0 { 74 return 75 } 76 s := fmt.Sprintf(format, args...) 77 _ = log.Output(2, s) 78 } 79 80 var pMap = map[*Vertex]int{} 81 82 func (c *OpContext) Logf(v *Vertex, format string, args ...interface{}) { 83 if Verbosity == 0 { 84 return 85 } 86 p := pMap[v] 87 if p == 0 { 88 p = len(pMap) + 1 89 pMap[v] = p 90 } 91 a := append([]interface{}{ 92 p, 93 v.Label.SelectorString(c), 94 v.Path(), 95 }, args...) 96 for i := 2; i < len(a); i++ { 97 switch x := a[i].(type) { 98 case Node: 99 a[i] = c.Str(x) 100 case Feature: 101 a[i] = x.SelectorString(c) 102 } 103 } 104 s := fmt.Sprintf(" [%d] %s/%v"+format, a...) 105 _ = log.Output(2, s) 106 } 107 108 // Runtime defines an interface for low-level representation conversion and 109 // lookup. 110 type Runtime interface { 111 // StringIndexer allows for converting string labels to and from a 112 // canonical numeric representation. 113 StringIndexer 114 115 // LoadImport loads a unique Vertex associated with a given import path. It 116 // returns an error if no import for this package could be found. 117 LoadImport(importPath string) (*Vertex, errors.Error) 118 119 // StoreType associates a CUE expression with a Go type. 120 StoreType(t reflect.Type, src ast.Expr, expr Expr) 121 122 // LoadType retrieves a previously stored CUE expression for a given Go 123 // type if available. 124 LoadType(t reflect.Type) (src ast.Expr, expr Expr, ok bool) 125 } 126 127 type Config struct { 128 Runtime 129 Format func(Node) string 130 } 131 132 // New creates an operation context. 133 func New(v *Vertex, cfg *Config) *OpContext { 134 if cfg.Runtime == nil { 135 panic("nil Runtime") 136 } 137 ctx := &OpContext{ 138 Runtime: cfg.Runtime, 139 Format: cfg.Format, 140 vertex: v, 141 } 142 if v != nil { 143 ctx.e = &Environment{Up: nil, Vertex: v} 144 } 145 return ctx 146 } 147 148 // An OpContext implements CUE's unification operation. It's operations only 149 // operation on values that are created with the Runtime with which an OpContext 150 // is associated. An OpContext is not goroutine save and only one goroutine may 151 // use an OpContext at a time. 152 type OpContext struct { 153 Runtime 154 Format func(Node) string 155 156 stats Stats 157 freeListNode *nodeContext 158 159 e *Environment 160 src ast.Node 161 errs *Bottom 162 positions []Node // keep track of error positions 163 164 // vertex is used to determine the path location in case of error. Turning 165 // this into a stack could also allow determining the cyclic path for 166 // structural cycle errors. 167 vertex *Vertex 168 169 nonMonotonicLookupNest int32 170 nonMonotonicRejectNest int32 171 nonMonotonicInsertNest int32 172 nonMonotonicGeneration int32 173 174 // These fields are used associate scratch fields for computing closedness 175 // of a Vertex. These fields could have been included in StructInfo (like 176 // Tomabechi's unification algorithm), but we opted for an indirection to 177 // allow concurrent unification. 178 // 179 // TODO(perf): have two generations: one for each pass of the closedness 180 // algorithm, so that the results of the first pass can be reused for all 181 // features of a node. 182 generation int 183 closed map[*closeInfo]*closeStats 184 todo *closeStats 185 186 // inDisjunct indicates that non-monotonic checks should be skipped. 187 // This is used if we want to do some extra work to eliminate disjunctions 188 // early. The result of unificantion should be thrown away if this check is 189 // used. 190 // 191 // TODO: replace this with a mechanism to determine the correct set (per 192 // conjunct) of StructInfos to include in closedness checking. 193 inDisjunct int 194 195 // inConstaint overrides inDisjunct as field matching should always be 196 // enabled. 197 inConstraint int 198 } 199 200 func (n *nodeContext) skipNonMonotonicChecks() bool { 201 if n.ctx.inConstraint > 0 { 202 return false 203 } 204 return n.ctx.inDisjunct > 0 205 } 206 207 // Impl is for internal use only. This will go. 208 func (c *OpContext) Impl() Runtime { 209 return c.Runtime 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 node.Parent = c.e.Vertex // TODO: Is this necessary? 237 return &Environment{ 238 Up: c.e, 239 Vertex: node, 240 241 // Copy cycle data. 242 Cyclic: c.e.Cyclic, 243 Deref: c.e.Deref, 244 Cycles: c.e.Cycles, 245 } 246 } 247 248 func (c *OpContext) Env(upCount int32) *Environment { 249 e := c.e 250 for ; upCount > 0; upCount-- { 251 e = e.Up 252 } 253 return e 254 } 255 256 func (c *OpContext) relNode(upCount int32) *Vertex { 257 e := c.e 258 for ; upCount > 0; upCount-- { 259 e = e.Up 260 } 261 c.Unify(e.Vertex, Partial) 262 return e.Vertex 263 } 264 265 func (c *OpContext) relLabel(upCount int32) Feature { 266 // locate current label. 267 e := c.e 268 for ; upCount > 0; upCount-- { 269 e = e.Up 270 } 271 return e.DynamicLabel 272 } 273 274 func (c *OpContext) concreteIsPossible(op Op, x Expr) bool { 275 if !AssertConcreteIsPossible(op, x) { 276 // No need to take position of expression. 277 c.AddErr(c.NewPosf(token.NoPos, 278 "invalid operand %s ('%s' requires concrete value)", x, op)) 279 return false 280 } 281 return true 282 } 283 284 // Assert that the given expression can evaluate to a concrete value. 285 func AssertConcreteIsPossible(op Op, x Expr) bool { 286 switch v := x.(type) { 287 case *Bottom: 288 case *BoundExpr: 289 return false 290 case Value: 291 return v.Concreteness() == Concrete 292 } 293 return true 294 } 295 296 // HasErr reports whether any error was reported, including whether value 297 // was incomplete. 298 func (c *OpContext) HasErr() bool { 299 return c.errs != nil 300 } 301 302 func (c *OpContext) Err() *Bottom { 303 b := c.errs 304 c.errs = nil 305 return b 306 } 307 308 func (c *OpContext) addErrf(code ErrorCode, pos token.Pos, msg string, args ...interface{}) { 309 err := c.NewPosf(pos, msg, args...) 310 c.addErr(code, err) 311 } 312 313 func (c *OpContext) addErr(code ErrorCode, err errors.Error) { 314 c.AddBottom(&Bottom{Code: code, Err: err}) 315 } 316 317 // AddBottom records an error in OpContext. 318 func (c *OpContext) AddBottom(b *Bottom) { 319 c.errs = CombineErrors(c.src, c.errs, b) 320 } 321 322 // AddErr records an error in OpContext. It returns errors collected so far. 323 func (c *OpContext) AddErr(err errors.Error) *Bottom { 324 if err != nil { 325 c.AddBottom(&Bottom{Err: err}) 326 } 327 return c.errs 328 } 329 330 // NewErrf creates a *Bottom value and returns it. The returned uses the 331 // current source as the point of origin of the error. 332 func (c *OpContext) NewErrf(format string, args ...interface{}) *Bottom { 333 // TODO: consider renaming ot NewBottomf: this is now confusing as we also 334 // have Newf. 335 err := c.Newf(format, args...) 336 return &Bottom{Src: c.src, Err: err, Code: EvalError} 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 } 349 350 func (c *OpContext) PushState(env *Environment, src ast.Node) (saved frame) { 351 saved.env = c.e 352 saved.err = c.errs 353 saved.src = c.src 354 355 c.errs = nil 356 if src != nil { 357 c.src = src 358 } 359 c.e = env 360 361 return saved 362 } 363 364 func (c *OpContext) PopState(s frame) *Bottom { 365 err := c.errs 366 c.e = s.env 367 c.errs = s.err 368 c.src = s.src 369 return err 370 } 371 372 // PushArc signals c that arc v is currently being processed for the purpose 373 // of error reporting. PopArc should be called with the returned value once 374 // processing of v is completed. 375 func (c *OpContext) PushArc(v *Vertex) (saved *Vertex) { 376 c.vertex, saved = v, c.vertex 377 return saved 378 } 379 380 // PopArc signals completion of processing the current arc. 381 func (c *OpContext) PopArc(saved *Vertex) { 382 c.vertex = saved 383 } 384 385 // Resolve finds a node in the tree. 386 // 387 // Should only be used to insert Conjuncts. TODO: perhaps only return Conjuncts 388 // and error. 389 func (c *OpContext) Resolve(env *Environment, r Resolver) (*Vertex, *Bottom) { 390 s := c.PushState(env, r.Source()) 391 392 arc := r.resolve(c, Partial) 393 394 err := c.PopState(s) 395 if err != nil { 396 return nil, err 397 } 398 399 if arc.ChildErrors != nil && arc.ChildErrors.Code == StructuralCycleError { 400 return nil, arc.ChildErrors 401 } 402 403 for { 404 x, ok := arc.BaseValue.(*Vertex) 405 if !ok { 406 break 407 } 408 arc = x 409 } 410 411 return arc, err 412 } 413 414 // Validate calls validates value for the given validator. 415 // 416 // TODO(errors): return boolean instead: only the caller has enough information 417 // to generate a proper error message. 418 func (c *OpContext) Validate(check Validator, value Value) *Bottom { 419 // TODO: use a position stack to push both values. 420 saved := c.src 421 c.src = check.Source() 422 423 err := check.validate(c, value) 424 425 c.src = saved 426 427 return err 428 } 429 430 // Yield evaluates a Yielder and calls f for each result. 431 func (c *OpContext) Yield(env *Environment, y Yielder, f YieldFunc) *Bottom { 432 s := c.PushState(env, y.Source()) 433 434 y.yield(c, f) 435 436 return c.PopState(s) 437 438 } 439 440 // Concrete returns the concrete value of x after evaluating it. 441 // msg is used to mention the context in which an error occurred, if any. 442 func (c *OpContext) Concrete(env *Environment, x Expr, msg interface{}) (result Value, complete bool) { 443 444 w, complete := c.Evaluate(env, x) 445 446 w, ok := c.getDefault(w) 447 if !ok { 448 return w, false 449 } 450 v := Unwrap(w) 451 452 if !IsConcrete(v) { 453 complete = false 454 b := c.NewErrf("non-concrete value %v in operand to %s", w, msg) 455 b.Code = IncompleteError 456 v = b 457 } 458 459 if !complete { 460 return v, complete 461 } 462 463 return v, true 464 } 465 466 // getDefault resolves a disjunction to a single value. If there is no default 467 // value, or if there is more than one default value, it reports an "incomplete" 468 // error and return false. In all other cases it will return true, even if 469 // v is already an error. v may be nil, in which case it will also return nil. 470 func (c *OpContext) getDefault(v Value) (result Value, ok bool) { 471 var d *Disjunction 472 switch x := v.(type) { 473 default: 474 return v, true 475 476 case *Vertex: 477 // TODO: return vertex if not disjunction. 478 switch t := x.BaseValue.(type) { 479 case *Disjunction: 480 d = t 481 482 case *Vertex: 483 return c.getDefault(t) 484 485 default: 486 return x, true 487 } 488 489 case *Disjunction: 490 d = x 491 } 492 493 if d.NumDefaults != 1 { 494 c.addErrf(IncompleteError, c.pos(), 495 "unresolved disjunction %s (type %s)", d, d.Kind()) 496 return nil, false 497 } 498 return c.getDefault(d.Values[0]) 499 } 500 501 // Evaluate evaluates an expression within the given environment and indicates 502 // whether the result is complete. It will always return a non-nil result. 503 func (c *OpContext) Evaluate(env *Environment, x Expr) (result Value, complete bool) { 504 s := c.PushState(env, x.Source()) 505 506 val := c.evalState(x, Partial) 507 508 complete = true 509 510 if err, _ := val.(*Bottom); err != nil && err.IsIncomplete() { 511 complete = false 512 } 513 if val == nil { 514 complete = false 515 // TODO ENSURE THIS DOESN"T HAPPEN> 516 val = &Bottom{ 517 Code: IncompleteError, 518 Err: c.Newf("UNANTICIPATED ERROR"), 519 } 520 521 } 522 523 _ = c.PopState(s) 524 525 if !complete || val == nil { 526 return val, false 527 } 528 529 return val, true 530 } 531 532 func (c *OpContext) evaluateRec(env *Environment, x Expr, state VertexStatus) Value { 533 s := c.PushState(env, x.Source()) 534 535 val := c.evalState(x, state) 536 if val == nil { 537 // Be defensive: this never happens, but just in case. 538 Assertf(false, "nil return value: unspecified error") 539 val = &Bottom{ 540 Code: IncompleteError, 541 Err: c.Newf("UNANTICIPATED ERROR"), 542 } 543 } 544 _ = c.PopState(s) 545 546 return val 547 } 548 549 // value evaluates expression v within the current environment. The result may 550 // be nil if the result is incomplete. value leaves errors untouched to that 551 // they can be collected by the caller. 552 func (c *OpContext) value(x Expr) (result Value) { 553 v := c.evalState(x, Partial) 554 555 v, _ = c.getDefault(v) 556 v = Unwrap(v) 557 return v 558 } 559 560 func (c *OpContext) evalState(v Expr, state VertexStatus) (result Value) { 561 savedSrc := c.src 562 c.src = v.Source() 563 err := c.errs 564 c.errs = nil 565 566 defer func() { 567 c.errs = CombineErrors(c.src, c.errs, err) 568 569 if v, ok := result.(*Vertex); ok { 570 if b, _ := v.BaseValue.(*Bottom); b != nil { 571 switch b.Code { 572 case IncompleteError: 573 case CycleError: 574 if state == Partial { 575 break 576 } 577 fallthrough 578 default: 579 result = b 580 } 581 } 582 } 583 584 // TODO: remove this when we handle errors more principally. 585 if b, ok := result.(*Bottom); ok { 586 if c.src != nil && 587 b.Code == CycleError && 588 len(errors.Positions(b.Err)) == 0 { 589 bb := *b 590 bb.Err = errors.Wrapf(b.Err, c.src.Pos(), "") 591 result = &bb 592 } 593 if c.errs != result { 594 c.errs = CombineErrors(c.src, c.errs, result) 595 } 596 } 597 if c.errs != nil { 598 result = c.errs 599 } 600 c.src = savedSrc 601 }() 602 603 switch x := v.(type) { 604 case Value: 605 return x 606 607 case Evaluator: 608 v := x.evaluate(c) 609 return v 610 611 case Resolver: 612 arc := x.resolve(c, state) 613 if c.HasErr() { 614 return nil 615 } 616 if arc == nil { 617 return nil 618 } 619 620 v := c.evaluate(arc, state) 621 return v 622 623 default: 624 // This can only happen, really, if v == nil, which is not allowed. 625 panic(fmt.Sprintf("unexpected Expr type %T", v)) 626 } 627 } 628 629 // unifyNode returns a possibly partially evaluated node value. 630 // 631 // TODO: maybe return *Vertex, *Bottom 632 func (c *OpContext) unifyNode(v Expr, state VertexStatus) (result Value) { 633 savedSrc := c.src 634 c.src = v.Source() 635 err := c.errs 636 c.errs = nil 637 638 defer func() { 639 c.errs = CombineErrors(c.src, c.errs, err) 640 641 if v, ok := result.(*Vertex); ok { 642 if b, _ := v.BaseValue.(*Bottom); b != nil { 643 switch b.Code { 644 case IncompleteError: 645 case CycleError: 646 if state == Partial { 647 break 648 } 649 fallthrough 650 default: 651 result = b 652 } 653 } 654 } 655 656 // TODO: remove this when we handle errors more principally. 657 if b, ok := result.(*Bottom); ok { 658 if c.src != nil && 659 b.Code == CycleError && 660 b.Err.Position() == token.NoPos && 661 len(b.Err.InputPositions()) == 0 { 662 bb := *b 663 bb.Err = errors.Wrapf(b.Err, c.src.Pos(), "") 664 result = &bb 665 } 666 c.errs = CombineErrors(c.src, c.errs, result) 667 } 668 if c.errs != nil { 669 result = c.errs 670 } 671 c.src = savedSrc 672 }() 673 674 switch x := v.(type) { 675 case Value: 676 return x 677 678 case Evaluator: 679 v := x.evaluate(c) 680 return v 681 682 case Resolver: 683 v := x.resolve(c, state) 684 if c.HasErr() { 685 return nil 686 } 687 if v == nil { 688 return nil 689 } 690 691 if v.isUndefined() { 692 // Use node itself to allow for cycle detection. 693 c.Unify(v, AllArcs) 694 } 695 696 return v 697 698 default: 699 // This can only happen, really, if v == nil, which is not allowed. 700 panic(fmt.Sprintf("unexpected Expr type %T", v)) 701 } 702 } 703 704 func (c *OpContext) lookup(x *Vertex, pos token.Pos, l Feature, state VertexStatus) *Vertex { 705 if l == InvalidLabel || x == nil { 706 // TODO: is it possible to have an invalid label here? Maybe through the 707 // API? 708 return &Vertex{} 709 } 710 711 // var kind Kind 712 // if x.BaseValue != nil { 713 // kind = x.BaseValue.Kind() 714 // } 715 716 switch x.BaseValue.(type) { 717 case *StructMarker: 718 if l.Typ() == IntLabel { 719 c.addErrf(0, pos, "invalid struct selector %s (type int)", l) 720 return nil 721 } 722 723 case *ListMarker: 724 switch { 725 case l.Typ() == IntLabel: 726 switch { 727 case l.Index() < 0: 728 c.addErrf(0, pos, "invalid list index %s (index must be non-negative)", l) 729 return nil 730 case l.Index() > len(x.Arcs): 731 c.addErrf(0, pos, "invalid list index %s (out of bounds)", l) 732 return nil 733 } 734 735 case l.IsDef(), l.IsHidden(): 736 737 default: 738 c.addErrf(0, pos, "invalid list index %s (type string)", l) 739 return nil 740 } 741 742 case nil: 743 // c.addErrf(IncompleteError, pos, "incomplete value %s", x) 744 // return nil 745 746 case *Bottom: 747 748 default: 749 kind := x.BaseValue.Kind() 750 if kind&(ListKind|StructKind) != 0 { 751 // c.addErrf(IncompleteError, pos, 752 // "cannot look up %s in incomplete type %s (type %s)", 753 // l, x.Source(), kind) 754 // return nil 755 } else if !l.IsDef() && !l.IsHidden() { 756 c.addErrf(0, pos, 757 "invalid selector %s for value of type %s", l, kind) 758 return nil 759 } 760 } 761 762 a := x.Lookup(l) 763 764 if a == nil { 765 if disjunction, ok := x.BaseValue.(*Disjunction); ok { 766 for _, val := range disjunction.Values { 767 a = val.Lookup(l) 768 if a != nil { 769 break 770 } 771 } 772 } 773 } 774 775 var hasCycle bool 776 outer: 777 switch { 778 case c.nonMonotonicLookupNest == 0 && c.nonMonotonicRejectNest == 0: 779 case a != nil: 780 if state == Partial { 781 a.nonMonotonicLookupGen = c.nonMonotonicGeneration 782 } 783 784 case x.state != nil && state == Partial: 785 for _, e := range x.state.exprs { 786 if isCyclePlaceholder(e.err) { 787 hasCycle = true 788 } 789 } 790 for _, a := range x.state.usedArcs { 791 if a.Label == l { 792 a.nonMonotonicLookupGen = c.nonMonotonicGeneration 793 if c.nonMonotonicRejectNest > 0 { 794 a.nonMonotonicReject = true 795 } 796 break outer 797 } 798 } 799 a := &Vertex{Label: l, nonMonotonicLookupGen: c.nonMonotonicGeneration} 800 if c.nonMonotonicRejectNest > 0 { 801 a.nonMonotonicReject = true 802 } 803 x.state.usedArcs = append(x.state.usedArcs, a) 804 } 805 if a == nil { 806 if x.state != nil { 807 for _, e := range x.state.exprs { 808 if isCyclePlaceholder(e.err) { 809 hasCycle = true 810 } 811 } 812 } 813 code := IncompleteError 814 if !x.Accept(c, l) { 815 code = 0 816 } else if hasCycle { 817 code = CycleError 818 } 819 // TODO: if the struct was a literal struct, we can also treat it as 820 // closed and make this a permanent error. 821 label := l.SelectorString(c.Runtime) 822 823 // TODO(errors): add path reference and make message 824 // "undefined field %s in %s" 825 if l.IsInt() { 826 c.addErrf(code, pos, "index out of range [%d] with length %d", 827 l.Index(), len(x.Elems())) 828 } else { 829 if code != 0 && x.IsOptional(l) { 830 c.addErrf(code, pos, 831 "cannot reference optional field: %s", label) 832 } else { 833 c.addErrf(code, pos, "undefined field: %s", label) 834 } 835 } 836 } 837 return a 838 } 839 840 func (c *OpContext) Label(src Expr, x Value) Feature { 841 return labelFromValue(c, src, x) 842 } 843 844 func (c *OpContext) typeError(v Value, k Kind) { 845 if isError(v) { 846 return 847 } 848 if !IsConcrete(v) && v.Kind()&k != 0 { 849 c.addErrf(IncompleteError, pos(v), "incomplete %s: %s", k, v) 850 } else { 851 c.AddErrf("cannot use %s (type %s) as type %s", v, v.Kind(), k) 852 } 853 } 854 855 func (c *OpContext) typeErrorAs(v Value, k Kind, as interface{}) { 856 if as == nil { 857 c.typeError(v, k) 858 return 859 } 860 if isError(v) { 861 return 862 } 863 if !IsConcrete(v) && v.Kind()&k != 0 { 864 c.addErrf(IncompleteError, pos(v), 865 "incomplete %s in %v: %s", k, as, v) 866 } else { 867 c.AddErrf("cannot use %s (type %s) as type %s in %v", v, v.Kind(), k, as) 868 } 869 } 870 871 var emptyNode = &Vertex{} 872 873 func pos(x Node) token.Pos { 874 if x.Source() == nil { 875 return token.NoPos 876 } 877 return x.Source().Pos() 878 } 879 880 func (c *OpContext) node(orig Node, x Expr, scalar bool, state VertexStatus) *Vertex { 881 // TODO: always get the vertex. This allows a whole bunch of trickery 882 // down the line. 883 v := c.unifyNode(x, state) 884 885 v, ok := c.getDefault(v) 886 if !ok { 887 // Error already generated by getDefault. 888 return emptyNode 889 } 890 891 // The two if blocks below are rather subtle. If we have an error of 892 // the sentinel value cycle, we have earlier determined that the cycle is 893 // allowed and that it can be ignored here. Any other CycleError is an 894 // annotated cycle error that could be taken as is. 895 // TODO: do something simpler. 896 if scalar { 897 if w := Unwrap(v); !isCyclePlaceholder(w) { 898 v = w 899 } 900 } 901 902 node, ok := v.(*Vertex) 903 if ok && !isCyclePlaceholder(node.BaseValue) { 904 v = node.Value() 905 } 906 907 switch nv := v.(type) { 908 case nil: 909 switch orig.(type) { 910 case *ForClause: 911 c.addErrf(IncompleteError, pos(x), 912 "cannot range over %s (incomplete)", x) 913 default: 914 c.addErrf(IncompleteError, pos(x), 915 "%s undefined (%s is incomplete)", orig, x) 916 } 917 return emptyNode 918 919 case *Bottom: 920 // TODO: this is a bit messy. In some cases errors are already added 921 // and in some cases not. Not a huge deal, as errors will be uniqued 922 // down the line, but could be better. 923 c.AddBottom(nv) 924 return emptyNode 925 926 case *Vertex: 927 if node == nil { 928 panic("unexpected markers with nil node") 929 } 930 931 default: 932 if kind := v.Kind(); kind&StructKind != 0 { 933 switch orig.(type) { 934 case *ForClause: 935 c.addErrf(IncompleteError, pos(x), 936 "cannot range over %s (incomplete type %s)", x, kind) 937 default: 938 c.addErrf(IncompleteError, pos(x), 939 "%s undefined as %s is incomplete (type %s)", orig, x, kind) 940 } 941 return emptyNode 942 943 } else if !ok { 944 c.addErrf(0, pos(x), // TODO(error): better message. 945 "invalid operand %s (found %s, want list or struct)", 946 x.Source(), v.Kind()) 947 return emptyNode 948 } 949 } 950 951 return node 952 } 953 954 // Elems returns the elements of a list. 955 func (c *OpContext) Elems(v Value) []*Vertex { 956 list := c.list(v) 957 return list.Elems() 958 } 959 960 func (c *OpContext) list(v Value) *Vertex { 961 x, ok := v.(*Vertex) 962 if !ok || !x.IsList() { 963 c.typeError(v, ListKind) 964 return emptyNode 965 } 966 return x 967 } 968 969 func (c *OpContext) scalar(v Value) Value { 970 v = Unwrap(v) 971 switch v.(type) { 972 case *Null, *Bool, *Num, *String, *Bytes: 973 default: 974 c.typeError(v, ScalarKinds) 975 } 976 return v 977 } 978 979 var zero = &Num{K: NumKind} 980 981 func (c *OpContext) Num(v Value, as interface{}) *Num { 982 v = Unwrap(v) 983 if isError(v) { 984 return zero 985 } 986 x, ok := v.(*Num) 987 if !ok { 988 c.typeErrorAs(v, NumKind, as) 989 return zero 990 } 991 return x 992 } 993 994 func (c *OpContext) Int64(v Value) int64 { 995 v = Unwrap(v) 996 if isError(v) { 997 return 0 998 } 999 x, ok := v.(*Num) 1000 if !ok { 1001 c.typeError(v, IntKind) 1002 return 0 1003 } 1004 i, err := x.X.Int64() 1005 if err != nil { 1006 c.AddErrf("number is not an int64: %v", err) 1007 return 0 1008 } 1009 return i 1010 } 1011 1012 func (c *OpContext) uint64(v Value, as string) uint64 { 1013 v = Unwrap(v) 1014 if isError(v) { 1015 return 0 1016 } 1017 x, ok := v.(*Num) 1018 if !ok { 1019 c.typeErrorAs(v, IntKind, as) 1020 return 0 1021 } 1022 if x.X.Negative { 1023 // TODO: improve message 1024 c.AddErrf("cannot convert negative number to uint64") 1025 return 0 1026 } 1027 if !x.X.Coeff.IsUint64() { 1028 // TODO: improve message 1029 c.AddErrf("cannot convert number %s to uint64", x.X) 1030 return 0 1031 } 1032 return x.X.Coeff.Uint64() 1033 } 1034 1035 func (c *OpContext) BoolValue(v Value) bool { 1036 return c.boolValue(v, nil) 1037 } 1038 1039 func (c *OpContext) boolValue(v Value, as interface{}) bool { 1040 v = Unwrap(v) 1041 if isError(v) { 1042 return false 1043 } 1044 x, ok := v.(*Bool) 1045 if !ok { 1046 c.typeErrorAs(v, BoolKind, as) 1047 return false 1048 } 1049 return x.B 1050 } 1051 1052 func (c *OpContext) StringValue(v Value) string { 1053 return c.stringValue(v, nil) 1054 } 1055 1056 // ToBytes returns the bytes value of a scalar value. 1057 func (c *OpContext) ToBytes(v Value) []byte { 1058 if x, ok := v.(*Bytes); ok { 1059 return x.B 1060 } 1061 return []byte(c.ToString(v)) 1062 } 1063 1064 // ToString returns the string value of a scalar value. 1065 func (c *OpContext) ToString(v Value) string { 1066 return c.toStringValue(v, StringKind|NumKind|BytesKind|BoolKind, nil) 1067 1068 } 1069 1070 func (c *OpContext) stringValue(v Value, as interface{}) string { 1071 return c.toStringValue(v, StringKind, as) 1072 } 1073 1074 func (c *OpContext) toStringValue(v Value, k Kind, as interface{}) string { 1075 v = Unwrap(v) 1076 if isError(v) { 1077 return "" 1078 } 1079 if v.Kind()&k == 0 { 1080 if as == nil { 1081 c.typeError(v, k) 1082 } else { 1083 c.typeErrorAs(v, k, as) 1084 } 1085 return "" 1086 } 1087 switch x := v.(type) { 1088 case *String: 1089 return x.Str 1090 1091 case *Bytes: 1092 return bytesToString(x.B) 1093 1094 case *Num: 1095 return x.X.String() 1096 1097 case *Bool: 1098 if x.B { 1099 return "true" 1100 } 1101 return "false" 1102 1103 default: 1104 c.addErrf(IncompleteError, c.pos(), 1105 "non-concrete value %s (type %s)", v, v.Kind()) 1106 } 1107 return "" 1108 } 1109 1110 func bytesToString(b []byte) string { 1111 b, _ = unicode.UTF8.NewDecoder().Bytes(b) 1112 return string(b) 1113 } 1114 1115 func (c *OpContext) bytesValue(v Value, as interface{}) []byte { 1116 v = Unwrap(v) 1117 if isError(v) { 1118 return nil 1119 } 1120 x, ok := v.(*Bytes) 1121 if !ok { 1122 c.typeErrorAs(v, BytesKind, as) 1123 return nil 1124 } 1125 return x.B 1126 } 1127 1128 var matchNone = regexp.MustCompile("^$") 1129 1130 func (c *OpContext) regexp(v Value) *regexp.Regexp { 1131 v = Unwrap(v) 1132 if isError(v) { 1133 return matchNone 1134 } 1135 switch x := v.(type) { 1136 case *String: 1137 if x.RE != nil { 1138 return x.RE 1139 } 1140 // TODO: synchronization 1141 p, err := regexp.Compile(x.Str) 1142 if err != nil { 1143 // FatalError? How to cache error 1144 c.AddErrf("invalid regexp: %s", err) 1145 x.RE = matchNone 1146 } else { 1147 x.RE = p 1148 } 1149 return x.RE 1150 1151 case *Bytes: 1152 if x.RE != nil { 1153 return x.RE 1154 } 1155 // TODO: synchronization 1156 p, err := regexp.Compile(string(x.B)) 1157 if err != nil { 1158 c.AddErrf("invalid regexp: %s", err) 1159 x.RE = matchNone 1160 } else { 1161 x.RE = p 1162 } 1163 return x.RE 1164 1165 default: 1166 c.typeError(v, StringKind|BytesKind) 1167 return matchNone 1168 } 1169 } 1170 1171 // newNum creates a new number of the given kind. It reports an error value 1172 // instead if any error occurred. 1173 func (c *OpContext) newNum(d *apd.Decimal, k Kind, sources ...Node) Value { 1174 if c.HasErr() { 1175 return c.Err() 1176 } 1177 return &Num{Src: c.src, X: *d, K: k} 1178 } 1179 1180 func (c *OpContext) NewInt64(n int64, sources ...Node) Value { 1181 if c.HasErr() { 1182 return c.Err() 1183 } 1184 d := apd.New(n, 0) 1185 return &Num{Src: c.src, X: *d, K: IntKind} 1186 } 1187 1188 func (c *OpContext) NewString(s string) Value { 1189 if c.HasErr() { 1190 return c.Err() 1191 } 1192 return &String{Src: c.src, Str: s} 1193 } 1194 1195 func (c *OpContext) newBytes(b []byte) Value { 1196 if c.HasErr() { 1197 return c.Err() 1198 } 1199 return &Bytes{Src: c.src, B: b} 1200 } 1201 1202 func (c *OpContext) newBool(b bool) Value { 1203 if c.HasErr() { 1204 return c.Err() 1205 } 1206 return &Bool{Src: c.src, B: b} 1207 } 1208 1209 func (c *OpContext) newList(src ast.Node, parent *Vertex) *Vertex { 1210 return &Vertex{Parent: parent, BaseValue: &ListMarker{}} 1211 } 1212 1213 // Str reports a debug string of x. 1214 func (c *OpContext) Str(x Node) string { 1215 if c.Format == nil { 1216 return fmt.Sprintf("%T", x) 1217 } 1218 return c.Format(x) 1219 } 1220 1221 // NewList returns a new list for the given values. 1222 func (c *OpContext) NewList(values ...Value) *Vertex { 1223 // TODO: consider making this a literal list instead. 1224 list := &ListLit{} 1225 v := &Vertex{ 1226 Conjuncts: []Conjunct{{Env: nil, x: list}}, 1227 } 1228 1229 for _, x := range values { 1230 list.Elems = append(list.Elems, x) 1231 } 1232 c.Unify(v, Finalized) 1233 return v 1234 }