@@ -28,6 +28,38 @@ module;
2828
2929private import codeql.util.Boolean
3030
31+ private newtype TConditionKind =
32+ TBooleanCondition( ) or
33+ TNullnessCondition( ) or
34+ TMatchingCondition( ) or
35+ TEmptinessCondition( )
36+
37+ /** A condition kind. This is used to classify different `ConditionalSuccessor`s. */
38+ class ConditionKind extends TConditionKind {
39+ /** Gets a textual representation of this condition kind. */
40+ string toString ( ) {
41+ this instanceof TBooleanCondition and result = "Boolean"
42+ or
43+ this instanceof TNullnessCondition and result = "Nullness"
44+ or
45+ this instanceof TMatchingCondition and result = "Matching"
46+ or
47+ this instanceof TEmptinessCondition and result = "Emptiness"
48+ }
49+
50+ /** Holds if this condition kind identifies `BooleanSuccessor`s. */
51+ predicate isBoolean ( ) { this instanceof TBooleanCondition }
52+
53+ /** Holds if this condition kind identifies `NullnessSuccessor`s. */
54+ predicate isNullness ( ) { this instanceof TNullnessCondition }
55+
56+ /** Holds if this condition kind identifies `MatchingSuccessor`s. */
57+ predicate isMatching ( ) { this instanceof TMatchingCondition }
58+
59+ /** Holds if this condition kind identifies `EmptinessSuccessor`s. */
60+ predicate isEmptiness ( ) { this instanceof TEmptinessCondition }
61+ }
62+
3163private newtype TSuccessorType =
3264 TDirectSuccessor ( ) or
3365 TBooleanSuccessor ( Boolean branch ) or
@@ -83,6 +115,18 @@ private class TConditionalSuccessor =
83115abstract private class ConditionalSuccessorImpl extends NormalSuccessorImpl , TConditionalSuccessor {
84116 /** Gets the Boolean value of this successor. */
85117 abstract boolean getValue ( ) ;
118+
119+ /** Gets the condition kind of this conditional successor. */
120+ abstract ConditionKind getKind ( ) ;
121+
122+ /**
123+ * Gets the dual of this conditional successor. That is, the conditional
124+ * successor of the same kind but with the opposite value.
125+ */
126+ ConditionalSuccessor getDual ( ) {
127+ this .getValue ( ) .booleanNot ( ) = result .getValue ( ) and
128+ this .getKind ( ) = result .getKind ( )
129+ }
86130}
87131
88132final class ConditionalSuccessor = ConditionalSuccessorImpl ;
@@ -116,6 +160,8 @@ final class ConditionalSuccessor = ConditionalSuccessorImpl;
116160class BooleanSuccessor extends ConditionalSuccessorImpl , TBooleanSuccessor {
117161 override boolean getValue ( ) { this = TBooleanSuccessor ( result ) }
118162
163+ override ConditionKind getKind ( ) { result = TBooleanCondition ( ) }
164+
119165 override string toString ( ) { result = this .getValue ( ) .toString ( ) }
120166}
121167
@@ -151,6 +197,8 @@ class NullnessSuccessor extends ConditionalSuccessorImpl, TNullnessSuccessor {
151197
152198 override boolean getValue ( ) { this = TNullnessSuccessor ( result ) }
153199
200+ override ConditionKind getKind ( ) { result = TNullnessCondition ( ) }
201+
154202 override string toString ( ) { if this .isNull ( ) then result = "null" else result = "non-null" }
155203}
156204
@@ -192,6 +240,8 @@ class MatchingSuccessor extends ConditionalSuccessorImpl, TMatchingSuccessor {
192240
193241 override boolean getValue ( ) { this = TMatchingSuccessor ( result ) }
194242
243+ override ConditionKind getKind ( ) { result = TMatchingCondition ( ) }
244+
195245 override string toString ( ) { if this .isMatch ( ) then result = "match" else result = "no-match" }
196246}
197247
@@ -233,6 +283,8 @@ class EmptinessSuccessor extends ConditionalSuccessorImpl, TEmptinessSuccessor {
233283
234284 override boolean getValue ( ) { this = TEmptinessSuccessor ( result ) }
235285
286+ override ConditionKind getKind ( ) { result = TEmptinessCondition ( ) }
287+
236288 override string toString ( ) { if this .isEmpty ( ) then result = "empty" else result = "non-empty" }
237289}
238290
0 commit comments