Skip to content

Commit 4d3eafa

Browse files
committed
internal/core/adt: split ccArc
Use a separate type for the notify slice and simplify the code. Now the code is split, we can use the fact that several of the arguments of addArcDepedency and addNotificationDependency (which used to be addDependency) are always the same or are derived in a particular way. This allows us to remove a bunch of assertions. The TODO that was mentioned was actually incorrect, and was computing the wrong derivative, which is why that assertion did not work. Splitting addDepedency now also allows us to merge addNotificationDependency with linkNotify. Note that the uniqueness check can now be removed and that the assertions are enforced by the compiler (because of the limitations of the function signature). Signed-off-by: Marcel van Lohuizen <[email protected]> Change-Id: I9042cb42be98d4e3f761f7a095f44348815a8dd2 Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1207453 Reviewed-by: Daniel Martí <[email protected]> Unity-Result: CUE porcuepine <[email protected]> TryBot-Result: CUEcueckoo <[email protected]>
1 parent 44a2e75 commit 4d3eafa

File tree

5 files changed

+45
-73
lines changed

5 files changed

+45
-73
lines changed

Diff for: internal/core/adt/conjunct.go

+8-9
Original file line numberDiff line numberDiff line change
@@ -520,20 +520,19 @@ func (n *nodeContext) insertAndSkipConjuncts(c Conjunct, id CloseInfo, depth int
520520
n.scheduleConjunct(c, id)
521521
}
522522

