github.com/joomcode/cue@v0.4.4-0.20221111115225-539fe3512047/internal/core/adt/expr.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 "bytes" 19 "fmt" 20 "io" 21 "regexp" 22 23 "github.com/cockroachdb/apd/v2" 24 25 "github.com/joomcode/cue/cue/ast" 26 "github.com/joomcode/cue/cue/errors" 27 "github.com/joomcode/cue/cue/token" 28 ) 29 30 // A StructLit represents an unevaluated struct literal or file body. 31 type StructLit struct { 32 Src ast.Node // ast.File or ast.StructLit 33 Decls []Decl 34 35 // TODO: record the merge order somewhere. 36 37 // The below fields are redundant to Decls and are computed with Init. 38 39 // field marks the optional conjuncts of all explicit Fields. 40 // Required Fields are marked as empty 41 Fields []FieldInfo 42 43 Dynamic []*DynamicField 44 45 // excluded are all literal fields that already exist. 46 Bulk []*BulkOptionalField 47 48 Additional []*Ellipsis 49 HasEmbed bool 50 IsOpen bool // has a ... 51 initialized bool 52 53 types OptionalType 54 55 // administrative fields like hasreferences. 56 // hasReferences bool 57 } 58 59 func (o *StructLit) IsFile() bool { 60 _, ok := o.Src.(*ast.File) 61 return ok 62 } 63 64 type FieldInfo struct { 65 Label Feature 66 Optional []Node 67 } 68 69 func (x *StructLit) HasOptional() bool { 70 return x.types&(HasField|HasPattern|HasAdditional) != 0 71 } 72 73 func (x *StructLit) Source() ast.Node { return x.Src } 74 75 func (x *StructLit) evaluate(c *OpContext) Value { 76 e := c.Env(0) 77 v := &Vertex{ 78 Parent: e.Vertex, 79 Conjuncts: []Conjunct{{e, x, CloseInfo{}}}, 80 } 81 // evaluate may not finalize a field, as the resulting value may be 82 // used in a context where more conjuncts are added. It may also lead 83 // to disjuncts being in a partially expanded state, leading to 84 // misaligned nodeContexts. 85 c.Unify(v, AllArcs) 86 return v 87 } 88 89 // TODO: remove this method 90 func (o *StructLit) MarkField(f Feature) { 91 o.Fields = append(o.Fields, FieldInfo{Label: f}) 92 } 93 94 func (o *StructLit) Init() { 95 if o.initialized { 96 return 97 } 98 o.initialized = true 99 for _, d := range o.Decls { 100 switch x := d.(type) { 101 case *Field: 102 if o.fieldIndex(x.Label) < 0 { 103 o.Fields = append(o.Fields, FieldInfo{Label: x.Label}) 104 } 105 106 case *OptionalField: 107 p := o.fieldIndex(x.Label) 108 if p < 0 { 109 p = len(o.Fields) 110 o.Fields = append(o.Fields, FieldInfo{Label: x.Label}) 111 } 112 o.Fields[p].Optional = append(o.Fields[p].Optional, x) 113 o.types |= HasField 114 115 case *DynamicField: 116 o.Dynamic = append(o.Dynamic, x) 117 o.types |= HasDynamic 118 119 case Expr: 120 o.HasEmbed = true 121 122 case *Comprehension: 123 o.HasEmbed = true 124 125 case *LetClause: 126 o.HasEmbed = true 127 128 case *BulkOptionalField: 129 o.Bulk = append(o.Bulk, x) 130 o.types |= HasPattern 131 switch x.Filter.(type) { 132 case *BasicType, *Top: 133 default: 134 o.types |= HasComplexPattern 135 } 136 137 case *Ellipsis: 138 switch x.Value.(type) { 139 case nil, *Top: 140 o.IsOpen = true 141 o.types |= IsOpen 142 143 default: 144 // TODO: consider only adding for non-top. 145 o.types |= HasAdditional 146 } 147 o.Additional = append(o.Additional, x) 148 149 default: 150 panic("unreachable") 151 } 152 } 153 } 154 155 func (o *StructLit) fieldIndex(f Feature) int { 156 for i := range o.Fields { 157 if o.Fields[i].Label == f { 158 return i 159 } 160 } 161 return -1 162 } 163 164 func (o *StructLit) OptionalTypes() OptionalType { 165 return o.types 166 } 167 168 func (o *StructLit) IsOptional(label Feature) bool { 169 for _, f := range o.Fields { 170 if f.Label == label && len(f.Optional) > 0 { 171 return true 172 } 173 } 174 return false 175 } 176 177 // FIELDS 178 // 179 // Fields can also be used as expressions whereby the value field is the 180 // expression this allows retaining more context. 181 182 // Field represents a field with a fixed label. It can be a regular field, 183 // definition or hidden field. 184 // 185 // foo: bar 186 // #foo: bar 187 // _foo: bar 188 // 189 // Legacy: 190 // 191 // Foo :: bar 192 // 193 type Field struct { 194 Src *ast.Field 195 196 Label Feature 197 Value Expr 198 } 199 200 func (x *Field) Source() ast.Node { 201 if x.Src == nil { 202 return nil 203 } 204 return x.Src 205 } 206 207 // An OptionalField represents an optional regular field. 208 // 209 // foo?: expr 210 // 211 type OptionalField struct { 212 Src *ast.Field 213 Label Feature 214 Value Expr 215 } 216 217 func (x *OptionalField) Source() ast.Node { 218 if x.Src == nil { 219 return nil 220 } 221 return x.Src 222 } 223 224 // A BulkOptionalField represents a set of optional field. 225 // 226 // [expr]: expr 227 // 228 type BulkOptionalField struct { 229 Src *ast.Field // Elipsis or Field 230 Filter Expr 231 Value Expr 232 Label Feature // for reference and formatting 233 } 234 235 func (x *BulkOptionalField) Source() ast.Node { 236 if x.Src == nil { 237 return nil 238 } 239 return x.Src 240 } 241 242 // A Ellipsis represents a set of optional fields of a given type. 243 // 244 // ...T 245 // 246 type Ellipsis struct { 247 Src *ast.Ellipsis 248 Value Expr 249 } 250 251 func (x *Ellipsis) Source() ast.Node { 252 if x.Src == nil { 253 return nil 254 } 255 return x.Src 256 } 257 258 // A DynamicField represents a regular field for which the key is computed. 259 // 260 // "\(expr)": expr 261 // (expr): expr 262 // 263 type DynamicField struct { 264 Src *ast.Field 265 Key Expr 266 Value Expr 267 } 268 269 func (x *DynamicField) IsOptional() bool { 270 return x.Src.Optional != token.NoPos 271 } 272 273 func (x *DynamicField) Source() ast.Node { 274 if x.Src == nil { 275 return nil 276 } 277 return x.Src 278 } 279 280 // A ListLit represents an unevaluated list literal. 281 // 282 // [a, for x in src { ... }, b, ...T] 283 // 284 type ListLit struct { 285 Src *ast.ListLit 286 287 // scalars, comprehensions, ...T 288 Elems []Elem 289 290 info *StructLit // Shared closedness info. 291 } 292 293 func (x *ListLit) Source() ast.Node { 294 if x.Src == nil { 295 return nil 296 } 297 return x.Src 298 } 299 300 func (x *ListLit) evaluate(c *OpContext) Value { 301 e := c.Env(0) 302 v := &Vertex{ 303 Parent: e.Vertex, 304 Conjuncts: []Conjunct{{e, x, CloseInfo{}}}, 305 } 306 // TODO: should be AllArcs and then use Finalize for builtins? 307 c.Unify(v, Finalized) // TODO: also partial okay? 308 return v 309 } 310 311 // Null represents null. It can be used as a Value and Expr. 312 type Null struct { 313 Src ast.Node 314 } 315 316 func (x *Null) Source() ast.Node { return x.Src } 317 func (x *Null) Kind() Kind { return NullKind } 318 319 // Bool is a boolean value. It can be used as a Value and Expr. 320 type Bool struct { 321 Src ast.Node 322 B bool 323 } 324 325 func (x *Bool) Source() ast.Node { return x.Src } 326 func (x *Bool) Kind() Kind { return BoolKind } 327 328 // Num is a numeric value. It can be used as a Value and Expr. 329 type Num struct { 330 Src ast.Node 331 K Kind // needed? 332 X apd.Decimal // Is integer if the apd.Decimal is an integer. 333 } 334 335 // TODO: do we need this? 336 // func NewNumFromString(src ast.Node, s string) Value { 337 // n := &Num{Src: src, K: IntKind} 338 // if strings.ContainsAny(s, "eE.") { 339 // n.K = FloatKind 340 // } 341 // _, _, err := n.X.SetString(s) 342 // if err != nil { 343 // pos := token.NoPos 344 // if src != nil { 345 // pos = src.Pos() 346 // } 347 // return &Bottom{Err: errors.Newf(pos, "invalid number: %v", err)} 348 // } 349 // return n 350 // } 351 352 func (x *Num) Source() ast.Node { return x.Src } 353 func (x *Num) Kind() Kind { return x.K } 354 355 // TODO: do we still need this? 356 // func (x *Num) Specialize(k Kind) Value { 357 // k = k & x.K 358 // if k == x.K { 359 // return x 360 // } 361 // y := *x 362 // y.K = k 363 // return &y 364 // } 365 366 // String is a string value. It can be used as a Value and Expr. 367 type String struct { 368 Src ast.Node 369 Str string 370 RE *regexp.Regexp // only set if needed 371 } 372 373 func (x *String) Source() ast.Node { return x.Src } 374 func (x *String) Kind() Kind { return StringKind } 375 376 // Bytes is a bytes value. It can be used as a Value and Expr. 377 type Bytes struct { 378 Src ast.Node 379 B []byte 380 RE *regexp.Regexp // only set if needed 381 } 382 383 func (x *Bytes) Source() ast.Node { return x.Src } 384 func (x *Bytes) Kind() Kind { return BytesKind } 385 386 // Composites: the evaluated fields of a composite are recorded in the arc 387 // vertices. 388 389 type ListMarker struct { 390 Src ast.Node 391 IsOpen bool 392 } 393 394 func (x *ListMarker) Source() ast.Node { return x.Src } 395 func (x *ListMarker) Kind() Kind { return ListKind } 396 func (x *ListMarker) node() {} 397 398 type StructMarker struct { 399 // NeedClose is used to signal that the evaluator should close this struct. 400 // It is only set by the close builtin. 401 NeedClose bool 402 } 403 404 func (x *StructMarker) Source() ast.Node { return nil } 405 func (x *StructMarker) Kind() Kind { return StructKind } 406 func (x *StructMarker) node() {} 407 408 // Top represents all possible values. It can be used as a Value and Expr. 409 type Top struct{ Src *ast.Ident } 410 411 func (x *Top) Source() ast.Node { 412 if x.Src == nil { 413 return nil 414 } 415 return x.Src 416 } 417 func (x *Top) Kind() Kind { return TopKind } 418 419 // BasicType represents all values of a certain Kind. It can be used as a Value 420 // and Expr. 421 // 422 // string 423 // int 424 // num 425 // bool 426 // 427 type BasicType struct { 428 Src ast.Node 429 K Kind 430 } 431 432 func (x *BasicType) Source() ast.Node { 433 if x.Src == nil { 434 return nil 435 } 436 return x.Src 437 } 438 func (x *BasicType) Kind() Kind { return x.K } 439 440 // TODO: do we still need this? 441 // func (x *BasicType) Specialize(k Kind) Value { 442 // k = x.K & k 443 // if k == x.K { 444 // return x 445 // } 446 // y := *x 447 // y.K = k 448 // return &y 449 // } 450 451 // TODO: should we use UnaryExpr for Bound now we have BoundValue? 452 453 // BoundExpr represents an unresolved unary comparator. 454 // 455 // <a 456 // =~MyPattern 457 // 458 type BoundExpr struct { 459 Src *ast.UnaryExpr 460 Op Op 461 Expr Expr 462 } 463 464 func (x *BoundExpr) Source() ast.Node { 465 if x.Src == nil { 466 return nil 467 } 468 return x.Src 469 } 470 471 func (x *BoundExpr) evaluate(ctx *OpContext) Value { 472 v := ctx.value(x.Expr) 473 if isError(v) { 474 return v 475 } 476 477 switch k := v.Kind(); k { 478 case IntKind, FloatKind, NumKind, StringKind, BytesKind: 479 case NullKind: 480 if x.Op != NotEqualOp { 481 err := ctx.NewPosf(pos(x.Expr), 482 "cannot use null for bound %s", x.Op) 483 return &Bottom{Err: err} 484 } 485 default: 486 mask := IntKind | FloatKind | NumKind | StringKind | BytesKind 487 if x.Op == NotEqualOp { 488 mask |= NullKind 489 } 490 if k&mask != 0 { 491 ctx.addErrf(IncompleteError, token.NoPos, // TODO(errors): use ctx.pos()? 492 "non-concrete value %s for bound %s", x.Expr, x.Op) 493 return nil 494 } 495 err := ctx.NewPosf(pos(x.Expr), 496 "invalid value %s (type %s) for bound %s", v, k, x.Op) 497 return &Bottom{Err: err} 498 } 499 500 if v, ok := x.Expr.(Value); ok { 501 if v == nil || v.Concreteness() > Concrete { 502 return ctx.NewErrf("bound has fixed non-concrete value") 503 } 504 return &BoundValue{x.Src, x.Op, v} 505 } 506 507 // This simplifies boundary expressions. It is an alternative to an 508 // evaluation strategy that makes nodes increasingly more specific. 509 // 510 // For instance, a completely different implementation would be to allow 511 // the precense of a concrete value to ignore incomplete errors. 512 // 513 // TODO: consider an alternative approach. 514 switch y := v.(type) { 515 case *BoundValue: 516 switch { 517 case y.Op == NotEqualOp: 518 switch x.Op { 519 case LessEqualOp, LessThanOp, GreaterEqualOp, GreaterThanOp: 520 // <(!=3) => number 521 // Smaller than an arbitrarily large number is any number. 522 return &BasicType{K: y.Kind()} 523 case NotEqualOp: 524 // !=(!=3) ==> 3 525 // Not a value that is anything but a given value is that 526 // given value. 527 return y.Value 528 } 529 530 case x.Op == NotEqualOp: 531 // Invert if applicable. 532 switch y.Op { 533 case LessEqualOp: 534 return &BoundValue{x.Src, GreaterThanOp, y.Value} 535 case LessThanOp: 536 return &BoundValue{x.Src, GreaterEqualOp, y.Value} 537 case GreaterEqualOp: 538 return &BoundValue{x.Src, LessThanOp, y.Value} 539 case GreaterThanOp: 540 return &BoundValue{x.Src, LessEqualOp, y.Value} 541 } 542 543 case (x.Op == LessThanOp || x.Op == LessEqualOp) && 544 (y.Op == GreaterThanOp || y.Op == GreaterEqualOp), 545 (x.Op == GreaterThanOp || x.Op == GreaterEqualOp) && 546 (y.Op == LessThanOp || y.Op == LessEqualOp): 547 // <(>=3) 548 // Something smaller than an arbitrarily large number is any number. 549 return &BasicType{K: y.Kind()} 550 551 case x.Op == LessThanOp && 552 (y.Op == LessEqualOp || y.Op == LessThanOp), 553 x.Op == GreaterThanOp && 554 (y.Op == GreaterEqualOp || y.Op == GreaterThanOp): 555 // <(<=x) => <x 556 // <(<x) => <x 557 // Less than something that is less or equal to x is less than x. 558 return &BoundValue{x.Src, x.Op, y.Value} 559 560 case x.Op == LessEqualOp && 561 (y.Op == LessEqualOp || y.Op == LessThanOp), 562 x.Op == GreaterEqualOp && 563 (y.Op == GreaterEqualOp || y.Op == GreaterThanOp): 564 // <=(<x) => <x 565 // <=(<=x) => <=x 566 // Less or equal than something that is less than x is less than x. 567 return y 568 } 569 570 case *BasicType: 571 switch x.Op { 572 case LessEqualOp, LessThanOp, GreaterEqualOp, GreaterThanOp: 573 return y 574 } 575 } 576 if v.Concreteness() > Concrete { 577 // TODO(errors): analyze dependencies of x.Expr to get positions. 578 ctx.addErrf(IncompleteError, token.NoPos, // TODO(errors): use ctx.pos()? 579 "non-concrete value %s for bound %s", x.Expr, x.Op) 580 return nil 581 } 582 return &BoundValue{x.Src, x.Op, v} 583 } 584 585 // A BoundValue is a fully evaluated unary comparator that can be used to 586 // validate other values. 587 // 588 // <5 589 // =~"Name$" 590 // 591 type BoundValue struct { 592 Src ast.Expr 593 Op Op 594 Value Value 595 } 596 597 func (x *BoundValue) Source() ast.Node { return x.Src } 598 func (x *BoundValue) Kind() Kind { 599 k := x.Value.Kind() 600 switch k { 601 case IntKind, FloatKind, NumKind: 602 return NumKind 603 604 case NullKind: 605 if x.Op == NotEqualOp { 606 return TopKind &^ NullKind 607 } 608 } 609 return k 610 } 611 612 func (x *BoundValue) validate(c *OpContext, y Value) *Bottom { 613 a := y // Can be list or struct. 614 b := c.scalar(x.Value) 615 if c.HasErr() { 616 return c.Err() 617 } 618 619 switch v := BinOp(c, x.Op, a, b).(type) { 620 case *Bottom: 621 return v 622 623 case *Bool: 624 if v.B { 625 return nil 626 } 627 // TODO(errors): use "invalid value %v (not an %s)" if x is a 628 // predeclared identifier such as `int`. 629 err := c.Newf("invalid value %v (out of bound %s)", y, x) 630 err.AddPosition(y) 631 return &Bottom{Src: c.src, Err: err, Code: EvalError} 632 633 default: 634 panic(fmt.Sprintf("unsupported type %T", v)) 635 } 636 } 637 638 func (x *BoundValue) validateStr(c *OpContext, a string) bool { 639 if str, ok := x.Value.(*String); ok { 640 b := str.Str 641 switch x.Op { 642 case LessEqualOp: 643 return a <= b 644 case LessThanOp: 645 return a < b 646 case GreaterEqualOp: 647 return a >= b 648 case GreaterThanOp: 649 return a > b 650 case EqualOp: 651 return a == b 652 case NotEqualOp: 653 return a != b 654 case MatchOp: 655 return c.regexp(x.Value).MatchString(a) 656 case NotMatchOp: 657 return !c.regexp(x.Value).MatchString(a) 658 } 659 } 660 return x.validate(c, &String{Str: a}) == nil 661 } 662 663 func (x *BoundValue) validateInt(c *OpContext, a int64) bool { 664 switch n := x.Value.(type) { 665 case *Num: 666 b, err := n.X.Int64() 667 if err != nil { 668 break 669 } 670 switch x.Op { 671 case LessEqualOp: 672 return a <= b 673 case LessThanOp: 674 return a < b 675 case GreaterEqualOp: 676 return a >= b 677 case GreaterThanOp: 678 return a > b 679 case EqualOp: 680 return a == b 681 case NotEqualOp: 682 return a != b 683 } 684 } 685 return x.validate(c, c.NewInt64(a)) == nil 686 } 687 688 // A NodeLink is used during computation to refer to an existing Vertex. 689 // It is used to signal a potential cycle or reference. 690 // Note that a NodeLink may be used as a value. This should be taken into 691 // account. 692 type NodeLink struct { 693 Node *Vertex 694 } 695 696 func (x *NodeLink) Kind() Kind { 697 return x.Node.Kind() 698 } 699 func (x *NodeLink) Source() ast.Node { return x.Node.Source() } 700 701 func (x *NodeLink) resolve(c *OpContext, state VertexStatus) *Vertex { 702 return x.Node 703 } 704 705 // A FieldReference represents a lexical reference to a field. 706 // 707 // a 708 // 709 type FieldReference struct { 710 Src *ast.Ident 711 UpCount int32 712 Label Feature 713 } 714 715 func (x *FieldReference) Source() ast.Node { 716 if x.Src == nil { 717 return nil 718 } 719 return x.Src 720 } 721 722 func (x *FieldReference) resolve(c *OpContext, state VertexStatus) *Vertex { 723 n := c.relNode(x.UpCount) 724 pos := pos(x) 725 return c.lookup(n, pos, x.Label, state) 726 } 727 728 // A ValueReference represents a lexical reference to a value. 729 // 730 // a: X=b 731 // 732 type ValueReference struct { 733 Src *ast.Ident 734 UpCount int32 735 Label Feature // for informative purposes 736 } 737 738 func (x *ValueReference) Source() ast.Node { 739 if x.Src == nil { 740 return nil 741 } 742 return x.Src 743 } 744 745 func (x *ValueReference) resolve(c *OpContext, state VertexStatus) *Vertex { 746 if x.UpCount == 0 { 747 return c.vertex 748 } 749 n := c.relNode(x.UpCount - 1) 750 return n 751 } 752 753 // A LabelReference refers to the string or integer value of a label. 754 // 755 // [X=Pattern]: b: X 756 // 757 type LabelReference struct { 758 Src *ast.Ident 759 UpCount int32 760 } 761 762 // TODO: should this implement resolver at all? 763 764 func (x *LabelReference) Source() ast.Node { 765 if x.Src == nil { 766 return nil 767 } 768 return x.Src 769 } 770 771 func (x *LabelReference) evaluate(ctx *OpContext) Value { 772 label := ctx.relLabel(x.UpCount) 773 if label == 0 { 774 // There is no label. This may happen if a LabelReference is evaluated 775 // outside of the context of a parent node, for instance if an 776 // "additional" items or properties is evaluated in isolation. 777 // 778 // TODO: this should return the pattern of the label. 779 return &BasicType{K: StringKind} 780 } 781 return label.ToValue(ctx) 782 } 783 784 // A DynamicReference is like a LabelReference, but with a computed label. 785 // 786 // X=(x): X 787 // X="\(x)": X 788 // 789 type DynamicReference struct { 790 Src *ast.Ident 791 UpCount int32 792 Label Expr 793 794 // TODO: only use aliases and store the actual expression only in the scope. 795 // The feature is unique for every instance. This will also allow dynamic 796 // fields to be ordered among normal fields. 797 // 798 // This could also be used to assign labels to embedded values, if they 799 // don't match a label. 800 Alias Feature 801 } 802 803 func (x *DynamicReference) Source() ast.Node { 804 if x.Src == nil { 805 return nil 806 } 807 return x.Src 808 } 809 810 func (x *DynamicReference) resolve(ctx *OpContext, state VertexStatus) *Vertex { 811 e := ctx.Env(x.UpCount) 812 frame := ctx.PushState(e, x.Src) 813 v := ctx.value(x.Label) 814 ctx.PopState(frame) 815 f := ctx.Label(x.Label, v) 816 return ctx.lookup(e.Vertex, pos(x), f, state) 817 } 818 819 // An ImportReference refers to an imported package. 820 // 821 // import "strings" 822 // 823 // strings.ToLower("Upper") 824 // 825 type ImportReference struct { 826 Src *ast.Ident 827 ImportPath Feature 828 Label Feature // for informative purposes 829 } 830 831 func (x *ImportReference) Source() ast.Node { 832 if x.Src == nil { 833 return nil 834 } 835 return x.Src 836 } 837 838 func (x *ImportReference) resolve(ctx *OpContext, state VertexStatus) *Vertex { 839 path := x.ImportPath.StringValue(ctx) 840 v := ctx.Runtime.LoadImport(path) 841 if v == nil { 842 ctx.addErrf(EvalError, x.Src.Pos(), "cannot find package %q", path) 843 } 844 return v 845 } 846 847 // A LetReference evaluates a let expression in its original environment. 848 // 849 // let X = x 850 // 851 type LetReference struct { 852 Src *ast.Ident 853 UpCount int32 854 Label Feature // for informative purposes 855 X Expr 856 } 857 858 func (x *LetReference) Source() ast.Node { 859 if x.Src == nil { 860 return nil 861 } 862 return x.Src 863 } 864 865 func (x *LetReference) resolve(c *OpContext, state VertexStatus) *Vertex { 866 e := c.Env(x.UpCount) 867 label := e.Vertex.Label 868 if x.X == nil { 869 panic("nil expression") 870 } 871 // Anonymous arc. 872 return &Vertex{Parent: nil, Label: label, Conjuncts: []Conjunct{{e, x.X, CloseInfo{}}}} 873 } 874 875 func (x *LetReference) evaluate(c *OpContext) Value { 876 e := c.Env(x.UpCount) 877 878 // Not caching let expressions may lead to exponential behavior. 879 return e.evalCached(c, x.X) 880 } 881 882 // A SelectorExpr looks up a fixed field in an expression. 883 // 884 // X.Sel 885 // 886 type SelectorExpr struct { 887 Src *ast.SelectorExpr 888 X Expr 889 Sel Feature 890 } 891 892 func (x *SelectorExpr) Source() ast.Node { 893 if x.Src == nil { 894 return nil 895 } 896 return x.Src 897 } 898 899 func (x *SelectorExpr) resolve(c *OpContext, state VertexStatus) *Vertex { 900 // TODO: the node should really be evaluated as AllArcs, but the order 901 // of evaluation is slightly off, causing too much to be evaluated. 902 // This may especially result in incorrect results when using embedded 903 // scalars. 904 n := c.node(x, x.X, x.Sel.IsRegular(), Partial) 905 if n == emptyNode { 906 return n 907 } 908 if n.status == Partial { 909 if b := n.state.incompleteErrors(); b != nil && b.Code < CycleError { 910 n.BaseValue = b 911 return n 912 } 913 } 914 return c.lookup(n, x.Src.Sel.Pos(), x.Sel, state) 915 } 916 917 // IndexExpr is like a selector, but selects an index. 918 // 919 // X[Index] 920 // 921 type IndexExpr struct { 922 Src *ast.IndexExpr 923 X Expr 924 Index Expr 925 } 926 927 func (x *IndexExpr) Source() ast.Node { 928 if x.Src == nil { 929 return nil 930 } 931 return x.Src 932 } 933 934 func (x *IndexExpr) resolve(ctx *OpContext, state VertexStatus) *Vertex { 935 // TODO: support byte index. 936 // TODO: the node should really be evaluated as AllArcs, but the order 937 // of evaluation is slightly off, causing too much to be evaluated. 938 // This may especially result in incorrect results when using embedded 939 // scalars. 940 n := ctx.node(x, x.X, true, Partial) 941 i := ctx.value(x.Index) 942 if n == emptyNode { 943 return n 944 } 945 if n.status == Partial { 946 if b := n.state.incompleteErrors(); b != nil && b.Code < CycleError { 947 n.BaseValue = b 948 return n 949 } 950 } 951 f := ctx.Label(x.Index, i) 952 return ctx.lookup(n, x.Src.Index.Pos(), f, state) 953 } 954 955 // A SliceExpr represents a slice operation. (Not currently in spec.) 956 // 957 // X[Lo:Hi:Stride] 958 // 959 type SliceExpr struct { 960 Src *ast.SliceExpr 961 X Expr 962 Lo Expr 963 Hi Expr 964 Stride Expr 965 } 966 967 func (x *SliceExpr) Source() ast.Node { 968 if x.Src == nil { 969 return nil 970 } 971 return x.Src 972 } 973 974 func (x *SliceExpr) evaluate(c *OpContext) Value { 975 // TODO: strides 976 977 v := c.value(x.X) 978 const as = "slice index" 979 980 switch v := v.(type) { 981 case nil: 982 c.addErrf(IncompleteError, c.pos(), "non-concrete slice subject %s", x.X) 983 return nil 984 case *Vertex: 985 if !v.IsList() { 986 break 987 } 988 989 var ( 990 lo = uint64(0) 991 hi = uint64(len(v.Arcs)) 992 ) 993 if x.Lo != nil { 994 lo = c.uint64(c.value(x.Lo), as) 995 } 996 if x.Hi != nil { 997 hi = c.uint64(c.value(x.Hi), as) 998 if hi > uint64(len(v.Arcs)) { 999 return c.NewErrf("index %d out of range", hi) 1000 } 1001 } 1002 if lo > hi { 1003 return c.NewErrf("invalid slice index: %d > %d", lo, hi) 1004 } 1005 1006 n := c.newList(c.src, v.Parent) 1007 for i, a := range v.Arcs[lo:hi] { 1008 label, err := MakeLabel(a.Source(), int64(i), IntLabel) 1009 if err != nil { 1010 c.AddBottom(&Bottom{Src: a.Source(), Err: err}) 1011 return nil 1012 } 1013 arc := *a 1014 arc.Parent = n 1015 arc.Label = label 1016 n.Arcs = append(n.Arcs, &arc) 1017 } 1018 n.status = Finalized 1019 return n 1020 1021 case *Bytes: 1022 var ( 1023 lo = uint64(0) 1024 hi = uint64(len(v.B)) 1025 ) 1026 if x.Lo != nil { 1027 lo = c.uint64(c.value(x.Lo), as) 1028 } 1029 if x.Hi != nil { 1030 hi = c.uint64(c.value(x.Hi), as) 1031 if hi > uint64(len(v.B)) { 1032 return c.NewErrf("index %d out of range", hi) 1033 } 1034 } 1035 if lo > hi { 1036 return c.NewErrf("invalid slice index: %d > %d", lo, hi) 1037 } 1038 return c.newBytes(v.B[lo:hi]) 1039 } 1040 1041 if isError(v) { 1042 return v 1043 } 1044 return c.NewErrf("cannot slice %v (type %s)", v, v.Kind()) 1045 } 1046 1047 // An Interpolation is a string interpolation. 1048 // 1049 // "a \(b) c" 1050 // 1051 type Interpolation struct { 1052 Src *ast.Interpolation 1053 K Kind // string or bytes 1054 Parts []Expr // odd: strings, even sources 1055 } 1056 1057 func (x *Interpolation) Source() ast.Node { 1058 if x.Src == nil { 1059 return nil 1060 } 1061 return x.Src 1062 } 1063 1064 func (x *Interpolation) evaluate(c *OpContext) Value { 1065 buf := bytes.Buffer{} 1066 for _, e := range x.Parts { 1067 v := c.value(e) 1068 if x.K == BytesKind { 1069 buf.Write(c.ToBytes(v)) 1070 } else { 1071 buf.WriteString(c.ToString(v)) 1072 } 1073 } 1074 if err := c.Err(); err != nil { 1075 err = &Bottom{ 1076 Code: err.Code, 1077 Err: errors.Wrapf(err.Err, pos(x), "invalid interpolation"), 1078 } 1079 // c.AddBottom(err) 1080 // return nil 1081 return err 1082 } 1083 if x.K == BytesKind { 1084 return &Bytes{x.Src, buf.Bytes(), nil} 1085 } 1086 return &String{x.Src, buf.String(), nil} 1087 } 1088 1089 // UnaryExpr is a unary expression. 1090 // 1091 // Op X 1092 // -X !X +X 1093 // 1094 type UnaryExpr struct { 1095 Src *ast.UnaryExpr 1096 Op Op 1097 X Expr 1098 } 1099 1100 func (x *UnaryExpr) Source() ast.Node { 1101 if x.Src == nil { 1102 return nil 1103 } 1104 return x.Src 1105 } 1106 1107 func (x *UnaryExpr) evaluate(c *OpContext) Value { 1108 if !c.concreteIsPossible(x.Op, x.X) { 1109 return nil 1110 } 1111 v := c.value(x.X) 1112 if isError(v) { 1113 return v 1114 } 1115 1116 op := x.Op 1117 k := kind(v) 1118 expectedKind := k 1119 switch op { 1120 case SubtractOp: 1121 if v, ok := v.(*Num); ok { 1122 f := *v 1123 f.X.Neg(&v.X) 1124 f.Src = x.Src 1125 return &f 1126 } 1127 expectedKind = NumKind 1128 1129 case AddOp: 1130 if v, ok := v.(*Num); ok { 1131 // TODO: wrap in thunk to save position of '+'? 1132 return v 1133 } 1134 expectedKind = NumKind 1135 1136 case NotOp: 1137 if v, ok := v.(*Bool); ok { 1138 return &Bool{x.Src, !v.B} 1139 } 1140 expectedKind = BoolKind 1141 } 1142 if k&expectedKind != BottomKind { 1143 c.addErrf(IncompleteError, pos(x.X), 1144 "operand %s of '%s' not concrete (was %s)", x.X, op, k) 1145 return nil 1146 } 1147 return c.NewErrf("invalid operation %s (%s %s)", x, op, k) 1148 } 1149 1150 // BinaryExpr is a binary expression. 1151 // 1152 // X + Y 1153 // X & Y 1154 // 1155 type BinaryExpr struct { 1156 Src *ast.BinaryExpr 1157 Op Op 1158 X Expr 1159 Y Expr 1160 } 1161 1162 func (x *BinaryExpr) Source() ast.Node { 1163 if x.Src == nil { 1164 return nil 1165 } 1166 return x.Src 1167 } 1168 1169 func (x *BinaryExpr) evaluate(c *OpContext) Value { 1170 env := c.Env(0) 1171 if x.Op == AndOp { 1172 // Anonymous Arc 1173 v := &Vertex{Conjuncts: []Conjunct{{env, x, CloseInfo{}}}} 1174 c.Unify(v, Finalized) 1175 return v 1176 } 1177 1178 if !c.concreteIsPossible(x.Op, x.X) || !c.concreteIsPossible(x.Op, x.Y) { 1179 return nil 1180 } 1181 1182 // TODO: allow comparing to a literal Bottom only. Find something more 1183 // principled perhaps. One should especially take care that two values 1184 // evaluating to Bottom don't evaluate to true. For now we check for 1185 // Bottom here and require that one of the values be a Bottom literal. 1186 if x.Op == EqualOp || x.Op == NotEqualOp { 1187 if isLiteralBottom(x.X) { 1188 return c.validate(env, x.Src, x.Y, x.Op) 1189 } 1190 if isLiteralBottom(x.Y) { 1191 return c.validate(env, x.Src, x.X, x.Op) 1192 } 1193 } 1194 1195 left, _ := c.Concrete(env, x.X, x.Op) 1196 right, _ := c.Concrete(env, x.Y, x.Op) 1197 1198 if err := CombineErrors(x.Src, left, right); err != nil { 1199 return err 1200 } 1201 1202 if err := c.Err(); err != nil { 1203 return err 1204 } 1205 1206 return BinOp(c, x.Op, left, right) 1207 } 1208 1209 func (c *OpContext) validate(env *Environment, src ast.Node, x Expr, op Op) (r Value) { 1210 s := c.PushState(env, src) 1211 if c.nonMonotonicLookupNest == 0 { 1212 c.nonMonotonicGeneration++ 1213 } 1214 1215 var match bool 1216 // NOTE: using Unwrap is maybe note entirely accurate, as it may discard 1217 // a future error. However, if it does so, the error will at least be 1218 // reported elsewhere. 1219 switch b := c.value(x).(type) { 1220 case nil: 1221 case *Bottom: 1222 if b.Code == CycleError { 1223 c.PopState(s) 1224 c.AddBottom(b) 1225 return nil 1226 } 1227 match = op == EqualOp 1228 // We have a nonmonotonic use of a failure. Referenced fields should 1229 // not be added anymore. 1230 c.nonMonotonicRejectNest++ 1231 c.evalState(x, Partial) 1232 c.nonMonotonicRejectNest-- 1233 1234 default: 1235 // TODO(cycle): if EqualOp: 1236 // - ensure to pass special status to if clause or keep a track of "hot" 1237 // paths. 1238 // - evaluate hypothetical struct 1239 // - walk over all fields and verify that fields are not contradicting 1240 // previously marked fields. 1241 // 1242 switch { 1243 case b.Concreteness() > Concrete: 1244 // TODO: mimic comparison to bottom semantics. If it is a valid 1245 // value, check for concreteness that this level only. This 1246 // should ultimately be replaced with an exists and valid 1247 // builtin. 1248 match = op == EqualOp 1249 default: 1250 match = op != EqualOp 1251 } 1252 c.nonMonotonicLookupNest++ 1253 c.evalState(x, Partial) 1254 c.nonMonotonicLookupNest-- 1255 } 1256 1257 c.PopState(s) 1258 return &Bool{src, match} 1259 } 1260 1261 // A CallExpr represents a call to a builtin. 1262 // 1263 // len(x) 1264 // strings.ToLower(x) 1265 // 1266 type CallExpr struct { 1267 Src *ast.CallExpr 1268 Fun Expr 1269 Args []Expr 1270 } 1271 1272 func (x *CallExpr) Source() ast.Node { 1273 if x.Src == nil { 1274 return nil 1275 } 1276 return x.Src 1277 } 1278 1279 func (x *CallExpr) evaluate(c *OpContext) Value { 1280 fun := c.value(x.Fun) 1281 var b *Builtin 1282 switch f := fun.(type) { 1283 case *Builtin: 1284 b = f 1285 1286 case *BuiltinValidator: 1287 // We allow a validator that takes no arguments accept the validated 1288 // value to be called with zero arguments. 1289 switch { 1290 case f.Src != nil: 1291 c.AddErrf("cannot call previously called validator %s", x.Fun) 1292 1293 case f.Builtin.IsValidator(len(x.Args)): 1294 v := *f 1295 v.Src = x 1296 return &v 1297 1298 default: 1299 b = f.Builtin 1300 } 1301 1302 default: 1303 c.AddErrf("cannot call non-function %s (type %s)", x.Fun, kind(fun)) 1304 return nil 1305 } 1306 args := []Value{} 1307 for i, a := range x.Args { 1308 expr := c.value(a) 1309 switch v := expr.(type) { 1310 case nil: 1311 // There SHOULD be an error in the context. If not, we generate 1312 // one. 1313 c.Assertf(pos(x.Fun), c.HasErr(), 1314 "argument %d to function %s is incomplete", i, x.Fun) 1315 1316 case *Bottom: 1317 // TODO(errors): consider adding an argument index for this errors. 1318 // On the other hand, this error is really not related to the 1319 // argument itself, so maybe it is good as it is. 1320 c.AddBottom(v) 1321 1322 default: 1323 args = append(args, expr) 1324 } 1325 } 1326 if c.HasErr() { 1327 return nil 1328 } 1329 if b.IsValidator(len(args)) { 1330 return &BuiltinValidator{x, b, args} 1331 } 1332 result := b.call(c, pos(x), args) 1333 if result == nil { 1334 return nil 1335 } 1336 return c.evalState(result, Partial) 1337 } 1338 1339 // A Builtin is a value representing a native function call. 1340 type Builtin struct { 1341 // TODO: make these values for better type checking. 1342 Params []Param 1343 Result Kind 1344 Func func(c *OpContext, args []Value) Expr 1345 1346 Package Feature 1347 Name string 1348 } 1349 1350 type Param struct { 1351 Name Feature // name of the argument; mostly for documentation 1352 Value Value // Could become Value later, using disjunctions for defaults. 1353 } 1354 1355 // Kind returns the kind mask of this parameter. 1356 func (p Param) Kind() Kind { 1357 return p.Value.Kind() 1358 } 1359 1360 // Default reports the default value for this Param or nil if there is none. 1361 func (p Param) Default() Value { 1362 d, ok := p.Value.(*Disjunction) 1363 if !ok || d.NumDefaults != 1 { 1364 return nil 1365 } 1366 return d.Values[0] 1367 } 1368 1369 func (x *Builtin) WriteName(w io.Writer, c *OpContext) { 1370 _, _ = fmt.Fprintf(w, "%s.%s", x.Package.StringValue(c), x.Name) 1371 } 1372 1373 // Kind here represents the case where Builtin is used as a Validator. 1374 func (x *Builtin) Kind() Kind { 1375 return FuncKind 1376 } 1377 1378 func (x *Builtin) BareValidator() *BuiltinValidator { 1379 if len(x.Params) != 1 || 1380 (x.Result != BoolKind && x.Result != BottomKind) { 1381 return nil 1382 } 1383 return &BuiltinValidator{Builtin: x} 1384 } 1385 1386 // IsValidator reports whether b should be interpreted as a Validator for the 1387 // given number of arguments. 1388 func (b *Builtin) IsValidator(numArgs int) bool { 1389 return numArgs == len(b.Params)-1 && 1390 b.Result&^BoolKind == 0 && 1391 b.Params[numArgs].Default() == nil 1392 } 1393 1394 func bottom(v Value) *Bottom { 1395 if x, ok := v.(*Vertex); ok { 1396 v = x.Value() 1397 } 1398 b, _ := v.(*Bottom) 1399 return b 1400 } 1401 1402 func (x *Builtin) call(c *OpContext, p token.Pos, args []Value) Expr { 1403 fun := x // right now always x. 1404 if len(args) > len(x.Params) { 1405 c.addErrf(0, p, 1406 "too many arguments in call to %s (have %d, want %d)", 1407 fun, len(args), len(x.Params)) 1408 return nil 1409 } 1410 for i := len(args); i < len(x.Params); i++ { 1411 v := x.Params[i].Default() 1412 if v == nil { 1413 c.addErrf(0, p, 1414 "not enough arguments in call to %s (have %d, want %d)", 1415 fun, len(args), len(x.Params)) 1416 return nil 1417 } 1418 args = append(args, v) 1419 } 1420 for i, a := range args { 1421 if x.Params[i].Kind() == BottomKind { 1422 continue 1423 } 1424 if b := bottom(a); b != nil { 1425 return b 1426 } 1427 if k := kind(a); x.Params[i].Kind()&k == BottomKind { 1428 code := EvalError 1429 b, _ := args[i].(*Bottom) 1430 if b != nil { 1431 code = b.Code 1432 } 1433 c.addErrf(code, pos(a), 1434 "cannot use %s (type %s) as %s in argument %d to %s", 1435 a, k, x.Params[i].Kind(), i+1, fun) 1436 return nil 1437 } 1438 v := x.Params[i].Value 1439 if _, ok := v.(*BasicType); !ok { 1440 env := c.Env(0) 1441 x := &BinaryExpr{Op: AndOp, X: v, Y: a} 1442 n := &Vertex{Conjuncts: []Conjunct{{env, x, CloseInfo{}}}} 1443 c.Unify(n, Finalized) 1444 if _, ok := n.BaseValue.(*Bottom); ok { 1445 c.addErrf(0, pos(a), 1446 "cannot use %s as %s in argument %d to %s", 1447 a, v, i+1, fun) 1448 return nil 1449 } 1450 args[i] = n 1451 } 1452 } 1453 return x.Func(c, args) 1454 } 1455 1456 func (x *Builtin) Source() ast.Node { return nil } 1457 1458 // A BuiltinValidator is a Value that results from evaluation a partial call 1459 // to a builtin (using CallExpr). 1460 // 1461 // strings.MinRunes(4) 1462 // 1463 type BuiltinValidator struct { 1464 Src *CallExpr 1465 Builtin *Builtin 1466 Args []Value // any but the first value 1467 } 1468 1469 func (x *BuiltinValidator) Source() ast.Node { 1470 if x.Src == nil { 1471 return x.Builtin.Source() 1472 } 1473 return x.Src.Source() 1474 } 1475 1476 func (x *BuiltinValidator) Pos() token.Pos { 1477 if src := x.Source(); src != nil { 1478 return src.Pos() 1479 } 1480 return token.NoPos 1481 } 1482 1483 func (x *BuiltinValidator) Kind() Kind { 1484 return x.Builtin.Params[0].Kind() 1485 } 1486 1487 func (x *BuiltinValidator) validate(c *OpContext, v Value) *Bottom { 1488 args := make([]Value, len(x.Args)+1) 1489 args[0] = v 1490 copy(args[1:], x.Args) 1491 1492 return validateWithBuiltin(c, x.Pos(), x.Builtin, args) 1493 } 1494 1495 func validateWithBuiltin(c *OpContext, src token.Pos, b *Builtin, args []Value) *Bottom { 1496 var severeness ErrorCode 1497 var err errors.Error 1498 1499 res := b.call(c, src, args) 1500 switch v := res.(type) { 1501 case nil: 1502 return nil 1503 1504 case *Bottom: 1505 if v == nil { 1506 return nil // caught elsewhere, but be defensive. 1507 } 1508 severeness = v.Code 1509 err = v.Err 1510 1511 case *Bool: 1512 if v.B { 1513 return nil 1514 } 1515 1516 default: 1517 return c.NewErrf("invalid validator %s.%s", b.Package.StringValue(c), b.Name) 1518 } 1519 1520 // failed: 1521 var buf bytes.Buffer 1522 b.WriteName(&buf, c) 1523 if len(args) > 1 { 1524 buf.WriteString("(") 1525 for i, a := range args[1:] { 1526 if i > 0 { 1527 _, _ = buf.WriteString(", ") 1528 } 1529 buf.WriteString(c.Str(a)) 1530 } 1531 buf.WriteString(")") 1532 } 1533 1534 vErr := c.NewPosf(src, "invalid value %s (does not satisfy %s)", args[0], buf.String()) 1535 1536 for _, v := range args { 1537 vErr.AddPosition(v) 1538 } 1539 1540 return &Bottom{Code: severeness, Err: errors.Wrap(vErr, err)} 1541 } 1542 1543 // A Disjunction represents a disjunction, where each disjunct may or may not 1544 // be marked as a default. 1545 type DisjunctionExpr struct { 1546 Src *ast.BinaryExpr 1547 Values []Disjunct 1548 1549 HasDefaults bool 1550 } 1551 1552 // A Disjunct is used in Disjunction. 1553 type Disjunct struct { 1554 Val Expr 1555 Default bool 1556 } 1557 1558 func (x *DisjunctionExpr) Source() ast.Node { 1559 if x.Src == nil { 1560 return nil 1561 } 1562 return x.Src 1563 } 1564 1565 func (x *DisjunctionExpr) evaluate(c *OpContext) Value { 1566 e := c.Env(0) 1567 v := &Vertex{Conjuncts: []Conjunct{{e, x, CloseInfo{}}}} 1568 c.Unify(v, Finalized) // TODO: also partial okay? 1569 // TODO: if the disjunction result originated from a literal value, we may 1570 // consider the result closed to create more permanent errors. 1571 return v 1572 } 1573 1574 // A Conjunction is a conjunction of values that cannot be represented as a 1575 // single value. It is the result of unification. 1576 type Conjunction struct { 1577 Src ast.Expr 1578 Values []Value 1579 } 1580 1581 func (x *Conjunction) Source() ast.Node { return x.Src } 1582 func (x *Conjunction) Kind() Kind { 1583 k := TopKind 1584 for _, v := range x.Values { 1585 k &= v.Kind() 1586 } 1587 return k 1588 } 1589 1590 // A disjunction is a disjunction of values. It is the result of expanding 1591 // a DisjunctionExpr if the expression cannot be represented as a single value. 1592 type Disjunction struct { 1593 Src ast.Expr 1594 1595 // Values are the non-error disjuncts of this expression. The first 1596 // NumDefault values are default values. 1597 Values []*Vertex 1598 1599 Errors *Bottom // []bottom 1600 1601 // NumDefaults indicates the number of default values. 1602 NumDefaults int 1603 HasDefaults bool 1604 } 1605 1606 func (x *Disjunction) Source() ast.Node { return x.Src } 1607 func (x *Disjunction) Kind() Kind { 1608 k := BottomKind 1609 for _, v := range x.Values { 1610 k |= v.Kind() 1611 } 1612 return k 1613 } 1614 1615 type Comprehension struct { 1616 Clauses Yielder 1617 Value Expr 1618 } 1619 1620 func (x *Comprehension) Source() ast.Node { 1621 if x.Clauses == nil { 1622 return nil 1623 } 1624 return x.Clauses.Source() 1625 } 1626 1627 // A ForClause represents a for clause of a comprehension. It can be used 1628 // as a struct or list element. 1629 // 1630 // for k, v in src {} 1631 // 1632 type ForClause struct { 1633 Syntax *ast.ForClause 1634 Key Feature 1635 Value Feature 1636 Src Expr 1637 Dst Yielder 1638 } 1639 1640 func (x *ForClause) Source() ast.Node { 1641 if x.Syntax == nil { 1642 return nil 1643 } 1644 return x.Syntax 1645 } 1646 1647 func (x *ForClause) yield(c *OpContext, f YieldFunc) { 1648 n := c.node(x, x.Src, true, Finalized) 1649 for _, a := range n.Arcs { 1650 if !a.Label.IsRegular() { 1651 continue 1652 } 1653 1654 c.Unify(a, Partial) 1655 1656 n := &Vertex{status: Finalized} 1657 1658 if x.Value != InvalidLabel { 1659 b := &Vertex{ 1660 Label: x.Value, 1661 BaseValue: a, 1662 } 1663 n.Arcs = append(n.Arcs, b) 1664 } 1665 1666 if x.Key != InvalidLabel { 1667 v := &Vertex{Label: x.Key} 1668 key := a.Label.ToValue(c) 1669 v.AddConjunct(MakeRootConjunct(c.Env(0), key)) 1670 v.SetValue(c, Finalized, key) 1671 n.Arcs = append(n.Arcs, v) 1672 } 1673 1674 sub := c.spawn(n) 1675 saved := c.PushState(sub, x.Dst.Source()) 1676 x.Dst.yield(c, f) 1677 if b := c.PopState(saved); b != nil { 1678 c.AddBottom(b) 1679 break 1680 } 1681 if c.HasErr() { 1682 break 1683 } 1684 } 1685 } 1686 1687 // An IfClause represents an if clause of a comprehension. It can be used 1688 // as a struct or list element. 1689 // 1690 // if cond {} 1691 // 1692 type IfClause struct { 1693 Src *ast.IfClause 1694 Condition Expr 1695 Dst Yielder 1696 } 1697 1698 func (x *IfClause) Source() ast.Node { 1699 if x.Src == nil { 1700 return nil 1701 } 1702 return x.Src 1703 } 1704 1705 func (x *IfClause) yield(ctx *OpContext, f YieldFunc) { 1706 if ctx.BoolValue(ctx.value(x.Condition)) { 1707 x.Dst.yield(ctx, f) 1708 } 1709 } 1710 1711 // An LetClause represents a let clause in a comprehension. 1712 // 1713 // let x = y 1714 // 1715 type LetClause struct { 1716 Src *ast.LetClause 1717 Label Feature 1718 Expr Expr 1719 Dst Yielder 1720 } 1721 1722 func (x *LetClause) Source() ast.Node { 1723 if x.Src == nil { 1724 return nil 1725 } 1726 return x.Src 1727 } 1728 1729 func (x *LetClause) yield(c *OpContext, f YieldFunc) { 1730 n := &Vertex{Arcs: []*Vertex{ 1731 {Label: x.Label, Conjuncts: []Conjunct{{c.Env(0), x.Expr, CloseInfo{}}}}, 1732 }} 1733 1734 sub := c.spawn(n) 1735 saved := c.PushState(sub, x.Dst.Source()) 1736 x.Dst.yield(c, f) 1737 if b := c.PopState(saved); b != nil { 1738 c.AddBottom(b) 1739 } 1740 } 1741 1742 // A ValueClause represents the value part of a comprehension. 1743 type ValueClause struct { 1744 *StructLit 1745 } 1746 1747 func (x *ValueClause) Source() ast.Node { 1748 if x.StructLit == nil { 1749 return nil 1750 } 1751 if x.Src == nil { 1752 return nil 1753 } 1754 return x.Src 1755 } 1756 1757 func (x *ValueClause) yield(op *OpContext, f YieldFunc) { 1758 f(op.Env(0)) 1759 }