Skip to content

Commit

Permalink
all: enable new sorting algorithm
Browse files Browse the repository at this point in the history
And hide it behind a CUE_EXPERIMENT=toposort flag

Introduce new export.VertexFeaturesUnsorted and switch to using that in
the subsumption code. This ensures we avoid paying the extra cost of
sorting where it's not needed.

Signed-off-by: Matthew Sackman <[email protected]>
Change-Id: I4a930c5c794c3405bf3a53f4484ae30e77a07cb4
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1202401
Reviewed-by: Marcel van Lohuizen <[email protected]>
TryBot-Result: CUEcueckoo <[email protected]>
Unity-Result: CUE porcuepine <[email protected]>
  • Loading branch information
cuematthew committed Nov 5, 2024
1 parent dbef7c5 commit edad6fc
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 2 deletions.
43 changes: 43 additions & 0 deletions internal/core/export/toposort.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import (
"slices"

"cuelang.org/go/internal/core/adt"
"cuelang.org/go/internal/core/toposort"
"cuelang.org/go/internal/cueexperiment"
)

// TODO: topological sort should go arguably in a more fundamental place as it
Expand All @@ -28,6 +30,14 @@ import (
// features than for which there are arcs and also includes features for
// optional fields. It assumes the Structs fields are initialized and evaluated.
func VertexFeatures(c *adt.OpContext, v *adt.Vertex) []adt.Feature {
if cueexperiment.Flags.TopoSort {
return toposort.VertexFeatures(c, v)
} else {
return vertexFeatures(c, v)
}
}

func vertexFeatures(c *adt.OpContext, v *adt.Vertex) []adt.Feature {
sets := extractFeatures(v.Structs)
m := sortArcs(sets) // TODO: use for convenience.

Expand Down Expand Up @@ -72,6 +82,39 @@ func extractFeatures(in []*adt.StructInfo) (a [][]adt.Feature) {
return a
}

// VertexFeaturesUnsorted returns the feature list of v. There will be
// no duplicate features in the returned list, but there is also no
// attempt made to sort the list.
func VertexFeaturesUnsorted(v *adt.Vertex) (features []adt.Feature) {
seen := make(map[adt.Feature]struct{})

for _, s := range v.Structs {
for _, decl := range s.Decls {
field, ok := decl.(*adt.Field)
if !ok {
continue
}
label := field.Label
if _, found := seen[label]; found {
continue
}
seen[label] = struct{}{}
features = append(features, label)
}
}

for _, arc := range v.Arcs {
label := arc.Label
if _, found := seen[label]; found {
continue
}
seen[label] = struct{}{}
features = append(features, label)
}

return features
}

// sortedArcs is like sortArcs, but returns a the features of optional and
// required fields in an sorted slice. Ultimately, the implementation should
// use merge sort everywhere, and this will be the preferred method. Also,
Expand Down
4 changes: 2 additions & 2 deletions internal/core/subsume/vertex.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func (s *subsumer) vertices(x, y *adt.Vertex) bool {
}

// All arcs in x must exist in y and its values must subsume.
xFeatures := export.VertexFeatures(s.ctx, x)
xFeatures := export.VertexFeaturesUnsorted(x)
for _, f := range xFeatures {
if s.Final && !f.IsRegular() {
continue
Expand Down Expand Up @@ -183,7 +183,7 @@ func (s *subsumer) vertices(x, y *adt.Vertex) bool {
return false
}

yFeatures := export.VertexFeatures(s.ctx, y)
yFeatures := export.VertexFeaturesUnsorted(y)
outer:
for _, f := range yFeatures {
if s.Final && !f.IsRegular() {
Expand Down
3 changes: 3 additions & 0 deletions internal/cueexperiment/exp.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ var Flags struct {
// `int64` rather than `int` as the default type for CUE integer values
// to ensure consistency with 32-bit platforms.
DecodeInt64 bool

// Enable topological sorting of struct fields
TopoSort bool
}

// Init initializes Flags. Note: this isn't named "init" because we
Expand Down

0 comments on commit edad6fc

Please sign in to comment.