def while_loop(ast, i, o): '''Reachability for a while loop. L: while (true) S In[S] = In[L] Out[L] = No L: while (false) S In[S] = No Out[L] = In[L] L: while (E) S In[S] = In[L] Out[L] = In[L]''' # Make sure that the while expression is a Boolean. if ast.expression.expr_type != ast_type.ASTType.ASTBoolean: raise reachability.ReachabilityError('While expression is not a boolean.') # The first two cases, where the expression has been resolved to True or # False. if ast.expression.const_value is not None: if ast.expression.const_value: # Though it doesn't affect our return value, check the children # statements for reachability. if ast.statement: reachability.check_block_or_statement(ast.statement, in_value=o) return o, NO else: # This while loop is unreachable. return NO, o # The last case, where our expression is not a constant. if ast.statement is not None: reachability.check_block_or_statement(ast.statement, in_value=o) return o, o
def if_statement(ast, i, o): '''Reachability for an IF statement. L: if (E) S_1 else S_2 In[S_1] = In[L] In[S_2] = In[L] Out[L] = Out[S_1] or Out[S_2]''' if ast.if_statement is not None: if_in, if_out = reachability.check_block_or_statement( ast.if_statement, in_value=o) if ast.else_statement is not None: else_in, else_out = reachability.check_block_or_statement( ast.else_statement, in_value=o) # The out value is the OR between the if and else out values. new_out = (MAYBE if if_out == MAYBE or else_out == MAYBE else NO) return o, new_out # If statement with no else: # Out[L] = Out[S_1] OR In[L] = In[L] = o return o, o
def for_loop(ast, i, o): '''Reachability for a for loop. L: for (S_1; false; S_2) S_3 In[S] = No Out[L] = In[L] L: for (S_1; true; S_2) S_3 In[S] = In[L] Out[L] = No L: for (S_1; E; S_2) S_3 In[S] = In[L] Out[L] = In[L]''' has_expr = (ast.expression is not None) # Make sure the for expression is a Boolean if it exists. if has_expr and ast.expression.expr_type != ast_type.ASTType.ASTBoolean: raise reachability.ReachabilityError('For expression is not a boolean.') # The first two cases, where the condition expression is a constant. if has_expr and ast.expression.const_value is not None: if ast.expression.const_value: # Check all children statements for reachability. if ast.init: reachability.check_block_or_statement(ast.init, in_value=o) if ast.update: reachability.check_block_or_statement(ast.update, in_value=o) if ast.statement: reachability.check_block_or_statement(ast.statement, in_value=o) return o, NO else: # The for loop is unreachable. return NO, o # Our expression is not a constant. # Check all children statements for reachability. if ast.init: reachability.check_block_or_statement(ast.init, in_value=o) if ast.update: reachability.check_block_or_statement(ast.update, in_value=o) if ast.statement: reachability.check_block_or_statement(ast.statement, in_value=o) # If there is no expression, the for loop runs forever. if not has_expr: return o, NO return o, o