@@ -277,45 +277,82 @@ class LetStmtTree extends PreOrderTree instanceof LetStmt {
277
277
278
278
class LiteralExprTree extends LeafTree instanceof LiteralExpr { }
279
279
280
- class LoopExprTree extends PostOrderTree instanceof LoopExpr {
280
+ abstract class LoopingExprTree extends PostOrderTree {
281
281
override predicate propagatesAbnormal ( AstNode child ) { none ( ) }
282
282
283
- override predicate first ( AstNode node ) { first ( super . getLoopBody ( ) , node ) }
283
+ abstract BlockExpr getLoopBody ( ) ;
284
284
285
- /** Whether this `LoopExpr` captures the `c` completion. */
286
- private predicate capturesLoopJumpCompletion ( LoopJumpCompletion c ) {
285
+ abstract Label getLabel ( ) ;
286
+
287
+ /** Whether this loop captures the `c` completion. */
288
+ predicate capturesLoopJumpCompletion ( LoopJumpCompletion c ) {
287
289
not c .hasLabel ( )
288
290
or
289
- c .getLabelName ( ) = super .getLabel ( ) .getLifetime ( ) .getText ( )
291
+ c .getLabelName ( ) = this .getLabel ( ) .getLifetime ( ) .getText ( )
290
292
}
291
293
292
294
override predicate succ ( AstNode pred , AstNode succ , Completion c ) {
295
+ // Edge for exiting the loop with a break expressions
296
+ last ( this .getLoopBody ( ) , pred , c ) and
297
+ c .( LoopJumpCompletion ) .isBreak ( ) and
298
+ this .capturesLoopJumpCompletion ( c ) and
299
+ succ = this
300
+ or
293
301
// Edge back to the start for final expression and continue expressions
294
- last ( super .getLoopBody ( ) , pred , c ) and
302
+ last ( this .getLoopBody ( ) , pred , c ) and
295
303
(
296
304
completionIsNormal ( c )
297
305
or
298
306
c .( LoopJumpCompletion ) .isContinue ( ) and this .capturesLoopJumpCompletion ( c )
299
307
) and
300
308
this .first ( succ )
301
- or
302
- // Edge for exiting the loop with a break expressions
303
- last ( super .getLoopBody ( ) , pred , c ) and
304
- c .( LoopJumpCompletion ) .isBreak ( ) and
305
- this .capturesLoopJumpCompletion ( c ) and
306
- succ = this
307
309
}
308
310
309
311
override predicate last ( AstNode last , Completion c ) {
310
312
super .last ( last , c )
311
313
or
312
314
// Any abnormal completions that this loop does not capture should propagate
313
- last ( super .getLoopBody ( ) , last , c ) and
315
+ last ( this .getLoopBody ( ) , last , c ) and
314
316
not completionIsNormal ( c ) and
315
317
not this .capturesLoopJumpCompletion ( c )
316
318
}
317
319
}
318
320
321
+ class LoopExprTree extends LoopingExprTree instanceof LoopExpr {
322
+ override BlockExpr getLoopBody ( ) { result = LoopExpr .super .getLoopBody ( ) }
323
+
324
+ override Label getLabel ( ) { result = LoopExpr .super .getLabel ( ) }
325
+
326
+ override predicate first ( AstNode node ) { first ( this .getLoopBody ( ) , node ) }
327
+ }
328
+
329
+ class WhileExprTree extends LoopingExprTree instanceof WhileExpr {
330
+ override BlockExpr getLoopBody ( ) { result = WhileExpr .super .getLoopBody ( ) }
331
+
332
+ override Label getLabel ( ) { result = WhileExpr .super .getLabel ( ) }
333
+
334
+ override predicate first ( AstNode node ) { first ( super .getCondition ( ) , node ) }
335
+
336
+ override predicate succ ( AstNode pred , AstNode succ , Completion c ) {
337
+ super .succ ( pred , succ , c )
338
+ or
339
+ last ( super .getCondition ( ) , pred , c ) and
340
+ c .( BooleanCompletion ) .succeeded ( ) and
341
+ first ( this .getLoopBody ( ) , succ )
342
+ or
343
+ last ( super .getCondition ( ) , pred , c ) and
344
+ c .( BooleanCompletion ) .failed ( ) and
345
+ succ = this
346
+ }
347
+
348
+ override predicate last ( AstNode last , Completion c ) {
349
+ super .last ( last , c )
350
+ or
351
+ last ( super .getCondition ( ) , last , c ) and
352
+ not completionIsNormal ( c )
353
+ }
354
+ }
355
+
319
356
class MatchArmTree extends ControlFlowTree instanceof MatchArm {
320
357
override predicate propagatesAbnormal ( AstNode child ) { child = super .getExpr ( ) }
321
358
0 commit comments