523-
func (n *nodeContext) addNotify2(v *Vertex, c CloseInfo) []receiver {
523+
func (n *nodeContext) addNotify2(v *Vertex, c CloseInfo) {
524524
// scheduleConjunct should ensure that the closeContext of of c is aligned
525525
// with v. We rely on this to be the case here. We enforce this invariant
526526
// here for clarity and to ensure correctness.
527527
n.ctx.Assertf(token.NoPos, c.cc.src == v, "close context not aligned with vertex")
528528

529529
// No need to do the notification mechanism if we are already complete.
530-
old := n.notify
531530
switch {
532531
case n.node.isFinal():
533-
return old
532+
return
534533
case !n.node.isInProgress():
535534
case n.meets(allAncestorsProcessed):
536-
return old
535+
return
537536
}
538537

539538
// Create a "root" closeContext to reflect the entry point of the
@@ -544,22 +543,22 @@ func (n *nodeContext) addNotify2(v *Vertex, c CloseInfo) []receiver {
544543
// is even possible by adding a panic.
545544
root := n.node.rootCloseContext(n.ctx)
546545
if root.isDecremented {
547-
return old
546+
return
548547
}
549548

550549
for _, r := range n.notify {
551550
if r.cc == c.cc {
552-
return old
551+
return
553552
}
554553
}
555554

556555
cc := c.cc
557556

558-
if root.linkNotify(n.ctx, cc) {
557+
if root.addNotifyDependency(n.ctx, cc) {
558+
// TODO: this is mostly identical to the slice in the root closeContext.
559+
// Use only one once V2 is removed.
559560
n.notify = append(n.notify, receiver{cc.src, cc})
560561
}
561-
562-
return old
563562
}
564563

565564
// Literal conjuncts

Diff for: internal/core/adt/dep.go

+18-50
Original file line numberDiff line numberDiff line change
@@ -133,94 +133,62 @@ func (c *closeContext) matchDecrement(ctx *OpContext, v *Vertex, kind depKind, d
133133
}
134134
}
135135

136-
// A ccArcRef x refers to the x.src.[arcs|notify][x.index]
136+
// A ccDepRef x refers to the x.src.[arcs|notify][x.index]
137137
//
138138
// We use this instead of pointers, because the address may change when
139139
// growing a slice. We use this instead mechanism instead of a pointers so
140140
// that we do not need to maintain separate free buffers once we use pools of
141141
// closeContext.
142-
type ccArcRef struct {
142+
type ccDepRef struct {
143143
src *closeContext
144144
kind depKind
145145
index int
146146
}
147147

148148
// addArc adds a dependent arc to c. If child is an arc, child.src == key
149-
func (c *closeContext) addArcDependency(ctx *OpContext, matched bool, key, child, root *closeContext) {
150-
const kind = ARC
149+
func (c *closeContext) addArcDependency(ctx *OpContext, matched bool, child *closeContext) {
150+
root := child.src.cc()
151151

152152
// NOTE: do not increment
153153
// - either root closeContext or otherwise resulting from sub closeContext
154154
// all conjuncts will be added now, notified, or scheduled as task.
155155
for _, a := range c.arcs {
156-
if a.key == key {
156+
if a.root == root {
157157
panic("addArc: Label already exists")
158158
}
159159
}
160-
child.incDependent(ctx, kind, c) // matched in decDependent REF(arcs)
160+
child.incDependent(ctx, ARC, c) // matched in decDependent REF(arcs)
161161

162162
c.arcs = append(c.arcs, ccArc{
163163
matched: matched,
164-
key: key,
164+
root: root,
165165
dst: child,
166166
})
167167

168-
// TODO: this tests seems sensible, but panics. Investigate what could
169-
// trigger this.
170-
// if child.src.Parent != c.src {
171-
// panic("addArc: inconsistent parent")
172-
// }
173-
if child.src.cc() != root.src.cc() {
174-
panic("addArc: inconsistent root")
175-
}
176-
177-
root.externalDeps = append(root.externalDeps, ccArcRef{
168+
root.externalDeps = append(root.externalDeps, ccDepRef{
178169
src: c,
179-
kind: kind,
170+
kind: ARC,
180171
index: len(c.arcs) - 1,
181172
})
182173
}
183174

184-
func (cc *closeContext) linkNotify(ctx *OpContext, key *closeContext) bool {
185-
for _, a := range cc.notify {
186-
if a.key == key {
187-
return false
188-
}
189-
}
190-
191-
cc.addNotificationDependency(ctx, false, key, key, key.src.cc())
192-
return true
193-
}
194-
195-
func (c *closeContext) addNotificationDependency(ctx *OpContext, matched bool, key, child, root *closeContext) {
196-
const kind = NOTIFY
175+
func (c *closeContext) addNotifyDependency(ctx *OpContext, dst *closeContext) bool {
197176
for _, a := range c.notify {
198-
if a.key == key {
199-
panic("addArc: Label already exists")
177+
if a.dst == dst {
178+
return false
200179
}
201180
}
202-
child.incDependent(ctx, kind, c) // matched in decDependent REF(arcs)
203-
204-
c.notify = append(c.notify, ccArc{
205-
matched: matched,
206-
key: key,
207-
dst: child,
208-
})
181+
dst.incDependent(ctx, NOTIFY, c) // matched in decDependent REF(arcs)
209182

210-
// TODO: this tests seems sensible, but panics. Investigate what could
211-
// trigger this.
212-
// if child.src.Parent != c.src {
213-
// panic("addArc: inconsistent parent")
214-
// }
215-
if child.src.cc() != root.src.cc() {
216-
panic("addArc: inconsistent root")
217-
}
183+
c.notify = append(c.notify, ccNotify{dst: dst})
218184

219-
root.externalDeps = append(root.externalDeps, ccArcRef{
185+
root := dst.src.cc()
186+
root.externalDeps = append(root.externalDeps, ccDepRef{
220187
src: c,
221-
kind: kind,
188+
kind: NOTIFY,
222189
index: len(c.notify) - 1,
223190
})
191+
return true
224192
}
225193

226194
// incDisjunct increases disjunction-related counters. We require kind to be

Diff for: internal/core/adt/disjunct2.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -738,7 +738,7 @@ func equalPartialNode(ctx *OpContext, x, y *closeContext) bool {
738738
outer:
739739
for _, a := range x.arcs {
740740
for _, b := range y.arcs {
741-
if a.key.src.Label != b.key.src.Label {
741+
if a.root.src.Label != b.root.src.Label {
742742
continue
743743
}
744744
if !equalPartialNode(ctx, a.dst, b.dst) {

Diff for: internal/core/adt/fields.go

+15-7
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ type closeContext struct {
182182
//
183183
// This is only used for root closedContext and only for debugging.
184184
// TODO: move to nodeContext.
185-
externalDeps []ccArcRef
185+
externalDeps []ccDepRef
186186

187187
// child links to a sequence which additional patterns need to be verified
188188
// against (&&). If there are more than one, these additional nodes are
@@ -273,7 +273,7 @@ type closeContext struct {
273273
// originate from a more specific closeContext, allowing it to stopped
274274
// sooner and possibly even remove the need for breaking dependency
275275
// cycles.
276-
notify []ccArc
276+
notify []ccNotify
277277

278278
// parentIndex is the position in the parent's arcs slice that corresponds
279279
// to this closeContext. This is currently unused. The intention is to use
@@ -329,9 +329,17 @@ type ccArc struct {
329329
// matched pattern and that it is not explicitly defined as a field.
330330
// This is only used for arcs and not for notify.
331331
matched bool
332-
// key is the closeContext is used to find the destination of the arc, which
333-
// is the root context.
334-
key *closeContext
332+
// root is dst.src.cc(). TODO: remove and use dst directly.
333+
root *closeContext
334+
// dst is the closeContext for which the counters are incremented and
335+
// decremented and which is the actual destination of the dependency.
336+
dst *closeContext
337+
}
338+
339+
type ccNotify struct {
340+
// decremented indicates whether [decDependant] has been called for this
341+
// dependency.
342+
decremented bool
335343
// dst is the closeContext for which the counters are incremented and
336344
// decremented and which is the actual destination of the dependency.
337345
dst *closeContext
@@ -403,7 +411,7 @@ func (v *Vertex) assignConjunct(ctx *OpContext, root *closeContext, c Conjunct,
403411
func (cc *closeContext) getKeyedCC(ctx *OpContext, key *closeContext, c CycleInfo, mode ArcType, checkClosed bool) *closeContext {
404412
for i := range cc.arcs {
405413
a := &cc.arcs[i]
406-
if a.key == key {
414+
if a.root == key {
407415
a.matched = a.matched && !checkClosed
408416
a.dst.updateArcType(ctx, mode)
409417
return a.dst
@@ -454,7 +462,7 @@ func (cc *closeContext) getKeyedCC(ctx *OpContext, key *closeContext, c CycleInf
454462
// prevent a dependency on self.
455463
if key.src != cc.src {
456464
matched := !checkClosed
457-
cc.addArcDependency(ctx, matched, key, arc, key)
465+
cc.addArcDependency(ctx, matched, arc)
458466
}
459467
}
460468

Diff for: internal/core/adt/overlay.go

+3-6
Original file line numberDiff line numberDiff line change
@@ -441,22 +441,19 @@ func (ctx *overlayContext) initCloneCC(x *closeContext) {
441441
if a.dst.overlay == nil {
442442
continue
443443
}
444-
if a.key.overlay != nil {
445-
a.key = a.key.overlay // TODO: is this necessary?
444+
if a.root.overlay != nil {
445+
a.root = a.root.overlay // TODO: is this necessary?
446446
}
447447
a.dst = a.dst.overlay
448448
o.arcs = append(o.arcs, a)
449449
}
450450

451451
for _, a := range x.notify {
452-
// If an arc does not have an overlay, we should not decrement the
452+
// If a notification does not have an overlay, we should not decrement the
453453
// dependency counter. We simply remove the dependency in that case.
454454
if a.dst.overlay == nil {
455455
continue
456456
}
457-
if a.key.overlay != nil {
458-
a.key = a.key.overlay // TODO: is this necessary?
459-
}
460457
a.dst = a.dst.overlay
461458
o.notify = append(o.notify, a)
462459
}

0 commit comments

Comments
 (0)