From 806fbb3cc34d8ea7080a4f90abe426d0f10d6ade Mon Sep 17 00:00:00 2001 From: Marcel van Lohuizen Date: Fri, 8 Mar 2024 19:55:40 +0100 Subject: [PATCH] internal/core/adt: use Vertex.Indirect in more places This prepares for several things, including the implementation of disjunctions and structure sharing. Issue #2851 Issue #2884 Issue #2854 Signed-off-by: Marcel van Lohuizen Change-Id: I831d5419e6b035667aae6f254f45456b34dfd93c --- internal/core/adt/composite.go | 2 ++ internal/core/adt/context.go | 10 ++++++++++ internal/core/adt/tasks.go | 3 +++ internal/core/adt/unify.go | 13 +++++++++++++ internal/core/debug/debug.go | 1 + 5 files changed, 29 insertions(+) diff --git a/internal/core/adt/composite.go b/internal/core/adt/composite.go index 53a952b46a1..e212a20e998 100644 --- a/internal/core/adt/composite.go +++ b/internal/core/adt/composite.go @@ -908,6 +908,8 @@ func (v *Vertex) IsList() bool { func (v *Vertex) Lookup(f Feature) *Vertex { for _, a := range v.Arcs { if a.Label == f { + // TODO(share): this indirection should ultimately be eliminated, + // and left up the caller, as it may remove useful information. a = a.Indirect() return a } diff --git a/internal/core/adt/context.go b/internal/core/adt/context.go index 528eb8c5cba..34bb272b6f9 100644 --- a/internal/core/adt/context.go +++ b/internal/core/adt/context.go @@ -703,6 +703,11 @@ func (c *OpContext) evalState(v Expr, state combinedFlags) (result Value) { if arc == nil { return nil } + // XXX: this should be in a standalone CL if it is on the path of + // the old evaluator as well. + // TODO: consider moving this after markCycle, depending on how we + // implement markCycle. + arc = arc.Indirect() // Save the old CloseInfo and restore after evaluate to avoid detecting // spurious cycles. @@ -823,6 +828,11 @@ func (c *OpContext) unifyNode(v Expr, state combinedFlags) (result Value) { if v == nil { return nil } + // XXX: this should be in a standalone CL if it is on the path of + // the old evaluator as well. + // TODO: consider moving this after markCycle, depending on how we + // implement markCycle. + v = v.Indirect() if c.isDevVersion() { if n := v.getState(c); n != nil { diff --git a/internal/core/adt/tasks.go b/internal/core/adt/tasks.go index 5de63aaaa9c..900e5d3238f 100644 --- a/internal/core/adt/tasks.go +++ b/internal/core/adt/tasks.go @@ -89,6 +89,9 @@ func processResolver(ctx *OpContext, t *task, mode runMode) { // TODO: yield instead? return } + // TODO: consider moving after markCycle or removing. + arc = arc.Indirect() + // A reference that points to itself indicates equality. In that case // we are done computing and we can return the arc as is. ci, skip := t.node.markCycle(arc, t.env, r, t.id) diff --git a/internal/core/adt/unify.go b/internal/core/adt/unify.go index 2f30e8c9b53..81e3c6697ea 100644 --- a/internal/core/adt/unify.go +++ b/internal/core/adt/unify.go @@ -122,6 +122,17 @@ func (v *Vertex) unify(c *OpContext, needs condition, mode runMode) bool { nodeOnlyNeeds := needs &^ (subFieldsProcessed) n.process(nodeOnlyNeeds, mode) + w := v.Indirect() // Dereference the disjunction result. + if w != v { + if w.Closed { + // Should resolve with dereference. + v.Closed = true + } + v.ArcType = w.ArcType + v.ChildErrors = CombineErrors(nil, v.ChildErrors, w.ChildErrors) + v.Arcs = nil + return w.state.meets(needs) + } n.updateScalar() // First process all but the subfields. @@ -431,6 +442,8 @@ func (v *Vertex) lookup(c *OpContext, pos token.Pos, f Feature, flags combinedFl needs := flags.conditions() runMode := flags.runMode() + v = v.Indirect() + c.Logf(c.vertex, "LOOKUP %v", f) state := v.getState(c) diff --git a/internal/core/debug/debug.go b/internal/core/debug/debug.go index fe32fd4e774..2d87a4a3370 100644 --- a/internal/core/debug/debug.go +++ b/internal/core/debug/debug.go @@ -161,6 +161,7 @@ func (w *printer) interpolation(x *adt.Interpolation) { func (w *printer) node(n adt.Node) { switch x := n.(type) { case *adt.Vertex: + x = x.Indirect() var kind adt.Kind if x.BaseValue != nil { kind = x.BaseValue.Kind()