def _translate_waitlevel_method( self, expr: sil.PermExpression, node: ast.Compare, ctx: Context) -> sil.BoolExpression: """Translate ``WaitLevel() < Level()`` in method contract.""" position = self.to_position(node, ctx) info = self.no_info(ctx) obligation_info = ctx.actual_function.obligation_info guard = obligation_info.get_wait_level_guard(node.left) exhale = self._create_level_below_inex( guard, expr, obligation_info.residue_level, ctx) translated_exhale = exhale.translate(self, ctx, position, info) if ctx.ignore_waitlevel_constraints: return sil.TrueLit() if ctx.obligation_context.is_translating_posts: obligation_info.add_postcondition(translated_exhale) caller_inhale = sil.InhaleExhale( sil.PermVar(obligation_info.current_wait_level) < expr, sil.TrueLit()) return caller_inhale else: obligation_info.add_precondition(translated_exhale) body_inhale = sil.InhaleExhale( sil.PermVar(obligation_info.residue_level) < expr, sil.TrueLit()) return body_inhale
def _create_level_below_inex(self, guard: sil.BoolExpression, expr: sil.PermExpression, level: PythonVar, ctx: Context) -> sil.BoolExpression: return sil.InhaleExhale( sil.TrueLit(), sil.Implies(guard, self.create_level_below(expr, sil.PermVar(level), ctx)))
def initialize_current_wait_level(self, current_wait_level: sil.PermExpression, residue_level_var: sil.PermExpression, ctx: Context) -> sil.BoolExpression: return sil.InhaleExhale( self._create_level_below_equal(current_wait_level, residue_level_var, ctx), sil.TrueLit())
def construct_use_method_unbounded(self) -> sil.BoolExpression: """Construct inhale exhale pair for use in method contract. Used for fresh obligations. """ if self._credit_only: exhale = self._credit_acc else: exhale = self._construct_unbounded_exhale() return sil.InhaleExhale(self._construct_inhale(True), exhale)
def _add_leak_check(self) -> None: """Add leak checks to invariant.""" reference_name = self._ctx.actual_function.get_fresh_name('_r') leak_check = self._obligation_manager.create_leak_check(reference_name) loop_check_before = sil.BoolVar( self._loop_obligation_info.loop_check_before_var) termination_flag = sil.BoolVar( self._loop_obligation_info.termination_flag_var) if not obligation_config.disable_loop_context_leak_check: must_terminate = self._obligation_manager.must_terminate_obligation predicate = must_terminate.create_predicate_access( self._obligation_info.current_thread_var) termination_leak_check = sil.CurrentPerm(predicate) == sil.NoPerm() loop_cond = self._loop_obligation_info.construct_loop_condition() before_loop_leak_check = sil.InhaleExhale( sil.TrueLit(), sil.Implies( loop_check_before, sil.BigOr([ termination_flag, sil.Not(loop_cond), sil.BigAnd([termination_leak_check, leak_check]) ]))) info = self._to_info('Leak check for context.') position = self._to_position( conversion_rules=rules.OBLIGATION_LOOP_CONTEXT_LEAK_CHECK_FAIL) self._obligation_loop.append_invariants([ before_loop_leak_check.translate(self._translator, self._ctx, position, info) ]) if not obligation_config.disable_loop_body_leak_check: body_leak_check = sil.InhaleExhale( sil.TrueLit(), sil.Implies(sil.Not(loop_check_before), leak_check)) info = self._to_info('Leak check for loop body.') position = self._to_position( conversion_rules=rules.OBLIGATION_LOOP_BODY_LEAK_CHECK_FAIL) self._obligation_loop.append_invariants([ body_leak_check.translate(self._translator, self._ctx, position, info) ])
def construct_use_method_bounded( self, measure_check: sil.BoolExpression, is_postconditon: bool) -> sil.BoolExpression: """Construct inhale exhale pair for use in method contract. Used for bounded obligations. """ if self._skip_exhale: exhale = sil.TrueLit() elif self._credit_only: exhale = self._credit_acc else: exhale = self._construct_bounded_exhale( measure_check if not is_postconditon else None) return sil.InhaleExhale(self._construct_inhale(False), exhale)
def construct_use_loop( self, measure_check: Optional[sil.BoolExpression], loop_check_before_var: sil.BoolVar) -> sil.BoolExpression: """Construct inhale exhale pair for use in loop invariant. ``measure_check is None`` indicates that obligation is fresh. """ if self._skip_exhale: exhale = sil.TrueLit() elif self._credit_only: exhale = self._credit_acc elif measure_check is None: exhale = self._construct_unbounded_exhale() else: exhale = sil.BoolCondExp( loop_check_before_var, self._construct_bounded_exhale(None), self._construct_bounded_exhale(measure_check)) inhale = self._construct_inhale(measure_check is None) return sil.InhaleExhale(inhale, exhale)
def _add_body_leak_check(self) -> None: """Add a leak check. Check that method body does not leak obligations. """ if obligation_config.disable_method_body_leak_check: return reference_name = self._python_method.get_fresh_name('_r') check = sil.InhaleExhale( sil.TrueLit(), self._obligation_manager.create_leak_check(reference_name)) node = self._python_method.node assert node position = self._translator.to_position( node, self._ctx, rules=rules.OBLIGATION_BODY_LEAK_CHECK_FAIL) info = self._translator.to_info(["Body leak check."], self._ctx) postcondition = check.translate(self._translator, self._ctx, position, info) self._obligation_method.append_postconditions([postcondition])
def _add_caller_leak_check(self) -> None: """Add a leak check. Check that if callee is not terminating, caller has no obligations. """ if obligation_config.disable_call_context_leak_check: return # MustTerminate leak check. must_terminate = self._obligation_manager.must_terminate_obligation cthread = self._obligation_info.current_thread_var predicate = must_terminate.create_predicate_access(cthread) termination_leak_check = sil.CurrentPerm(predicate) == sil.NoPerm() # Other obligations leak check. reference_name = self._python_method.get_fresh_name('_r') leak_check = self._obligation_manager.create_leak_check(reference_name) if self._python_method.interface: if must_terminate.is_interface_method_terminating( self._python_method.interface_dict): exhale = self._obligation_info.caller_measure_map.check( sil.RefVar(self._obligation_info.current_thread_var), sil.RawIntExpression(1)) else: exhale = sil.BigAnd([termination_leak_check, leak_check]) else: # Termination condition. tcond = self._obligation_info.create_termination_check(False) # Combination. exhale = sil.BigOr( [tcond, sil.BigAnd([termination_leak_check, leak_check])]) check = sil.InhaleExhale(sil.TrueLit(), exhale) # Translate to Silver. node = self.get_function_node() position = self._translator.to_position( node, self._ctx, rules=rules.OBLIGATION_CALL_LEAK_CHECK_FAIL) info = self._translator.to_info(["Caller side leak check"], self._ctx) precondition = check.translate(self._translator, self._ctx, position, info) self._obligation_method.append_preconditions([precondition])