Skip to content

Commit

Permalink
internal/core/adt: add wrapper for inline Vertex
Browse files Browse the repository at this point in the history
When working on the evaluator and changing the
representation of Vertex, it is important to consider all
instantiations of it. A common case is an "inline" Vertex,
which does not have a place in the evaluation tree (does not
correspond to a CUE path), but is part of the computation.
This is treated slightly different for structural cycle detection.

Creating these with a special wrapper reduces the number of
literal Vertex values in the code.

Signed-off-by: Marcel van Lohuizen <mpvl@gmail.com>
Change-Id: I5b9732973bb961c3f5be6192223b7752fa534667
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/551887
Reviewed-by: Roger Peppe <rogpeppe@gmail.com>
Unity-Result: CUEcueckoo <cueckoo@cuelang.org>
TryBot-Result: CUEcueckoo <cueckoo@cuelang.org>
  • Loading branch information
mpvl committed Apr 5, 2023
1 parent d5dd9ec commit 071c4ab
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 32 deletions.
6 changes: 2 additions & 4 deletions internal/core/adt/binop.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,7 @@ func BinOp(c *OpContext, op Op, left, right Value) Value {
},
}

n := &Vertex{}
n.AddConjunct(MakeConjunct(c.Env(0), list, c.ci))
n := c.newInlineVertex(nil, nil, MakeConjunct(c.Env(0), list, c.ci))
n.CompleteArcs(c)

return n
Expand Down Expand Up @@ -267,8 +266,7 @@ func BinOp(c *OpContext, op Op, left, right Value) Value {
return err
}

n := &Vertex{}
n.AddConjunct(MakeConjunct(c.Env(0), list, c.ci))
n := c.newInlineVertex(nil, nil, MakeConjunct(c.Env(0), list, c.ci))
n.CompleteArcs(c)

return n
Expand Down
12 changes: 12 additions & 0 deletions internal/core/adt/composite.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,18 @@ type Vertex struct {
Structs []*StructInfo
}

// newInlineVertex creates a Vertex that is needed for computation, but for
// which there is no CUE path defined from the root Vertex.
func (ctx *OpContext) newInlineVertex(parent *Vertex, v BaseValue, a ...Conjunct) *Vertex {
return &Vertex{
Parent: parent,
BaseValue: v,
IsDynamic: true,
ArcType: ArcMember,
Conjuncts: a,
}
}

// updateArcType updates v.ArcType if t is more restrictive.
func (v *Vertex) updateArcType(t ArcType) {
if t < v.ArcType {
Expand Down
11 changes: 2 additions & 9 deletions internal/core/adt/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -1302,11 +1302,7 @@ func (c *OpContext) newBool(b bool) Value {
}

func (c *OpContext) newList(src ast.Node, parent *Vertex) *Vertex {
return &Vertex{
Parent: parent,
BaseValue: &ListMarker{},
IsDynamic: true,
}
return c.newInlineVertex(parent, &ListMarker{})
}

// Str reports a debug string of x.
Expand All @@ -1321,10 +1317,7 @@ func (c *OpContext) Str(x Node) string {
func (c *OpContext) NewList(values ...Value) *Vertex {
// TODO: consider making this a literal list instead.
list := &ListLit{}
v := &Vertex{
IsDynamic: true,
Conjuncts: []Conjunct{{Env: nil, x: list}},
}
v := c.newInlineVertex(nil, nil, Conjunct{Env: nil, x: list})

for _, x := range values {
list.Elems = append(list.Elems, x)
Expand Down
24 changes: 5 additions & 19 deletions internal/core/adt/expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,7 @@ func (x *StructLit) Source() ast.Node { return x.Src }

func (x *StructLit) evaluate(c *OpContext, state vertexStatus) Value {
e := c.Env(0)
v := &Vertex{
Parent: e.Vertex,
IsDynamic: true,
Conjuncts: []Conjunct{{e, x, c.ci}},
}
v := c.newInlineVertex(e.Vertex, nil, Conjunct{e, x, c.ci})
// evaluate may not finalize a field, as the resulting value may be
// used in a context where more conjuncts are added. It may also lead
// to disjuncts being in a partially expanded state, leading to
Expand Down Expand Up @@ -287,11 +283,7 @@ func (x *ListLit) Source() ast.Node {

func (x *ListLit) evaluate(c *OpContext, state vertexStatus) Value {
e := c.Env(0)
v := &Vertex{
Parent: e.Vertex,
IsDynamic: true,
Conjuncts: []Conjunct{{e, x, c.ci}},
}
v := c.newInlineVertex(e.Vertex, nil, Conjunct{e, x, c.ci})
v.CompleteArcs(c)
return v
}
Expand Down Expand Up @@ -1239,10 +1231,7 @@ func (x *BinaryExpr) Source() ast.Node {
func (x *BinaryExpr) evaluate(c *OpContext, state vertexStatus) Value {
env := c.Env(0)
if x.Op == AndOp {
v := &Vertex{
IsDynamic: true,
Conjuncts: []Conjunct{makeAnonymousConjunct(env, x, c.ci.Refs)},
}
v := c.newInlineVertex(nil, nil, makeAnonymousConjunct(env, x, c.ci.Refs))

// Do not fully evaluate the Vertex: if it is embedded within a
// struct with arcs that are referenced from within this expression,
Expand Down Expand Up @@ -1602,10 +1591,7 @@ func (x *Builtin) call(c *OpContext, p token.Pos, validate bool, args []Value) E
if _, ok := v.(*BasicType); !ok {
env := c.Env(0)
x := &BinaryExpr{Op: AndOp, X: v, Y: a}
n := &Vertex{
IsDynamic: true,
Conjuncts: []Conjunct{{env, x, c.ci}},
}
n := c.newInlineVertex(nil, nil, Conjunct{env, x, c.ci})
n.Finalize(c)
if _, ok := n.BaseValue.(*Bottom); ok {
c.addErrf(0, pos(a),
Expand Down Expand Up @@ -1740,7 +1726,7 @@ func (x *DisjunctionExpr) Source() ast.Node {

func (x *DisjunctionExpr) evaluate(c *OpContext, state vertexStatus) Value {
e := c.Env(0)
v := &Vertex{Conjuncts: []Conjunct{{e, x, c.ci}}}
v := c.newInlineVertex(nil, nil, Conjunct{e, x, c.ci})
v.Finalize(c) // TODO: also partial okay?
// TODO: if the disjunction result originated from a literal value, we may
// consider the result closed to create more permanent errors.
Expand Down

0 comments on commit 071c4ab

Please sign in to comment.