cuelang.org/go@v0.10.1/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/v3"
    24  
    25  	"cuelang.org/go/cue/ast"
    26  	"cuelang.org/go/cue/errors"
    27  	"cuelang.org/go/cue/token"
    28  )
    29  
    30  var _ Elem = &ConjunctGroup{}
    31  
    32  // A ConjunctGroup is an Elem that is used for internal grouping of Conjuncts
    33  // only.
    34  type ConjunctGroup []Conjunct
    35  
    36  func (g *ConjunctGroup) Source() ast.Node {
    37  	return nil
    38  }
    39  
    40  // A StructLit represents an unevaluated struct literal or file body.
    41  type StructLit struct {
    42  	Src   ast.Node // ast.File or ast.StructLit
    43  	Decls []Decl
    44  
    45  	// TODO: record the merge order somewhere.
    46  
    47  	// The below fields are redundant to Decls and are computed with Init.
    48  
    49  	// field marks the optional conjuncts of all explicit Fields.
    50  	// Required Fields are marked as empty
    51  	Fields []FieldInfo
    52  
    53  	Dynamic []*DynamicField
    54  
    55  	// excluded are all literal fields that already exist.
    56  	Bulk []*BulkOptionalField
    57  
    58  	Additional  []*Ellipsis
    59  	HasEmbed    bool
    60  	IsOpen      bool // has a ...
    61  	initialized bool
    62  
    63  	types OptionalType
    64  
    65  	// administrative fields like hasreferences.
    66  	// hasReferences bool
    67  }
    68  
    69  func (o *StructLit) IsFile() bool {
    70  	_, ok := o.Src.(*ast.File)
    71  	return ok
    72  }
    73  
    74  type FieldInfo struct {
    75  	Label Feature
    76  }
    77  
    78  func (x *StructLit) HasOptional() bool {
    79  	return x.types&(HasPattern|HasAdditional) != 0
    80  }
    81  
    82  func (x *StructLit) Source() ast.Node { return x.Src }
    83  
    84  func (x *StructLit) evaluate(c *OpContext, state combinedFlags) Value {
    85  	e := c.Env(0)
    86  	v := c.newInlineVertex(e.Vertex, nil, Conjunct{e, x, c.ci})
    87  	// evaluate may not finalize a field, as the resulting value may be
    88  	// used in a context where more conjuncts are added. It may also lead
    89  	// to disjuncts being in a partially expanded state, leading to
    90  	// misaligned nodeContexts.
    91  	v.CompleteArcs(c)
    92  	return v
    93  }
    94  
    95  // TODO: remove this method
    96  func (o *StructLit) MarkField(f Feature) {
    97  	o.Fields = append(o.Fields, FieldInfo{Label: f})
    98  }
    99  
   100  func (o *StructLit) Init(ctx *OpContext) {
   101  	if o.initialized {
   102  		return
   103  	}
   104  	o.initialized = true
   105  
   106  	if ctx.isDevVersion() {
   107  		return
   108  	}
   109  
   110  	for _, d := range o.Decls {
   111  		switch x := d.(type) {
   112  		case *Field:
   113  			if o.fieldIndex(x.Label) < 0 {
   114  				o.Fields = append(o.Fields, FieldInfo{Label: x.Label})
   115  			}
   116  			if x.ArcType > ArcMember {
   117  				o.types |= HasField
   118  			}
   119  
   120  		case *LetField:
   121  			if o.fieldIndex(x.Label) >= 0 {
   122  				panic("duplicate let identifier")
   123  			}
   124  			o.Fields = append(o.Fields, FieldInfo{Label: x.Label})
   125  
   126  		case *DynamicField:
   127  			o.Dynamic = append(o.Dynamic, x)
   128  			o.types |= HasDynamic
   129  
   130  		case Expr:
   131  			o.HasEmbed = true
   132  
   133  		case *Comprehension:
   134  			o.HasEmbed = true
   135  
   136  		case *LetClause:
   137  			o.HasEmbed = true
   138  
   139  		case *BulkOptionalField:
   140  			o.Bulk = append(o.Bulk, x)
   141  			o.types |= HasPattern
   142  			switch x.Filter.(type) {
   143  			case *BasicType, *Top:
   144  			default:
   145  				o.types |= HasComplexPattern
   146  			}
   147  
   148  		case *Ellipsis:
   149  			switch x.Value.(type) {
   150  			case nil, *Top:
   151  				o.IsOpen = true
   152  				o.types |= IsOpen
   153  
   154  			default:
   155  				// TODO: consider only adding for non-top.
   156  				o.types |= HasAdditional
   157  			}
   158  			o.Additional = append(o.Additional, x)
   159  
   160  		default:
   161  			panic("unreachable")
   162  		}
   163  	}
   164  }
   165  
   166  func (o *StructLit) fieldIndex(f Feature) int {
   167  	for i := range o.Fields {
   168  		if o.Fields[i].Label == f {
   169  			return i
   170  		}
   171  	}
   172  	return -1
   173  }
   174  
   175  func (o *StructLit) OptionalTypes() OptionalType {
   176  	return o.types
   177  }
   178  
   179  // FIELDS
   180  //
   181  // Fields can also be used as expressions whereby the value field is the
   182  // expression this allows retaining more context.
   183  
   184  // Field represents a regular field or field constraint with a fixed label.
   185  // The label can be a regular field, definition or hidden field.
   186  //
   187  //	foo: bar
   188  //	#foo: bar
   189  //	_foo: bar
   190  type Field struct {
   191  	Src *ast.Field
   192  
   193  	ArcType ArcType
   194  	Label   Feature
   195  	Value   Expr
   196  }
   197  
   198  func (x *Field) Source() ast.Node {
   199  	if x.Src == nil {
   200  		return nil
   201  	}
   202  	return x.Src
   203  }
   204  
   205  // A LetField represents a field that is only visible in the local scope.
   206  //
   207  //	let X = expr
   208  type LetField struct {
   209  	Src   *ast.LetClause
   210  	Label Feature
   211  	// IsMulti is true when this let field should be replicated for each
   212  	// incarnation. This is the case when its expression refers to the
   213  	// variables of a for comprehension embedded within a struct.
   214  	IsMulti bool
   215  	Value   Expr
   216  }
   217  
   218  func (x *LetField) Source() ast.Node {
   219  	if x.Src == nil {
   220  		return nil
   221  	}
   222  	return x.Src
   223  }
   224  
   225  // A BulkOptionalField represents a set of optional field.
   226  //
   227  //	[expr]: expr
   228  type BulkOptionalField struct {
   229  	Src    *ast.Field // Ellipsis 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  type Ellipsis struct {
   246  	Src   *ast.Ellipsis
   247  	Value Expr
   248  }
   249  
   250  func (x *Ellipsis) Source() ast.Node {
   251  	if x.Src == nil {
   252  		return nil
   253  	}
   254  	return x.Src
   255  }
   256  
   257  // A DynamicField represents a regular field for which the key is computed.
   258  //
   259  //	"\(expr)": expr
   260  //	(expr): expr
   261  type DynamicField struct {
   262  	Src *ast.Field
   263  
   264  	ArcType ArcType
   265  	Key     Expr
   266  	Value   Expr
   267  }
   268  
   269  func (x *DynamicField) Source() ast.Node {
   270  	if x.Src == nil {
   271  		return nil
   272  	}
   273  	return x.Src
   274  }
   275  
   276  // A ListLit represents an unevaluated list literal.
   277  //
   278  //	[a, for x in src { ... }, b, ...T]
   279  type ListLit struct {
   280  	Src *ast.ListLit
   281  
   282  	// scalars, comprehensions, ...T
   283  	Elems []Elem
   284  
   285  	info *StructLit // Shared closedness info.
   286  }
   287  
   288  func (x *ListLit) Source() ast.Node {
   289  	if x.Src == nil {
   290  		return nil
   291  	}
   292  	return x.Src
   293  }
   294  
   295  func (x *ListLit) evaluate(c *OpContext, state combinedFlags) Value {
   296  	e := c.Env(0)
   297  	v := c.newInlineVertex(e.Vertex, nil, Conjunct{e, x, c.ci})
   298  	v.CompleteArcs(c)
   299  	return v
   300  }
   301  
   302  // Null represents null. It can be used as a Value and Expr.
   303  type Null struct {
   304  	Src ast.Node
   305  }
   306  
   307  func (x *Null) Source() ast.Node { return x.Src }
   308  func (x *Null) Kind() Kind       { return NullKind }
   309  
   310  // Bool is a boolean value. It can be used as a Value and Expr.
   311  type Bool struct {
   312  	Src ast.Node
   313  	B   bool
   314  }
   315  
   316  func (x *Bool) Source() ast.Node { return x.Src }
   317  func (x *Bool) Kind() Kind       { return BoolKind }
   318  
   319  // Num is a numeric value. It can be used as a Value and Expr.
   320  type Num struct {
   321  	Src ast.Node
   322  	K   Kind        // needed?
   323  	X   apd.Decimal // Is integer if the apd.Decimal is an integer.
   324  }
   325  
   326  // TODO: do we need this?
   327  // func NewNumFromString(src ast.Node, s string) Value {
   328  // 	n := &Num{Src: src, K: IntKind}
   329  // 	if strings.ContainsAny(s, "eE.") {
   330  // 		n.K = FloatKind
   331  // 	}
   332  // 	_, _, err := n.X.SetString(s)
   333  // 	if err != nil {
   334  // 		pos := token.NoPos
   335  // 		if src != nil {
   336  // 			pos = src.Pos()
   337  // 		}
   338  // 		return &Bottom{Err: errors.Newf(pos, "invalid number: %v", err)}
   339  // 	}
   340  // 	return n
   341  // }
   342  
   343  func (x *Num) Source() ast.Node { return x.Src }
   344  func (x *Num) Kind() Kind       { return x.K }
   345  
   346  // TODO: do we still need this?
   347  // func (x *Num) Specialize(k Kind) Value {
   348  // 	k = k & x.K
   349  // 	if k == x.K {
   350  // 		return x
   351  // 	}
   352  // 	y := *x
   353  // 	y.K = k
   354  // 	return &y
   355  // }
   356  
   357  // String is a string value. It can be used as a Value and Expr.
   358  type String struct {
   359  	Src ast.Node
   360  	Str string
   361  	RE  *regexp.Regexp // only set if needed
   362  }
   363  
   364  func (x *String) Source() ast.Node { return x.Src }
   365  func (x *String) Kind() Kind       { return StringKind }
   366  
   367  // Bytes is a bytes value. It can be used as a Value and Expr.
   368  type Bytes struct {
   369  	Src ast.Node
   370  	B   []byte
   371  	RE  *regexp.Regexp // only set if needed
   372  }
   373  
   374  func (x *Bytes) Source() ast.Node { return x.Src }
   375  func (x *Bytes) Kind() Kind       { return BytesKind }
   376  
   377  // Composites: the evaluated fields of a composite are recorded in the arc
   378  // vertices.
   379  
   380  type ListMarker struct {
   381  	Src    ast.Expr
   382  	IsOpen bool
   383  }
   384  
   385  func (x *ListMarker) Source() ast.Node { return x.Src }
   386  func (x *ListMarker) Kind() Kind       { return ListKind }
   387  func (x *ListMarker) node()            {}
   388  
   389  type StructMarker struct {
   390  	// NeedClose is used to signal that the evaluator should close this struct.
   391  	// It is only set by the close builtin.
   392  	NeedClose bool
   393  }
   394  
   395  func (x *StructMarker) Source() ast.Node { return nil }
   396  func (x *StructMarker) Kind() Kind       { return StructKind }
   397  func (x *StructMarker) node()            {}
   398  
   399  // Top represents all possible values. It can be used as a Value and Expr.
   400  type Top struct{ Src *ast.Ident }
   401  
   402  func (x *Top) Source() ast.Node {
   403  	if x.Src == nil {
   404  		return nil
   405  	}
   406  	return x.Src
   407  }
   408  func (x *Top) Kind() Kind { return TopKind }
   409  
   410  // BasicType represents all values of a certain Kind. It can be used as a Value
   411  // and Expr.
   412  //
   413  //	string
   414  //	int
   415  //	num
   416  //	bool
   417  type BasicType struct {
   418  	Src ast.Node
   419  	K   Kind
   420  }
   421  
   422  func (x *BasicType) Source() ast.Node {
   423  	if x.Src == nil {
   424  		return nil
   425  	}
   426  	return x.Src
   427  }
   428  func (x *BasicType) Kind() Kind { return x.K }
   429  
   430  // TODO: do we still need this?
   431  // func (x *BasicType) Specialize(k Kind) Value {
   432  // 	k = x.K & k
   433  // 	if k == x.K {
   434  // 		return x
   435  // 	}
   436  // 	y := *x
   437  // 	y.K = k
   438  // 	return &y
   439  // }
   440  
   441  // TODO: should we use UnaryExpr for Bound now we have BoundValue?
   442  
   443  // BoundExpr represents an unresolved unary comparator.
   444  //
   445  //	<a
   446  //	=~MyPattern
   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, state combinedFlags) Value {
   461  	// scalarKnown is used here to ensure we know the value. The result does
   462  	// not have to be concrete, though.
   463  	v := ctx.value(x.Expr, require(partial, scalarKnown))
   464  	if isError(v) {
   465  		return v
   466  	}
   467  
   468  	switch k := v.Kind(); k {
   469  	case IntKind, FloatKind, NumberKind, StringKind, BytesKind:
   470  	case NullKind:
   471  		if x.Op != NotEqualOp {
   472  			err := ctx.NewPosf(pos(x.Expr),
   473  				"cannot use null for bound %s", x.Op)
   474  			return &Bottom{Err: err}
   475  		}
   476  	default:
   477  		mask := IntKind | FloatKind | NumberKind | StringKind | BytesKind
   478  		if x.Op == NotEqualOp {
   479  			mask |= NullKind
   480  		}
   481  		if k&mask != 0 {
   482  			ctx.addErrf(IncompleteError, token.NoPos, // TODO(errors): use ctx.pos()?
   483  				"non-concrete value %s for bound %s", x.Expr, x.Op)
   484  			return nil
   485  		}
   486  		err := ctx.NewPosf(pos(x.Expr),
   487  			"invalid value %s (type %s) for bound %s", v, k, x.Op)
   488  		return &Bottom{Err: err}
   489  	}
   490  
   491  	if v, ok := x.Expr.(Value); ok {
   492  		if v == nil || v.Concreteness() > Concrete {
   493  			return ctx.NewErrf("bound has fixed non-concrete value")
   494  		}
   495  		return &BoundValue{x.Src, x.Op, v}
   496  	}
   497  
   498  	// This simplifies boundary expressions. It is an alternative to an
   499  	// evaluation strategy that makes nodes increasingly more specific.
   500  	//
   501  	// For instance, a completely different implementation would be to allow
   502  	// the presence of a concrete value to ignore incomplete errors.
   503  	//
   504  	// TODO: consider an alternative approach.
   505  	switch y := v.(type) {
   506  	case *BoundValue:
   507  		switch {
   508  		case y.Op == NotEqualOp:
   509  			switch x.Op {
   510  			case LessEqualOp, LessThanOp, GreaterEqualOp, GreaterThanOp:
   511  				// <(!=3)  =>  number
   512  				// Smaller than an arbitrarily large number is any number.
   513  				return &BasicType{K: y.Kind()}
   514  			case NotEqualOp:
   515  				// !=(!=3) ==> 3
   516  				// Not a value that is anything but a given value is that
   517  				// given value.
   518  				return y.Value
   519  			}
   520  
   521  		case x.Op == NotEqualOp:
   522  			// Invert if applicable.
   523  			switch y.Op {
   524  			case LessEqualOp:
   525  				return &BoundValue{x.Src, GreaterThanOp, y.Value}
   526  			case LessThanOp:
   527  				return &BoundValue{x.Src, GreaterEqualOp, y.Value}
   528  			case GreaterEqualOp:
   529  				return &BoundValue{x.Src, LessThanOp, y.Value}
   530  			case GreaterThanOp:
   531  				return &BoundValue{x.Src, LessEqualOp, y.Value}
   532  			}
   533  
   534  		case (x.Op == LessThanOp || x.Op == LessEqualOp) &&
   535  			(y.Op == GreaterThanOp || y.Op == GreaterEqualOp),
   536  			(x.Op == GreaterThanOp || x.Op == GreaterEqualOp) &&
   537  				(y.Op == LessThanOp || y.Op == LessEqualOp):
   538  			// <(>=3)
   539  			// Something smaller than an arbitrarily large number is any number.
   540  			return &BasicType{K: y.Kind()}
   541  
   542  		case x.Op == LessThanOp &&
   543  			(y.Op == LessEqualOp || y.Op == LessThanOp),
   544  			x.Op == GreaterThanOp &&
   545  				(y.Op == GreaterEqualOp || y.Op == GreaterThanOp):
   546  			// <(<=x)  => <x
   547  			// <(<x)   => <x
   548  			// Less than something that is less or equal to x is less than x.
   549  			return &BoundValue{x.Src, x.Op, y.Value}
   550  
   551  		case x.Op == LessEqualOp &&
   552  			(y.Op == LessEqualOp || y.Op == LessThanOp),
   553  			x.Op == GreaterEqualOp &&
   554  				(y.Op == GreaterEqualOp || y.Op == GreaterThanOp):
   555  			// <=(<x)   => <x
   556  			// <=(<=x)  => <=x
   557  			// Less or equal than something that is less than x is less than x.
   558  			return y
   559  		}
   560  
   561  	case *BasicType:
   562  		switch x.Op {
   563  		case LessEqualOp, LessThanOp, GreaterEqualOp, GreaterThanOp:
   564  			// TODO: this does not seem correct and results in some weird
   565  			// behavior for bounds.
   566  			ctx.addErrf(IncompleteError, token.NoPos,
   567  				"non-concrete value %s for bound %s", x.Expr, x.Op)
   568  			return nil
   569  		}
   570  	}
   571  	if v.Concreteness() > Concrete {
   572  		// TODO(errors): analyze dependencies of x.Expr to get positions.
   573  		ctx.addErrf(IncompleteError, token.NoPos, // TODO(errors): use ctx.pos()?
   574  			"non-concrete value %s for bound %s", x.Expr, x.Op)
   575  		return nil
   576  	}
   577  	return &BoundValue{x.Src, x.Op, v}
   578  }
   579  
   580  // A BoundValue is a fully evaluated unary comparator that can be used to
   581  // validate other values.
   582  //
   583  //	<5
   584  //	=~"Name$"
   585  type BoundValue struct {
   586  	Src   ast.Expr
   587  	Op    Op
   588  	Value Value
   589  }
   590  
   591  func (x *BoundValue) Source() ast.Node { return x.Src }
   592  func (x *BoundValue) Kind() Kind {
   593  	k := x.Value.Kind()
   594  	switch k {
   595  	case IntKind, FloatKind, NumberKind:
   596  		return NumberKind
   597  
   598  	case NullKind:
   599  		if x.Op == NotEqualOp {
   600  			return TopKind &^ NullKind
   601  		}
   602  	}
   603  	return k
   604  }
   605  
   606  func (x *BoundValue) validate(c *OpContext, y Value) *Bottom {
   607  	a := y // Can be list or struct.
   608  	b := c.scalar(x.Value)
   609  	if c.HasErr() {
   610  		return c.Err()
   611  	}
   612  
   613  	switch v := BinOp(c, x.Op, a, b).(type) {
   614  	case *Bottom:
   615  		return v
   616  
   617  	case *Bool:
   618  		if v.B {
   619  			return nil
   620  		}
   621  		// TODO(errors): use "invalid value %v (not an %s)" if x is a
   622  		// predeclared identifier such as `int`.
   623  		err := c.Newf("invalid value %v (out of bound %s)", y, x)
   624  		err.AddPosition(y)
   625  		return &Bottom{Src: c.src, Err: err, Code: EvalError}
   626  
   627  	default:
   628  		panic(fmt.Sprintf("unsupported type %T", v))
   629  	}
   630  }
   631  
   632  func (x *BoundValue) validateStr(c *OpContext, a string) bool {
   633  	if str, ok := x.Value.(*String); ok {
   634  		b := str.Str
   635  		switch x.Op {
   636  		case LessEqualOp:
   637  			return a <= b
   638  		case LessThanOp:
   639  			return a < b
   640  		case GreaterEqualOp:
   641  			return a >= b
   642  		case GreaterThanOp:
   643  			return a > b
   644  		case EqualOp:
   645  			return a == b
   646  		case NotEqualOp:
   647  			return a != b
   648  		case MatchOp:
   649  			return c.regexp(x.Value).MatchString(a)
   650  		case NotMatchOp:
   651  			return !c.regexp(x.Value).MatchString(a)
   652  		}
   653  	}
   654  	return x.validate(c, &String{Str: a}) == nil
   655  }
   656  
   657  func (x *BoundValue) validateInt(c *OpContext, a int64) bool {
   658  	switch n := x.Value.(type) {
   659  	case *Num:
   660  		b, err := n.X.Int64()
   661  		if err != nil {
   662  			break
   663  		}
   664  		switch x.Op {
   665  		case LessEqualOp:
   666  			return a <= b
   667  		case LessThanOp:
   668  			return a < b
   669  		case GreaterEqualOp:
   670  			return a >= b
   671  		case GreaterThanOp:
   672  			return a > b
   673  		case EqualOp:
   674  			return a == b
   675  		case NotEqualOp:
   676  			return a != b
   677  		}
   678  	}
   679  	return x.validate(c, c.NewInt64(a)) == nil
   680  }
   681  
   682  // A NodeLink is used during computation to refer to an existing Vertex.
   683  // It is used to signal a potential cycle or reference.
   684  // Note that a NodeLink may be used as a value. This should be taken into
   685  // account.
   686  type NodeLink struct {
   687  	Node *Vertex
   688  }
   689  
   690  func (x *NodeLink) Kind() Kind {
   691  	return x.Node.Kind()
   692  }
   693  func (x *NodeLink) Source() ast.Node { return x.Node.Source() }
   694  
   695  func (x *NodeLink) resolve(c *OpContext, state combinedFlags) *Vertex {
   696  	return x.Node
   697  }
   698  
   699  // A FieldReference represents a lexical reference to a field.
   700  //
   701  //	a
   702  type FieldReference struct {
   703  	Src     *ast.Ident
   704  	UpCount int32
   705  	Label   Feature
   706  }
   707  
   708  func (x *FieldReference) Source() ast.Node {
   709  	if x.Src == nil {
   710  		return nil
   711  	}
   712  	return x.Src
   713  }
   714  
   715  func (x *FieldReference) resolve(c *OpContext, state combinedFlags) *Vertex {
   716  	n := c.relNode(x.UpCount)
   717  	pos := pos(x)
   718  	return c.lookup(n, pos, x.Label, state)
   719  }
   720  
   721  // A ValueReference represents a lexical reference to a value.
   722  //
   723  // Example: an X referring to
   724  //
   725  //	a: X=b
   726  type ValueReference struct {
   727  	Src     *ast.Ident
   728  	UpCount int32
   729  	Label   Feature // for informative purposes
   730  }
   731  
   732  func (x *ValueReference) Source() ast.Node {
   733  	if x.Src == nil {
   734  		return nil
   735  	}
   736  	return x.Src
   737  }
   738  
   739  func (x *ValueReference) resolve(c *OpContext, state combinedFlags) *Vertex {
   740  	if x.UpCount == 0 {
   741  		return c.vertex
   742  	}
   743  	n := c.relNode(x.UpCount - 1)
   744  	return n
   745  }
   746  
   747  // A LabelReference refers to the string or integer value of a label.
   748  //
   749  // Example: an X referring to
   750  //
   751  //	[X=Pattern]: b: a
   752  type LabelReference struct {
   753  	Src     *ast.Ident
   754  	UpCount int32
   755  }
   756  
   757  // TODO: should this implement resolver at all?
   758  
   759  func (x *LabelReference) Source() ast.Node {
   760  	if x.Src == nil {
   761  		return nil
   762  	}
   763  	return x.Src
   764  }
   765  
   766  func (x *LabelReference) evaluate(ctx *OpContext, state combinedFlags) Value {
   767  	label := ctx.relLabel(x.UpCount)
   768  	if label == 0 {
   769  		// There is no label. This may happen if a LabelReference is evaluated
   770  		// outside of the context of a parent node, for instance if an
   771  		// "additional" items or properties is evaluated in isolation.
   772  		//
   773  		// TODO: this should return the pattern of the label.
   774  		return &BasicType{K: StringKind}
   775  	}
   776  	return label.ToValue(ctx)
   777  }
   778  
   779  // A DynamicReference is like a FieldReference, but with a computed label.
   780  //
   781  // Example: an X referring to
   782  //
   783  //	X=(x): v
   784  //	X="\(x)": v
   785  //	X=[string]: v
   786  type DynamicReference struct {
   787  	Src     *ast.Ident
   788  	UpCount int32
   789  	Label   Expr
   790  
   791  	// TODO: only use aliases and store the actual expression only in the scope.
   792  	// The feature is unique for every instance. This will also allow dynamic
   793  	// fields to be ordered among normal fields.
   794  	//
   795  	// This could also be used to assign labels to embedded values, if they
   796  	// don't match a label.
   797  	Alias Feature
   798  }
   799  
   800  func (x *DynamicReference) Source() ast.Node {
   801  	if x.Src == nil {
   802  		return nil
   803  	}
   804  	return x.Src
   805  }
   806  
   807  func (x *DynamicReference) EvaluateLabel(ctx *OpContext, env *Environment) Feature {
   808  	env = env.up(ctx, x.UpCount)
   809  	frame := ctx.PushState(env, x.Src)
   810  	v := ctx.value(x.Label, require(partial, scalarKnown))
   811  	ctx.PopState(frame)
   812  	return ctx.Label(x, v)
   813  }
   814  
   815  func (x *DynamicReference) resolve(ctx *OpContext, state combinedFlags) *Vertex {
   816  	e := ctx.Env(x.UpCount)
   817  	frame := ctx.PushState(e, x.Src)
   818  	v := ctx.value(x.Label, require(partial, scalarKnown))
   819  	ctx.PopState(frame)
   820  	f := ctx.Label(x.Label, v)
   821  	return ctx.lookup(e.Vertex, pos(x), f, state)
   822  }
   823  
   824  // An ImportReference refers to an imported package.
   825  //
   826  // Example: strings in
   827  //
   828  //	import "strings"
   829  //
   830  //	strings.ToLower("Upper")
   831  type ImportReference struct {
   832  	Src        *ast.Ident
   833  	ImportPath Feature
   834  	Label      Feature // for informative purposes
   835  }
   836  
   837  func (x *ImportReference) Source() ast.Node {
   838  	if x.Src == nil {
   839  		return nil
   840  	}
   841  	return x.Src
   842  }
   843  
   844  func (x *ImportReference) resolve(ctx *OpContext, state combinedFlags) *Vertex {
   845  	path := x.ImportPath.StringValue(ctx)
   846  	v := ctx.Runtime.LoadImport(path)
   847  	if v == nil {
   848  		ctx.addErrf(EvalError, x.Src.Pos(), "cannot find package %q", path)
   849  	}
   850  	return v
   851  }
   852  
   853  // A LetReference evaluates a let expression in its original environment.
   854  //
   855  // Example: an X referring to
   856  //
   857  //	let X = x
   858  type LetReference struct {
   859  	Src     *ast.Ident
   860  	UpCount int32
   861  	Label   Feature // for informative purposes
   862  	X       Expr
   863  }
   864  
   865  func (x *LetReference) Source() ast.Node {
   866  	if x.Src == nil {
   867  		return nil
   868  	}
   869  	return x.Src
   870  }
   871  
   872  func (x *LetReference) resolve(ctx *OpContext, state combinedFlags) *Vertex {
   873  	e := ctx.Env(x.UpCount)
   874  	n := e.Vertex
   875  
   876  	// No need to Unify n, as Let references can only result from evaluating
   877  	// an expression within n, in which case evaluation must already have
   878  	// started.
   879  	if n.status < evaluating && !ctx.isDevVersion() {
   880  		panic("unexpected node state < Evaluating")
   881  	}
   882  
   883  	arc := ctx.lookup(n, pos(x), x.Label, state)
   884  	if arc == nil {
   885  		return nil
   886  	}
   887  
   888  	// Using a let arc directly saves an allocation, but should not be done
   889  	// in the following circumstances:
   890  	// 1) multiple Environments to be resolved for a single let
   891  	// 2) in case of error: some errors, like structural cycles, may only
   892  	//    occur when an arc is resolved directly, but not when used in an
   893  	//    expression. Consider, for instance:
   894  	//
   895  	//        a: {
   896  	//            b: 1
   897  	//            let X = a  // structural cycle
   898  	//            c: X.b     // not a structural cycle
   899  	//        }
   900  	//
   901  	//     In other words, a Vertex is not necessarily erroneous when a let
   902  	//     field contained in that Vertex is erroneous.
   903  
   904  	// TODO(order): Do not finalize? Although it is safe to finalize a let
   905  	// by itself, it is not necessarily safe, at this point, to finalize any
   906  	// references it makes. Originally, let finalization was requested to
   907  	// detect cases where multi-mode should be enabled. With the recent compiler
   908  	// changes, though, this should be detected statically. Leave this on for
   909  	// now, though, as it is not entirely clear it is fine to remove this.
   910  	// We can reevaluate this once we have redone some of the planned order of
   911  	// evaluation work.
   912  	arc.Finalize(ctx)
   913  	b := arc.Bottom()
   914  	if !arc.MultiLet && b == nil {
   915  		return arc
   916  	}
   917  
   918  	// Not caching let expressions may lead to exponential behavior.
   919  	// The expr uses the expression of a Let field, which can never be used in
   920  	// any other context.
   921  	c := arc.Conjuncts[0]
   922  	expr := c.Expr()
   923  
   924  	// A let field always has a single expression and thus ConjunctGroups
   925  	// should always have been eliminated. This is critical, as we must
   926  	// ensure that Comprehensions, which may be wrapped in ConjunctGroups,
   927  	// are eliminated.
   928  	_, isGroup := expr.(*ConjunctGroup)
   929  	ctx.Assertf(pos(expr), !isGroup, "unexpected number of expressions")
   930  
   931  	key := cacheKey{expr, arc}
   932  	v, ok := e.cache[key]
   933  	if !ok {
   934  		// Link in the right environment to ensure comprehension context is not
   935  		// lost. Use a Vertex to piggyback on cycle processing.
   936  		c.Env = e
   937  		c.x = expr
   938  
   939  		if e.cache == nil {
   940  			e.cache = map[cacheKey]Value{}
   941  		}
   942  		n := &Vertex{
   943  			Parent:    arc.Parent,
   944  			Label:     x.Label,
   945  			IsDynamic: b != nil && b.Code == StructuralCycleError,
   946  			Conjuncts: []Conjunct{c},
   947  		}
   948  		v = n
   949  		e.cache[key] = n
   950  		if ctx.isDevVersion() {
   951  			nc := n.getState(ctx)
   952  			// TODO: unlike with the old evaluator, we do not allow the first
   953  			// cycle to be skipped. Doing so can lead to hanging evaluation.
   954  			// As the cycle detection works slightly differently in the new
   955  			// evaluator (and is not entirely completed), this can happen. We
   956  			// should revisit this once we have completed the structural cycle
   957  			// detection.
   958  			// nc.hasNonCycle = true
   959  			// Allow a first cycle to be skipped.
   960  			nc.free()
   961  			n.unify(ctx, allKnown, finalize)
   962  		} else {
   963  			nc := n.getNodeContext(ctx, 0)
   964  			nc.hasNonCycle = true // Allow a first cycle to be skipped.
   965  		}
   966  
   967  		// Parents cannot add more conjuncts to a let expression, so set of
   968  		// conjuncts is always complete.
   969  		//
   970  		// NOTE(let finalization): as this let expression is not recorded as
   971  		// a subfield within its parent arc, setParentDone will not be called
   972  		// as part of normal processing. The same is true for finalization.
   973  		// The use of setParentDone has the additional effect that the arc
   974  		// will be finalized where it is needed. See the namesake NOTE for the
   975  		// location where this is triggered.
   976  		n.setParentDone()
   977  	}
   978  	return v.(*Vertex)
   979  }
   980  
   981  // A SelectorExpr looks up a fixed field in an expression.
   982  //
   983  //	a.sel
   984  type SelectorExpr struct {
   985  	Src *ast.SelectorExpr
   986  	X   Expr
   987  	Sel Feature
   988  }
   989  
   990  func (x *SelectorExpr) Source() ast.Node {
   991  	if x.Src == nil {
   992  		return nil
   993  	}
   994  	return x.Src
   995  }
   996  
   997  func (x *SelectorExpr) resolve(c *OpContext, state combinedFlags) *Vertex {
   998  	// TODO: the node should really be evaluated as AllConjunctsDone, but the
   999  	// order of evaluation is slightly off, causing too much to be evaluated.
  1000  	// This may especially result in incorrect results when using embedded
  1001  	// scalars.
  1002  	// In the new evaluator, evaluation of the node is done in lookup.
  1003  	// TODO:
  1004  	// - attempt: if we ensure that errors are propagated in pending arcs.
  1005  	// - require: if we want to ensure that all arcs
  1006  	//  are known now.
  1007  	n := c.node(x, x.X, x.Sel.IsRegular(), attempt(partial, needFieldSetKnown))
  1008  	if n == emptyNode {
  1009  		return n
  1010  	}
  1011  	if n.status == partial && !c.isDevVersion() {
  1012  		if b := n.state.incompleteErrors(false); b != nil && b.Code < CycleError {
  1013  			c.AddBottom(b)
  1014  			return n
  1015  		}
  1016  	}
  1017  	// TODO(eval): dynamic nodes should be fully evaluated here as the result
  1018  	// will otherwise be discarded and there will be no other chance to check
  1019  	// the struct is valid.
  1020  
  1021  	pos := x.Src.Sel.Pos()
  1022  	return c.lookup(n, pos, x.Sel, state)
  1023  }
  1024  
  1025  // IndexExpr is like a selector, but selects an index.
  1026  //
  1027  //	a[index]
  1028  type IndexExpr struct {
  1029  	Src   *ast.IndexExpr
  1030  	X     Expr
  1031  	Index Expr
  1032  }
  1033  
  1034  func (x *IndexExpr) Source() ast.Node {
  1035  	if x.Src == nil {
  1036  		return nil
  1037  	}
  1038  	return x.Src
  1039  }
  1040  
  1041  func (x *IndexExpr) resolve(ctx *OpContext, state combinedFlags) *Vertex {
  1042  	// TODO: support byte index.
  1043  	// TODO: the node should really be evaluated as AllConjunctsDone, but the
  1044  	// order of evaluation is slightly off, causing too much to be evaluated.
  1045  	// This may especially result in incorrect results when using embedded
  1046  	// scalars.
  1047  	n := ctx.node(x, x.X, true, attempt(partial, needFieldSetKnown))
  1048  	i := ctx.value(x.Index, require(partial, scalarKnown))
  1049  	if n == emptyNode {
  1050  		return n
  1051  	}
  1052  	if n.status == partial && !ctx.isDevVersion() {
  1053  		if b := n.state.incompleteErrors(false); b != nil && b.Code < CycleError {
  1054  			ctx.AddBottom(b)
  1055  			return n
  1056  		}
  1057  	}
  1058  	// TODO(eval): dynamic nodes should be fully evaluated here as the result
  1059  	// will otherwise be discarded and there will be no other chance to check
  1060  	// the struct is valid.
  1061  
  1062  	f := ctx.Label(x.Index, i)
  1063  
  1064  	// Within lookup, errors collected in ctx may be associated with n. This is
  1065  	// correct if the error is generated within lookup, but not if it has
  1066  	// already been generated at this point. We therefore bail out early here if
  1067  	// we already have an error.
  1068  	// TODO: this code can probably go once we have cleaned up error generation.
  1069  	if ctx.errs != nil {
  1070  		return nil
  1071  	}
  1072  	pos := x.Src.Index.Pos()
  1073  	return ctx.lookup(n, pos, f, state)
  1074  }
  1075  
  1076  // A SliceExpr represents a slice operation. (Not currently in spec.)
  1077  //
  1078  //	X[Lo:Hi:Stride]
  1079  type SliceExpr struct {
  1080  	Src    *ast.SliceExpr
  1081  	X      Expr
  1082  	Lo     Expr
  1083  	Hi     Expr
  1084  	Stride Expr
  1085  }
  1086  
  1087  func (x *SliceExpr) Source() ast.Node {
  1088  	if x.Src == nil {
  1089  		return nil
  1090  	}
  1091  	return x.Src
  1092  }
  1093  
  1094  func (x *SliceExpr) evaluate(c *OpContext, state combinedFlags) Value {
  1095  	// TODO: strides
  1096  
  1097  	v := c.value(x.X, require(partial, fieldSetKnown))
  1098  	const as = "slice index"
  1099  
  1100  	switch v := v.(type) {
  1101  	case nil:
  1102  		c.addErrf(IncompleteError, c.pos(), "non-concrete slice subject %s", x.X)
  1103  		return nil
  1104  	case *Vertex:
  1105  		if !v.IsList() {
  1106  			break
  1107  		}
  1108  
  1109  		var (
  1110  			lo = uint64(0)
  1111  			hi = uint64(len(v.Arcs))
  1112  		)
  1113  		if x.Lo != nil {
  1114  			lo = c.uint64(c.value(x.Lo, require(partial, scalarKnown)), as)
  1115  		}
  1116  		if x.Hi != nil {
  1117  			hi = c.uint64(c.value(x.Hi, require(partial, scalarKnown)), as)
  1118  			if hi > uint64(len(v.Arcs)) {
  1119  				return c.NewErrf("index %d out of range", hi)
  1120  			}
  1121  		}
  1122  		if lo > hi {
  1123  			return c.NewErrf("invalid slice index: %d > %d", lo, hi)
  1124  		}
  1125  
  1126  		n := c.newList(c.src, v.Parent)
  1127  		for i, a := range v.Arcs[lo:hi] {
  1128  			label, err := MakeLabel(a.Source(), int64(i), IntLabel)
  1129  			if err != nil {
  1130  				c.AddBottom(&Bottom{Src: a.Source(), Err: err})
  1131  				return nil
  1132  			}
  1133  			arc := *a
  1134  			arc.Parent = n
  1135  			arc.Label = label
  1136  			n.Arcs = append(n.Arcs, &arc)
  1137  		}
  1138  		n.status = finalized
  1139  		return n
  1140  
  1141  	case *Bytes:
  1142  		var (
  1143  			lo = uint64(0)
  1144  			hi = uint64(len(v.B))
  1145  		)
  1146  		if x.Lo != nil {
  1147  			lo = c.uint64(c.value(x.Lo, require(partial, scalarKnown)), as)
  1148  		}
  1149  		if x.Hi != nil {
  1150  			hi = c.uint64(c.value(x.Hi, require(partial, scalarKnown)), as)
  1151  			if hi > uint64(len(v.B)) {
  1152  				return c.NewErrf("index %d out of range", hi)
  1153  			}
  1154  		}
  1155  		if lo > hi {
  1156  			return c.NewErrf("invalid slice index: %d > %d", lo, hi)
  1157  		}
  1158  		return c.newBytes(v.B[lo:hi])
  1159  	}
  1160  
  1161  	if isError(v) {
  1162  		return v
  1163  	}
  1164  	return c.NewErrf("cannot slice %v (type %s)", v, v.Kind())
  1165  }
  1166  
  1167  // An Interpolation is a string interpolation.
  1168  //
  1169  //	"a \(b) c"
  1170  type Interpolation struct {
  1171  	Src   *ast.Interpolation
  1172  	K     Kind   // string or bytes
  1173  	Parts []Expr // odd: strings, even sources
  1174  }
  1175  
  1176  func (x *Interpolation) Source() ast.Node {
  1177  	if x.Src == nil {
  1178  		return nil
  1179  	}
  1180  	return x.Src
  1181  }
  1182  
  1183  func (x *Interpolation) evaluate(c *OpContext, state combinedFlags) Value {
  1184  	buf := bytes.Buffer{}
  1185  	for _, e := range x.Parts {
  1186  		v := c.value(e, require(partial, scalarKnown))
  1187  		if x.K == BytesKind {
  1188  			buf.Write(c.ToBytes(v))
  1189  		} else {
  1190  			buf.WriteString(c.ToString(v))
  1191  		}
  1192  	}
  1193  	if err := c.Err(); err != nil {
  1194  		err = &Bottom{
  1195  			Code: err.Code,
  1196  			Err:  errors.Wrapf(err.Err, pos(x), "invalid interpolation"),
  1197  		}
  1198  		// c.AddBottom(err)
  1199  		// return nil
  1200  		return err
  1201  	}
  1202  	if x.K == BytesKind {
  1203  		return &Bytes{x.Src, buf.Bytes(), nil}
  1204  	}
  1205  	return &String{x.Src, buf.String(), nil}
  1206  }
  1207  
  1208  // UnaryExpr is a unary expression.
  1209  //
  1210  //	Op X
  1211  //	-X !X +X
  1212  type UnaryExpr struct {
  1213  	Src *ast.UnaryExpr
  1214  	Op  Op
  1215  	X   Expr
  1216  }
  1217  
  1218  func (x *UnaryExpr) Source() ast.Node {
  1219  	if x.Src == nil {
  1220  		return nil
  1221  	}
  1222  	return x.Src
  1223  }
  1224  
  1225  func (x *UnaryExpr) evaluate(c *OpContext, state combinedFlags) Value {
  1226  	if !c.concreteIsPossible(x.Op, x.X) {
  1227  		return nil
  1228  	}
  1229  	v := c.value(x.X, require(partial, scalarKnown))
  1230  	if isError(v) {
  1231  		return v
  1232  	}
  1233  
  1234  	op := x.Op
  1235  	k := kind(v)
  1236  	expectedKind := k
  1237  	switch op {
  1238  	case SubtractOp:
  1239  		if v, ok := v.(*Num); ok {
  1240  			f := *v
  1241  			f.X.Neg(&v.X)
  1242  			f.Src = x.Src
  1243  			return &f
  1244  		}
  1245  		expectedKind = NumberKind
  1246  
  1247  	case AddOp:
  1248  		if v, ok := v.(*Num); ok {
  1249  			// TODO: wrap in thunk to save position of '+'?
  1250  			return v
  1251  		}
  1252  		expectedKind = NumberKind
  1253  
  1254  	case NotOp:
  1255  		if v, ok := v.(*Bool); ok {
  1256  			return &Bool{x.Src, !v.B}
  1257  		}
  1258  		expectedKind = BoolKind
  1259  	}
  1260  	if k&expectedKind != BottomKind {
  1261  		c.addErrf(IncompleteError, pos(x.X),
  1262  			"operand %s of '%s' not concrete (was %s)", x.X, op, k)
  1263  		return nil
  1264  	}
  1265  	return c.NewErrf("invalid operation %v (%s %s)", x, op, k)
  1266  }
  1267  
  1268  // BinaryExpr is a binary expression.
  1269  //
  1270  //	X + Y
  1271  //	X & Y
  1272  type BinaryExpr struct {
  1273  	Src *ast.BinaryExpr
  1274  	Op  Op
  1275  	X   Expr
  1276  	Y   Expr
  1277  }
  1278  
  1279  func (x *BinaryExpr) Source() ast.Node {
  1280  	if x.Src == nil {
  1281  		return nil
  1282  	}
  1283  	return x.Src
  1284  }
  1285  
  1286  func (x *BinaryExpr) evaluate(c *OpContext, state combinedFlags) Value {
  1287  	env := c.Env(0)
  1288  	if x.Op == AndOp {
  1289  		v := c.newInlineVertex(nil, nil, makeAnonymousConjunct(env, x, c.ci.Refs))
  1290  
  1291  		// Do not fully evaluate the Vertex: if it is embedded within a
  1292  		// struct with arcs that are referenced from within this expression,
  1293  		// it will end up adding "locked" fields, resulting in an error.
  1294  		// It will be the responsibility of the "caller" to get the result
  1295  		// to the required state. If the struct is already dynamic, we will
  1296  		// evaluate the struct regardless to ensure that cycle reporting
  1297  		// keeps working.
  1298  		if env.Vertex.IsDynamic || c.inValidator > 0 {
  1299  			v.Finalize(c)
  1300  		} else {
  1301  			v.CompleteArcs(c)
  1302  		}
  1303  
  1304  		return v
  1305  	}
  1306  
  1307  	if !c.concreteIsPossible(x.Op, x.X) || !c.concreteIsPossible(x.Op, x.Y) {
  1308  		return nil
  1309  	}
  1310  
  1311  	// TODO: allow comparing to a literal Bottom only. Find something more
  1312  	// principled perhaps. One should especially take care that two values
  1313  	// evaluating to Bottom don't evaluate to true. For now we check for
  1314  	// Bottom here and require that one of the values be a Bottom literal.
  1315  	if x.Op == EqualOp || x.Op == NotEqualOp {
  1316  		if isLiteralBottom(x.X) {
  1317  			return c.validate(env, x.Src, x.Y, x.Op, state)
  1318  		}
  1319  		if isLiteralBottom(x.Y) {
  1320  			return c.validate(env, x.Src, x.X, x.Op, state)
  1321  		}
  1322  	}
  1323  
  1324  	left, _ := c.concrete(env, x.X, x.Op)
  1325  	right, _ := c.concrete(env, x.Y, x.Op)
  1326  
  1327  	if err := CombineErrors(x.Src, left, right); err != nil {
  1328  		return err
  1329  	}
  1330  
  1331  	if err := c.Err(); err != nil {
  1332  		return err
  1333  	}
  1334  
  1335  	return BinOp(c, x.Op, left, right)
  1336  }
  1337  
  1338  func (c *OpContext) validate(env *Environment, src ast.Node, x Expr, op Op, flags combinedFlags) (r Value) {
  1339  	state := flags.vertexStatus()
  1340  
  1341  	s := c.PushState(env, src)
  1342  
  1343  	match := op != EqualOp // non-error case
  1344  
  1345  	// Like value(), but retain the original, unwrapped result.
  1346  	c.inValidator++
  1347  	req := flags
  1348  	req = final(state, needTasksDone)
  1349  	v := c.evalState(x, req)
  1350  	c.inValidator--
  1351  	u, _ := c.getDefault(v)
  1352  	u = Unwrap(u)
  1353  
  1354  	// If our final (unwrapped) value is potentially a recursive structure, we
  1355  	// still need to recursively check for errors. We do so by treating it
  1356  	// as the original value, which if it is a Vertex will be evaluated
  1357  	// recursively below.
  1358  	if u != nil && u.Kind().IsAnyOf(StructKind|ListKind) {
  1359  		u = v
  1360  	}
  1361  
  1362  	switch v := u.(type) {
  1363  	case nil:
  1364  	case *Bottom:
  1365  		switch v.Code {
  1366  		case CycleError:
  1367  			c.PopState(s)
  1368  			c.AddBottom(v)
  1369  			// TODO: add this. This erases some
  1370  			// c.verifyNonMonotonicResult(env, x, true)
  1371  			return nil
  1372  
  1373  		case IncompleteError:
  1374  			c.evalState(x, oldOnly(finalized))
  1375  
  1376  			// We have a nonmonotonic use of a failure. Referenced fields should
  1377  			// not be added anymore.
  1378  			c.verifyNonMonotonicResult(env, x, true)
  1379  		}
  1380  
  1381  		match = op == EqualOp
  1382  
  1383  	case *Vertex:
  1384  		// TODO(cycle): if EqualOp:
  1385  		// - ensure to pass special status to if clause or keep a track of "hot"
  1386  		//   paths.
  1387  		// - evaluate hypothetical struct
  1388  		// - walk over all fields and verify that fields are not contradicting
  1389  		//   previously marked fields.
  1390  		//
  1391  		v.Finalize(c)
  1392  
  1393  		if v.status == evaluatingArcs {
  1394  			// We have a cycle, which may be an error. Cycle errors may occur
  1395  			// in chains that are themselves not a cycle. It suffices to check
  1396  			// for non-monotonic results at the end for this particular path.
  1397  			// TODO(perf): finding the right path through such comprehensions
  1398  			// may be expensive. Finding a path in a directed graph is O(n),
  1399  			// though, so we should ensure that the implementation conforms to
  1400  			// this.
  1401  			c.verifyNonMonotonicResult(env, x, true)
  1402  			match = op == EqualOp
  1403  			break
  1404  		}
  1405  
  1406  		switch {
  1407  		case !v.IsDefined(c):
  1408  			c.verifyNonMonotonicResult(env, x, true) // TODO: remove?
  1409  
  1410  			// TODO: mimic comparison to bottom semantics. If it is a valid
  1411  			// value, check for concreteness that this level only. This
  1412  			// should ultimately be replaced with an exists and valid
  1413  			// builtin.
  1414  			match = op == EqualOp
  1415  
  1416  		case isFinalError(v):
  1417  			// Need to recursively check for errors, so we need to evaluate the
  1418  			// Vertex in case it hadn't been evaluated yet.
  1419  			match = op == EqualOp
  1420  		}
  1421  
  1422  	default:
  1423  		if v.Kind().IsAnyOf(CompositeKind) && v.Concreteness() > Concrete && state < conjuncts {
  1424  			c.PopState(s)
  1425  			c.AddBottom(cycle)
  1426  			return nil
  1427  		}
  1428  
  1429  		c.verifyNonMonotonicResult(env, x, false)
  1430  
  1431  		if v.Concreteness() > Concrete {
  1432  			// TODO: mimic comparison to bottom semantics. If it is a valid
  1433  			// value, check for concreteness that this level only. This
  1434  			// should ultimately be replaced with an exists and valid
  1435  			// builtin.
  1436  			match = op == EqualOp
  1437  		}
  1438  
  1439  		c.evalState(x, require(state, needTasksDone))
  1440  	}
  1441  
  1442  	c.PopState(s)
  1443  	return &Bool{src, match}
  1444  }
  1445  
  1446  func isFinalError(n *Vertex) bool {
  1447  	n = n.DerefValue()
  1448  	if b, ok := Unwrap(n).(*Bottom); ok && b.Code < IncompleteError {
  1449  		return true
  1450  	}
  1451  	return false
  1452  }
  1453  
  1454  // verifyNonMonotonicResult re-evaluates the given expression at a later point
  1455  // to ensure that the result has not changed. This is relevant when a function
  1456  // uses reflection, as in `if a != _|_`, where the result of an evaluation may
  1457  // change after the fact.
  1458  // expectError indicates whether the value should evaluate to an error or not.
  1459  func (c *OpContext) verifyNonMonotonicResult(env *Environment, x Expr, expectError bool) {
  1460  	if n := env.Vertex.state; n != nil {
  1461  		n.postChecks = append(n.postChecks, envCheck{
  1462  			env:         env,
  1463  			expr:        x,
  1464  			expectError: expectError,
  1465  		})
  1466  	}
  1467  }
  1468  
  1469  // A CallExpr represents a call to a builtin.
  1470  //
  1471  //	len(x)
  1472  //	strings.ToLower(x)
  1473  type CallExpr struct {
  1474  	Src  *ast.CallExpr
  1475  	Fun  Expr
  1476  	Args []Expr
  1477  }
  1478  
  1479  func (x *CallExpr) Source() ast.Node {
  1480  	if x.Src == nil {
  1481  		return nil
  1482  	}
  1483  	return x.Src
  1484  }
  1485  
  1486  func (x *CallExpr) evaluate(c *OpContext, state combinedFlags) Value {
  1487  	fun := c.value(x.Fun, require(partial, concreteKnown))
  1488  	var b *Builtin
  1489  	switch f := fun.(type) {
  1490  	case *Builtin:
  1491  		b = f
  1492  
  1493  	case *BuiltinValidator:
  1494  		// We allow a validator that takes no arguments except the validated
  1495  		// value to be called with zero arguments.
  1496  		switch {
  1497  		case f.Src != nil:
  1498  			c.AddErrf("cannot call previously called validator %s", x.Fun)
  1499  
  1500  		case f.Builtin.IsValidator(len(x.Args)):
  1501  			v := *f
  1502  			v.Src = x
  1503  			return &v
  1504  
  1505  		default:
  1506  			b = f.Builtin
  1507  		}
  1508  
  1509  	default:
  1510  		c.AddErrf("cannot call non-function %s (type %s)", x.Fun, kind(fun))
  1511  		return nil
  1512  	}
  1513  	args := []Value{}
  1514  	for i, a := range x.Args {
  1515  		saved := c.errs
  1516  		c.errs = nil
  1517  		// XXX: XXX: clear id.closeContext per argument and remove from runTask?
  1518  
  1519  		runMode := state.runMode()
  1520  		cond := state.conditions() | allAncestorsProcessed | concreteKnown
  1521  		state = combineMode(cond, runMode).withVertexStatus(state.vertexStatus())
  1522  
  1523  		expr := c.value(a, state)
  1524  
  1525  		switch v := expr.(type) {
  1526  		case nil:
  1527  			if c.errs == nil {
  1528  				// There SHOULD be an error in the context. If not, we generate
  1529  				// one.
  1530  				c.Assertf(pos(x.Fun), c.HasErr(),
  1531  					"argument %d to function %s is incomplete", i, x.Fun)
  1532  			}
  1533  
  1534  		case *Bottom:
  1535  			// TODO(errors): consider adding an argument index for this errors.
  1536  			c.errs = CombineErrors(a.Source(), c.errs, v)
  1537  
  1538  		default:
  1539  			args = append(args, expr)
  1540  		}
  1541  		c.errs = CombineErrors(a.Source(), saved, c.errs)
  1542  	}
  1543  	if c.HasErr() {
  1544  		return nil
  1545  	}
  1546  	if b.IsValidator(len(args)) {
  1547  		return &BuiltinValidator{x, b, args}
  1548  	}
  1549  	result := b.call(c, pos(x), false, args)
  1550  	if result == nil {
  1551  		return nil
  1552  	}
  1553  	return c.evalState(result, state.withVertexStatus(partial))
  1554  }
  1555  
  1556  // A Builtin is a value representing a native function call.
  1557  type Builtin struct {
  1558  	// TODO:  make these values for better type checking.
  1559  	Params []Param
  1560  	Result Kind
  1561  	Func   func(c *OpContext, args []Value) Expr
  1562  
  1563  	Package Feature
  1564  	Name    string
  1565  }
  1566  
  1567  type Param struct {
  1568  	Name  Feature // name of the argument; mostly for documentation
  1569  	Value Value   // Could become Value later, using disjunctions for defaults.
  1570  }
  1571  
  1572  // Kind returns the kind mask of this parameter.
  1573  func (p Param) Kind() Kind {
  1574  	return p.Value.Kind()
  1575  }
  1576  
  1577  // Default reports the default value for this Param or nil if there is none.
  1578  func (p Param) Default() Value {
  1579  	d, ok := p.Value.(*Disjunction)
  1580  	if !ok || d.NumDefaults != 1 {
  1581  		return nil
  1582  	}
  1583  	return d.Values[0]
  1584  }
  1585  
  1586  func (x *Builtin) WriteName(w io.Writer, c *OpContext) {
  1587  	_, _ = fmt.Fprintf(w, "%s.%s", x.Package.StringValue(c), x.Name)
  1588  }
  1589  
  1590  // Kind here represents the case where Builtin is used as a Validator.
  1591  func (x *Builtin) Kind() Kind {
  1592  	return FuncKind
  1593  }
  1594  
  1595  func (x *Builtin) BareValidator() *BuiltinValidator {
  1596  	if len(x.Params) != 1 ||
  1597  		(x.Result != BoolKind && x.Result != BottomKind) {
  1598  		return nil
  1599  	}
  1600  	return &BuiltinValidator{Builtin: x}
  1601  }
  1602  
  1603  // IsValidator reports whether b should be interpreted as a Validator for the
  1604  // given number of arguments.
  1605  func (b *Builtin) IsValidator(numArgs int) bool {
  1606  	return numArgs == len(b.Params)-1 &&
  1607  		b.Result&^BoolKind == 0 &&
  1608  		b.Params[numArgs].Default() == nil
  1609  }
  1610  
  1611  func bottom(v Value) *Bottom {
  1612  	if x, ok := v.(*Vertex); ok {
  1613  		v = x.Value()
  1614  	}
  1615  	b, _ := v.(*Bottom)
  1616  	return b
  1617  }
  1618  
  1619  func (x *Builtin) call(c *OpContext, p token.Pos, validate bool, args []Value) Expr {
  1620  	fun := x // right now always x.
  1621  	if len(args) > len(x.Params) {
  1622  		c.addErrf(0, p,
  1623  			"too many arguments in call to %v (have %d, want %d)",
  1624  			fun, len(args), len(x.Params))
  1625  		return nil
  1626  	}
  1627  	for i := len(args); i < len(x.Params); i++ {
  1628  		v := x.Params[i].Default()
  1629  		if v == nil {
  1630  			c.addErrf(0, p,
  1631  				"not enough arguments in call to %v (have %d, want %d)",
  1632  				fun, len(args), len(x.Params))
  1633  			return nil
  1634  		}
  1635  		args = append(args, v)
  1636  	}
  1637  	for i, a := range args {
  1638  		if x.Params[i].Kind() == BottomKind {
  1639  			continue
  1640  		}
  1641  		if b := bottom(a); b != nil {
  1642  			return b
  1643  		}
  1644  		if k := kind(a); x.Params[i].Kind()&k == BottomKind {
  1645  			code := EvalError
  1646  			b, _ := args[i].(*Bottom)
  1647  			if b != nil {
  1648  				code = b.Code
  1649  			}
  1650  			c.addErrf(code, pos(a),
  1651  				"cannot use %s (type %s) as %s in argument %d to %v",
  1652  				a, k, x.Params[i].Kind(), i+1, fun)
  1653  			return nil
  1654  		}
  1655  		v := x.Params[i].Value
  1656  		if _, ok := v.(*BasicType); !ok {
  1657  			env := c.Env(0)
  1658  			x := &BinaryExpr{Op: AndOp, X: v, Y: a}
  1659  			n := c.newInlineVertex(nil, nil, Conjunct{env, x, c.ci})
  1660  			n.Finalize(c)
  1661  			if n.IsErr() {
  1662  				c.addErrf(0, pos(a),
  1663  					"cannot use %s as %s in argument %d to %v",
  1664  					a, v, i+1, fun)
  1665  				return nil
  1666  			}
  1667  			args[i] = n
  1668  		}
  1669  	}
  1670  	saved := c.IsValidator
  1671  	c.IsValidator = validate
  1672  	ret := x.Func(c, args)
  1673  	c.IsValidator = saved
  1674  
  1675  	return ret
  1676  }
  1677  
  1678  func (x *Builtin) Source() ast.Node { return nil }
  1679  
  1680  // A BuiltinValidator is a Value that results from evaluation a partial call
  1681  // to a builtin (using CallExpr).
  1682  //
  1683  //	strings.MinRunes(4)
  1684  type BuiltinValidator struct {
  1685  	Src     *CallExpr
  1686  	Builtin *Builtin
  1687  	Args    []Value // any but the first value
  1688  }
  1689  
  1690  func (x *BuiltinValidator) Source() ast.Node {
  1691  	if x.Src == nil {
  1692  		return x.Builtin.Source()
  1693  	}
  1694  	return x.Src.Source()
  1695  }
  1696  
  1697  func (x *BuiltinValidator) Pos() token.Pos {
  1698  	if src := x.Source(); src != nil {
  1699  		return src.Pos()
  1700  	}
  1701  	return token.NoPos
  1702  }
  1703  
  1704  func (x *BuiltinValidator) Kind() Kind {
  1705  	return x.Builtin.Params[0].Kind()
  1706  }
  1707  
  1708  func (x *BuiltinValidator) validate(c *OpContext, v Value) *Bottom {
  1709  	args := make([]Value, len(x.Args)+1)
  1710  	args[0] = v
  1711  	copy(args[1:], x.Args)
  1712  
  1713  	return validateWithBuiltin(c, x.Pos(), x.Builtin, args)
  1714  }
  1715  
  1716  func validateWithBuiltin(c *OpContext, src token.Pos, b *Builtin, args []Value) *Bottom {
  1717  	var severeness ErrorCode
  1718  	var err errors.Error
  1719  
  1720  	res := b.call(c, src, true, args)
  1721  	switch v := res.(type) {
  1722  	case nil:
  1723  		return nil
  1724  
  1725  	case *Bottom:
  1726  		if v == nil {
  1727  			return nil // caught elsewhere, but be defensive.
  1728  		}
  1729  		severeness = v.Code
  1730  		err = v.Err
  1731  
  1732  	case *Bool:
  1733  		if v.B {
  1734  			return nil
  1735  		}
  1736  
  1737  	default:
  1738  		return c.NewErrf("invalid validator %s.%s", b.Package.StringValue(c), b.Name)
  1739  	}
  1740  
  1741  	// failed:
  1742  	var buf bytes.Buffer
  1743  	b.WriteName(&buf, c)
  1744  	if len(args) > 1 {
  1745  		buf.WriteString("(")
  1746  		for i, a := range args[1:] {
  1747  			if i > 0 {
  1748  				_, _ = buf.WriteString(", ")
  1749  			}
  1750  			buf.WriteString(c.Str(a))
  1751  		}
  1752  		buf.WriteString(")")
  1753  	}
  1754  
  1755  	// If the validator returns an error and we already had an error, just
  1756  	// return the original error.
  1757  	if b, ok := Unwrap(args[0]).(*Bottom); ok {
  1758  		return b
  1759  	}
  1760  
  1761  	vErr := c.NewPosf(src, "invalid value %s (does not satisfy %s)", args[0], buf.String())
  1762  
  1763  	for _, v := range args {
  1764  		vErr.AddPosition(v)
  1765  	}
  1766  
  1767  	return &Bottom{Code: severeness, Err: errors.Wrap(vErr, err)}
  1768  }
  1769  
  1770  // A Disjunction represents a disjunction, where each disjunct may or may not
  1771  // be marked as a default.
  1772  type DisjunctionExpr struct {
  1773  	Src    *ast.BinaryExpr
  1774  	Values []Disjunct
  1775  
  1776  	HasDefaults bool
  1777  }
  1778  
  1779  // A Disjunct is used in Disjunction.
  1780  type Disjunct struct {
  1781  	Val     Expr
  1782  	Default bool
  1783  }
  1784  
  1785  func (x *DisjunctionExpr) Source() ast.Node {
  1786  	if x.Src == nil {
  1787  		return nil
  1788  	}
  1789  	return x.Src
  1790  }
  1791  
  1792  func (x *DisjunctionExpr) evaluate(c *OpContext, state combinedFlags) Value {
  1793  	e := c.Env(0)
  1794  	v := c.newInlineVertex(nil, nil, Conjunct{e, x, c.ci})
  1795  	v.Finalize(c) // TODO: also partial okay?
  1796  	// TODO: if the disjunction result originated from a literal value, we may
  1797  	// consider the result closed to create more permanent errors.
  1798  	return v
  1799  }
  1800  
  1801  // A Conjunction is a conjunction of values that cannot be represented as a
  1802  // single value. It is the result of unification.
  1803  type Conjunction struct {
  1804  	Src    ast.Expr
  1805  	Values []Value
  1806  }
  1807  
  1808  func (x *Conjunction) Source() ast.Node { return x.Src }
  1809  func (x *Conjunction) Kind() Kind {
  1810  	k := TopKind
  1811  	for _, v := range x.Values {
  1812  		k &= v.Kind()
  1813  	}
  1814  	return k
  1815  }
  1816  
  1817  // A disjunction is a disjunction of values. It is the result of expanding
  1818  // a DisjunctionExpr if the expression cannot be represented as a single value.
  1819  type Disjunction struct {
  1820  	Src ast.Expr
  1821  
  1822  	// Values are the non-error disjuncts of this expression. The first
  1823  	// NumDefaults values are default values.
  1824  	Values []Value
  1825  
  1826  	Errors *Bottom // []bottom
  1827  
  1828  	// NumDefaults indicates the number of default values.
  1829  	NumDefaults int
  1830  	HasDefaults bool
  1831  }
  1832  
  1833  func (x *Disjunction) Source() ast.Node { return x.Src }
  1834  func (x *Disjunction) Kind() Kind {
  1835  	k := BottomKind
  1836  	for _, v := range x.Values {
  1837  		k |= v.Kind()
  1838  	}
  1839  	return k
  1840  }
  1841  
  1842  type Comprehension struct {
  1843  	Syntax ast.Node
  1844  
  1845  	// Clauses is the list of for, if, and other clauses of a comprehension,
  1846  	// not including the yielded value (in curly braces).
  1847  	Clauses []Yielder
  1848  
  1849  	// Value can be either a StructLit if this is a compiled expression or
  1850  	// a Field if this is a computed Comprehension. Value holds a Field,
  1851  	// rather than an Expr, in the latter case to preserve as much position
  1852  	// information as possible.
  1853  	Value Node
  1854  
  1855  	// The type of field as which the comprehension is added.
  1856  	arcType ArcType
  1857  
  1858  	// The closeContext into which the comprehension is added. Upon a successful
  1859  	// completion of the comprehension, the arcType should be updated in this
  1860  	// closeContext. After this is done, the corresponding parent closeContext
  1861  	// must be closed.
  1862  	arcCC *closeContext
  1863  
  1864  	// This is incremented by the Comprehension upon creation, and decremented
  1865  	// once it is known whether the comprehension succeeded.
  1866  	cc *closeContext
  1867  
  1868  	// Only used for partial comprehensions.
  1869  	comp   *envComprehension
  1870  	parent *Comprehension // comprehension from which this one was derived, if any
  1871  	arc    *Vertex        // arc to which this comprehension was added.
  1872  }
  1873  
  1874  // Nest returns the nesting level of void arcs of this comprehension.
  1875  func (c *Comprehension) Nest() int {
  1876  	count := 0
  1877  	for ; c.parent != nil; c = c.parent {
  1878  		count++
  1879  	}
  1880  	return count
  1881  }
  1882  
  1883  // Envs returns all Environments yielded from an evaluated comprehension.
  1884  // Together with the Comprehension value, each Environment represents a
  1885  // result value of the comprehension.
  1886  func (c *Comprehension) Envs() []*Environment {
  1887  	if c.comp == nil {
  1888  		return nil
  1889  	}
  1890  	return c.comp.envs
  1891  }
  1892  
  1893  // DidResolve reports whether a comprehension was processed and resulted in at
  1894  // least one yielded value.
  1895  func (x *Comprehension) DidResolve() bool {
  1896  	return x.comp.done && len(x.comp.envs) > 0
  1897  }
  1898  
  1899  func (x *Comprehension) Source() ast.Node {
  1900  	if x.Syntax == nil {
  1901  		return nil
  1902  	}
  1903  	return x.Syntax
  1904  }
  1905  
  1906  // A ForClause represents a for clause of a comprehension. It can be used
  1907  // as a struct or list element.
  1908  //
  1909  //	for k, v in src {}
  1910  type ForClause struct {
  1911  	Syntax *ast.ForClause
  1912  	Key    Feature
  1913  	Value  Feature
  1914  	Src    Expr
  1915  }
  1916  
  1917  func (x *ForClause) Source() ast.Node {
  1918  	if x.Syntax == nil {
  1919  		return nil
  1920  	}
  1921  	return x.Syntax
  1922  }
  1923  
  1924  func (c *OpContext) forSource(x Expr) *Vertex {
  1925  	state := require(conjuncts, needFieldSetKnown)
  1926  
  1927  	// TODO: always get the vertex. This allows a whole bunch of trickery
  1928  	// down the line.
  1929  	v := c.unifyNode(x, state)
  1930  
  1931  	node, ok := v.(*Vertex)
  1932  	if ok && c.isDevVersion() {
  1933  		node.unify(c, state.conditions(), yield)
  1934  	}
  1935  
  1936  	v, ok = c.getDefault(v)
  1937  
  1938  	if !ok {
  1939  		// Error already generated by getDefault.
  1940  		return emptyNode
  1941  	}
  1942  
  1943  	// TODO: skip in new evaluator? Check once we introduce disjunctions.
  1944  	if w := Unwrap(v); !isCyclePlaceholder(w) {
  1945  		v = w
  1946  	}
  1947  	node, ok = v.(*Vertex)
  1948  	if ok && !isCyclePlaceholder(node.BaseValue) {
  1949  		v = node.Value()
  1950  	}
  1951  
  1952  	switch nv := v.(type) {
  1953  	case nil:
  1954  		c.addErrf(IncompleteError, pos(x),
  1955  			"cannot range over %s (incomplete)", x)
  1956  		return emptyNode
  1957  
  1958  	case *Bottom:
  1959  		// TODO: this is a bit messy. In some cases errors are already added
  1960  		// and in some cases not. Not a huge deal, as errors will be uniqued
  1961  		// down the line, but could be better.
  1962  		c.AddBottom(nv)
  1963  		return emptyNode
  1964  
  1965  	case *Vertex:
  1966  		if node == nil {
  1967  			panic("unexpected markers with nil node")
  1968  		}
  1969  
  1970  	default:
  1971  		if kind := v.Kind(); kind&StructKind != 0 {
  1972  			c.addErrf(IncompleteError, pos(x),
  1973  				"cannot range over %s (incomplete type %s)", x, kind)
  1974  			return emptyNode
  1975  
  1976  		} else if !ok {
  1977  			c.addErrf(0, pos(x), // TODO(error): better message.
  1978  				"cannot range over %s (found %s, want list or struct)",
  1979  				x.Source(), v.Kind())
  1980  			return emptyNode
  1981  		}
  1982  	}
  1983  
  1984  	return node
  1985  }
  1986  
  1987  func (x *ForClause) yield(s *compState) {
  1988  	c := s.ctx
  1989  	n := c.forSource(x.Src)
  1990  
  1991  	if c.isDevVersion() {
  1992  		if s := n.getState(c); s != nil {
  1993  			s.freeze(fieldSetKnown)
  1994  		}
  1995  	} else {
  1996  		if n.status == evaluating && !n.LockArcs {
  1997  			c.AddBottom(&Bottom{
  1998  				Code:     CycleError,
  1999  				ForCycle: true,
  2000  				Value:    n,
  2001  				Err:      errors.Newf(pos(x.Src), "comprehension source references itself"),
  2002  			})
  2003  			return
  2004  		}
  2005  		if c.HasErr() {
  2006  			return
  2007  		}
  2008  		n.LockArcs = true
  2009  	}
  2010  
  2011  	for _, a := range n.Arcs {
  2012  		if !a.Label.IsRegular() {
  2013  			continue
  2014  		}
  2015  
  2016  		if c.isDevVersion() {
  2017  			c.require(a, arcTypeKnown)
  2018  		} else {
  2019  			if !a.isDefined() {
  2020  				a.Finalize(c)
  2021  			}
  2022  			if !a.definitelyExists() {
  2023  				continue
  2024  			}
  2025  		}
  2026  
  2027  		switch a.ArcType {
  2028  		case ArcMember:
  2029  		case ArcRequired:
  2030  			c.AddBottom(newRequiredFieldInComprehensionError(c, x, a))
  2031  			continue
  2032  		default:
  2033  			continue
  2034  		}
  2035  
  2036  		n := &Vertex{
  2037  			Parent: c.Env(0).Vertex,
  2038  
  2039  			// Using Finalized here ensures that no nodeContext is allocated,
  2040  			// preventing a leak, as this "helper" struct bypasses normal
  2041  			// processing, eluding the deallocation step.
  2042  			status:    finalized,
  2043  			IsDynamic: true,
  2044  			ArcType:   ArcMember,
  2045  		}
  2046  
  2047  		if x.Value != InvalidLabel {
  2048  			b := &Vertex{
  2049  				Label:     x.Value,
  2050  				BaseValue: a,
  2051  				IsDynamic: true,
  2052  				ArcType:   ArcPending,
  2053  			}
  2054  			n.Arcs = append(n.Arcs, b)
  2055  		}
  2056  
  2057  		if x.Key != InvalidLabel {
  2058  			v := &Vertex{
  2059  				Label:     x.Key,
  2060  				IsDynamic: true,
  2061  			}
  2062  			key := a.Label.ToValue(c)
  2063  			v.AddConjunct(MakeRootConjunct(c.Env(0), key))
  2064  			v.SetValue(c, key)
  2065  			n.Arcs = append(n.Arcs, v)
  2066  		}
  2067  
  2068  		sub := c.spawn(n)
  2069  		if !s.yield(sub) {
  2070  			break
  2071  		}
  2072  	}
  2073  }
  2074  
  2075  // An IfClause represents an if clause of a comprehension. It can be used
  2076  // as a struct or list element.
  2077  //
  2078  //	if cond {}
  2079  type IfClause struct {
  2080  	Src       *ast.IfClause
  2081  	Condition Expr
  2082  }
  2083  
  2084  func (x *IfClause) Source() ast.Node {
  2085  	if x.Src == nil {
  2086  		return nil
  2087  	}
  2088  	return x.Src
  2089  }
  2090  
  2091  func (x *IfClause) yield(s *compState) {
  2092  	ctx := s.ctx
  2093  	if ctx.BoolValue(ctx.value(x.Condition, require(s.state, scalarKnown))) {
  2094  		s.yield(ctx.e)
  2095  	}
  2096  }
  2097  
  2098  // A LetClause represents a let clause in a comprehension.
  2099  //
  2100  //	let x = y
  2101  type LetClause struct {
  2102  	Src   *ast.LetClause
  2103  	Label Feature
  2104  	Expr  Expr
  2105  }
  2106  
  2107  func (x *LetClause) Source() ast.Node {
  2108  	if x.Src == nil {
  2109  		return nil
  2110  	}
  2111  	return x.Src
  2112  }
  2113  
  2114  func (x *LetClause) yield(s *compState) {
  2115  	c := s.ctx
  2116  	n := &Vertex{Arcs: []*Vertex{
  2117  		{
  2118  			Label:     x.Label,
  2119  			IsDynamic: true,
  2120  			Conjuncts: []Conjunct{{c.Env(0), x.Expr, c.ci}},
  2121  		},
  2122  	}}
  2123  
  2124  	s.yield(c.spawn(n))
  2125  }