From 071c4ab6df8df3731271b655b1bdc0b0733758d8 Mon Sep 17 00:00:00 2001 From: Marcel van Lohuizen Date: Fri, 24 Mar 2023 16:37:44 +0100 Subject: [PATCH] internal/core/adt: add wrapper for inline Vertex 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 Change-Id: I5b9732973bb961c3f5be6192223b7752fa534667 Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/551887 Reviewed-by: Roger Peppe Unity-Result: CUEcueckoo TryBot-Result: CUEcueckoo --- internal/core/adt/binop.go | 6 ++---- internal/core/adt/composite.go | 12 ++++++++++++ internal/core/adt/context.go | 11 ++--------- internal/core/adt/expr.go | 24 +++++------------------- 4 files changed, 21 insertions(+), 32 deletions(-) diff --git a/internal/core/adt/binop.go b/internal/core/adt/binop.go index 4ba0d027df8..157ef80a22e 100644 --- a/internal/core/adt/binop.go +++ b/internal/core/adt/binop.go @@ -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 @@ -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 diff --git a/internal/core/adt/composite.go b/internal/core/adt/composite.go index a02f344bebb..286844a54dc 100644 --- a/internal/core/adt/composite.go +++ b/internal/core/adt/composite.go @@ -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 { diff --git a/internal/core/adt/context.go b/internal/core/adt/context.go index 5009e745263..86472d0de60 100644 --- a/internal/core/adt/context.go +++ b/internal/core/adt/context.go @@ -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. @@ -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) diff --git a/internal/core/adt/expr.go b/internal/core/adt/expr.go index 5775b4b7d94..b138a816df9 100644 --- a/internal/core/adt/expr.go +++ b/internal/core/adt/expr.go @@ -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 @@ -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 } @@ -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, @@ -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), @@ -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.