@@ -207,29 +207,70 @@ module Stmts {
207207 override FailStmt ast ;
208208 }
209209
210- private class StmtConditionTree extends AstPostOrderTree {
210+ private class StmtConditionTree extends AstPreOrderTree {
211211 override StmtCondition ast ;
212212
213213 final override predicate propagatesAbnormal ( ControlFlowElement child ) {
214- child .asAstNode ( ) = ast .getAnElement ( ) .getUnderlyingCondition ( )
214+ child .asAstNode ( ) = ast .getAnElement ( ) .getInitializer ( ) .getFullyConverted ( )
215+ or
216+ child .asAstNode ( ) = ast .getAnElement ( ) .getPattern ( ) .getFullyUnresolved ( )
217+ or
218+ child .asAstNode ( ) = ast .getAnElement ( ) .getBoolean ( ) .getFullyConverted ( )
215219 }
216220
217- final override predicate first ( ControlFlowElement first ) {
218- astFirst ( ast .getFirstElement ( ) .getUnderlyingCondition ( ) .getFullyUnresolved ( ) , first )
221+ predicate firstElement ( int i , ControlFlowElement first ) {
222+ // If there is an initializer in the first element, evaluate that first
223+ astFirst ( ast .getElement ( i ) .getInitializer ( ) .getFullyConverted ( ) , first )
224+ or
225+ // Otherwise, the first element is a boolean condition.
226+ not exists ( ast .getElement ( i ) .getInitializer ( ) ) and
227+ astFirst ( ast .getElement ( i ) .getBoolean ( ) .getFullyConverted ( ) , first )
219228 }
220229
221- final override predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
222- // Left-to-right evaluation of elements
223- exists ( int i |
224- astLast ( ast .getElement ( i ) .getUnderlyingCondition ( ) .getFullyUnresolved ( ) , pred , c ) and
225- c instanceof NormalCompletion and
226- astFirst ( ast .getElement ( i + 1 ) .getUnderlyingCondition ( ) .getFullyUnresolved ( ) , succ )
227- )
230+ predicate succElement ( int i , ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
231+ // Evaluate the pattern after the initializer
232+ astLast ( ast .getElement ( i ) .getInitializer ( ) .getFullyConverted ( ) , pred , c ) and
233+ c instanceof NormalCompletion and
234+ astFirst ( ast .getElement ( i ) .getPattern ( ) .getFullyUnresolved ( ) , succ )
228235 or
229- // Post-order: flow from thrown expression to the throw statement.
230- astLast ( ast .getLastElement ( ) .getUnderlyingCondition ( ) .getFullyUnresolved ( ) , pred , c ) and
236+ (
237+ // After evaluating the pattern
238+ astLast ( ast .getElement ( i ) .getPattern ( ) .getFullyUnresolved ( ) , pred , c )
239+ or
240+ // ... or the boolean ...
241+ astLast ( ast .getElement ( i ) .getBoolean ( ) .getFullyConverted ( ) , pred , c )
242+ ) and
243+ // We evaluate the next element
231244 c instanceof NormalCompletion and
232- succ .asAstNode ( ) = ast
245+ this .firstElement ( i + 1 , succ )
246+ }
247+
248+ final override predicate last ( ControlFlowElement last , Completion c ) {
249+ // Stop if a boolean check failed
250+ astLast ( ast .getAnElement ( ) .getBoolean ( ) .getFullyConverted ( ) , last , c ) and
251+ c instanceof FalseCompletion
252+ or
253+ // Stop is a pattern match failed
254+ astLast ( ast .getAnElement ( ) .getPattern ( ) .getFullyUnresolved ( ) , last , c ) and
255+ not c .( MatchingCompletion ) .isMatch ( )
256+ or
257+ // Stop if we sucesfully evaluated all the conditionals
258+ (
259+ astLast ( ast .getLastElement ( ) .getBoolean ( ) .getFullyConverted ( ) , last , c )
260+ or
261+ astLast ( ast .getLastElement ( ) .getPattern ( ) .getFullyUnresolved ( ) , last , c )
262+ ) and
263+ c instanceof NormalCompletion
264+ }
265+
266+ final override predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
267+ // Pre-order: Flow from this ast node to the first condition
268+ pred .asAstNode ( ) = ast and
269+ c instanceof SimpleCompletion and
270+ this .firstElement ( 0 , succ )
271+ or
272+ // Left-to-right evaluation of elements
273+ succElement ( _, pred , succ , c )
233274 }
234275 }
235276
@@ -245,7 +286,7 @@ module Stmts {
245286 final override predicate last ( ControlFlowElement last , Completion c ) {
246287 // Condition exits with a false completion and there is no `else` branch
247288 astLast ( ast .getCondition ( ) .getFullyUnresolved ( ) , last , c ) and
248- c instanceof FalseCompletion and
289+ c instanceof FalseOrNonMatchCompletion and
249290 not exists ( ast .getElse ( ) )
250291 or
251292 // Then/Else branch exits with any completion
@@ -261,10 +302,12 @@ module Stmts {
261302 astLast ( ast .getCondition ( ) .getFullyUnresolved ( ) , pred , c ) and
262303 (
263304 // Flow from last element of condition to first element of then branch
264- c instanceof TrueCompletion and astFirst ( ast .getThen ( ) , succ )
305+ c instanceof TrueOrMatchCompletion and
306+ astFirst ( ast .getThen ( ) , succ )
265307 or
266308 // Flow from last element of condition to first element of else branch
267- c instanceof FalseCompletion and astFirst ( ast .getElse ( ) , succ )
309+ c instanceof FalseOrNonMatchCompletion and
310+ astFirst ( ast .getElse ( ) , succ )
268311 )
269312 }
270313 }
@@ -284,7 +327,7 @@ module Stmts {
284327 or
285328 // Exit when a condition is true
286329 astLast ( ast .getCondition ( ) .getFullyUnresolved ( ) , last , c ) and
287- c instanceof TrueCompletion
330+ c instanceof TrueOrMatchCompletion
288331 }
289332
290333 final override predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
@@ -295,7 +338,7 @@ module Stmts {
295338 or
296339 // Flow to the body when the condition is false
297340 astLast ( ast .getCondition ( ) .getFullyUnresolved ( ) , pred , c ) and
298- c instanceof FalseCompletion and
341+ c instanceof FalseOrNonMatchCompletion and
299342 astFirst ( ast .getBody ( ) , succ )
300343 }
301344 }
@@ -322,7 +365,7 @@ module Stmts {
322365 final override predicate last ( ControlFlowElement last , Completion c ) {
323366 // Condition exits with a false completion
324367 last ( this .getCondition ( ) , last , c ) and
325- c instanceof FalseCompletion
368+ c instanceof FalseOrNonMatchCompletion
326369 or
327370 // Body exits with a break completion
328371 exists ( BreakCompletion break |
@@ -339,7 +382,7 @@ module Stmts {
339382
340383 override predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
341384 last ( this .getCondition ( ) , pred , c ) and
342- c instanceof TrueCompletion and
385+ c instanceof TrueOrMatchCompletion and
343386 first ( this .getBody ( ) , succ )
344387 or
345388 last ( this .getBody ( ) , pred , c ) and
@@ -484,9 +527,8 @@ module Stmts {
484527 astLast ( ast .getExpr ( ) .getFullyConverted ( ) , last , c ) and
485528 c instanceof NormalCompletion
486529 or
487- // A statement exits (TODO: with a `break` completion?)
488- astLast ( ast .getACase ( ) .getBody ( ) , last , c ) and
489- c instanceof NormalCompletion
530+ // A statement exits
531+ astLast ( ast .getACase ( ) .getBody ( ) , last , c )
490532 // Note: There's no need for an exit with a non-match as
491533 // Swift's switch statements are always exhaustive.
492534 }
@@ -849,7 +891,7 @@ module Patterns {
849891 or
850892 // Or we got to the some/none check and it failed
851893 n .asAstNode ( ) = ast and
852- not c .( MatchingCompletion ) .isMatch ( )
894+ c .( MatchingCompletion ) .isNonMatch ( )
853895 }
854896
855897 override predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
0 commit comments