Skip to content

Commit

Permalink
internal/core/adt: refactor unifyNode
Browse files Browse the repository at this point in the history
We want to do the same processing for Evaluator
as for a Resolver, if the former resolves to a Vertex.
We refactor the code in a separate CL to make the
diff smaller later.

Issue #3731
Issue #3634

Signed-off-by: Marcel van Lohuizen <[email protected]>
Change-Id: I33e300b9c873ebf10d4e40bbe8f507c74f3bc426
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1209384
TryBot-Result: CUEcueckoo <[email protected]>
Reviewed-by: Matthew Sackman <[email protected]>
  • Loading branch information
mpvl committed Feb 27, 2025
1 parent 8ed768a commit e55c7a8
Showing 1 changed file with 43 additions and 40 deletions.
83 changes: 43 additions & 40 deletions internal/core/adt/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -772,9 +772,9 @@ func (c *OpContext) wrapCycleError(src ast.Node, b *Bottom) *Bottom {
// unifyNode returns a possibly partially evaluated node value.
//
// TODO: maybe return *Vertex, *Bottom
func (c *OpContext) unifyNode(v Expr, state combinedFlags) (result Value) {
func (c *OpContext) unifyNode(expr Expr, state combinedFlags) (result Value) {
savedSrc := c.src
c.src = v.Source()
c.src = expr.Source()
err := c.errs
c.errs = nil

Expand Down Expand Up @@ -805,7 +805,9 @@ func (c *OpContext) unifyNode(v Expr, state combinedFlags) (result Value) {
c.src = savedSrc
}()

switch x := v.(type) {
var v *Vertex

switch x := expr.(type) {
case Value:
return x

Expand All @@ -814,48 +816,49 @@ func (c *OpContext) unifyNode(v Expr, state combinedFlags) (result Value) {
return v

case Resolver:
v := x.resolve(c, state)
if c.HasErr() {
return nil
}
if v == nil {
return nil
}
v = v.DerefValue()
v = x.resolve(c, state)

// TODO: consider moving this after markCycle, depending on how we
// implement markCycle, or whether we need it at all.
// TODO: is this indirect necessary?
// v = v.Indirect()
default:
// This can only happen, really, if v == nil, which is not allowed.
panic(fmt.Sprintf("unexpected Expr type %T", expr))
}

if c.isDevVersion() {
if n := v.getState(c); n != nil {
// A lookup counts as new structure. See the commend in Section
// "Lookups in inline cycles" in cycle.go.
n.hasNonCycle = true

// Always yield to not get spurious errors.
n.process(arcTypeKnown, yield)
// It is possible that the node is only midway through
// evaluating a disjunction. In this case, we want to ensure
// that disjunctions are finalized, so that disjunction shows
// up in BaseValue.
if len(n.disjuncts) > 0 {
n.node.unify(c, arcTypeKnown, yield)
}
}
} else {
if v.isUndefined() || state.vertexStatus() > v.Status() {
c.unify(v, state)
}
}
if c.HasErr() {
return nil
}
if v == nil {
return nil
}
v = v.DerefValue()

return v
// TODO: consider moving this after markCycle, depending on how we
// implement markCycle, or whether we need it at all.
// TODO: is this indirect necessary?
// v = v.Indirect()

default:
// This can only happen, really, if v == nil, which is not allowed.
panic(fmt.Sprintf("unexpected Expr type %T", v))
if c.isDevVersion() {
if n := v.getState(c); n != nil {
// A lookup counts as new structure. See the commend in Section
// "Lookups in inline cycles" in cycle.go.
n.hasNonCycle = true

// Always yield to not get spurious errors.
n.process(arcTypeKnown, yield)
// It is possible that the node is only midway through
// evaluating a disjunction. In this case, we want to ensure
// that disjunctions are finalized, so that disjunction shows
// up in BaseValue.
if len(n.disjuncts) > 0 {
n.node.unify(c, arcTypeKnown, yield)
}
}
} else {
if v.isUndefined() || state.vertexStatus() > v.Status() {
c.unify(v, state)
}
}

return v
}

func (c *OpContext) lookup(x *Vertex, pos token.Pos, l Feature, flags combinedFlags) *Vertex {
Expand Down

0 comments on commit e55c7a8

Please sign in to comment.