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