ProtectedcleanCounter for generating unique group IDs
ProtectedgroupMaps group ID to the values in it - read through valuesOf and groupEntries.
PrivaterevisionProtected ReadonlytoProtectedvalueMaps a value to the group it is in - read through groupOf.
The state the set is in, as a stamp that no two states of any two sets share.
Every method that writes anything moves it on (touch), so a memo taken off the set is valid for exactly as long as this is what it was taken at - which is a check the memo cannot forget to make, there being nothing to invalidate.
ProtectedcarriesWhether the group holds something its single remaining member would still be constrained by.
The group to check
whether it does; never at this level
Resets the set to its initial state, dropping every group.
A copy that shares no state with this one, so that either may be mutated on its own.
the copy
ProtectedcopyCopies the state of this set into target, which subclasses extend with the state they add.
The set to copy into
ProtectedcreateCreates a group holding no values at all, which is only reachable through whatever a subclass makes point at it - the positions of a triple pin, for datastructures/TermClusterSet!TermClusterSet.
the new group
ProtectedcreateProtecteddropDeletes a group and every value in it, which subclasses extend with the state they add.
The group to drop
Gets or creates a group for a value.
The value to get/create a group for
the group ID
Every group and its values, in the order the groups were created.
the pairs
Whether the group exists at all - a group nothing points at any more does not.
The group to check
whether it exists
ProtectedisWhether the group is still worth keeping: two members constrain each other, and a single one is constrained by whatever the group carriesInformation about.
The group to check
whether it is worth keeping; a subclass that lets something outside the group's values point at it overrides this, dropping such a group leaving that reference dangling
ProtectedmergeMerges two groups by id, which is what a group nothing names can be merged by - the values-only half of a merge, whatever else a subclass hangs off a group being migrated by migrateGroupData.
One group
The other
the ids involved, or undefined when the two ids are the same group
ProtectedmigrateMoves everything the disappearing group carried besides its values onto the surviving one. Subclasses
that give a group more state migrate it here, calling super first so that whatever a class further up
carries over is already in place.
The group disappearing
The group surviving
ProtectedtouchMoves revision on, invalidating whatever was memoised off the state the set was just in.
Called by the method that writes rather than by whoever asked for the write, so that a caller has
nothing to remember. Most of the calls sit on the choke points the writes of this class pass through -
clear, copyInto, createEmptyGroup, remove, dropGroup,
mergeGroupIds - which is what a subclass extending one of them inherits rather than has to
repeat, and what makes createGroup and every super-chaining override safe without a call of their
own.
A subclass writing state no ancestor writes owes a call here on its own account, since no choke
point of this class covers it. Those are narrowRange and resolveAllConstraints on
datastructures/TermClusterSet!TermClusterSet, assertTermTypeRange on
datastructures/AssertionClusterSet!AssertionClusterSet, and sortClusters,
registerExpressionToGroup and the static-validation branch of register on ClusterSolver!ClusterSolver
The values of a group.
The group to read
its values, empty when the group does not exist
A union-find over values, grouping the ones that have to be equal. Complexity: n*log(n).
Allegedly this can be compressed down to O(invAckerman(n)): https://claude.ai/share/8db9c2e2-918f-42ed-af83-e5564a6f80a3