Skip to content

Commit 759f26e

Browse files
committed
internal/core/adt: move and rename Indirect
There are now different kinds of dereferencing. We rename Indirect to DerefValue and move it close to its siblings. Goals: - keep all types of dereference together - keep naming consistent - use DerefValue, instead of Deref or DerefAll, to make the purpose of this particular dereference clear: getting the underlying value. Added notes on which dereferences might need to change in the future. Issue #2854 Signed-off-by: Marcel van Lohuizen <[email protected]> Change-Id: I3ccde0ac21e248f65d9a462515840c77348f658a Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1194087 Reviewed-by: Daniel Martí <[email protected]> TryBot-Result: CUEcueckoo <[email protected]> Unity-Result: CUE porcuepine <[email protected]>
1 parent d9c5ae0 commit 759f26e

File tree

11 files changed

+66
-38
lines changed

11 files changed

+66
-38
lines changed

cue/types.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,11 +235,11 @@ func (i *Iterator) Next() bool {
235235
p := linkParent(i.val.parent_, i.val.v, arc)
236236
i.f = arc.Label
237237
i.arcType = arc.ArcType
238-
// TODO: this should not indirect disjunctions, as this will cause losing
238+
// TODO(deref): this should not indirect disjunctions, as this will cause losing
239239
// information, which is now available in the new evaluator. Find a safe
240240
// way to preserve disjunction information while keeping backward
241241
// compatibility in the API.
242-
arc = arc.Indirect()
242+
arc = arc.DerefValue()
243243
i.cur = makeValue(i.val.idx, arc, p)
244244
i.p++
245245
return true

internal/core/adt/composite.go

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ type Vertex struct {
267267
}
268268

269269
func deref(v *Vertex) *Vertex {
270-
v = v.Indirect()
270+
v = v.DerefValue()
271271
n := v.state
272272
if n != nil {
273273
v = n.underlying
@@ -679,7 +679,10 @@ func (v *Vertex) isUndefined() bool {
679679

680680
// isFinal reports whether this node may no longer be modified.
681681
func (v *Vertex) isFinal() bool {
682-
v = v.Indirect()
682+
// TODO(deref): the accounting of what is final should be recorded
683+
// in the original node. Remove this dereference once the old
684+
// evaluator has been removed.
685+
v = v.DerefValue()
683686
return v.status == finalized
684687
}
685688

@@ -852,7 +855,11 @@ func Unwrap(v Value) Value {
852855
if !ok {
853856
return v
854857
}
855-
x = x.Indirect()
858+
// TODO(deref): BaseValue is currently overloaded to track cycles as well
859+
// as the actual or dereferenced value. Once the old evaluator can be
860+
// removed, we should use the new cycle tracking mechanism for cycle
861+
// detection and keep BaseValue clean.
862+
x = x.DerefValue()
856863
if n := x.state; n != nil && isCyclePlaceholder(x.BaseValue) {
857864
if n.errs != nil && !n.errs.IsIncomplete() {
858865
return n.errs
@@ -864,19 +871,6 @@ func Unwrap(v Value) Value {
864871
return x.Value()
865872
}
866873

867-
// Indirect unrolls indirections of Vertex values. These may be introduced,
868-
// for instance, by temporary bindings such as comprehension values.
869-
// It returns v itself if v does not point to another Vertex.
870-
func (v *Vertex) Indirect() *Vertex {
871-
for {
872-
arc, ok := v.BaseValue.(*Vertex)
873-
if !ok {
874-
return v
875-
}
876-
v = arc
877-
}
878-
}
879-
880874
// OptionalType is a bit field of the type of optional constraints in use by an
881875
// Acceptor.
882876
type OptionalType int8
@@ -973,7 +967,14 @@ func (v *Vertex) Accept(ctx *OpContext, f Feature) bool {
973967
return true
974968
}
975969

976-
v = v.Indirect()
970+
// TODO(deref): right now a dereferenced value holds all the necessary
971+
// closedness information. In the future we may want to allow sharing nodes
972+
// with different closedness information. In that case, we should reconsider
973+
// the use of this dereference. Consider, for instance:
974+
//
975+
// #a: b // this node is currently not shared, but could be.
976+
// b: {c: 1}
977+
v = v.DerefValue()
977978
if x, ok := v.BaseValue.(*Disjunction); ok {
978979
for _, v := range x.Values {
979980
if x, ok := v.(*Vertex); ok && x.Accept(ctx, f) {
@@ -1068,12 +1069,12 @@ func (v *Vertex) IsList() bool {
10681069
func (v *Vertex) Lookup(f Feature) *Vertex {
10691070
for _, a := range v.Arcs {
10701071
if a.Label == f {
1071-
// TODO(share): this indirection should ultimately be eliminated:
1072-
// the original node may have useful information (like original
1073-
// conjuncts) that are eliminated after indirection.
1074-
// We should leave it up to the user of Lookup at what point an
1072+
// TODO(P1)/TODO(deref): this indirection should ultimately be
1073+
// eliminated: the original node may have useful information (like
1074+
// original conjuncts) that are eliminated after indirection. We
1075+
// should leave it up to the user of Lookup at what point an
10751076
// indirection is necessary.
1076-
a = a.Indirect()
1077+
a = a.DerefValue()
10771078
return a
10781079
}
10791080
}

internal/core/adt/context.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ func (c *OpContext) resolveState(x Conjunct, r Resolver, state combinedFlags) (*
497497
}
498498

499499
if !c.isDevVersion() {
500-
arc = arc.Indirect()
500+
arc = arc.DerefValue()
501501
}
502502

503503
return arc, err
@@ -512,7 +512,9 @@ func (c *OpContext) Lookup(env *Environment, r Resolver) (*Vertex, *Bottom) {
512512
err := c.PopState(s)
513513

514514
if arc != nil {
515-
arc = arc.Indirect()
515+
// TODO(P1)/TODO(deref): lookup should probably not use DerefValue, but
516+
// rather only dereference disjunctions.
517+
arc = arc.DerefValue()
516518
}
517519

518520
return arc, err

internal/core/adt/default.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ func (d *Disjunction) Default() Value {
4545
//
4646
// It also closes a list, representing its default value.
4747
func (v *Vertex) Default() *Vertex {
48-
v = v.Indirect()
48+
v = v.DerefValue()
4949
switch d := v.BaseValue.(type) {
5050
default:
5151
return v

internal/core/adt/disjunct2.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,7 @@ func appendDisjunct(ctx *OpContext, a []*nodeContext, x *nodeContext) []*nodeCon
517517
return a
518518
}
519519

520-
nv := x.node.Indirect()
520+
nv := x.node.DerefValue()
521521
nx := nv.BaseValue
522522
if nx == nil || isCyclePlaceholder(nx) {
523523
nx = x.getValidators(finalized)
@@ -528,7 +528,7 @@ func appendDisjunct(ctx *OpContext, a []*nodeContext, x *nodeContext) []*nodeCon
528528
// (overlayed) closeContexts are identical.
529529
outer:
530530
for _, xn := range a {
531-
xv := xn.node.Indirect()
531+
xv := xn.node.DerefValue()
532532
if xv.status != finalized || nv.status != finalized {
533533
// Partial node
534534

@@ -564,7 +564,7 @@ outer:
564564
}
565565
} else {
566566
// Complete nodes.
567-
if !Equal(ctx, xn.node.Indirect(), x.node.Indirect(), CheckStructural) {
567+
if !Equal(ctx, xn.node.DerefValue(), x.node.DerefValue(), CheckStructural) {
568568
continue outer
569569
}
570570
}

internal/core/adt/equality.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ func equalVertex(ctx *OpContext, x *Vertex, v Value, flags Flag) bool {
5353
return false
5454
}
5555

56-
x = x.Indirect()
57-
y = y.Indirect()
56+
x = x.DerefValue()
57+
y = y.DerefValue()
5858

5959
if x == y {
6060
return true

internal/core/adt/eval.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -614,7 +614,7 @@ func (n *nodeContext) validateValue(state vertexStatus) {
614614
} else if len(n.node.Structs) > 0 {
615615
markStruct = n.kind&StructKind != 0 && !n.hasTop
616616
}
617-
v := n.node.Indirect().Value()
617+
v := n.node.DerefValue().Value()
618618
if n.node.BaseValue == nil && markStruct {
619619
n.node.BaseValue = &StructMarker{}
620620
v = n.node

internal/core/adt/expr.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1431,7 +1431,7 @@ func (c *OpContext) validate(env *Environment, src ast.Node, x Expr, op Op, flag
14311431
}
14321432

14331433
func isFinalError(n *Vertex) bool {
1434-
n = n.Indirect()
1434+
n = n.DerefValue()
14351435
if b, ok := Unwrap(n).(*Bottom); ok && b.Code < IncompleteError {
14361436
return true
14371437
}

internal/core/adt/share.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,31 @@ func (n *nodeContext) shareIfPossible(c Conjunct, arc *Vertex, id CloseInfo) boo
106106
return true
107107
}
108108

109+
// Vertex values that are held in BaseValue will be wrapped in the following
110+
// order:
111+
//
112+
// disjuncts -> (shared | computed | data)
113+
//
114+
// DerefDisjunct
115+
// - get the current value under computation
116+
//
117+
// DerefValue
118+
// - get the value the node ultimately represents.
119+
//
120+
121+
// DerefValue unrolls indirections of Vertex values. These may be introduced,
122+
// for instance, by temporary bindings such as comprehension values.
123+
// It returns v itself if v does not point to another Vertex.
124+
func (v *Vertex) DerefValue() *Vertex {
125+
for {
126+
arc, ok := v.BaseValue.(*Vertex)
127+
if !ok {
128+
return v
129+
}
130+
v = arc
131+
}
132+
}
133+
109134
// DerefDisjunct indirects a node that points to a disjunction.
110135
func (v *Vertex) DerefDisjunct() *Vertex {
111136
for {

internal/core/adt/unify.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ func (v *Vertex) unify(c *OpContext, needs condition, mode runMode) bool {
273273

274274
n.finalizeDisjunctions()
275275

276-
w = v.Indirect() // Dereference anything, including shared nodes.
276+
w = v.DerefValue() // Dereference anything, including shared nodes.
277277
if w != v {
278278
// Clear value fields that are now referred to in the dereferenced
279279
// value (w).
@@ -595,7 +595,7 @@ func (v *Vertex) lookup(c *OpContext, pos token.Pos, f Feature, flags combinedFl
595595
needs := flags.conditions()
596596
runMode := flags.runMode()
597597

598-
v = v.Indirect()
598+
v = v.DerefValue()
599599

600600
c.Logf(c.vertex, "LOOKUP %v", f)
601601

@@ -731,7 +731,7 @@ func (v *Vertex) accept(ctx *OpContext, f Feature) bool {
731731
// return true, true
732732
// }
733733

734-
v = v.Indirect()
734+
v = v.DerefValue()
735735

736736
pc := v.PatternConstraints
737737
if pc == nil {

0 commit comments

Comments
 (0)