@@ -24,21 +24,36 @@ signature module MkSetsInp {
2424 * class, `ValueSet`, that canonically represents a set of `Value`s. In
2525 * particular, if two keys `k1` and `k2` relate to the same set of values, then
2626 * `getValueSet(k1) = getValueSet(k2)`.
27+ *
28+ * If the given `totalorder` is not a total order, then the keys for which we
29+ * cannot order the values cannot be given a canonical representation, and
30+ * instead the key is simply reused as the set representation. This provides a
31+ * reasonable fallback where `getValueSet(k).contains(v)` remains equivalent to
32+ * `v = getAValue(k)`.
2733 */
2834module MakeSets< MkSetsInp Inp> {
2935 private import Inp
3036
37+ private int totalorderExt ( Value v ) {
38+ result = 0 and v = getAValue ( _) and not exists ( totalorder ( v ) )
39+ or
40+ result = totalorder ( v )
41+ }
42+
3143 private predicate rankedValue ( Key k , Value v , int r ) {
32- v = rank [ r ] ( Value v0 | v0 = getAValue ( k ) | v0 order by totalorder ( v0 ) )
44+ v = rank [ r ] ( Value v0 | v0 = getAValue ( k ) | v0 order by totalorderExt ( v0 ) )
3345 }
3446
35- private int maxRank ( Key k ) { result = max ( int r | rankedValue ( k , _, r ) ) }
47+ private predicate unordered ( Key k ) {
48+ strictcount ( int r | rankedValue ( k , _, r ) ) != strictcount ( getAValue ( k ) )
49+ }
3650
37- predicate consistency ( int r , int bs ) { bs = strictcount ( Value v | totalorder ( v ) = r ) and bs != 1 }
51+ private int maxRank ( Key k ) { result = max ( int r | rankedValue ( k , _ , r ) ) and not unordered ( k ) }
3852
3953 private newtype TValList =
4054 TValListNil ( ) or
41- TValListCons ( Value head , int r , TValList tail ) { hasValListCons ( _, head , r , tail ) }
55+ TValListCons ( Value head , int r , TValList tail ) { hasValListCons ( _, head , r , tail ) } or
56+ TValListUnordered ( Key k ) { exists ( getAValue ( k ) ) and unordered ( k ) }
4257
4358 private predicate hasValListCons ( Key k , Value head , int r , TValList tail ) {
4459 rankedValue ( k , head , r ) and
@@ -54,21 +69,31 @@ module MakeSets<MkSetsInp Inp> {
5469 )
5570 }
5671
57- private predicate hasValueSet ( Key k , TValListCons vs ) { hasValList ( k , maxRank ( k ) , vs ) }
72+ private predicate hasValueSet ( Key k , TValList vs ) {
73+ hasValList ( k , maxRank ( k ) , vs ) or vs = TValListUnordered ( k )
74+ }
5875
5976 /** A set of `Value`s. */
60- class ValueSet extends TValListCons {
77+ class ValueSet extends TValList {
6178 ValueSet ( ) { hasValueSet ( _, this ) }
6279
63- string toString ( ) { result = "ValueSet" }
80+ string toString ( ) {
81+ this instanceof TValListCons and result = "ValueSet"
82+ or
83+ this instanceof TValListUnordered and result = "ValueSetUnordered"
84+ }
6485
6586 private predicate sublist ( TValListCons l ) {
6687 this = l or
6788 this .sublist ( TValListCons ( _, _, l ) )
6889 }
6990
7091 /** Holds if this set contains `v`. */
71- predicate contains ( Value v ) { this .sublist ( TValListCons ( v , _, _) ) }
92+ predicate contains ( Value v ) {
93+ this .sublist ( TValListCons ( v , _, _) )
94+ or
95+ exists ( Key k | this = TValListUnordered ( k ) and v = getAValue ( k ) )
96+ }
7297 }
7398
7499 /**
0 commit comments