@@ -15,13 +15,13 @@ private Declaration referenceAttribute(Expr e) {
1515}
1616
1717/** Gets the AST node kind element `e`. */
18- private int elementKind ( Element e ) {
18+ private int elementKind ( ControlFlowElement e ) {
1919 expressions ( e , result , _)
2020 or
2121 exists ( int k | statements ( e , k ) | result = - k )
2222}
2323
24- private int getNumberOfActualChildren ( Element e ) {
24+ private int getNumberOfActualChildren ( ControlFlowElement e ) {
2525 if e .( MemberAccess ) .targetIsThisInstance ( )
2626 then result = e .getNumberOfChildren ( ) - 1
2727 else result = e .getNumberOfChildren ( )
@@ -55,21 +55,25 @@ abstract class StructuralComparisonConfiguration extends string {
5555 * In fact, not including the symmetrically implied fact will save
5656 * half the computation time on the structural comparison.
5757 */
58- abstract predicate candidate ( Element x , Element y ) ;
58+ abstract predicate candidate ( ControlFlowElement x , ControlFlowElement y ) ;
5959
60- private predicate candidateInternal ( Element x , Element y ) {
61- (
62- candidate ( x , y )
63- or
64- exists ( Element xParent , Element yParent , int i | candidateInternal ( xParent , yParent ) |
65- hasChild ( xParent , i , x ) and
66- hasChild ( yParent , i , y )
67- )
60+ private predicate candidateInternal ( ControlFlowElement x , ControlFlowElement y ) {
61+ candidate ( x , y )
62+ or
63+ exists ( ControlFlowElement xParent , ControlFlowElement yParent , int i |
64+ candidateInternalChild ( xParent , i , x , yParent )
65+ |
66+ y = yParent .getChild ( i )
6867 )
6968 }
7069
7170 pragma [ noinline]
72- private predicate hasChild ( Element e , int i , Element child ) { child = e .getChild ( i ) }
71+ private predicate candidateInternalChild (
72+ ControlFlowElement x , int i , ControlFlowElement xChild , ControlFlowElement y
73+ ) {
74+ candidateInternal ( x , y ) and
75+ xChild = x .getChild ( i )
76+ }
7377
7478 private predicate sameByValue ( Expr x , Expr y ) { sameByValueAux ( x , y , y .getValue ( ) ) }
7579
@@ -79,47 +83,57 @@ abstract class StructuralComparisonConfiguration extends string {
7983 value = x .getValue ( )
8084 }
8185
86+ private ControlFlowElement getRankedChild ( ControlFlowElement cfe , int rnk , int i ) {
87+ ( candidateInternal ( cfe , _) or candidateInternal ( _, cfe ) ) and
88+ i = rank [ rnk ] ( int j |
89+ exists ( ControlFlowElement child | child = cfe .getChild ( j ) |
90+ not ( j = - 1 and cfe .( MemberAccess ) .targetIsThisInstance ( ) )
91+ )
92+ ) and
93+ result = cfe .getChild ( i )
94+ }
95+
8296 pragma [ nomagic]
83- private predicate sameByStructure ( Element x , Element y ) {
97+ private predicate sameByStructure0 (
98+ ControlFlowElement x , ControlFlowElement y , int elementKind , int children
99+ ) {
100+ candidateInternal ( x , y ) and
101+ elementKind = elementKind ( x ) and
102+ children = getNumberOfActualChildren ( x ) and
103+ not ( x .( Expr ) .hasValue ( ) and y .( Expr ) .hasValue ( ) )
104+ }
105+
106+ pragma [ nomagic]
107+ private predicate sameByStructure ( ControlFlowElement x , ControlFlowElement y , int i ) {
108+ i = 0 and
84109 // At least one of `x` and `y` must not have a value, they must have
85110 // the same kind, and the same number of children
86- sameByStructureCandidate ( x , y , elementKind ( y ) , getNumberOfActualChildren ( y ) ) and
111+ sameByStructure0 ( x , y , elementKind ( y ) , getNumberOfActualChildren ( y ) ) and
87112 // If one of them has a reference attribute, they should both reference
88113 // the same node
89114 ( exists ( referenceAttribute ( x ) ) implies referenceAttribute ( x ) = referenceAttribute ( y ) ) and
90115 // x is a member access on `this` iff y is
91116 ( x .( MemberAccess ) .targetIsThisInstance ( ) implies y .( MemberAccess ) .targetIsThisInstance ( ) ) and
92- ( y .( MemberAccess ) .targetIsThisInstance ( ) implies x .( MemberAccess ) .targetIsThisInstance ( ) ) and
93- // All of their corresponding children must be structurally equal
94- forall ( int i , Element xc |
95- xc = x .getChild ( i ) and
96- // exclude `this` qualifier, which has been checked above
97- not ( i = - 1 and x .( MemberAccess ) .targetIsThisInstance ( ) )
98- |
99- sameInternal ( xc , y .getChild ( i ) )
117+ ( y .( MemberAccess ) .targetIsThisInstance ( ) implies x .( MemberAccess ) .targetIsThisInstance ( ) )
118+ or
119+ exists ( int j | sameByStructure ( x , y , i - 1 ) |
120+ sameInternal ( getRankedChild ( x , i , j ) , getRankedChild ( y , i , j ) )
100121 )
101122 }
102123
103- private predicate sameByStructureCandidate ( Element x , Element y , int elementKind , int children ) {
104- candidateInternal ( x , y ) and
105- elementKind = elementKind ( x ) and
106- children = getNumberOfActualChildren ( x ) and
107- not ( x .( Expr ) .hasValue ( ) and y .( Expr ) .hasValue ( ) )
108- }
109-
110124 pragma [ nomagic]
111- private predicate sameInternal ( Element x , Element y ) {
125+ private predicate sameInternal ( ControlFlowElement x , ControlFlowElement y ) {
112126 sameByValue ( x , y )
113127 or
114- sameByStructure ( x , y )
128+ sameByStructure ( x , y , getNumberOfActualChildren ( x ) )
115129 }
116130
117131 /**
118132 * Holds if elements `x` and `y` structurally equal. `x` and `y` must be
119133 * flagged as candidates for structural equality, that is,
120134 * `candidate(x, y)` must hold.
121135 */
122- predicate same ( Element x , Element y ) {
136+ predicate same ( ControlFlowElement x , ControlFlowElement y ) {
123137 candidate ( x , y ) and
124138 sameInternal ( x , y )
125139 }
@@ -166,21 +180,25 @@ module Internal {
166180 * In fact, not including the symmetrically implied fact will save
167181 * half the computation time on the structural comparison.
168182 */
169- abstract predicate candidate ( Element x , Element y ) ;
170-
171- private predicate candidateInternal ( Element x , Element y ) {
172- (
173- candidate ( x , y )
174- or
175- exists ( Element xParent , Element yParent , int i | candidateInternal ( xParent , yParent ) |
176- hasChild ( xParent , i , x ) and
177- hasChild ( yParent , i , y )
178- )
183+ abstract predicate candidate ( ControlFlowElement x , ControlFlowElement y ) ;
184+
185+ private predicate candidateInternal ( ControlFlowElement x , ControlFlowElement y ) {
186+ candidate ( x , y )
187+ or
188+ exists ( ControlFlowElement xParent , ControlFlowElement yParent , int i |
189+ candidateInternalChild ( xParent , i , x , yParent )
190+ |
191+ y = yParent .getChild ( i )
179192 )
180193 }
181194
182195 pragma [ noinline]
183- private predicate hasChild ( Element e , int i , Element child ) { child = e .getChild ( i ) }
196+ private predicate candidateInternalChild (
197+ ControlFlowElement x , int i , ControlFlowElement xChild , ControlFlowElement y
198+ ) {
199+ candidateInternal ( x , y ) and
200+ xChild = x .getChild ( i )
201+ }
184202
185203 private predicate sameByValue ( Expr x , Expr y ) { sameByValueAux ( x , y , y .getValue ( ) ) }
186204
@@ -190,47 +208,57 @@ module Internal {
190208 value = x .getValue ( )
191209 }
192210
211+ private ControlFlowElement getRankedChild ( ControlFlowElement cfe , int rnk , int i ) {
212+ ( candidateInternal ( cfe , _) or candidateInternal ( _, cfe ) ) and
213+ i = rank [ rnk ] ( int j |
214+ exists ( ControlFlowElement child | child = cfe .getChild ( j ) |
215+ not ( j = - 1 and cfe .( MemberAccess ) .targetIsThisInstance ( ) )
216+ )
217+ ) and
218+ result = cfe .getChild ( i )
219+ }
220+
221+ pragma [ nomagic]
222+ private predicate sameByStructure0 (
223+ ControlFlowElement x , ControlFlowElement y , int elementKind , int children
224+ ) {
225+ candidateInternal ( x , y ) and
226+ elementKind = elementKind ( x ) and
227+ children = getNumberOfActualChildren ( x ) and
228+ not ( x .( Expr ) .hasValue ( ) and y .( Expr ) .hasValue ( ) )
229+ }
230+
193231 pragma [ nomagic]
194- private predicate sameByStructure ( Element x , Element y ) {
232+ private predicate sameByStructure ( ControlFlowElement x , ControlFlowElement y , int i ) {
233+ i = 0 and
195234 // At least one of `x` and `y` must not have a value, they must have
196235 // the same kind, and the same number of children
197- sameByStructureCandidate ( x , y , elementKind ( y ) , getNumberOfActualChildren ( y ) ) and
236+ sameByStructure0 ( x , y , elementKind ( y ) , getNumberOfActualChildren ( y ) ) and
198237 // If one of them has a reference attribute, they should both reference
199238 // the same node
200239 ( exists ( referenceAttribute ( x ) ) implies referenceAttribute ( x ) = referenceAttribute ( y ) ) and
201240 // x is a member access on `this` iff y is
202241 ( x .( MemberAccess ) .targetIsThisInstance ( ) implies y .( MemberAccess ) .targetIsThisInstance ( ) ) and
203- ( y .( MemberAccess ) .targetIsThisInstance ( ) implies x .( MemberAccess ) .targetIsThisInstance ( ) ) and
204- // All of their corresponding children must be structurally equal
205- forall ( int i , Element xc |
206- xc = x .getChild ( i ) and
207- // exclude `this` qualifier, which has been checked above
208- not ( i = - 1 and x .( MemberAccess ) .targetIsThisInstance ( ) )
209- |
210- sameInternal ( xc , y .getChild ( i ) )
242+ ( y .( MemberAccess ) .targetIsThisInstance ( ) implies x .( MemberAccess ) .targetIsThisInstance ( ) )
243+ or
244+ exists ( int j | sameByStructure ( x , y , i - 1 ) |
245+ sameInternal ( getRankedChild ( x , i , j ) , getRankedChild ( y , i , j ) )
211246 )
212247 }
213248
214- private predicate sameByStructureCandidate ( Element x , Element y , int elementKind , int children ) {
215- candidateInternal ( x , y ) and
216- elementKind = elementKind ( x ) and
217- children = getNumberOfActualChildren ( x ) and
218- not ( x .( Expr ) .hasValue ( ) and y .( Expr ) .hasValue ( ) )
219- }
220-
221249 pragma [ nomagic]
222- private predicate sameInternal ( Element x , Element y ) {
250+ private predicate sameInternal ( ControlFlowElement x , ControlFlowElement y ) {
223251 sameByValue ( x , y )
224252 or
225- sameByStructure ( x , y )
253+ sameByStructure ( x , y , getNumberOfActualChildren ( x ) )
226254 }
227255
228256 /**
229257 * Holds if elements `x` and `y` structurally equal. `x` and `y` must be
230258 * flagged as candidates for structural equality, that is,
231259 * `candidate(x, y)` must hold.
232260 */
233- predicate same ( Element x , Element y ) {
261+ predicate same ( ControlFlowElement x , ControlFlowElement y ) {
234262 candidate ( x , y ) and
235263 sameInternal ( x , y )
236264 }
0 commit comments