コード例 #1
0
 def translate_unfold(self, node: ast.Call, ctx: Context) -> StmtsAndExpr:
     """
     Translates a call to the Unfold() contract function.
     """
     if len(node.args) != 1:
         raise InvalidProgramException(node, 'invalid.contract.call')
     if not isinstance(node.args[0], ast.Call):
         raise InvalidProgramException(node, 'invalid.contract.call')
     if get_func_name(node.args[0]) in ('Acc', 'Rd'):
         pred_call = node.args[0].args[0]
     else:
         pred_call = node.args[0]
     target_pred = self.get_target(pred_call, ctx)
     if (target_pred and (not isinstance(target_pred, PythonMethod)
                          or not target_pred.predicate)):
         raise InvalidProgramException(node, 'invalid.contract.call')
     pred_stmt, pred = self.translate_expr(node.args[0], ctx,
                                           self.viper.Bool, True)
     if self._is_family_fold(node):
         # Predicate called on receiver, so it belongs to a family
         if ctx.ignore_family_folds:
             return [], None
     if pred_stmt:
         raise InvalidProgramException(node, 'purity.violated')
     unfold = self.viper.Unfold(pred, self.to_position(node, ctx),
                                self.no_info(ctx))
     return [unfold], None
コード例 #2
0
    def translate_unfolding(self,
                            node: ast.Call,
                            ctx: Context,
                            impure=False) -> StmtsAndExpr:
        """
        Translates a call to the Unfolding() contract function.
        """
        if len(node.args) != 2:
            raise InvalidProgramException(node, 'invalid.contract.call')
        if not isinstance(node.args[0], ast.Call):
            raise InvalidProgramException(node, 'invalid.contract.call')
        if get_func_name(node.args[0]) in ('Acc', 'Rd'):
            pred_call = node.args[0].args[0]
        else:
            pred_call = node.args[0]
        target_pred = self.get_target(pred_call, ctx)
        if (target_pred and (not isinstance(target_pred, PythonMethod)
                             or not target_pred.predicate)):
            raise InvalidProgramException(node, 'invalid.contract.call')

        pred_stmt, pred = self.translate_expr(node.args[0], ctx,
                                              self.viper.Bool, True)
        if pred_stmt:
            raise InvalidProgramException(node, 'purity.violated')
        expr_stmt, expr = self.translate_expr(node.args[1], ctx)
        if expr_stmt:
            raise InvalidProgramException(node, 'purity.violated')
        expr = self.unwrap(expr)
        unfold = self.viper.Unfolding(pred, expr, self.to_position(node, ctx),
                                      self.no_info(ctx))
        return expr_stmt, unfold
コード例 #3
0
    def translate_acc_global(self, node: ast.Call, perm: Expr,
                             ctx: Context) -> StmtsAndExpr:
        """
        Translates an access permission to a global variable.
        """
        var = self.get_target(node.args[0], ctx)
        if not isinstance(var, PythonGlobalVar):
            raise InvalidProgramException(node, 'invalid.acc')
        if var.is_final:
            raise InvalidProgramException(node, 'permission.to.final.var')
        pos = self.to_position(node, ctx)
        info = self.no_info(ctx)
        var_func = self.viper.FuncApp(var.sil_name, [], pos, info,
                                      self.viper.Ref, [])
        var_type = self.translate_type(var.type, ctx)
        field = self.viper.Field(GLOBAL_VAR_FIELD, var_type, pos, info)
        field_acc = self.viper.FieldAccess(var_func, field, pos, info)
        pred = self.viper.FieldAccessPredicate(field_acc, perm, pos, info)

        # Add type information
        if var.type.name not in PRIMITIVES:
            type_info = self.type_check(field_acc, var.type,
                                        self.no_position(ctx), ctx)
            pred = self.viper.And(pred, type_info, pos, info)
        return [], pred
