@@ -114,39 +114,12 @@ class ClassList extends TClassList {
114114 this = Empty ( ) and result = Empty ( )
115115 }
116116
117- predicate legalMergeHead ( ClassObjectInternal cls ) {
118- this .getTail ( ) .doesNotContain ( cls )
119- or
120- this = Empty ( )
121- }
122-
123117 predicate contains ( ClassObjectInternal cls ) {
124118 cls = this .getHead ( )
125119 or
126120 this .getTail ( ) .contains ( cls )
127121 }
128122
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-
150123 ClassObjectInternal findDeclaringClass ( string name ) {
151124 exists ( ClassDecl head | head = this .getHead ( ) .getClassDeclaration ( ) |
152125 if head .declaresAttribute ( name )
@@ -199,12 +172,18 @@ class ClassList extends TClassList {
199172 or
200173 this .duplicate ( n ) and result = this .deduplicate ( n + 1 )
201174 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 )
205178 )
206179 }
207180
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+
208187 predicate isEmpty ( ) { this = Empty ( ) }
209188
210189 ClassList reverse ( ) { reverse_step ( this , Empty ( ) , result ) }
@@ -299,13 +278,23 @@ private class ClassListList extends TClassListList {
299278 removed_head = this .getItem ( n ) .removeHead ( cls ) and
300279 removed_tail = EmptyList ( )
301280 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 ) {
302286 exists ( ClassList prev_head , ClassListList prev_tail |
303287 this .removedClassParts ( cls , prev_head , prev_tail , n + 1 ) and
304- removed_head = this .getItem ( n ) .removeHead ( cls ) and
305288 removed_tail = ConsList ( prev_head , prev_tail )
306289 )
307290 }
308291
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+
309298 ClassListList remove ( ClassObjectInternal cls ) {
310299 exists ( ClassList removed_head , ClassListList removed_tail |
311300 this .removedClassParts ( cls , removed_head , removed_tail , 0 ) and
@@ -315,18 +304,34 @@ private class ClassListList extends TClassListList {
315304 this = EmptyList ( ) and result = EmptyList ( )
316305 }
317306
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 ) {
319319 cls = this .getAHead ( ) and n = this .length ( )
320320 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 )
323325 }
324326
325327 predicate legalMergeCandidate ( ClassObjectInternal cls ) { this .legalMergeCandidate ( cls , 0 ) }
326328
327329 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+ )
330335 }
331336
332337 ClassObjectInternal bestMergeCandidate ( int n ) {
@@ -417,14 +422,25 @@ private predicate merge_step(
417422 remaining_list = original
418423 or
419424 /* 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 |
421440 merge_step ( prev_reverse_mro , prev_list , original ) and
422441 head = prev_list .bestMergeCandidate ( ) and
423- reversed_mro = Cons ( head , prev_reverse_mro ) and
424442 remaining_list = prev_list .remove ( head )
425443 )
426- or
427- merge_step ( reversed_mro , ConsList ( Empty ( ) , remaining_list ) , original )
428444}
429445
430446/* Helpers for `ClassList.reverse()` */
@@ -439,10 +455,17 @@ private predicate reverse_step(ClassList lst, ClassList remainder, ClassList rev
439455 or
440456 exists ( ClassObjectInternal head , ClassList tail |
441457 reversed = Cons ( head , tail ) and
442- reverse_step ( lst , Cons ( head , remainder ) , tail )
458+ reverse_stepCons ( lst , remainder , head , tail )
443459 )
444460}
445461
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+
446469module Mro {
447470 cached
448471 ClassList newStyleMro ( ClassObjectInternal cls ) {
0 commit comments