Exemple #1
0
    def get_method_call(self, receiver: PythonType, func_name: str,
                        args: List[Expr], arg_types: List[PythonType],
                        targets: List['silver.ast.LocalVarRef'], node: ast.AST,
                        ctx: Context) -> List[Stmt]:
        """
        Creates a method call to the method called func_name, with the given
        receiver and arguments. Boxes arguments if necessary. When the receiver
        is of union type, a method call is created for each type in the union
        with its respective guard.
        """
        position = self.to_position(node, ctx)
        info = self.no_info(ctx)
        if receiver and type(receiver) is UnionType:
            guarded_methods = []
            for cls in toposort_classes(receiver.get_types() - {None}):

                # Create guard checking if receiver is an instance of this class
                guard = self.type_check(args[0], cls, position, ctx)

                # Translate the method call on this particular receiver's class
                method = self._get_method_call(cls, func_name,
                                               list(args), arg_types,
                                               list(targets), node, ctx)

                # Translated method call into a block
                block = self.translate_block(method, position, info)

                # Stores guard and translated method call as tuple in a list
                guarded_methods.append((guard, block))

            # Chain list of guard and function call tuples in an if-then-else
            # statement
            return [
                chain_if_stmts(guarded_methods, self.viper, position, info,
                               ctx)
            ]
        else:
            # Pass-through
            return self._get_method_call(receiver, func_name, args, arg_types,
                                         targets, node, ctx)
Exemple #2
0
    def get_function_call(self,
                          receiver: PythonType,
                          func_name: str,
                          args: List[Expr],
                          arg_types: List[PythonType],
                          node: ast.AST,
                          ctx: Context,
                          position: Position = None) -> FuncApp:
        """
        Creates a function application of the function called func_name, with
        the given receiver and arguments. Boxes arguments if necessary, and
        unboxed the result if needed as well. When the receiver is of union
        type, a function call application is created for each type in the
        union with its respective guard.
        """
        if receiver and type(receiver) is UnionType:
            position = self.to_position(node,
                                        ctx) if position is None else position
            guarded_functions = []
            for cls in toposort_classes(receiver.get_types() - {None}):

                # Create guard checking if receiver is an instance of this class
                guard = self.type_check(args[0], cls, position, ctx)

                # Translate the function call on this particular receiver's class
                function = self._get_function_call(cls, func_name, args,
                                                   arg_types, node, ctx,
                                                   position)

                # Stores guard and translated function call as tuple in a list
                guarded_functions.append((guard, function))

            # Chain list of guard and function call tuples in an if-then-else
            # expression
            return chain_cond_exp(guarded_functions, self.viper, position,
                                  self.no_info(ctx), ctx)
        else:
            # Pass-through
            return self._get_function_call(receiver, func_name, args,
                                           arg_types, node, ctx, position)