コード例 #4
0
 def translate_may_set(self, node: ast.Call, ctx: Context) -> StmtsAndExpr:
     """
     Translates a call to MaySet().
     """
     pos = self.to_position(node, ctx)
     info = self.no_info(ctx)
     stmt, rec = self.translate_expr(node.args[0], ctx)
     rec_type = self.get_type(node.args[0], ctx)
     if stmt:
         raise InvalidProgramException(node.args[0], 'purity.violated')
     if not isinstance(node.args[1], ast.Str):
         raise InvalidProgramException(node.args[1], 'invalid.may.set')
     field = rec_type.get_field(node.args[1].s)
     if not field:
         raise InvalidProgramException(node.args[1], 'invalid.may.set')
     may_set_pred = self.get_may_set_predicate(rec, field, ctx, pos)
     sil_field = self.viper.Field(field.sil_name,
                                  self.translate_type(field.type, ctx), pos,
                                  info)
     field_acc = self.viper.FieldAccess(rec, sil_field, pos, info)
     full_perm = self.viper.FullPerm(pos, info)
     normal_acc = self._translate_acc_field(field_acc, field.type,
                                            full_perm, pos, ctx)
     normal_perm = self.viper.CurrentPerm(field_acc, pos, info)
     have_normal_perm = self.viper.PermGtCmp(normal_perm,
                                             self.viper.NoPerm(pos, info),
                                             pos, info)
     result_ex = self.viper.CondExp(have_normal_perm, normal_acc,
                                    may_set_pred, pos, info)
     unknown = self.get_unknown_bool(ctx)
     result_in = self.viper.CondExp(unknown, normal_acc, may_set_pred, pos,
                                    info)
     return [], self.viper.InhaleExhaleExp(result_in, result_ex, pos, info)
コード例 #5
0
 def translate_acc_field(self, node: ast.Call, perm: Expr,
                         ctx: Context) -> StmtsAndExpr:
     assert isinstance(node.args[0], ast.Attribute)
     field = self.get_target(node.args[0], ctx)
     if not isinstance(field, PythonField):
         raise InvalidProgramException(node, 'invalid.acc')
     stmt, field_acc = self.translate_expr(node.args[0], ctx)
     if stmt:
         raise InvalidProgramException(node, 'purity.violated')
     field_type = self.get_type(node.args[0], ctx)
     pred = self._translate_acc_field(field_acc, field_type, perm,
                                      self.to_position(node, ctx), ctx)
     return [], pred
コード例 #6
0
ファイル: method.py プロジェクト: zeta1999/nagini
    def translate_function(self, func: PythonMethod,
                           ctx: Context) -> 'silver.ast.Function':
        """
        Translates a pure Python function (may or not belong to a class) to a
        Viper function
        """
        old_function = ctx.current_function
        ctx.current_function = func
        self.bind_type_vars(func, ctx)
        pos = self.to_position(func.node, ctx)
        if not func.type:
            raise InvalidProgramException(func.node, 'function.type.none')
        type = self.translate_type(func.type, ctx)
        args = self._translate_params(func, ctx)
        if func.declared_exceptions:
            raise InvalidProgramException(func.node,
                                          'function.throws.exception')
        # Create preconditions
        pres = self._translate_pres(func, ctx)
        # Create postconditions
        posts = []
        for post, aliases in func.postcondition:
            with ctx.additional_aliases(aliases):
                stmt, expr = self.translate_expr(post, ctx, self.viper.Bool)
            if stmt:
                raise InvalidProgramException(post, 'purity.violated')
            posts.append(expr)
        # Create typeof preconditions
        pres = self._create_typeof_pres(func, False, ctx) + pres
        if func.type.name not in PRIMITIVES:
            res_type_pos = self.to_position(func.node, ctx,
                                            '"return type is correct"')
            res_type = self.translate_type(func.type, ctx)
            result = self.viper.Result(res_type, res_type_pos, self.no_info(ctx))
            check = self.type_check(result, func.type, res_type_pos, ctx)
            posts = [check] + posts

        statements = func.node.body
        start, end = get_body_indices(statements)
        # Translate body
        actual_body = statements[start:end]
        if (func.contract_only or
                (len(actual_body) == 1 and isinstance(actual_body[0], ast.Expr) and
                 isinstance(actual_body[0].value, ast.Ellipsis))):
            body = None
        else:
            body = self.translate_exprs(actual_body, func, ctx)
        ctx.current_function = old_function
        name = func.sil_name
        return self.viper.Function(name, args, type, pres, posts, body,
                                   pos, self.no_info(ctx))
