github.com/joomcode/cue@v0.4.4-0.20221111115225-539fe3512047/internal/core/adt/eval.go (about)

     1  // Copyright 2021 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 eval contains the high level CUE evaluation strategy.
    16  //
    17  // CUE allows for a significant amount of freedom in order of evaluation due to
    18  // the commutativity of the unification operation. This package implements one
    19  // of the possible strategies.
    20  package adt
    21  
    22  // TODO:
    23  //   - result should be nodeContext: this allows optionals info to be extracted
    24  //     and computed.
    25  //
    26  
    27  import (
    28  	"fmt"
    29  	"html/template"
    30  	"strings"
    31  
    32  	"github.com/joomcode/cue/cue/ast"
    33  	"github.com/joomcode/cue/cue/errors"
    34  	"github.com/joomcode/cue/cue/token"
    35  )
    36  
    37  // TODO TODO TODO TODO TODO TODO  TODO TODO TODO  TODO TODO TODO  TODO TODO TODO
    38  //
    39  // - Reuse work from previous cycles. For instance, if we can guarantee that a
    40  //   value is always correct for partial results, we can just process the arcs
    41  //   going from Partial to Finalized, without having to reevaluate the value.
    42  //
    43  // - Test closedness far more thoroughly.
    44  //
    45  
    46  type Stats struct {
    47  	DisjunctCount int
    48  	UnifyCount    int
    49  
    50  	Freed    int
    51  	Retained int
    52  	Reused   int
    53  	Allocs   int
    54  }
    55  
    56  // Leaks reports the number of nodeContext structs leaked. These are typically
    57  // benign, as they will just be garbage collected, as long as the pointer from
    58  // the original nodes has been eliminated or the original nodes are also not
    59  // referred to. But Leaks may have notable impact on performance, and thus
    60  // should be avoided.
    61  func (s *Stats) Leaks() int {
    62  	return s.Allocs + s.Reused - s.Freed
    63  }
    64  
    65  var stats = template.Must(template.New("stats").Parse(`{{"" -}}
    66  
    67  Leaks:  {{.Leaks}}
    68  Freed:  {{.Freed}}
    69  Reused: {{.Reused}}
    70  Allocs: {{.Allocs}}
    71  Retain: {{.Retained}}
    72  
    73  Unifications: {{.UnifyCount}}
    74  Disjuncts:    {{.DisjunctCount}}`))
    75  
    76  func (s *Stats) String() string {
    77  	buf := &strings.Builder{}
    78  	_ = stats.Execute(buf, s)
    79  	return buf.String()
    80  }
    81  
    82  func (c *OpContext) Stats() *Stats {
    83  	return &c.stats
    84  }
    85  
    86  // TODO: Note: NewContext takes essentially a cue.Value. By making this
    87  // type more central, we can perhaps avoid context creation.
    88  
    89  // func NewContext(r Runtime, v *Vertex) *OpContext {
    90  // 	e := NewUnifier(r)
    91  // 	return e.NewContext(v)
    92  // }
    93  
    94  var structSentinel = &StructMarker{}
    95  
    96  var incompleteSentinel = &Bottom{
    97  	Code: IncompleteError,
    98  	Err:  errors.Newf(token.NoPos, "incomplete"),
    99  }
   100  
   101  // evaluate returns the evaluated value associated with v. It may return a
   102  // partial result. That is, if v was not yet unified, it may return a
   103  // concrete value that must be the result assuming the configuration has no
   104  // errors.
   105  //
   106  // This semantics allows CUE to break reference cycles in a straightforward
   107  // manner.
   108  //
   109  // Vertex v must still be evaluated at some point to catch the underlying
   110  // error.
   111  //
   112  // TODO: return *Vertex
   113  func (c *OpContext) evaluate(v *Vertex, state VertexStatus) Value {
   114  	if v.isUndefined() {
   115  		// Use node itself to allow for cycle detection.
   116  		c.Unify(v, state)
   117  	}
   118  
   119  	if n := v.state; n != nil {
   120  		if n.errs != nil && !n.errs.IsIncomplete() {
   121  			return n.errs
   122  		}
   123  		if n.scalar != nil && isCyclePlaceholder(v.BaseValue) {
   124  			return n.scalar
   125  		}
   126  	}
   127  
   128  	switch x := v.BaseValue.(type) {
   129  	case *Bottom:
   130  		if x.IsIncomplete() {
   131  			c.AddBottom(x)
   132  			return nil
   133  		}
   134  		return x
   135  
   136  	case nil:
   137  		if v.state != nil {
   138  			switch x := v.state.getValidators().(type) {
   139  			case Value:
   140  				return x
   141  			default:
   142  				w := *v
   143  				w.BaseValue = x
   144  				return &w
   145  			}
   146  		}
   147  		Assertf(false, "no BaseValue: state: %v; requested: %v", v.status, state)
   148  	}
   149  
   150  	if v.status < Finalized && v.state != nil {
   151  		// TODO: errors are slightly better if we always add addNotify, but
   152  		// in this case it is less likely to cause a performance penalty.
   153  		// See https://cuelang.org/issue/661. It may be possible to
   154  		// relax this again once we have proper tests to prevent regressions of
   155  		// that issue.
   156  		if !v.state.done() || v.state.errs != nil {
   157  			v.state.addNotify(c.vertex)
   158  		}
   159  	}
   160  
   161  	return v
   162  }
   163  
   164  // Unify fully unifies all values of a Vertex to completion and stores
   165  // the result in the Vertex. If unify was called on v before it returns
   166  // the cached results.
   167  func (c *OpContext) Unify(v *Vertex, state VertexStatus) {
   168  	// defer c.PopVertex(c.PushVertex(v))
   169  	if Debug {
   170  		c.nest++
   171  		c.Logf(v, "Unify")
   172  		defer func() {
   173  			c.Logf(v, "END Unify")
   174  			c.nest--
   175  		}()
   176  	}
   177  
   178  	// Ensure a node will always have a nodeContext after calling Unify if it is
   179  	// not yet Finalized.
   180  	n := v.getNodeContext(c)
   181  	defer v.freeNode(n)
   182  
   183  	if state <= v.Status() {
   184  		if v.Status() != Partial && state != Partial {
   185  			return
   186  		}
   187  	}
   188  
   189  	switch v.Status() {
   190  	case Evaluating:
   191  		n.insertConjuncts()
   192  		return
   193  
   194  	case EvaluatingArcs:
   195  		Assertf(v.status > 0, "unexpected status %d", v.status)
   196  		return
   197  
   198  	case 0:
   199  		if v.Label.IsDef() {
   200  			v.Closed = true
   201  		}
   202  
   203  		if v.Parent != nil {
   204  			if v.Parent.Closed {
   205  				v.Closed = true
   206  			}
   207  		}
   208  
   209  		if p := v.Parent; p != nil && p.state != nil && v.Label.IsString() {
   210  			for _, s := range p.state.node.Structs {
   211  				if s.Disable {
   212  					continue
   213  				}
   214  				s.MatchAndInsert(n.ctx, v)
   215  			}
   216  		}
   217  
   218  		if !n.checkClosed(state) {
   219  			return
   220  		}
   221  
   222  		defer c.PopArc(c.PushArc(v))
   223  
   224  		c.stats.UnifyCount++
   225  
   226  		// Clear any remaining error.
   227  		if err := c.Err(); err != nil {
   228  			panic("uncaught error")
   229  		}
   230  
   231  		// Set the cache to a cycle error to ensure a cyclic reference will result
   232  		// in an error if applicable. A cyclic error may be ignored for
   233  		// non-expression references. The cycle error may also be removed as soon
   234  		// as there is evidence what a correct value must be, but before all
   235  		// validation has taken place.
   236  		//
   237  		// TODO(cycle): having a more recursive algorithm would make this
   238  		// special cycle handling unnecessary.
   239  		v.BaseValue = cycle
   240  
   241  		v.UpdateStatus(Evaluating)
   242  
   243  		n.conjuncts = v.Conjuncts
   244  		n.insertConjuncts()
   245  
   246  		fallthrough
   247  
   248  	case Partial:
   249  		defer c.PopArc(c.PushArc(v))
   250  
   251  		v.status = Evaluating
   252  
   253  		// Use maybeSetCache for cycle breaking
   254  		for n.maybeSetCache(); n.expandOne(); n.maybeSetCache() {
   255  		}
   256  
   257  		n.doNotify()
   258  
   259  		if !n.done() {
   260  			switch {
   261  			case len(n.disjunctions) > 0 && isCyclePlaceholder(v.BaseValue):
   262  				// We disallow entering computations of disjunctions with
   263  				// incomplete data.
   264  				if state == Finalized {
   265  					b := c.NewErrf("incomplete cause disjunction")
   266  					b.Code = IncompleteError
   267  					n.errs = CombineErrors(nil, n.errs, b)
   268  					v.SetValue(n.ctx, Finalized, b)
   269  				} else {
   270  					n.node.UpdateStatus(Partial)
   271  				}
   272  				return
   273  
   274  			case state <= AllArcs:
   275  				n.node.UpdateStatus(Partial)
   276  				return
   277  			}
   278  		}
   279  
   280  		if s := v.Status(); state <= s {
   281  			// We have found a partial result. There may still be errors
   282  			// down the line which may result from further evaluating this
   283  			// field, but that will be caught when evaluating this field
   284  			// for real.
   285  
   286  			// This also covers the case where a recursive evaluation triggered
   287  			// this field to become finalized in the mean time. In that case
   288  			// we can avoid running another expandDisjuncts.
   289  			return
   290  		}
   291  
   292  		// Disjunctions should always be finalized. If there are nested
   293  		// disjunctions the last one should be finalized.
   294  		disState := state
   295  		if len(n.disjunctions) > 0 && disState != Finalized {
   296  			disState = Finalized
   297  		}
   298  		n.expandDisjuncts(disState, n, maybeDefault, false, true)
   299  
   300  		n.finalizeDisjuncts()
   301  
   302  		switch len(n.disjuncts) {
   303  		case 0:
   304  		case 1:
   305  			x := n.disjuncts[0].result
   306  			x.state = nil
   307  			*v = x
   308  
   309  		default:
   310  			d := n.createDisjunct()
   311  			v.BaseValue = d
   312  			// The conjuncts will have too much information. Better have no
   313  			// information than incorrect information.
   314  			for _, d := range d.Values {
   315  				// We clear the conjuncts for now. As these disjuncts are for API
   316  				// use only, we will fill them out when necessary (using Defaults).
   317  				d.Conjuncts = nil
   318  
   319  				// TODO: use a more principled form of dereferencing. For instance,
   320  				// disjuncts could already be assumed to be the given Vertex, and
   321  				// the the main vertex could be dereferenced during evaluation.
   322  				for _, a := range d.Arcs {
   323  					for _, x := range a.Conjuncts {
   324  						// All the environments for embedded structs need to be
   325  						// dereferenced.
   326  						for env := x.Env; env != nil && env.Vertex == v; env = env.Up {
   327  							env.Vertex = d
   328  						}
   329  					}
   330  				}
   331  			}
   332  			v.Arcs = nil
   333  			// v.Structs = nil // TODO: should we keep or discard the Structs?
   334  			// TODO: how to represent closedness information? Do we need it?
   335  		}
   336  
   337  		// If the state has changed, it is because a disjunct has been run, or
   338  		// because a single disjunct has replaced it. Restore the old state as
   339  		// to not confuse memory management.
   340  		v.state = n
   341  
   342  		// We don't do this in postDisjuncts, as it should only be done after
   343  		// completing all disjunctions.
   344  		if !n.done() {
   345  			if err := n.incompleteErrors(); err != nil {
   346  				b, _ := n.node.BaseValue.(*Bottom)
   347  				if b != err {
   348  					err = CombineErrors(n.ctx.src, b, err)
   349  				}
   350  				n.node.BaseValue = err
   351  			}
   352  		}
   353  
   354  		if state != Finalized {
   355  			return
   356  		}
   357  
   358  		if v.BaseValue == nil {
   359  			v.BaseValue = n.getValidators()
   360  		}
   361  
   362  		// Free memory here?
   363  		v.UpdateStatus(Finalized)
   364  
   365  	case AllArcs:
   366  		if !n.checkClosed(state) {
   367  			break
   368  		}
   369  
   370  		defer c.PopArc(c.PushArc(v))
   371  
   372  		n.completeArcs(state)
   373  
   374  	case Finalized:
   375  	}
   376  }
   377  
   378  // insertConjuncts inserts conjuncts previously uninserted.
   379  func (n *nodeContext) insertConjuncts() {
   380  	for len(n.conjuncts) > 0 {
   381  		nInfos := len(n.node.Structs)
   382  		p := &n.conjuncts[0]
   383  		n.conjuncts = n.conjuncts[1:]
   384  		n.addExprConjunct(*p)
   385  
   386  		// Record the OptionalTypes for all structs that were inferred by this
   387  		// Conjunct. This information can be used by algorithms such as trim.
   388  		for i := nInfos; i < len(n.node.Structs); i++ {
   389  			p.CloseInfo.FieldTypes |= n.node.Structs[i].types
   390  		}
   391  	}
   392  }
   393  
   394  // finalizeDisjuncts: incomplete errors are kept around and not removed early.
   395  // This call filters the incomplete errors and removes them
   396  //
   397  // This also collects all errors of empty disjunctions. These cannot be
   398  // collected during the finalization state of individual disjuncts. Care should
   399  // be taken to only call this after all disjuncts have been finalized.
   400  func (n *nodeContext) finalizeDisjuncts() {
   401  	a := n.disjuncts
   402  	if len(a) == 0 {
   403  		return
   404  	}
   405  	k := 0
   406  	for i, d := range a {
   407  		switch d.finalDone() {
   408  		case true:
   409  			a[k], a[i] = d, a[k]
   410  			k++
   411  		default:
   412  			if err := d.incompleteErrors(); err != nil {
   413  				n.disjunctErrs = append(n.disjunctErrs, err)
   414  			}
   415  		}
   416  		d.free()
   417  	}
   418  	if k == 0 {
   419  		n.makeError()
   420  	}
   421  	n.disjuncts = a[:k]
   422  }
   423  
   424  func (n *nodeContext) doNotify() {
   425  	if n.errs == nil || len(n.notify) == 0 {
   426  		return
   427  	}
   428  	for _, v := range n.notify {
   429  		if v.state == nil {
   430  			if b, ok := v.BaseValue.(*Bottom); ok {
   431  				v.BaseValue = CombineErrors(nil, b, n.errs)
   432  			} else {
   433  				v.BaseValue = n.errs
   434  			}
   435  		} else {
   436  			v.state.addBottom(n.errs)
   437  		}
   438  	}
   439  	n.notify = n.notify[:0]
   440  }
   441  
   442  func (n *nodeContext) postDisjunct(state VertexStatus) {
   443  	ctx := n.ctx
   444  
   445  	for {
   446  		// Use maybeSetCache for cycle breaking
   447  		for n.maybeSetCache(); n.expandOne(); n.maybeSetCache() {
   448  		}
   449  
   450  		if aList, id := n.addLists(); aList != nil {
   451  			n.updateNodeType(ListKind, aList, id)
   452  		} else {
   453  			break
   454  		}
   455  	}
   456  
   457  	if n.aStruct != nil {
   458  		n.updateNodeType(StructKind, n.aStruct, n.aStructID)
   459  	}
   460  
   461  	switch err := n.getErr(); {
   462  	case err != nil:
   463  		n.node.BaseValue = err
   464  		n.errs = nil
   465  
   466  	default:
   467  		if isCyclePlaceholder(n.node.BaseValue) {
   468  			if !n.done() {
   469  				n.node.BaseValue = n.incompleteErrors()
   470  			} else {
   471  				n.node.BaseValue = nil
   472  			}
   473  		}
   474  		// TODO: this ideally should be done here. However, doing so causes
   475  		// a somewhat more aggressive cutoff in disjunction cycles, which cause
   476  		// some incompatibilities. Fix in another CL.
   477  		//
   478  		// else if !n.done() {
   479  		// 	n.expandOne()
   480  		// 	if err := n.incompleteErrors(); err != nil {
   481  		// 		n.node.BaseValue = err
   482  		// 	}
   483  		// }
   484  
   485  		// We are no longer evaluating.
   486  		// n.node.UpdateStatus(Partial)
   487  		n.node.UpdateStatus(Evaluating)
   488  
   489  		// Either set to Conjunction or error.
   490  		// TODO: verify and simplify the below code to determine whether
   491  		// something is a struct.
   492  		markStruct := false
   493  		if n.aStruct != nil {
   494  			markStruct = true
   495  		} else if len(n.node.Structs) > 0 {
   496  			markStruct = n.kind&StructKind != 0 && !n.hasTop
   497  		}
   498  		v := n.node.Value()
   499  		if n.node.BaseValue == nil && markStruct {
   500  			n.node.BaseValue = &StructMarker{}
   501  			v = n.node
   502  		}
   503  		if v != nil && IsConcrete(v) {
   504  			// Also check when we already have errors as we may find more
   505  			// serious errors and would like to know about all errors anyway.
   506  
   507  			if n.lowerBound != nil {
   508  				if b := ctx.Validate(n.lowerBound, v); b != nil {
   509  					// TODO(errors): make Validate return boolean and generate
   510  					// optimized conflict message. Also track and inject IDs
   511  					// to determine origin location.s
   512  					if e, _ := b.Err.(*ValueError); e != nil {
   513  						e.AddPosition(n.lowerBound)
   514  						e.AddPosition(v)
   515  					}
   516  					n.addBottom(b)
   517  				}
   518  			}
   519  			if n.upperBound != nil {
   520  				if b := ctx.Validate(n.upperBound, v); b != nil {
   521  					// TODO(errors): make Validate return boolean and generate
   522  					// optimized conflict message. Also track and inject IDs
   523  					// to determine origin location.s
   524  					if e, _ := b.Err.(*ValueError); e != nil {
   525  						e.AddPosition(n.upperBound)
   526  						e.AddPosition(v)
   527  					}
   528  					n.addBottom(b)
   529  				}
   530  			}
   531  			// MOVE BELOW
   532  			// TODO(perf): only delay processing of actual non-monotonic checks.
   533  			skip := n.skipNonMonotonicChecks()
   534  			if v := n.node.Value(); v != nil && IsConcrete(v) && !skip {
   535  				for _, v := range n.checks {
   536  					// TODO(errors): make Validate return bottom and generate
   537  					// optimized conflict message. Also track and inject IDs
   538  					// to determine origin location.s
   539  					if b := ctx.Validate(v, n.node); b != nil {
   540  						n.addBottom(b)
   541  					}
   542  				}
   543  			}
   544  		} else if state == Finalized {
   545  			n.node.BaseValue = n.getValidators()
   546  		}
   547  
   548  		if v == nil {
   549  			break
   550  		}
   551  
   552  		switch {
   553  		case v.Kind() == ListKind:
   554  			for _, a := range n.node.Arcs {
   555  				if a.Label.Typ() == StringLabel {
   556  					n.addErr(ctx.Newf("list may not have regular fields"))
   557  					// TODO(errors): add positions for list and arc definitions.
   558  
   559  				}
   560  			}
   561  
   562  			// case !isStruct(n.node) && v.Kind() != BottomKind:
   563  			// 	for _, a := range n.node.Arcs {
   564  			// 		if a.Label.IsRegular() {
   565  			// 			n.addErr(errors.Newf(token.NoPos,
   566  			// 				// TODO(errors): add positions of non-struct values and arcs.
   567  			// 				"cannot combine scalar values with arcs"))
   568  			// 		}
   569  			// 	}
   570  		}
   571  	}
   572  
   573  	if err := n.getErr(); err != nil {
   574  		if b, _ := n.node.BaseValue.(*Bottom); b != nil {
   575  			err = CombineErrors(nil, b, err)
   576  		}
   577  		n.node.BaseValue = err
   578  		// TODO: add return: if evaluation of arcs is important it can be done
   579  		// later. Logically we're done.
   580  	}
   581  
   582  	n.completeArcs(state)
   583  }
   584  
   585  func (n *nodeContext) incompleteErrors() *Bottom {
   586  	// collect incomplete errors.
   587  	var err *Bottom // n.incomplete
   588  	for _, d := range n.dynamicFields {
   589  		err = CombineErrors(nil, err, d.err)
   590  	}
   591  	for _, c := range n.comprehensions {
   592  		err = CombineErrors(nil, err, c.err)
   593  	}
   594  	for _, x := range n.exprs {
   595  		err = CombineErrors(nil, err, x.err)
   596  	}
   597  	if err == nil {
   598  		// safeguard.
   599  		err = incompleteSentinel
   600  	}
   601  	return err
   602  }
   603  
   604  // TODO(perf): ideally we should always perform a closedness check if
   605  // state is Finalized. This is currently not possible when computing a
   606  // partial disjunction as the closedness information is not yet
   607  // complete, possibly leading to a disjunct to be rejected prematurely.
   608  // It is probably possible to fix this if we could add StructInfo
   609  // structures demarked per conjunct.
   610  //
   611  // In practice this should not be a problem: when disjuncts originate
   612  // from the same disjunct, they will have the same StructInfos, and thus
   613  // Equal is able to equate them even in the precense of optional field.
   614  // In general, combining any limited set of disjuncts will soon reach
   615  // a fixed point where duplicate elements can be eliminated this way.
   616  //
   617  // Note that not checking closedness is irrelevant for disjunctions of
   618  // scalars. This means it also doesn't hurt performance where structs
   619  // have a discriminator field (e.g. Kubernetes). We should take care,
   620  // though, that any potential performance issues are eliminated for
   621  // Protobuf-like oneOf fields.
   622  func (n *nodeContext) checkClosed(state VertexStatus) bool {
   623  	ignore := state != Finalized || n.skipNonMonotonicChecks()
   624  
   625  	v := n.node
   626  	if !v.Label.IsInt() && v.Parent != nil && !ignore {
   627  		ctx := n.ctx
   628  		// Visit arcs recursively to validate and compute error.
   629  		if _, err := verifyArc2(ctx, v.Label, v, v.Closed); err != nil {
   630  			// Record error in child node to allow recording multiple
   631  			// conflicts at the appropriate place, to allow valid fields to
   632  			// be represented normally and, most importantly, to avoid
   633  			// recursive processing of a disallowed field.
   634  			v.SetValue(ctx, Finalized, err)
   635  			return false
   636  		}
   637  	}
   638  	return true
   639  }
   640  
   641  func (n *nodeContext) completeArcs(state VertexStatus) {
   642  	if DebugSort > 0 {
   643  		DebugSortArcs(n.ctx, n.node)
   644  	}
   645  
   646  	if state <= AllArcs {
   647  		n.node.UpdateStatus(AllArcs)
   648  		return
   649  	}
   650  
   651  	n.node.UpdateStatus(EvaluatingArcs)
   652  
   653  	ctx := n.ctx
   654  
   655  	if !assertStructuralCycle(n) {
   656  		// Visit arcs recursively to validate and compute error.
   657  		for _, a := range n.node.Arcs {
   658  			if a.nonMonotonicInsertGen >= a.nonMonotonicLookupGen && a.nonMonotonicLookupGen > 0 {
   659  				err := ctx.Newf(
   660  					"cycle: field inserted by if clause that was previously evaluated by another if clause: %s", a.Label)
   661  				err.AddPosition(n.node)
   662  				n.node.BaseValue = &Bottom{Err: err}
   663  			} else if a.nonMonotonicReject {
   664  				err := ctx.Newf(
   665  					"cycle: field was added after an if clause evaluated it: %s",
   666  					a.Label)
   667  				err.AddPosition(n.node)
   668  				n.node.BaseValue = &Bottom{Err: err}
   669  			}
   670  
   671  			// Call UpdateStatus here to be absolutely sure the status is set
   672  			// correctly and that we are not regressing.
   673  			n.node.UpdateStatus(EvaluatingArcs)
   674  			ctx.Unify(a, state)
   675  			// Don't set the state to Finalized if the child arcs are not done.
   676  			if state == Finalized && a.status < Finalized {
   677  				state = AllArcs
   678  			}
   679  			if err, _ := a.BaseValue.(*Bottom); err != nil {
   680  				n.node.AddChildError(err)
   681  			}
   682  		}
   683  	}
   684  
   685  	n.node.UpdateStatus(state)
   686  }
   687  
   688  func assertStructuralCycle(n *nodeContext) bool {
   689  	if cyclic := n.hasCycle && !n.hasNonCycle; cyclic {
   690  		n.node.BaseValue = CombineErrors(nil,
   691  			n.node.Value(),
   692  			&Bottom{
   693  				Code:  StructuralCycleError,
   694  				Err:   n.ctx.Newf("structural cycle"),
   695  				Value: n.node.Value(),
   696  				// TODO: probably, this should have the referenced arc.
   697  			})
   698  		// Don't process Arcs. This is mostly to ensure that no Arcs with
   699  		// an Unprocessed status remain in the output.
   700  		n.node.Arcs = nil
   701  		return true
   702  	}
   703  	return false
   704  }
   705  
   706  // TODO: this is now a sentinel. Use a user-facing error that traces where
   707  // the cycle originates.
   708  var cycle = &Bottom{
   709  	Err:  errors.Newf(token.NoPos, "cycle error"),
   710  	Code: CycleError,
   711  }
   712  
   713  func isCyclePlaceholder(v BaseValue) bool {
   714  	return v == cycle
   715  }
   716  
   717  func (n *nodeContext) createDisjunct() *Disjunction {
   718  	a := make([]*Vertex, len(n.disjuncts))
   719  	p := 0
   720  	hasDefaults := false
   721  	for i, x := range n.disjuncts {
   722  		v := new(Vertex)
   723  		*v = x.result
   724  		v.state = nil
   725  		switch x.defaultMode {
   726  		case isDefault:
   727  			a[i] = a[p]
   728  			a[p] = v
   729  			p++
   730  			hasDefaults = true
   731  
   732  		case notDefault:
   733  			hasDefaults = true
   734  			fallthrough
   735  		case maybeDefault:
   736  			a[i] = v
   737  		}
   738  	}
   739  	// TODO: disambiguate based on concrete values.
   740  	// TODO: consider not storing defaults.
   741  	// if p > 0 {
   742  	// 	a = a[:p]
   743  	// }
   744  	return &Disjunction{
   745  		Values:      a,
   746  		NumDefaults: p,
   747  		HasDefaults: hasDefaults,
   748  	}
   749  }
   750  
   751  type arcKey struct {
   752  	arc *Vertex
   753  	id  CloseInfo
   754  }
   755  
   756  // A nodeContext is used to collate all conjuncts of a value to facilitate
   757  // unification. Conceptually order of unification does not matter. However,
   758  // order has relevance when performing checks of non-monotic properities. Such
   759  // checks should only be performed once the full value is known.
   760  type nodeContext struct {
   761  	nextFree *nodeContext
   762  	refCount int
   763  
   764  	ctx  *OpContext
   765  	node *Vertex
   766  
   767  	// usedArcs is a list of arcs that were looked up during non-monotonic operations, but do not exist yet.
   768  	usedArcs []*Vertex
   769  
   770  	// TODO: (this is CL is first step)
   771  	// filter *Vertex a subset of composite with concrete fields for
   772  	// bloom-like filtering of disjuncts. We should first verify, however,
   773  	// whether some breath-first search gives sufficient performance, as this
   774  	// should already ensure a quick-fail for struct disjunctions with
   775  	// discriminators.
   776  
   777  	arcMap []arcKey
   778  
   779  	// snapshot holds the last value of the vertex before calling postDisjunct.
   780  	snapshot Vertex
   781  
   782  	// Result holds the last evaluated value of the vertex after calling
   783  	// postDisjunct.
   784  	result Vertex
   785  
   786  	// Current value (may be under construction)
   787  	scalar   Value // TODO: use Value in node.
   788  	scalarID CloseInfo
   789  
   790  	// Concrete conjuncts
   791  	kind       Kind
   792  	kindExpr   Expr        // expr that adjust last value (for error reporting)
   793  	kindID     CloseInfo   // for error tracing
   794  	lowerBound *BoundValue // > or >=
   795  	upperBound *BoundValue // < or <=
   796  	checks     []Validator // BuiltinValidator, other bound values.
   797  	errs       *Bottom
   798  
   799  	// Conjuncts holds a reference to the Vertex Arcs that still need
   800  	// processing. It does NOT need to be copied.
   801  	conjuncts []Conjunct
   802  
   803  	// notify is used to communicate errors in cyclic dependencies.
   804  	// TODO: also use this to communicate increasingly more concrete values.
   805  	notify []*Vertex
   806  
   807  	// Struct information
   808  	dynamicFields  []envDynamic
   809  	comprehensions []envYield
   810  	aStruct        Expr
   811  	aStructID      CloseInfo
   812  
   813  	// Expression conjuncts
   814  	lists  []envList
   815  	vLists []*Vertex
   816  	exprs  []envExpr
   817  
   818  	hasTop      bool
   819  	hasCycle    bool // has conjunct with structural cycle
   820  	hasNonCycle bool // has conjunct without structural cycle
   821  
   822  	// Disjunction handling
   823  	disjunctions []envDisjunct
   824  
   825  	// usedDefault indicates the for each of possibly multiple parent
   826  	// disjunctions whether it is unified with a default disjunct or not.
   827  	// This is then later used to determine whether a disjunction should
   828  	// be treated as a marked disjunction.
   829  	usedDefault []defaultInfo
   830  
   831  	defaultMode  defaultMode
   832  	disjuncts    []*nodeContext
   833  	buffer       []*nodeContext
   834  	disjunctErrs []*Bottom
   835  }
   836  
   837  type defaultInfo struct {
   838  	// parentMode indicates whether this values was used as a default value,
   839  	// based on the parent mode.
   840  	parentMode defaultMode
   841  
   842  	// The result of default evaluation for a nested disjunction.
   843  	nestedMode defaultMode
   844  
   845  	origMode defaultMode
   846  }
   847  
   848  func (n *nodeContext) addNotify(v *Vertex) {
   849  	if v != nil {
   850  		n.notify = append(n.notify, v)
   851  	}
   852  }
   853  
   854  func (n *nodeContext) clone() *nodeContext {
   855  	d := n.ctx.newNodeContext(n.node)
   856  
   857  	d.refCount++
   858  
   859  	d.ctx = n.ctx
   860  	d.node = n.node
   861  
   862  	d.scalar = n.scalar
   863  	d.scalarID = n.scalarID
   864  	d.kind = n.kind
   865  	d.kindExpr = n.kindExpr
   866  	d.kindID = n.kindID
   867  	d.aStruct = n.aStruct
   868  	d.aStructID = n.aStructID
   869  	d.hasTop = n.hasTop
   870  
   871  	d.lowerBound = n.lowerBound
   872  	d.upperBound = n.upperBound
   873  	d.errs = n.errs
   874  	d.hasTop = n.hasTop
   875  	d.hasCycle = n.hasCycle
   876  	d.hasNonCycle = n.hasNonCycle
   877  
   878  	// d.arcMap = append(d.arcMap, n.arcMap...) // XXX add?
   879  	// d.usedArcs = append(d.usedArcs, n.usedArcs...) // XXX: add?
   880  	d.notify = append(d.notify, n.notify...)
   881  	d.checks = append(d.checks, n.checks...)
   882  	d.dynamicFields = append(d.dynamicFields, n.dynamicFields...)
   883  	d.comprehensions = append(d.comprehensions, n.comprehensions...)
   884  	d.lists = append(d.lists, n.lists...)
   885  	d.vLists = append(d.vLists, n.vLists...)
   886  	d.exprs = append(d.exprs, n.exprs...)
   887  	d.usedDefault = append(d.usedDefault, n.usedDefault...)
   888  
   889  	// No need to clone d.disjunctions
   890  
   891  	return d
   892  }
   893  
   894  func (c *OpContext) newNodeContext(node *Vertex) *nodeContext {
   895  	if n := c.freeListNode; n != nil {
   896  		c.stats.Reused++
   897  		c.freeListNode = n.nextFree
   898  
   899  		*n = nodeContext{
   900  			ctx:            c,
   901  			node:           node,
   902  			kind:           TopKind,
   903  			usedArcs:       n.usedArcs[:0],
   904  			arcMap:         n.arcMap[:0],
   905  			notify:         n.notify[:0],
   906  			checks:         n.checks[:0],
   907  			dynamicFields:  n.dynamicFields[:0],
   908  			comprehensions: n.comprehensions[:0],
   909  			lists:          n.lists[:0],
   910  			vLists:         n.vLists[:0],
   911  			exprs:          n.exprs[:0],
   912  			disjunctions:   n.disjunctions[:0],
   913  			usedDefault:    n.usedDefault[:0],
   914  			disjunctErrs:   n.disjunctErrs[:0],
   915  			disjuncts:      n.disjuncts[:0],
   916  			buffer:         n.buffer[:0],
   917  		}
   918  
   919  		return n
   920  	}
   921  	c.stats.Allocs++
   922  
   923  	return &nodeContext{
   924  		ctx:  c,
   925  		node: node,
   926  		kind: TopKind,
   927  	}
   928  }
   929  
   930  func (v *Vertex) getNodeContext(c *OpContext) *nodeContext {
   931  	if v.state == nil {
   932  		if v.status == Finalized {
   933  			return nil
   934  		}
   935  		v.state = c.newNodeContext(v)
   936  	} else if v.state.node != v {
   937  		panic("getNodeContext: nodeContext out of sync")
   938  	}
   939  	v.state.refCount++
   940  	return v.state
   941  }
   942  
   943  func (v *Vertex) freeNode(n *nodeContext) {
   944  	if n == nil {
   945  		return
   946  	}
   947  	if n.node != v {
   948  		panic("freeNode: unpaired free")
   949  	}
   950  	if v.state != nil && v.state != n {
   951  		panic("freeNode: nodeContext out of sync")
   952  	}
   953  	if n.refCount--; n.refCount == 0 {
   954  		if v.status == Finalized {
   955  			v.freeNodeState()
   956  		} else {
   957  			n.ctx.stats.Retained++
   958  		}
   959  	}
   960  }
   961  
   962  func (v *Vertex) freeNodeState() {
   963  	if v.state == nil {
   964  		return
   965  	}
   966  	state := v.state
   967  	v.state = nil
   968  
   969  	state.ctx.freeNodeContext(state)
   970  }
   971  
   972  func (n *nodeContext) free() {
   973  	if n.refCount--; n.refCount == 0 {
   974  		n.ctx.freeNodeContext(n)
   975  	}
   976  }
   977  
   978  func (c *OpContext) freeNodeContext(n *nodeContext) {
   979  	c.stats.Freed++
   980  	n.nextFree = c.freeListNode
   981  	c.freeListNode = n
   982  	n.node = nil
   983  	n.refCount = 0
   984  }
   985  
   986  // TODO(perf): return a dedicated ConflictError that can track original
   987  // positions on demand.
   988  func (n *nodeContext) reportConflict(
   989  	v1, v2 Node,
   990  	k1, k2 Kind,
   991  	ids ...CloseInfo) {
   992  
   993  	ctx := n.ctx
   994  
   995  	var err *ValueError
   996  	if k1 == k2 {
   997  		err = ctx.NewPosf(token.NoPos, "conflicting values %s and %s", v1, v2)
   998  	} else {
   999  		err = ctx.NewPosf(token.NoPos,
  1000  			"conflicting values %s and %s (mismatched types %s and %s)",
  1001  			v1, v2, k1, k2)
  1002  	}
  1003  
  1004  	err.AddPosition(v1)
  1005  	err.AddPosition(v2)
  1006  	for _, id := range ids {
  1007  		err.AddClosedPositions(id)
  1008  	}
  1009  
  1010  	n.addErr(err)
  1011  }
  1012  
  1013  // reportFieldMismatch reports the mixture of regular fields with non-struct
  1014  // values. Either s or f needs to be given.
  1015  func (n *nodeContext) reportFieldMismatch(
  1016  	p token.Pos,
  1017  	s *StructLit,
  1018  	f Feature,
  1019  	scalar Expr,
  1020  	id ...CloseInfo) {
  1021  
  1022  	ctx := n.ctx
  1023  
  1024  	if f == InvalidLabel {
  1025  		for _, a := range s.Decls {
  1026  			if x, ok := a.(*Field); ok && x.Label.IsRegular() {
  1027  				f = x.Label
  1028  				p = pos(x)
  1029  				break
  1030  			}
  1031  		}
  1032  		if f == InvalidLabel {
  1033  			n.reportConflict(scalar, s, n.kind, StructKind, id...)
  1034  			return
  1035  		}
  1036  	}
  1037  
  1038  	err := ctx.NewPosf(p, "cannot combine regular field %q with %v", f, scalar)
  1039  
  1040  	if s != nil {
  1041  		err.AddPosition(s)
  1042  	}
  1043  
  1044  	for _, ci := range id {
  1045  		err.AddClosedPositions(ci)
  1046  	}
  1047  
  1048  	n.addErr(err)
  1049  }
  1050  
  1051  func (n *nodeContext) updateNodeType(k Kind, v Expr, id CloseInfo) bool {
  1052  	ctx := n.ctx
  1053  	kind := n.kind & k
  1054  
  1055  	switch {
  1056  	case n.kind == BottomKind,
  1057  		k == BottomKind:
  1058  		return false
  1059  
  1060  	case kind != BottomKind:
  1061  
  1062  	// TODO: we could consider changing the reporting for structs, but this
  1063  	// makes only sense in case they are for embeddings. Otherwise the type
  1064  	// of a struct is more relevant for the failure.
  1065  	// case k == StructKind:
  1066  	// 	s, _ := v.(*StructLit)
  1067  	// 	n.reportFieldMismatch(token.NoPos, s, 0, n.kindExpr, id, n.kindID)
  1068  
  1069  	case n.kindExpr != nil:
  1070  		n.reportConflict(n.kindExpr, v, n.kind, k, n.kindID, id)
  1071  
  1072  	default:
  1073  		n.addErr(ctx.Newf(
  1074  			"conflicting value %s (mismatched types %s and %s)",
  1075  			v, n.kind, k))
  1076  	}
  1077  
  1078  	if n.kind != kind || n.kindExpr == nil {
  1079  		n.kindExpr = v
  1080  	}
  1081  	n.kind = kind
  1082  	return kind != BottomKind
  1083  }
  1084  
  1085  func (n *nodeContext) done() bool {
  1086  	return len(n.dynamicFields) == 0 &&
  1087  		len(n.comprehensions) == 0 &&
  1088  		len(n.exprs) == 0
  1089  }
  1090  
  1091  // finalDone is like done, but allows for cycle errors, which can be ignored
  1092  // as they essentially indicate a = a & _.
  1093  func (n *nodeContext) finalDone() bool {
  1094  	for _, x := range n.exprs {
  1095  		if x.err.Code != CycleError {
  1096  			return false
  1097  		}
  1098  	}
  1099  	return len(n.dynamicFields) == 0 && len(n.comprehensions) == 0
  1100  }
  1101  
  1102  // hasErr is used to determine if an evaluation path, for instance a single
  1103  // path after expanding all disjunctions, has an error.
  1104  func (n *nodeContext) hasErr() bool {
  1105  	if n.node.ChildErrors != nil {
  1106  		return true
  1107  	}
  1108  	if n.node.Status() > Evaluating && n.node.IsErr() {
  1109  		return true
  1110  	}
  1111  	return n.ctx.HasErr() || n.errs != nil
  1112  }
  1113  
  1114  func (n *nodeContext) getErr() *Bottom {
  1115  	n.errs = CombineErrors(nil, n.errs, n.ctx.Err())
  1116  	return n.errs
  1117  }
  1118  
  1119  // getValidators sets the vertex' Value in case there was no concrete value.
  1120  func (n *nodeContext) getValidators() BaseValue {
  1121  	ctx := n.ctx
  1122  
  1123  	a := []Value{}
  1124  	// if n.node.Value != nil {
  1125  	// 	a = append(a, n.node.Value)
  1126  	// }
  1127  	kind := TopKind
  1128  	if n.lowerBound != nil {
  1129  		a = append(a, n.lowerBound)
  1130  		kind &= n.lowerBound.Kind()
  1131  	}
  1132  	if n.upperBound != nil {
  1133  		a = append(a, n.upperBound)
  1134  		kind &= n.upperBound.Kind()
  1135  	}
  1136  	for _, c := range n.checks {
  1137  		// Drop !=x if x is out of bounds with another bound.
  1138  		if b, _ := c.(*BoundValue); b != nil && b.Op == NotEqualOp {
  1139  			if n.upperBound != nil &&
  1140  				SimplifyBounds(ctx, n.kind, n.upperBound, b) != nil {
  1141  				continue
  1142  			}
  1143  			if n.lowerBound != nil &&
  1144  				SimplifyBounds(ctx, n.kind, n.lowerBound, b) != nil {
  1145  				continue
  1146  			}
  1147  		}
  1148  		a = append(a, c)
  1149  		kind &= c.Kind()
  1150  	}
  1151  
  1152  	if kind&^n.kind != 0 {
  1153  		a = append(a, &BasicType{
  1154  			Src: n.kindExpr.Source(), // TODO:Is this always a BasicType?
  1155  			K:   n.kind,
  1156  		})
  1157  	}
  1158  
  1159  	var v BaseValue
  1160  	switch len(a) {
  1161  	case 0:
  1162  		// Src is the combined input.
  1163  		v = &BasicType{K: n.kind}
  1164  
  1165  	case 1:
  1166  		v = a[0].(Value) // remove cast
  1167  
  1168  	default:
  1169  		v = &Conjunction{Values: a}
  1170  	}
  1171  
  1172  	return v
  1173  }
  1174  
  1175  // TODO: this function can probably go as this is now handled in the nodeContext.
  1176  func (n *nodeContext) maybeSetCache() {
  1177  	if n.node.Status() > Partial { // n.node.BaseValue != nil
  1178  		return
  1179  	}
  1180  	if n.scalar != nil {
  1181  		n.node.BaseValue = n.scalar
  1182  	}
  1183  	// NOTE: this is now handled by associating the nodeContext
  1184  	// if n.errs != nil {
  1185  	// 	n.node.SetValue(n.ctx, Partial, n.errs)
  1186  	// }
  1187  }
  1188  
  1189  type envExpr struct {
  1190  	c   Conjunct
  1191  	err *Bottom
  1192  }
  1193  
  1194  type envDynamic struct {
  1195  	env   *Environment
  1196  	field *DynamicField
  1197  	id    CloseInfo
  1198  	err   *Bottom
  1199  }
  1200  
  1201  type envList struct {
  1202  	env     *Environment
  1203  	list    *ListLit
  1204  	n       int64 // recorded length after evaluator
  1205  	elipsis *Ellipsis
  1206  	id      CloseInfo
  1207  }
  1208  
  1209  func (n *nodeContext) addBottom(b *Bottom) {
  1210  	n.errs = CombineErrors(nil, n.errs, b)
  1211  	// TODO(errors): consider doing this
  1212  	// n.kindExpr = n.errs
  1213  	// n.kind = 0
  1214  }
  1215  
  1216  func (n *nodeContext) addErr(err errors.Error) {
  1217  	if err != nil {
  1218  		n.addBottom(&Bottom{Err: err})
  1219  	}
  1220  }
  1221  
  1222  // addExprConjuncts will attempt to evaluate an Expr and insert the value
  1223  // into the nodeContext if successful or queue it for later evaluation if it is
  1224  // incomplete or is not value.
  1225  func (n *nodeContext) addExprConjunct(v Conjunct) {
  1226  	env := v.Env
  1227  	id := v.CloseInfo
  1228  
  1229  	switch x := v.Elem().(type) {
  1230  	case *Vertex:
  1231  		if x.IsData() {
  1232  			n.addValueConjunct(env, x, id)
  1233  		} else {
  1234  			n.addVertexConjuncts(v, x, true)
  1235  		}
  1236  
  1237  	case Value:
  1238  		n.addValueConjunct(env, x, id)
  1239  
  1240  	case *BinaryExpr:
  1241  		if x.Op == AndOp {
  1242  			n.addExprConjunct(MakeConjunct(env, x.X, id))
  1243  			n.addExprConjunct(MakeConjunct(env, x.Y, id))
  1244  		} else {
  1245  			n.evalExpr(v)
  1246  		}
  1247  
  1248  	case *StructLit:
  1249  		n.addStruct(env, x, id)
  1250  
  1251  	case *ListLit:
  1252  		childEnv := &Environment{
  1253  			Up:     env,
  1254  			Vertex: n.node,
  1255  		}
  1256  		if env != nil {
  1257  			childEnv.Cyclic = env.Cyclic
  1258  			childEnv.Deref = env.Deref
  1259  		}
  1260  		n.lists = append(n.lists, envList{env: childEnv, list: x, id: id})
  1261  
  1262  	case *DisjunctionExpr:
  1263  		n.addDisjunction(env, x, id)
  1264  
  1265  	default:
  1266  		// Must be Resolver or Evaluator.
  1267  		n.evalExpr(v)
  1268  	}
  1269  }
  1270  
  1271  // evalExpr is only called by addExprConjunct. If an error occurs, it records
  1272  // the error in n and returns nil.
  1273  func (n *nodeContext) evalExpr(v Conjunct) {
  1274  	// Require an Environment.
  1275  	ctx := n.ctx
  1276  
  1277  	closeID := v.CloseInfo
  1278  
  1279  	// TODO: see if we can do without these counters.
  1280  	for _, d := range v.Env.Deref {
  1281  		d.EvalCount++
  1282  	}
  1283  	for _, d := range v.Env.Cycles {
  1284  		d.SelfCount++
  1285  	}
  1286  	defer func() {
  1287  		for _, d := range v.Env.Deref {
  1288  			d.EvalCount--
  1289  		}
  1290  		for _, d := range v.Env.Cycles {
  1291  			d.SelfCount++
  1292  		}
  1293  	}()
  1294  
  1295  	switch x := v.Expr().(type) {
  1296  	case Resolver:
  1297  		arc, err := ctx.Resolve(v.Env, x)
  1298  		if err != nil && !err.IsIncomplete() {
  1299  			n.addBottom(err)
  1300  			break
  1301  		}
  1302  		if arc == nil {
  1303  			n.exprs = append(n.exprs, envExpr{v, err})
  1304  			break
  1305  		}
  1306  
  1307  		n.addVertexConjuncts(v, arc, false)
  1308  
  1309  	case Evaluator:
  1310  		// Interpolation, UnaryExpr, BinaryExpr, CallExpr
  1311  		// Could be unify?
  1312  		val := ctx.evaluateRec(v.Env, v.Expr(), Partial)
  1313  		if b, ok := val.(*Bottom); ok && b.IsIncomplete() {
  1314  			n.exprs = append(n.exprs, envExpr{v, b})
  1315  			break
  1316  		}
  1317  
  1318  		if v, ok := val.(*Vertex); ok {
  1319  			// Handle generated disjunctions (as in the 'or' builtin).
  1320  			// These come as a Vertex, but should not be added as a value.
  1321  			b, ok := v.BaseValue.(*Bottom)
  1322  			if ok && b.IsIncomplete() && len(v.Conjuncts) > 0 {
  1323  				for _, c := range v.Conjuncts {
  1324  					c.CloseInfo = closeID
  1325  					n.addExprConjunct(c)
  1326  				}
  1327  				break
  1328  			}
  1329  		}
  1330  
  1331  		// TODO: also to through normal Vertex handling here. At the moment
  1332  		// addValueConjunct handles StructMarker.NeedsClose, as this is always
  1333  		// only needed when evaluation an Evaluator, and not a Resolver.
  1334  		// The two code paths should ideally be merged once this separate
  1335  		// mechanism is eliminated.
  1336  		//
  1337  		// if arc, ok := val.(*Vertex); ok && !arc.IsData() {
  1338  		// 	n.addVertexConjuncts(v.Env, closeID, v.Expr(), arc)
  1339  		// 	break
  1340  		// }
  1341  
  1342  		// TODO: insert in vertex as well
  1343  		n.addValueConjunct(v.Env, val, closeID)
  1344  
  1345  	default:
  1346  		panic(fmt.Sprintf("unknown expression of type %T", x))
  1347  	}
  1348  }
  1349  
  1350  func (n *nodeContext) addVertexConjuncts(c Conjunct, arc *Vertex, inline bool) {
  1351  	closeInfo := c.CloseInfo
  1352  
  1353  	// We need to ensure that each arc is only unified once (or at least) a
  1354  	// bounded time, witch each conjunct. Comprehensions, for instance, may
  1355  	// distribute a value across many values that get unified back into the
  1356  	// same value. If such a value is a disjunction, than a disjunction of N
  1357  	// disjuncts will result in a factor N more unifications for each
  1358  	// occurrence of such value, resulting in exponential running time. This
  1359  	// is especially common values that are used as a type.
  1360  	//
  1361  	// However, unification is idempotent, so each such conjunct only needs
  1362  	// to be unified once. This cache checks for this and prevents an
  1363  	// exponential blowup in such case.
  1364  	//
  1365  	// TODO(perf): this cache ensures the conjuncts of an arc at most once
  1366  	// per ID. However, we really need to add the conjuncts of an arc only
  1367  	// once total, and then add the close information once per close ID
  1368  	// (pointer can probably be shared). Aside from being more performant,
  1369  	// this is probably the best way to guarantee that conjunctions are
  1370  	// linear in this case.
  1371  	key := arcKey{arc, closeInfo}
  1372  	for _, k := range n.arcMap {
  1373  		if key == k {
  1374  			return
  1375  		}
  1376  	}
  1377  	n.arcMap = append(n.arcMap, key)
  1378  
  1379  	env := c.Env
  1380  	// Pass detection of structural cycles from parent to children.
  1381  	cyclic := false
  1382  	if env != nil {
  1383  		// If a reference is in a tainted set, so is the value it refers to.
  1384  		cyclic = env.Cyclic
  1385  	}
  1386  
  1387  	status := arc.Status()
  1388  
  1389  	switch status {
  1390  	case Evaluating:
  1391  		// Reference cycle detected. We have reached a fixed point and
  1392  		// adding conjuncts at this point will not change the value. Also,
  1393  		// continuing to pursue this value will result in an infinite loop.
  1394  
  1395  		// TODO: add a mechanism so that the computation will only have to
  1396  		// be done once?
  1397  
  1398  		if arc == n.node {
  1399  			// TODO: we could use node sharing here. This may avoid an
  1400  			// exponential blowup during evaluation, like is possible with
  1401  			// YAML.
  1402  			return
  1403  		}
  1404  
  1405  	case EvaluatingArcs:
  1406  		// Structural cycle detected. Continue evaluation as usual, but
  1407  		// keep track of whether any other conjuncts without structural
  1408  		// cycles are added. If not, evaluation of child arcs will end
  1409  		// with this node.
  1410  
  1411  		// For the purpose of determining whether at least one non-cyclic
  1412  		// conjuncts exists, we consider all conjuncts of a cyclic conjuncts
  1413  		// also cyclic.
  1414  
  1415  		cyclic = true
  1416  		n.hasCycle = true
  1417  
  1418  		// As the EvaluatingArcs mechanism bypasses the self-reference
  1419  		// mechanism, we need to separately keep track of it here.
  1420  		// If this (originally) is a self-reference node, adding them
  1421  		// will result in recursively adding the same reference. For this
  1422  		// we also mark the node as evaluating.
  1423  		if arc.SelfCount > 0 {
  1424  			return
  1425  		}
  1426  
  1427  		// This count is added for values that are directly added below.
  1428  		// The count is handled separately for delayed values.
  1429  		arc.SelfCount++
  1430  		defer func() { arc.SelfCount-- }()
  1431  	}
  1432  
  1433  	// Performance: the following if check filters cases that are not strictly
  1434  	// necessary for correct functioning. Not updating the closeInfo may cause
  1435  	// some position information to be lost for top-level positions of merges
  1436  	// resulting form APIs. These tend to be fairly uninteresting.
  1437  	// At the same time, this optimization may prevent considerable slowdown
  1438  	// in case an API does many calls to Unify.
  1439  	x := c.Expr()
  1440  	if !inline || arc.IsClosedStruct() || arc.IsClosedList() {
  1441  		closeInfo = closeInfo.SpawnRef(arc, IsDef(x), x)
  1442  	}
  1443  
  1444  	if arc.status == 0 && !inline {
  1445  		// This is a rare condition, but can happen in certain
  1446  		// evaluation orders. Unfortunately, adding this breaks
  1447  		// resolution of cyclic mutually referring disjunctions. But it
  1448  		// is necessary to prevent lookups in unevaluated structs.
  1449  		// TODO(cycles): this can probably most easily be fixed with a
  1450  		// having a more recursive implementation.
  1451  		n.ctx.Unify(arc, Partial)
  1452  	}
  1453  
  1454  	for _, c := range arc.Conjuncts {
  1455  		var a []*Vertex
  1456  		if env != nil {
  1457  			a = env.Deref
  1458  		}
  1459  		if inline {
  1460  			c = updateCyclic(c, cyclic, nil, nil)
  1461  		} else {
  1462  			c = updateCyclic(c, cyclic, arc, a)
  1463  		}
  1464  
  1465  		// Note that we are resetting the tree here. We hereby assume that
  1466  		// closedness conflicts resulting from unifying the referenced arc were
  1467  		// already caught there and that we can ignore further errors here.
  1468  		c.CloseInfo = closeInfo
  1469  		n.addExprConjunct(c)
  1470  	}
  1471  }
  1472  
  1473  // isDef reports whether an expressions is a reference that references a
  1474  // definition anywhere in its selection path.
  1475  //
  1476  // TODO(performance): this should be merged with resolve(). But for now keeping
  1477  // this code isolated makes it easier to see what it is for.
  1478  func isDef(x Expr) bool {
  1479  	switch r := x.(type) {
  1480  	case *FieldReference:
  1481  		return r.Label.IsDef()
  1482  
  1483  	case *SelectorExpr:
  1484  		if r.Sel.IsDef() {
  1485  			return true
  1486  		}
  1487  		return isDef(r.X)
  1488  
  1489  	case *IndexExpr:
  1490  		return isDef(r.X)
  1491  	}
  1492  	return false
  1493  }
  1494  
  1495  // updateCyclicStatus looks for proof of non-cyclic conjuncts to override
  1496  // a structural cycle.
  1497  func (n *nodeContext) updateCyclicStatus(env *Environment) {
  1498  	if env == nil || !env.Cyclic {
  1499  		n.hasNonCycle = true
  1500  	}
  1501  }
  1502  
  1503  func updateCyclic(c Conjunct, cyclic bool, deref *Vertex, a []*Vertex) Conjunct {
  1504  	env := c.Env
  1505  	switch {
  1506  	case env == nil:
  1507  		if !cyclic && deref == nil {
  1508  			return c
  1509  		}
  1510  		env = &Environment{Cyclic: cyclic}
  1511  	case deref == nil && env.Cyclic == cyclic && len(a) == 0:
  1512  		return c
  1513  	default:
  1514  		// The conjunct may still be in use in other fields, so we should
  1515  		// make a new copy to mark Cyclic only for this case.
  1516  		e := *env
  1517  		e.Cyclic = e.Cyclic || cyclic
  1518  		env = &e
  1519  	}
  1520  	if deref != nil || len(a) > 0 {
  1521  		cp := make([]*Vertex, 0, len(a)+1)
  1522  		cp = append(cp, a...)
  1523  		if deref != nil {
  1524  			cp = append(cp, deref)
  1525  		}
  1526  		env.Deref = cp
  1527  	}
  1528  	if deref != nil {
  1529  		env.Cycles = append(env.Cycles, deref)
  1530  	}
  1531  	return MakeConjunct(env, c.Elem(), c.CloseInfo)
  1532  }
  1533  
  1534  func (n *nodeContext) addValueConjunct(env *Environment, v Value, id CloseInfo) {
  1535  	n.updateCyclicStatus(env)
  1536  
  1537  	ctx := n.ctx
  1538  
  1539  	if x, ok := v.(*Vertex); ok {
  1540  		if m, ok := x.BaseValue.(*StructMarker); ok {
  1541  			n.aStruct = x
  1542  			n.aStructID = id
  1543  			if m.NeedClose {
  1544  				id = id.SpawnRef(x, IsDef(x), x)
  1545  				id.IsClosed = true
  1546  			}
  1547  		}
  1548  
  1549  		cyclic := env != nil && env.Cyclic
  1550  
  1551  		if !x.IsData() {
  1552  			// TODO: this really shouldn't happen anymore.
  1553  			if isComplexStruct(ctx, x) {
  1554  				// This really shouldn't happen, but just in case.
  1555  				n.addVertexConjuncts(MakeConjunct(env, x, id), x, true)
  1556  				return
  1557  			}
  1558  
  1559  			for _, c := range x.Conjuncts {
  1560  				c = updateCyclic(c, cyclic, nil, nil)
  1561  				c.CloseInfo = id
  1562  				n.addExprConjunct(c) // TODO: Pass from eval
  1563  			}
  1564  			return
  1565  		}
  1566  
  1567  		// TODO: evaluate value?
  1568  		switch v := x.BaseValue.(type) {
  1569  		default:
  1570  			panic(fmt.Sprintf("invalid type %T", x.BaseValue))
  1571  
  1572  		case *ListMarker:
  1573  			n.vLists = append(n.vLists, x)
  1574  			return
  1575  
  1576  		case *StructMarker:
  1577  
  1578  		case Value:
  1579  			n.addValueConjunct(env, v, id)
  1580  		}
  1581  
  1582  		if len(x.Arcs) == 0 {
  1583  			return
  1584  		}
  1585  
  1586  		s := &StructLit{}
  1587  
  1588  		// Keep ordering of Go struct for topological sort.
  1589  		n.node.AddStruct(s, env, id)
  1590  		n.node.Structs = append(n.node.Structs, x.Structs...)
  1591  
  1592  		for _, a := range x.Arcs {
  1593  			// TODO(errors): report error when this is a regular field.
  1594  			c := MakeConjunct(nil, a, id)
  1595  			c = updateCyclic(c, cyclic, nil, nil)
  1596  			n.insertField(a.Label, c)
  1597  			s.MarkField(a.Label)
  1598  		}
  1599  		return
  1600  	}
  1601  
  1602  	switch b := v.(type) {
  1603  	case *Bottom:
  1604  		n.addBottom(b)
  1605  		return
  1606  	case *Builtin:
  1607  		if v := b.BareValidator(); v != nil {
  1608  			n.addValueConjunct(env, v, id)
  1609  			return
  1610  		}
  1611  	}
  1612  
  1613  	if !n.updateNodeType(v.Kind(), v, id) {
  1614  		return
  1615  	}
  1616  
  1617  	switch x := v.(type) {
  1618  	case *Disjunction:
  1619  		n.addDisjunctionValue(env, x, id)
  1620  
  1621  	case *Conjunction:
  1622  		for _, x := range x.Values {
  1623  			n.addValueConjunct(env, x, id)
  1624  		}
  1625  
  1626  	case *Top:
  1627  		n.hasTop = true
  1628  
  1629  	case *BasicType:
  1630  		// handled above
  1631  
  1632  	case *BoundValue:
  1633  		switch x.Op {
  1634  		case LessThanOp, LessEqualOp:
  1635  			if y := n.upperBound; y != nil {
  1636  				n.upperBound = nil
  1637  				v := SimplifyBounds(ctx, n.kind, x, y)
  1638  				if err := valueError(v); err != nil {
  1639  					err.AddPosition(v)
  1640  					err.AddPosition(n.upperBound)
  1641  					err.AddClosedPositions(id)
  1642  				}
  1643  				n.addValueConjunct(env, v, id)
  1644  				return
  1645  			}
  1646  			n.upperBound = x
  1647  
  1648  		case GreaterThanOp, GreaterEqualOp:
  1649  			if y := n.lowerBound; y != nil {
  1650  				n.lowerBound = nil
  1651  				v := SimplifyBounds(ctx, n.kind, x, y)
  1652  				if err := valueError(v); err != nil {
  1653  					err.AddPosition(v)
  1654  					err.AddPosition(n.lowerBound)
  1655  					err.AddClosedPositions(id)
  1656  				}
  1657  				n.addValueConjunct(env, v, id)
  1658  				return
  1659  			}
  1660  			n.lowerBound = x
  1661  
  1662  		case EqualOp, NotEqualOp, MatchOp, NotMatchOp:
  1663  			// This check serves as simplifier, but also to remove duplicates.
  1664  			k := 0
  1665  			match := false
  1666  			for _, c := range n.checks {
  1667  				if y, ok := c.(*BoundValue); ok {
  1668  					switch z := SimplifyBounds(ctx, n.kind, x, y); {
  1669  					case z == y:
  1670  						match = true
  1671  					case z == x:
  1672  						continue
  1673  					}
  1674  				}
  1675  				n.checks[k] = c
  1676  				k++
  1677  			}
  1678  			n.checks = n.checks[:k]
  1679  			if !match {
  1680  				n.checks = append(n.checks, x)
  1681  			}
  1682  			return
  1683  		}
  1684  
  1685  	case Validator:
  1686  		// This check serves as simplifier, but also to remove duplicates.
  1687  		for i, y := range n.checks {
  1688  			if b := SimplifyValidator(ctx, x, y); b != nil {
  1689  				n.checks[i] = b
  1690  				return
  1691  			}
  1692  		}
  1693  		n.updateNodeType(x.Kind(), x, id)
  1694  		n.checks = append(n.checks, x)
  1695  
  1696  	case *Vertex:
  1697  	// handled above.
  1698  
  1699  	case Value: // *NullLit, *BoolLit, *NumLit, *StringLit, *BytesLit, *Builtin
  1700  		if y := n.scalar; y != nil {
  1701  			if b, ok := BinOp(ctx, EqualOp, x, y).(*Bool); !ok || !b.B {
  1702  				n.reportConflict(x, y, x.Kind(), y.Kind(), n.scalarID, id)
  1703  			}
  1704  			// TODO: do we need to explicitly add again?
  1705  			// n.scalar = nil
  1706  			// n.addValueConjunct(c, BinOp(c, EqualOp, x, y))
  1707  			break
  1708  		}
  1709  		n.scalar = x
  1710  		n.scalarID = id
  1711  
  1712  	default:
  1713  		panic(fmt.Sprintf("unknown value type %T", x))
  1714  	}
  1715  
  1716  	if n.lowerBound != nil && n.upperBound != nil {
  1717  		if u := SimplifyBounds(ctx, n.kind, n.lowerBound, n.upperBound); u != nil {
  1718  			if err := valueError(u); err != nil {
  1719  				err.AddPosition(n.lowerBound)
  1720  				err.AddPosition(n.upperBound)
  1721  				err.AddClosedPositions(id)
  1722  			}
  1723  			n.lowerBound = nil
  1724  			n.upperBound = nil
  1725  			n.addValueConjunct(env, u, id)
  1726  		}
  1727  	}
  1728  }
  1729  
  1730  func valueError(v Value) *ValueError {
  1731  	if v == nil {
  1732  		return nil
  1733  	}
  1734  	b, _ := v.(*Bottom)
  1735  	if b == nil {
  1736  		return nil
  1737  	}
  1738  	err, _ := b.Err.(*ValueError)
  1739  	if err == nil {
  1740  		return nil
  1741  	}
  1742  	return err
  1743  }
  1744  
  1745  // addStruct collates the declarations of a struct.
  1746  //
  1747  // addStruct fulfills two additional pivotal functions:
  1748  //   1) Implement vertex unification (this happens through De Bruijn indices
  1749  //      combined with proper set up of Environments).
  1750  //   2) Implied closedness for definitions.
  1751  //
  1752  func (n *nodeContext) addStruct(
  1753  	env *Environment,
  1754  	s *StructLit,
  1755  	closeInfo CloseInfo) {
  1756  
  1757  	n.updateCyclicStatus(env) // to handle empty structs.
  1758  
  1759  	// NOTE: This is a crucial point in the code:
  1760  	// Unification derferencing happens here. The child nodes are set to
  1761  	// an Environment linked to the current node. Together with the De Bruijn
  1762  	// indices, this determines to which Vertex a reference resolves.
  1763  
  1764  	// TODO(perf): consider using environment cache:
  1765  	// var childEnv *Environment
  1766  	// for _, s := range n.nodeCache.sub {
  1767  	// 	if s.Up == env {
  1768  	// 		childEnv = s
  1769  	// 	}
  1770  	// }
  1771  	childEnv := &Environment{
  1772  		Up:     env,
  1773  		Vertex: n.node,
  1774  	}
  1775  	if env != nil {
  1776  		childEnv.Cyclic = env.Cyclic
  1777  		childEnv.Deref = env.Deref
  1778  	}
  1779  
  1780  	s.Init()
  1781  
  1782  	if s.HasEmbed && !s.IsFile() {
  1783  		closeInfo = closeInfo.SpawnGroup(nil)
  1784  	}
  1785  
  1786  	parent := n.node.AddStruct(s, childEnv, closeInfo)
  1787  	closeInfo.IsClosed = false
  1788  	parent.Disable = true // disable until processing is done.
  1789  
  1790  	for _, d := range s.Decls {
  1791  		switch x := d.(type) {
  1792  		case *Field:
  1793  			// handle in next iteration.
  1794  
  1795  		case *DynamicField:
  1796  			n.aStruct = s
  1797  			n.aStructID = closeInfo
  1798  			n.dynamicFields = append(n.dynamicFields, envDynamic{childEnv, x, closeInfo, nil})
  1799  
  1800  		case *Comprehension:
  1801  			n.insertComprehension(childEnv, x, closeInfo)
  1802  
  1803  		case Expr:
  1804  			// add embedding to optional
  1805  
  1806  			// TODO(perf): only do this if addExprConjunct below will result in
  1807  			// a fieldSet. Otherwise the entry will just be removed next.
  1808  			id := closeInfo.SpawnEmbed(x)
  1809  
  1810  			// push and opo embedding type.
  1811  			n.addExprConjunct(MakeConjunct(childEnv, x, id))
  1812  
  1813  		case *OptionalField, *BulkOptionalField, *Ellipsis:
  1814  			// Nothing to do here. Note that the precense of these fields do not
  1815  			// excluded embedded scalars: only when they match actual fields
  1816  			// does it exclude those.
  1817  
  1818  		default:
  1819  			panic("unreachable")
  1820  		}
  1821  	}
  1822  
  1823  	if !s.HasEmbed {
  1824  		n.aStruct = s
  1825  		n.aStructID = closeInfo
  1826  	}
  1827  
  1828  	parent.Disable = false
  1829  
  1830  	for _, d := range s.Decls {
  1831  		switch x := d.(type) {
  1832  		case *Field:
  1833  			if x.Label.IsString() {
  1834  				n.aStruct = s
  1835  				n.aStructID = closeInfo
  1836  			}
  1837  			n.insertField(x.Label, MakeConjunct(childEnv, x, closeInfo))
  1838  		}
  1839  	}
  1840  }
  1841  
  1842  // TODO(perf): if an arc is the only arc with that label added to a Vertex, and
  1843  // if there are no conjuncts of optional fields to be added, then the arc could
  1844  // be added as is until any of these conditions change. This would allow
  1845  // structure sharing in many cases. One should be careful, however, to
  1846  // recursively track arcs of previously unified evaluated vertices ot make this
  1847  // optimization meaningful.
  1848  //
  1849  // An alternative approach to avoid evaluating optional arcs (if we take that
  1850  // route) is to not recursively evaluate those arcs, even for Finalize. This is
  1851  // possible as it is not necessary to evaluate optional arcs to evaluate
  1852  // disjunctions.
  1853  func (n *nodeContext) insertField(f Feature, x Conjunct) *Vertex {
  1854  	ctx := n.ctx
  1855  	arc, _ := n.node.GetArc(ctx, f)
  1856  
  1857  	arc.addConjunct(x)
  1858  
  1859  	switch {
  1860  	case arc.state != nil:
  1861  		s := arc.state
  1862  		switch {
  1863  		case arc.Status() <= AllArcs:
  1864  			// This may happen when a struct has multiple comprehensions, where
  1865  			// the insertion of one of which depends on the outcome of another.
  1866  
  1867  			// TODO: to something more principled by allowing values to
  1868  			// monotonically increase.
  1869  			arc.status = Partial
  1870  			arc.BaseValue = nil
  1871  			s.disjuncts = s.disjuncts[:0]
  1872  			s.disjunctErrs = s.disjunctErrs[:0]
  1873  
  1874  			fallthrough
  1875  
  1876  		default:
  1877  			arc.state.addExprConjunct(x)
  1878  		}
  1879  
  1880  	case arc.Status() == 0:
  1881  	default:
  1882  		n.addBottom(&Bottom{
  1883  			Code: IncompleteError,
  1884  			Err: ctx.NewPosf(pos(x.Field()),
  1885  				"cannot add field %s: was already used",
  1886  				f.SelectorString(ctx)),
  1887  		})
  1888  	}
  1889  	return arc
  1890  }
  1891  
  1892  // expandOne adds dynamic fields to a node until a fixed point is reached.
  1893  // On each iteration, dynamic fields that cannot resolve due to incomplete
  1894  // values are skipped. They will be retried on the next iteration until no
  1895  // progress can be made. Note that a dynamic field may add more dynamic fields.
  1896  //
  1897  // forClauses are processed after all other clauses. A struct may be referenced
  1898  // before it is complete, meaning that fields added by other forms of injection
  1899  // may influence the result of a for clause _after_ it has already been
  1900  // processed. We could instead detect such insertion and feed it to the
  1901  // ForClause to generate another entry or have the for clause be recomputed.
  1902  // This seems to be too complicated and lead to iffy edge cases.
  1903  // TODO(errors): detect when a field is added to a struct that is already used
  1904  // in a for clause.
  1905  func (n *nodeContext) expandOne() (done bool) {
  1906  	// Don't expand incomplete expressions if we detected a cycle.
  1907  	if n.done() || (n.hasCycle && !n.hasNonCycle) {
  1908  		return false
  1909  	}
  1910  
  1911  	var progress bool
  1912  
  1913  	if progress = n.injectDynamic(); progress {
  1914  		return true
  1915  	}
  1916  
  1917  	if progress = n.injectComprehensions(&(n.comprehensions)); progress {
  1918  		return true
  1919  	}
  1920  
  1921  	// Do expressions after comprehensions, as comprehensions can never
  1922  	// refer to embedded scalars, whereas expressions may refer to generated
  1923  	// fields if we were to allow attributes to be defined alongside
  1924  	// scalars.
  1925  	exprs := n.exprs
  1926  	n.exprs = n.exprs[:0]
  1927  	for _, x := range exprs {
  1928  		n.addExprConjunct(x.c)
  1929  
  1930  		// collect and and or
  1931  	}
  1932  	if len(n.exprs) < len(exprs) {
  1933  		return true
  1934  	}
  1935  
  1936  	// No progress, report error later if needed: unification with
  1937  	// disjuncts may resolve this later later on.
  1938  	return false
  1939  }
  1940  
  1941  // injectDynamic evaluates and inserts dynamic declarations.
  1942  func (n *nodeContext) injectDynamic() (progress bool) {
  1943  	ctx := n.ctx
  1944  	k := 0
  1945  
  1946  	a := n.dynamicFields
  1947  	for _, d := range n.dynamicFields {
  1948  		var f Feature
  1949  		v, complete := ctx.Evaluate(d.env, d.field.Key)
  1950  		if !complete {
  1951  			d.err, _ = v.(*Bottom)
  1952  			a[k] = d
  1953  			k++
  1954  			continue
  1955  		}
  1956  		if b, _ := v.(*Bottom); b != nil {
  1957  			n.addValueConjunct(nil, b, d.id)
  1958  			continue
  1959  		}
  1960  		f = ctx.Label(d.field.Key, v)
  1961  		if f.IsInt() {
  1962  			n.addErr(ctx.NewPosf(pos(d.field.Key), "integer fields not supported"))
  1963  		}
  1964  		n.insertField(f, MakeConjunct(d.env, d.field, d.id))
  1965  	}
  1966  
  1967  	progress = k < len(n.dynamicFields)
  1968  
  1969  	n.dynamicFields = a[:k]
  1970  
  1971  	return progress
  1972  }
  1973  
  1974  // addLists
  1975  //
  1976  // TODO: association arrays:
  1977  // If an association array marker was present in a struct, create a struct node
  1978  // instead of a list node. In either case, a node may only have list fields
  1979  // or struct fields and not both.
  1980  //
  1981  // addLists should be run after the fixpoint expansion:
  1982  //    - it enforces that comprehensions may not refer to the list itself
  1983  //    - there may be no other fields within the list.
  1984  //
  1985  // TODO(embeddedScalars): for embedded scalars, there should be another pass
  1986  // of evaluation expressions after expanding lists.
  1987  func (n *nodeContext) addLists() (oneOfTheLists Expr, anID CloseInfo) {
  1988  	if len(n.lists) == 0 && len(n.vLists) == 0 {
  1989  		return nil, CloseInfo{}
  1990  	}
  1991  
  1992  	isOpen := true
  1993  	max := 0
  1994  	var maxNode Expr
  1995  
  1996  	if m, ok := n.node.BaseValue.(*ListMarker); ok {
  1997  		isOpen = m.IsOpen
  1998  		max = len(n.node.Arcs)
  1999  	}
  2000  
  2001  	c := n.ctx
  2002  
  2003  	for _, l := range n.vLists {
  2004  		oneOfTheLists = l
  2005  
  2006  		elems := l.Elems()
  2007  		isClosed := l.IsClosedList()
  2008  
  2009  		switch {
  2010  		case len(elems) < max:
  2011  			if isClosed {
  2012  				n.invalidListLength(len(elems), max, l, maxNode)
  2013  				continue
  2014  			}
  2015  
  2016  		case len(elems) > max:
  2017  			if !isOpen {
  2018  				n.invalidListLength(max, len(elems), maxNode, l)
  2019  				continue
  2020  			}
  2021  			isOpen = !isClosed
  2022  			max = len(elems)
  2023  			maxNode = l
  2024  
  2025  		case isClosed:
  2026  			isOpen = false
  2027  			maxNode = l
  2028  		}
  2029  
  2030  		for _, a := range elems {
  2031  			if a.Conjuncts == nil {
  2032  				x := a.BaseValue.(Value)
  2033  				n.insertField(a.Label, MakeConjunct(nil, x, CloseInfo{}))
  2034  				continue
  2035  			}
  2036  			for _, c := range a.Conjuncts {
  2037  				n.insertField(a.Label, c)
  2038  			}
  2039  		}
  2040  	}
  2041  
  2042  outer:
  2043  	for i, l := range n.lists {
  2044  		n.updateCyclicStatus(l.env.Up)
  2045  
  2046  		index := int64(0)
  2047  		hasComprehension := false
  2048  		for j, elem := range l.list.Elems {
  2049  			switch x := elem.(type) {
  2050  			case *Comprehension:
  2051  				err := c.Yield(l.env, x, func(e *Environment) {
  2052  					label, err := MakeLabel(x.Source(), index, IntLabel)
  2053  					n.addErr(err)
  2054  					index++
  2055  					c := MakeConjunct(e, x.Value, l.id)
  2056  					n.insertField(label, c)
  2057  				})
  2058  				hasComprehension = true
  2059  				if err != nil {
  2060  					n.addBottom(err)
  2061  					continue outer
  2062  				}
  2063  
  2064  			case *Ellipsis:
  2065  				if j != len(l.list.Elems)-1 {
  2066  					n.addErr(c.Newf("ellipsis must be last element in list"))
  2067  				}
  2068  
  2069  				n.lists[i].elipsis = x
  2070  
  2071  			default:
  2072  				label, err := MakeLabel(x.Source(), index, IntLabel)
  2073  				n.addErr(err)
  2074  				index++ // TODO: don't use insertField.
  2075  				n.insertField(label, MakeConjunct(l.env, x, l.id))
  2076  			}
  2077  
  2078  			// Terminate early in case of runaway comprehension.
  2079  			if !isOpen && int(index) > max {
  2080  				n.invalidListLength(max, len(l.list.Elems), maxNode, l.list)
  2081  				continue outer
  2082  			}
  2083  		}
  2084  
  2085  		oneOfTheLists = l.list
  2086  		anID = l.id
  2087  
  2088  		switch closed := n.lists[i].elipsis == nil; {
  2089  		case int(index) < max:
  2090  			if closed {
  2091  				n.invalidListLength(int(index), max, l.list, maxNode)
  2092  				continue
  2093  			}
  2094  
  2095  		case int(index) > max,
  2096  			closed && isOpen,
  2097  			(!closed == isOpen) && !hasComprehension:
  2098  			max = int(index)
  2099  			maxNode = l.list
  2100  			isOpen = !closed
  2101  		}
  2102  
  2103  		n.lists[i].n = index
  2104  	}
  2105  
  2106  	// add additionalItem values to list and construct optionals.
  2107  	elems := n.node.Elems()
  2108  	for _, l := range n.vLists {
  2109  		if !l.IsClosedList() {
  2110  			continue
  2111  		}
  2112  
  2113  		newElems := l.Elems()
  2114  		if len(newElems) >= len(elems) {
  2115  			continue // error generated earlier, if applicable.
  2116  		}
  2117  
  2118  		for _, arc := range elems[len(newElems):] {
  2119  			l.MatchAndInsert(c, arc)
  2120  		}
  2121  	}
  2122  
  2123  	for _, l := range n.lists {
  2124  		if l.elipsis == nil {
  2125  			continue
  2126  		}
  2127  
  2128  		s := l.list.info
  2129  		if s == nil {
  2130  			s = &StructLit{Decls: []Decl{l.elipsis}}
  2131  			s.Init()
  2132  			l.list.info = s
  2133  		}
  2134  		info := n.node.AddStruct(s, l.env, l.id)
  2135  
  2136  		for _, arc := range elems[l.n:] {
  2137  			info.MatchAndInsert(c, arc)
  2138  		}
  2139  	}
  2140  
  2141  	sources := []ast.Expr{}
  2142  	// Add conjuncts for additional items.
  2143  	for _, l := range n.lists {
  2144  		if l.elipsis == nil {
  2145  			continue
  2146  		}
  2147  		if src, _ := l.elipsis.Source().(ast.Expr); src != nil {
  2148  			sources = append(sources, src)
  2149  		}
  2150  	}
  2151  
  2152  	if m, ok := n.node.BaseValue.(*ListMarker); !ok {
  2153  		n.node.SetValue(c, Partial, &ListMarker{
  2154  			Src:    ast.NewBinExpr(token.AND, sources...),
  2155  			IsOpen: isOpen,
  2156  		})
  2157  	} else {
  2158  		if expr, _ := m.Src.(ast.Expr); expr != nil {
  2159  			sources = append(sources, expr)
  2160  		}
  2161  		m.Src = ast.NewBinExpr(token.AND, sources...)
  2162  		m.IsOpen = m.IsOpen && isOpen
  2163  	}
  2164  
  2165  	n.lists = n.lists[:0]
  2166  	n.vLists = n.vLists[:0]
  2167  
  2168  	return oneOfTheLists, anID
  2169  }
  2170  
  2171  func (n *nodeContext) invalidListLength(na, nb int, a, b Expr) {
  2172  	n.addErr(n.ctx.Newf("incompatible list lengths (%d and %d)", na, nb))
  2173  }