Exemple #3
0
 def translate_contractfunc_call(self,
                                 node: ast.Call,
                                 ctx: Context,
                                 impure=False,
                                 statement=False) -> StmtsAndExpr:
     """
     Translates calls to contract functions like Result() and Acc()
     """
     func_name = get_func_name(node)
     if func_name == 'Result':
         return self.translate_result(node, ctx)
     elif func_name == 'RaisedException':
         return self.translate_raised_exception(node, ctx)
     elif func_name in ('Acc', 'Rd', 'Wildcard'):
         if not impure:
             raise InvalidProgramException(node,
                                           'invalid.contract.position')
         if func_name == 'Rd':
             perm = self.get_arp_for_context(node, ctx)
         elif func_name == 'Wildcard':
             perm = self.viper.WildcardPerm(self.to_position(node, ctx),
                                            self.no_info(ctx))
         else:
             perm = self._get_perm(node, ctx)
         if isinstance(node.args[0], ast.Call):
             return self.translate_acc_predicate(node, perm, ctx)
         else:
             if isinstance(node.args[0], ast.Attribute):
                 type = self.get_type(node.args[0].value, ctx)
                 if isinstance(type, UnionType):
                     guarded_field_access = []
                     stmt, receiver = self.translate_expr(
                         node.args[0].value, ctx)
                     for recv_type in toposort_classes(type.get_types() -
                                                       {None}):
                         target = self.get_target(node.args[0].value, ctx)
                         field_guard = self.var_type_check(
                             target.sil_name, recv_type,
                             self.to_position(node, ctx), ctx)
                         field = recv_type.get_field(
                             node.args[0].attr).actual_field
                         field_access = self.viper.FieldAccess(
                             receiver, field.sil_field,
                             self.to_position(node, ctx), self.no_info(ctx))
                         field_acc = self._translate_acc_field(
                             field_access, field.type, perm,
                             self.to_position(node, ctx), ctx)
                         guarded_field_access.append(
                             (field_guard, field_acc))
                     if len(guarded_field_access) == 1:
                         _, field_acc = guarded_field_access[0]
                         return stmt, field_acc
                     else:
                         return (stmt,
                                 chain_cond_exp(guarded_field_access,
                                                self.viper,
                                                self.to_position(node, ctx),
                                                self.no_info(ctx), ctx))
             target = self.get_target(node.args[0], ctx)
             if isinstance(target, PythonField):
                 return self.translate_acc_field(node, perm, ctx)
             else:
                 if not isinstance(target, PythonGlobalVar):
                     raise InvalidProgramException(node, 'invalid.acc')
                 return self.translate_acc_global(node, perm, ctx)
     elif func_name in BUILTIN_PREDICATES:
         return [], self.translate_unwrapped_builtin_predicate(node, ctx)
     elif func_name == 'MaySet':
         return self.translate_may_set(node, ctx)
     elif func_name == 'MayCreate':
         return self.translate_may_create(node, ctx)
     elif func_name in ('Assert', 'Assume', 'Fold', 'Unfold'):
         if not statement:
             raise InvalidProgramException(node,
                                           'invalid.contract.position')
         if func_name == 'Assert':
             return self.translate_assert(node, ctx)
         elif func_name == 'Assume':
             return self.translate_assume(node, ctx)
         elif func_name == 'Fold':
             return self.translate_fold(node, ctx)
         elif func_name == 'Unfold':
             return self.translate_unfold(node, ctx)
     elif func_name == 'Implies':
         return self.translate_implies(node, ctx, impure)
     elif func_name == 'Old':
         return self.translate_old(node, ctx)
     elif func_name == 'Unfolding':
         return self.translate_unfolding(node, ctx, impure)
     elif func_name == 'Low':
         return self.translate_low(node, ctx)
     elif func_name == 'LowVal':
         return self.translate_lowval(node, ctx)
     elif func_name == 'LowEvent':
         return self.translate_lowevent(node, ctx)
     elif func_name == 'LowExit':
         return self.translate_lowexit(node, ctx)
     elif func_name == 'Declassify':
         return self.translate_declassify(node, ctx)
     elif func_name == 'TerminatesSif':
         return self.translate_terminates_sif(node, ctx)
     elif func_name == 'Forall':
         return self.translate_forall(node, ctx, impure)
     elif func_name == 'Previous':
         return self.translate_previous(node, ctx)
     elif func_name == 'Let':
         return self.translate_let(node, ctx, impure)
     elif func_name == PSEQ_TYPE:
         return self.translate_sequence(node, ctx)
     elif func_name == PSET_TYPE:
         return self.translate_pset(node, ctx)
     elif func_name == PMSET_TYPE:
         return self.translate_mset(node, ctx)
     elif func_name == 'ToSeq':
         return self.translate_to_sequence(node, ctx)
     elif func_name == 'Joinable':
         return self.translate_joinable(node, ctx)
     elif func_name == 'getArg':
         return self.translate_get_arg(node, ctx)
     elif func_name == 'getOld':
         return self.translate_get_old(node, ctx)
     elif func_name == 'getMethod':
         raise InvalidProgramException(node, 'invalid.get.method.use')
     elif func_name == 'arg':
         raise InvalidProgramException(node, 'invalid.arg.use')
     else:
         raise UnsupportedException(node)