コード例 #7
0
 def translate_obligation_contractfunc_call(self, node: ast.Call,
                                            ctx: Context) -> StmtsAndExpr:
     """Translate a call to obligation contract function."""
     func_name = get_func_name(node)
     if func_name == 'MustTerminate':
         return self._translate_must_terminate(node, ctx)
     elif func_name == 'MustRelease':
         return self._translate_must_release(node, ctx)
     elif func_name == 'WaitLevel':
         raise InvalidProgramException(node, 'invalid.wait_level.use')
     elif func_name == 'Level':
         raise InvalidProgramException(node, 'invalid.level.use')
     else:
         raise UnsupportedException(node, 'Unsupported contract function.')
コード例 #8
0
ファイル: common.py プロジェクト: marcoeilers/nagini
 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. This method only
     handles receivers of non-union types.
     """
     if receiver:
         target_cls = receiver
         func = target_cls.get_method(func_name)
     else:
         func = ctx.module.methods[func_name]
     if not func:
         raise InvalidProgramException(node, 'unknown.method.called')
     actual_args = []
     for arg, param, _ in zip(args, func.get_args(), arg_types):
         if param.type.name == PRIMITIVE_BOOL_TYPE:
             actual_arg = self.to_bool(arg, ctx)
         elif param.type.name == '__prim__int':
             actual_arg = self.to_int(arg, ctx)
         else:
             actual_arg = self.to_ref(arg, ctx)
         actual_args.append(actual_arg)
     sil_name = func.sil_name
     call = self.create_method_call_node(
         ctx, sil_name, actual_args, targets, self.to_position(node, ctx),
         self.no_info(ctx), target_method=func, target_node=node)
     return call
コード例 #9
0
 def translate_may_create(self, node: ast.Call,
                          ctx: Context) -> StmtsAndExpr:
     """
     Translates a call to MayCreate().
     """
     pos = self.to_position(node, ctx)
     stmt, rec = self.translate_expr(node.args[0], ctx)
     rec_type = self.get_type(node.args[0], ctx)
     if stmt:
         raise InvalidProgramException(node.args[0], 'purity.violated')
     if not isinstance(node.args[1], ast.Str):
         raise InvalidProgramException(node.args[1], 'invalid.may.create')
     field = rec_type.get_field(node.args[1].s)
     if not field:
         raise InvalidProgramException(node.args[1], 'invalid.may.create')
     return [], self.get_may_set_predicate(rec, field, ctx, pos)
コード例 #10
0
ファイル: method.py プロジェクト: zeta1999/nagini
    def _translate_pres(self, method: PythonMethod,
                        ctx: Context) -> List[Expr]:
        """
        Translates the preconditions specified for 'method'.
        """
        pres = []
        for pre, aliases in method.precondition:
            with ctx.additional_aliases(aliases):
                stmt, expr = self.translate_expr(pre, ctx, self.viper.Bool, True)
            if stmt:
                raise InvalidProgramException(pre, 'purity.violated')
            pres.append(expr)

        if method.cls and method.method_type is MethodType.normal:
            error_string = '"call receiver is not None"'
            pos = self.to_position(method.node, ctx, error_string)
            not_null = self.viper.NeCmp(next(iter(method.args.values())).ref(),
                                        self.viper.NullLit(
                                            self.no_position(ctx),
                                            self.no_info(ctx)),
                                        pos,
                                        self.no_info(ctx))
            pres = [not_null] + pres

        return pres
コード例 #11
0
ファイル: method.py プロジェクト: zeta1999/nagini
    def _translate_posts(self, method: PythonMethod,
                         err_var: 'viper.ast.LocalVar',
                         ctx: Context) -> List[Expr]:
        """
        Translates the postconditions specified for 'method'.
        """
        ctx.obligation_context.is_translating_posts = True
        posts = []
        no_error = self.viper.EqCmp(err_var,
                                    self.viper.NullLit(self.no_position(ctx),
                                                       self.no_info(ctx)),
                                    self.no_position(ctx), self.no_info(ctx))
        for post, aliases in method.postcondition:
            with ctx.additional_aliases(aliases):
                stmt, expr = self.translate_expr(post, ctx, self.viper.Bool, True)
            if stmt:
                raise InvalidProgramException(post, 'purity.violated')
            if method.declared_exceptions:
                expr = self.viper.Implies(no_error, expr,
                                          self.to_position(post, ctx),
                                          self.no_info(ctx))
            posts.append(expr)

        ctx.obligation_context.is_translating_posts = False
        return posts
コード例 #12
0
    def translate_let(self,
                      node: ast.Call,
                      ctx: Context,
                      impure: bool = False) -> StmtsAndExpr:
        type = self.get_target(node.args[1], ctx)
        if not isinstance(type, PythonType) or not isinstance(
                node.args[2], ast.Lambda):
            raise InvalidProgramException(node, 'invalid.let')
        lambda_ = node.args[2]
        lambda_prefix = construct_lambda_prefix(
            lambda_.lineno, getattr(lambda_, 'col_offset', None))
        lambda_prefix += '$'
        arg = lambda_.args.args[0]
        var = ctx.actual_function.get_variable(lambda_prefix + arg.arg)

        exp_stmt, exp_val = self.translate_expr(node.args[0], ctx)

        ctx.set_alias(arg.arg, var, None)

        body_stmt, body_val = self.translate_expr(lambda_.body,
                                                  ctx,
                                                  impure=impure)

        ctx.remove_alias(arg.arg)
        pos = self.to_position(node, ctx)
        info = self.no_info(ctx)
        let = self.viper.Let(var.decl, exp_val, body_val, pos, info)
        return exp_stmt + body_stmt, let
コード例 #13
0
 def _raise_invalid_operation(self, error_type: str, node: ast.AST = None):
     """Raise InvalidProgramException."""
     node = node or self._current_node
     raise InvalidProgramException(
         node,
         'invalid.io_operation.' + error_type,
     )
コード例 #14
0
 def translate_unwrapped_builtin_predicate(self, node: ast.Call,
                                           ctx: Context) -> Expr:
     args = []
     stmt, arg = self.translate_expr(node.args[0], ctx)
     if stmt:
         raise InvalidProgramException(node, 'purity.violated')
     perm = self.viper.FullPerm(self.no_position(ctx), self.no_info(ctx))
     return self.translate_builtin_predicate(node, perm, [arg], ctx)
コード例 #15
0
    def _translate_triggers(self, body: ast.AST, node: ast.Call,
                            ctx: Context) -> List['silver.ast.Trigger']:
        """
        Assuming the given body is a tuple whose second element is a list
        literal containing any number of list literals containing expressions,
        translates those to a list of triggers.
        """
        if (not isinstance(body, ast.Tuple) or len(body.elts) != 2):
            raise InvalidProgramException(node, 'invalid.trigger')
        trigger_node = body.elts[1]
        triggers = []
        if not isinstance(trigger_node, ast.List):
            raise InvalidProgramException(node, 'invalid.trigger')
        outer = trigger_node

        if outer.elts:
            for el in outer.elts:
                trigger = []
                if not isinstance(el, ast.List):
                    raise InvalidProgramException(el, 'invalid.trigger')
                for inner in el.elts:
                    if (isinstance(inner, ast.Compare) and len(inner.ops) == 1
                            and isinstance(inner.ops[0], ast.In)):
                        # Use the less complex and more efficient trigger translation we
                        # also use for the domain of the forall quantifier.
                        assert len(inner.comparators) == 1
                        lhs_stmt, lhs = self.translate_expr(inner.left, ctx)
                        part_stmt, part, valid = self._create_quantifier_contains_expr(
                            lhs, inner.comparators[0], ctx)
                        if part_stmt:
                            raise InvalidProgramException(
                                inner, 'purity.violated')
                        if valid and not part_stmt and not lhs_stmt:
                            trigger.append(part)
                            continue

                    part_stmt, part = self.translate_expr(inner, ctx)
                    if part_stmt:
                        raise InvalidProgramException(inner, 'purity.violated')
                    part = self.unwrap(part)
                    trigger.append(part)
                trigger = self.viper.Trigger(trigger, self.no_position(ctx),
                                             self.no_info(ctx))
                triggers.append(trigger)
        return triggers
コード例 #16
0
ファイル: permission.py プロジェクト: zeta1999/nagini
 def translate_perm_or_int(self, node: ast.AST, ctx: Context):
     if isinstance(node, ast.Num):
         stmt, int_val = self.translate_expr(node, ctx, self.viper.Int)
         if stmt:
             raise InvalidProgramException(node, 'purity.violated')
         return int_val, True
     else:
         int_or_perm_val = self.translate_perm(node, ctx)
         return int_or_perm_val, int_or_perm_val.typ() == self.viper.Int
コード例 #17
0
 def translate_contract_Call(self, node: ast.Call, ctx: Context) -> Expr:
     if get_func_name(node) in CONTRACT_WRAPPER_FUNCS:
         stmt, res = self.translate_expr(node.args[0], ctx, self.viper.Bool,
                                         True)
         if stmt:
             raise InvalidProgramException(node, 'purity.violated')
         return res
     else:
         raise UnsupportedException(node)
コード例 #18
0
 def _translate_must_terminate(self, node: ast.Call,
                               ctx: Context) -> StmtsAndExpr:
     """Translate a call to ``MustTerminate``."""
     if ctx.obligation_context.is_translating_loop():
         return self._loop_translator.translate_must_terminate(node, ctx)
     elif ctx.obligation_context.is_translating_posts:
         raise InvalidProgramException(
             node, 'obligation.must_terminate.in_postcondition')
     else:
         return self._method_translator.translate_must_terminate(node, ctx)
コード例 #19
0
 def translate_terminates_sif(self, node: ast.Call,
                              ctx: Context) -> StmtsAndExpr:
     """
     Translates a call to the TerminatesSif() contract function.
     """
     cond_stmts, cond = self.translate_expr(node.args[0], ctx)
     rank_stmts, rank = self.translate_expr(node.args[1], ctx)
     if cond_stmts or rank_stmts:
         raise InvalidProgramException(node, 'purity.violated')
     return self.translator.obligation_translator._translate_must_terminate(
         node, ctx)
コード例 #20
0
ファイル: permission.py プロジェクト: zeta1999/nagini
    def translate_perm_Call(self, node: ast.Call, ctx: Context) -> Expr:
        func_name = get_func_name(node)
        if func_name == 'ARP':
            if not ctx.arp:
                raise UnsupportedException(
                    node, 'ARP not supported. Use --arp flag.')
            if len(node.args) == 0:
                return self.get_arp_for_context(node, ctx)
            elif len(node.args) == 1:
                arg0_stmt, arg0 = self.translate_expr(node.args[0], ctx,
                                                      self.viper.Int)
                if arg0_stmt:
                    raise InvalidProgramException(node, 'purity.violated')
                formal_arg = self.viper.LocalVarDecl(
                    'count', self.viper.Int, self.to_position(node, ctx),
                    self.no_info(ctx))
                return self.viper.FuncApp('rdc', [arg0],
                                          self.to_position(node, ctx),
                                          self.no_info(ctx), self.viper.Perm,
                                          [formal_arg])
        elif func_name == 'getARP':
            if not ctx.arp:
                raise UnsupportedException(
                    node, 'ARP not supported. Use --arp flag.')
            if len(node.args) == 1:
                formal_arg = self.viper.LocalVarDecl(
                    'tk', self.viper.Ref, self.to_position(node, ctx),
                    self.no_info(ctx))
                arg0_stmt, arg0 = self.translate_expr(node.args[0], ctx,
                                                      self.viper.Ref)
                if arg0_stmt:
                    raise InvalidProgramException(node, 'purity.violated')
                return self.viper.FuncApp('rd_token', [arg0],
                                          self.to_position(node, ctx),
                                          self.no_info(ctx), self.viper.Perm,
                                          [formal_arg])

        call_stmt, call = self.translate_expr(node, ctx, self.viper.Int)
        if not call_stmt:
            return call
        raise InvalidProgramException(node, 'purity.violated')
コード例 #21
0
ファイル: permission.py プロジェクト: zeta1999/nagini
 def translate_perm_Name(self, node: ast.Name, ctx: Context) -> Expr:
     if node.id == 'RD_PRED':
         if not ctx.arp:
             raise UnsupportedException(
                 node, 'ARP not supported. Use --arp flag.')
         return self.viper.FuncApp('globalRd', [],
                                   self.to_position(node, ctx),
                                   self.no_info(ctx), self.viper.Perm, {})
     stmt, res = self.translate_expr(node, ctx)
     if stmt:
         raise InvalidProgramException(node, 'purity.violated')
     return res
コード例 #22
0
ファイル: method.py プロジェクト: zeta1999/nagini
    def _translate_exceptional_posts(self, method: PythonMethod,
                                     err_var: 'viper.ast.LocalVar',
                                     ctx: Context) -> List[Expr]:
        """
        Translates the exceptional postconditions specified for 'method'.
        """
        ctx.obligation_context.is_translating_posts = True
        posts = []
        error = self.viper.NeCmp(err_var,
                                 self.viper.NullLit(self.no_position(ctx),
                                                    self.no_info(ctx)),
                                 self.no_position(ctx), self.no_info(ctx))
        error_type_conds = []
        error_string = '"method only raises exceptions of type{0} {1}"'.format(
            's' if len(method.declared_exceptions) > 1 else '',
            ', '.join([e.name for e in method.declared_exceptions]))
        error_type_pos = self.to_position(method.node, ctx, error_string)
        for exception in method.declared_exceptions:
            has_type = self.var_type_check(ERROR_NAME,
                                           exception,
                                           error_type_pos,
                                           ctx, inhale_exhale=False)
            error_type_conds.append(has_type)
            condition = self.viper.And(error, has_type, self.no_position(ctx),
                                       self.no_info(ctx))
            assert ctx.current_contract_exception is None
            ctx.current_contract_exception = exception
            for post, aliases in method.declared_exceptions[exception]:
                with ctx.additional_aliases(aliases):
                    stmt, expr = self.translate_expr(post, ctx, self.viper.Bool, True)
                if stmt:
                    raise InvalidProgramException(post, 'purity.violated')
                expr = self.viper.Implies(condition, expr,
                                          self.to_position(post, ctx),
                                          self.no_info(ctx))
                posts.append(expr)
            ctx.current_contract_exception = None

        error_type_cond = None
        for type in error_type_conds:
            if error_type_cond is None:
                error_type_cond = type
            else:
                error_type_cond = self.viper.Or(error_type_cond, type,
                                                error_type_pos,
                                                self.no_info(ctx))
        if error_type_cond is not None:
            posts.append(self.viper.Implies(error, error_type_cond,
                                            error_type_pos,
                                            self.no_info(ctx)))

        ctx.obligation_context.is_translating_posts = False
        return posts
コード例 #23
0
ファイル: contract.py プロジェクト: zeta1999/nagini
 def translate_declassify(self, node: ast.Call,
                          ctx: Context) -> StmtsAndExpr:
     """
     Translates a call to the Declassify() contract function.
     """
     stmts, expr = self.translate_expr(node.args[0], ctx)
     if stmts:
         raise InvalidProgramException(node, 'purity.violated')
     return [
         self.viper.Declassify(expr, self.to_position(node, ctx),
                               self.no_info(ctx))
     ], None
コード例 #24
0
ファイル: permission.py プロジェクト: marcoeilers/nagini
 def translate_perm_or_int(self, node: ast.AST, ctx: Context):
     num_class = ast.Num
     import sys
     if sys.version_info[1] >= 8:
         num_class = ast.Constant
     if isinstance(node, num_class):
         stmt, int_val = self.translate_expr(node, ctx, self.viper.Int)
         if stmt:
             raise InvalidProgramException(node, 'purity.violated')
         return int_val, True
     else:
         int_or_perm_val = self.translate_perm(node, ctx)
         return int_or_perm_val, int_or_perm_val.typ() == self.viper.Int
コード例 #25
0
 def translate_previous(self, node: ast.Call, ctx: Context) -> StmtsAndExpr:
     arg = node.args[0]
     if not isinstance(arg, ast.Name):
         raise InvalidProgramException(node, 'invalid.previous')
     loop = find_loop_for_previous(node, arg.id)
     if not loop:
         raise InvalidProgramException(node, 'invalid.previous')
     pos = self.to_position(node, ctx)
     info = self.no_info(ctx)
     iterator = ctx.loop_iterators[loop].ref()
     list_field = self.viper.Field('__previous',
                                   self.viper.SeqType(self.viper.Ref), pos,
                                   info)
     field_acc = self.viper.FieldAccess(iterator, list_field, pos, info)
     seq_type = ctx.module.global_module.classes[PSEQ_TYPE]
     content_type = self.get_type(node.args[0], ctx)
     type_lit = self.type_factory.translate_type_literal(
         content_type, pos, ctx)
     res = self.get_function_call(seq_type, '__create__',
                                  [field_acc, type_lit], [None, None], node,
                                  ctx)
     return [], res
コード例 #26
0
ファイル: contract.py プロジェクト: zeta1999/nagini
 def translate_low(self, node: ast.Call, ctx: Context) -> StmtsAndExpr:
     """
     Translates a call to the Low() contract function.
     """
     if len(node.args) != 1:
         raise UnsupportedException(node,
                                    "Low() requires exactly one argument")
     stmts, expr = self.translate_expr(node.args[0], ctx)
     if stmts:
         raise InvalidProgramException(node, 'purity.violated')
     info = self._create_dyn_check_info(ctx)
     return [], self.viper.Low(expr, None, self.to_position(node, ctx),
                               info)
コード例 #27
0
 def translate_must_invoke_ctoken(self, node: ast.Call,
                                  ctx: Context) -> StmtsAndExpr:
     """Translate a call to ``ctoken``."""
     if ctx.obligation_context.is_translating_loop():
         return self._loop_translator.translate_may_invoke(node, ctx)
     elif ctx.obligation_context.is_translating_posts:
         if ctx.actual_function.name != 'Gap':
             raise InvalidProgramException(
                 node, 'invalid.postcondition.ctoken_not_allowed')
         else:
             return self._method_translator.translate_may_invoke(node, ctx)
     else:
         return self._method_translator.translate_may_invoke(node, ctx)
コード例 #28
0
    def _translate_eval_io(self, node: ast.Call, ctx: Context) -> StmtsAndExpr:
        """
        Translates a reference to the eval_io IOOperation as usual. Also stores the
        information that given argument function is among the argument functions used with
        eval_io in the program; this information is used to generate additional return
        type postconditions for the result getter of eval_io.
        """
        if not isinstance(node.args[1], ast.Name):
            raise InvalidProgramException(node, 'invalid.eval.function')
        target = self.get_target(node.args[1], ctx)
        if (ctx.current_function.name != 'Eval'
                and (not isinstance(target, PythonMethod) or not target.pure)):
            raise InvalidProgramException(node, 'invalid.eval.function')
        stmt, res = self.translate_io_operation_call(node, ctx)
        func_stmt, func_arg = self.translate_expr(node.args[1], ctx)
        if func_stmt:
            raise InvalidProgramException(node, 'purity.violated')
        eval_io = self.get_target(node, ctx)

        arg_type = self.get_type(node.args[1], ctx)
        if arg_type.name != CALLABLE_TYPE:
            eval_io.func_args.append((func_arg, arg_type))
        return stmt, res
コード例 #29
0
ファイル: predicate.py プロジェクト: marcoeilers/nagini
    def translate_predicate(self, pred: PythonMethod,
                            ctx: Context) -> 'ast.silver.Predicate':
        """
        Translates pred to a Silver predicate.
        """
        if not pred.type or pred.type.name != BOOL_TYPE:
            raise InvalidProgramException(pred.node, 'invalid.predicate')
        assert ctx.current_function is None
        ctx.current_function = pred
        args = []
        arg_types = self.viper.TrueLit(self.no_position(ctx),
                                       self.no_info(ctx))
        for name, arg in pred.args.items():
            args.append(arg.decl)
            arg_type = self.type_check(arg.ref(), arg.type,
                                       self.no_position(ctx), ctx)
            arg_types = self.viper.And(arg_types, arg_type,
                                       self.no_position(ctx),
                                       self.no_info(ctx))
        if len(pred.node.body) != 1:
            raise InvalidProgramException(pred.node, 'invalid.predicate')

        content = pred.node.body[0]
        if isinstance(content, ast.Return):
            content = content.value
        stmt, body = self.translate_expr(content,
                                         ctx,
                                         impure=True,
                                         target_type=self.viper.Bool)
        if stmt:
            raise InvalidProgramException(pred.node, 'invalid.predicate')
        body = self.viper.And(arg_types, body, self.no_position(ctx),
                              self.no_info(ctx))
        ctx.current_function = None
        return self.viper.Predicate(pred.sil_name, args, body,
                                    self.to_position(pred.node, ctx),
                                    self.no_info(ctx))
コード例 #30
0
    def _translate_eval(self, node: ast.Call, ctx: Context) -> StmtsAndExpr:
        """
        Translates a call to the Eval method (which implements the eval_io IOOperation).
        The translation is like for other method calls, except we also inhale that the
        result of the operation is equal to the given function applied to the given
        argument.
        """
        position = self.to_position(node, ctx)
        info = self.no_info(ctx)
        if not isinstance(node.args[1], ast.Name):
            raise InvalidProgramException(node, 'invalid.eval.function')
        target = self.get_target(node.args[1], ctx)
        if not target.pure:
            raise InvalidProgramException(node, 'invalid.eval.function')
        arg_stmt, arg = self.translate_expr(node.args[2], ctx)
        if arg_stmt:
            raise InvalidProgramException(node, 'purity.violated')
        arg_type = self.get_type(node.args[2], ctx)
        func_stmt, func_val = self.translate_normal_call(
            target, [], [arg], [arg_type], node, ctx)
        if func_stmt:
            raise InvalidProgramException(node, 'purity.violated')
        call_stmt, call = self.translate_normal_call_node(node, ctx)
        args = []
        for arg in node.args:
            stmt, arg_val = self.translate_expr(arg, ctx)
            assert not stmt
            args.append(arg_val)

        eval_io = self._get_eval_io_operation(ctx)
        getter = self.create_result_getter(node,
                                           eval_io.get_results()[0], ctx, args,
                                           eval_io)
        assume = self.viper.Inhale(
            self.viper.EqCmp(func_val, getter, position, info), position, info)
        return call_stmt + [assume], call