@@ -114,39 +114,12 @@ class ClassList extends TClassList {
114
114
this = Empty ( ) and result = Empty ( )
115
115
}
116
116
117
- predicate legalMergeHead ( ClassObjectInternal cls ) {
118
- this .getTail ( ) .doesNotContain ( cls )
119
- or
120
- this = Empty ( )
121
- }
122
-
123
117
predicate contains ( ClassObjectInternal cls ) {
124
118
cls = this .getHead ( )
125
119
or
126
120
this .getTail ( ) .contains ( cls )
127
121
}
128
122
129
- /** Use negative formulation to avoid negative recursion */
130
- predicate doesNotContain ( ClassObjectInternal cls ) {
131
- this .relevantForContains ( cls ) and
132
- cls != this .getHead ( ) and
133
- this .getTail ( ) .doesNotContain ( cls )
134
- or
135
- this = Empty ( )
136
- }
137
-
138
- private predicate relevantForContains ( ClassObjectInternal cls ) {
139
- exists ( ClassListList list |
140
- list .getItem ( _) .getHead ( ) = cls and
141
- list .getItem ( _) = this
142
- )
143
- or
144
- exists ( ClassList l |
145
- l .relevantForContains ( cls ) and
146
- this = l .getTail ( )
147
- )
148
- }
149
-
150
123
ClassObjectInternal findDeclaringClass ( string name ) {
151
124
exists ( ClassDecl head | head = this .getHead ( ) .getClassDeclaration ( ) |
152
125
if head .declaresAttribute ( name )
@@ -199,12 +172,18 @@ class ClassList extends TClassList {
199
172
or
200
173
this .duplicate ( n ) and result = this .deduplicate ( n + 1 )
201
174
or
202
- exists ( ClassObjectInternal cls |
203
- n = this . firstIndex ( cls ) and
204
- result = Cons ( cls , this . deduplicate ( n + 1 ) )
175
+ exists ( ClassObjectInternal cls , ClassList tail |
176
+ deduplicateCons ( n , cls , tail ) and
177
+ result = Cons ( cls , tail )
205
178
)
206
179
}
207
180
181
+ pragma [ nomagic]
182
+ private predicate deduplicateCons ( int n , ClassObjectInternal cls , ClassList tail ) {
183
+ n = this .firstIndex ( cls ) and
184
+ tail = this .deduplicate ( n + 1 )
185
+ }
186
+
208
187
predicate isEmpty ( ) { this = Empty ( ) }
209
188
210
189
ClassList reverse ( ) { reverse_step ( this , Empty ( ) , result ) }
@@ -299,13 +278,23 @@ private class ClassListList extends TClassListList {
299
278
removed_head = this .getItem ( n ) .removeHead ( cls ) and
300
279
removed_tail = EmptyList ( )
301
280
or
281
+ removed_head = this .removedClassPartsCons1 ( cls , removed_tail , n ) .removeHead ( cls )
282
+ }
283
+
284
+ pragma [ noinline]
285
+ predicate removedClassPartsCons0 ( ClassObjectInternal cls , ClassListList removed_tail , int n ) {
302
286
exists ( ClassList prev_head , ClassListList prev_tail |
303
287
this .removedClassParts ( cls , prev_head , prev_tail , n + 1 ) and
304
- removed_head = this .getItem ( n ) .removeHead ( cls ) and
305
288
removed_tail = ConsList ( prev_head , prev_tail )
306
289
)
307
290
}
308
291
292
+ pragma [ noinline]
293
+ ClassList removedClassPartsCons1 ( ClassObjectInternal cls , ClassListList removed_tail , int n ) {
294
+ removedClassPartsCons0 ( cls , removed_tail , n ) and
295
+ result = this .getItem ( n )
296
+ }
297
+
309
298
ClassListList remove ( ClassObjectInternal cls ) {
310
299
exists ( ClassList removed_head , ClassListList removed_tail |
311
300
this .removedClassParts ( cls , removed_head , removed_tail , 0 ) and
@@ -315,18 +304,34 @@ private class ClassListList extends TClassListList {
315
304
this = EmptyList ( ) and result = EmptyList ( )
316
305
}
317
306
318
- predicate legalMergeCandidate ( ClassObjectInternal cls , int n ) {
307
+ pragma [ nomagic]
308
+ private predicate legalMergeCandidateNonEmpty ( ClassObjectInternal cls , int n , ClassList cl , int j ) {
309
+ this .legalMergeCandidate ( cls , n + 1 ) and
310
+ cl = this .getItem ( n ) and
311
+ j = cl .length ( )
312
+ or
313
+ legalMergeCandidateNonEmpty ( cls , n , cl , j + 1 ) and
314
+ j >= 1 and
315
+ cls != cl .getItem ( j )
316
+ }
317
+
318
+ private predicate legalMergeCandidate ( ClassObjectInternal cls , int n ) {
319
319
cls = this .getAHead ( ) and n = this .length ( )
320
320
or
321
- this .getItem ( n ) .legalMergeHead ( cls ) and
322
- this .legalMergeCandidate ( cls , n + 1 )
321
+ this .legalMergeCandidate ( cls , n + 1 ) and
322
+ this .getItem ( n ) = Empty ( )
323
+ or
324
+ legalMergeCandidateNonEmpty ( cls , n , _, 1 )
323
325
}
324
326
325
327
predicate legalMergeCandidate ( ClassObjectInternal cls ) { this .legalMergeCandidate ( cls , 0 ) }
326
328
327
329
predicate illegalMergeCandidate ( ClassObjectInternal cls ) {
328
- cls = this .getAHead ( ) and
329
- this .getItem ( _) .getTail ( ) .contains ( cls )
330
+ exists ( ClassList cl , int j |
331
+ legalMergeCandidateNonEmpty ( cls , _, cl , j + 1 ) and
332
+ j >= 1 and
333
+ cls = cl .getItem ( j )
334
+ )
330
335
}
331
336
332
337
ClassObjectInternal bestMergeCandidate ( int n ) {
@@ -417,14 +422,25 @@ private predicate merge_step(
417
422
remaining_list = original
418
423
or
419
424
/* Removes the best merge candidate from `remaining_list` and prepends it to `reversed_mro` */
420
- exists ( ClassObjectInternal head , ClassList prev_reverse_mro , ClassListList prev_list |
425
+ exists ( ClassObjectInternal head , ClassList prev_reverse_mro |
426
+ merge_stepCons ( head , prev_reverse_mro , remaining_list , original ) and
427
+ reversed_mro = Cons ( head , prev_reverse_mro )
428
+ )
429
+ or
430
+ merge_step ( reversed_mro , ConsList ( Empty ( ) , remaining_list ) , original )
431
+ }
432
+
433
+ pragma [ nomagic]
434
+ private predicate merge_stepCons (
435
+ ClassObjectInternal head , ClassList prev_reverse_mro , ClassListList remaining_list ,
436
+ ClassListList original
437
+ ) {
438
+ /* Removes the best merge candidate from `remaining_list` and prepends it to `reversed_mro` */
439
+ exists ( ClassListList prev_list |
421
440
merge_step ( prev_reverse_mro , prev_list , original ) and
422
441
head = prev_list .bestMergeCandidate ( ) and
423
- reversed_mro = Cons ( head , prev_reverse_mro ) and
424
442
remaining_list = prev_list .remove ( head )
425
443
)
426
- or
427
- merge_step ( reversed_mro , ConsList ( Empty ( ) , remaining_list ) , original )
428
444
}
429
445
430
446
/* Helpers for `ClassList.reverse()` */
@@ -439,10 +455,17 @@ private predicate reverse_step(ClassList lst, ClassList remainder, ClassList rev
439
455
or
440
456
exists ( ClassObjectInternal head , ClassList tail |
441
457
reversed = Cons ( head , tail ) and
442
- reverse_step ( lst , Cons ( head , remainder ) , tail )
458
+ reverse_stepCons ( lst , remainder , head , tail )
443
459
)
444
460
}
445
461
462
+ pragma [ nomagic]
463
+ private predicate reverse_stepCons (
464
+ ClassList lst , ClassList remainder , ClassObjectInternal head , ClassList tail
465
+ ) {
466
+ reverse_step ( lst , Cons ( head , remainder ) , tail )
467
+ }
468
+
446
469
module Mro {
447
470
cached
448
471
ClassList newStyleMro ( ClassObjectInternal cls ) {
0 commit comments