Ejemplo n.º 1
0
 def get_sequence(self,
                  receiver: PythonType,
                  arg: Expr,
                  arg_type: PythonType,
                  node: ast.AST,
                  ctx: Context,
                  position: Position = None) -> Expr:
     """
     Returns a sequence (Viper type Seq[Ref]) representing the contents of arg.
     Defaults to type___sil_seq__, but used simpler expressions for known types
     to improve performance/triggering.
     """
     position = position if position else self.to_position(node, ctx)
     info = self.no_info(ctx)
     if not isinstance(receiver, UnionType) or isinstance(
             receiver, OptionalType):
         if receiver.name == LIST_TYPE:
             seq_ref = self.viper.SeqType(self.viper.Ref)
             field = self.viper.Field('list_acc', seq_ref, position, info)
             res = self.viper.FieldAccess(arg, field, position, info)
             return res
         if receiver.name == PSEQ_TYPE:
             if (isinstance(arg, self.viper.ast.FuncApp)
                     and arg.funcname() == 'PSeq___create__'):
                 args = self.viper.to_list(arg.args())
                 return args[0]
     return self.get_function_call(receiver, '__sil_seq__', [arg],
                                   [arg_type], node, ctx, position)
Ejemplo n.º 2
0
 def to_int(self, e: Expr, ctx: Context) -> Expr:
     """
     Converts the given expression to an expression of the Silver type Int
     if it isn't already, either by unboxing a reference or undoing a
     previous boxing operation.
     """
     # Avoid wrapping non-pure expressions (leads to errors within Silver's
     # Consistency object)
     if not self._is_pure(e):
         return e
     if e.typ() == self.viper.Int:
         return e
     if e.typ() != self.viper.Ref:
         e = self.to_ref(e, ctx)
     if (isinstance(e, self.viper.ast.FuncApp)
             and e.funcname() == '__prim__int___box__'):
         return e.args().head()
     result = e
     int_type = ctx.module.global_module.classes[INT_TYPE]
     result = self.get_function_call(int_type,
                                     '__unbox__', [result], [None],
                                     None,
                                     ctx,
                                     position=e.pos())
     return result
Ejemplo n.º 3
0
 def to_ref(self, e: Expr, ctx: Context) -> Expr:
     """
     Converts the given expression to an expression of the Silver type Ref
     if it isn't already, either by boxing a primitive or undoing a
     previous unboxing operation.
     """
     # Avoid wrapping non-pure expressions (leads to errors within Silver's
     # Consistency object)
     if not self._is_pure(e):
         return e
     result = e
     if e.typ() == self.viper.Int:
         if (isinstance(e, self.viper.ast.FuncApp) and
                 e.funcname() == 'int___unbox__'):
             result = e.args().head()
         else:
             prim_int = ctx.module.global_module.classes[PRIMITIVE_INT_TYPE]
             result = self.get_function_call(prim_int, '__box__',
                                             [result], [None], None, ctx,
                                             position=e.pos())
     elif e.typ() == self.viper.Bool:
         if (isinstance(e, self.viper.ast.FuncApp) and
                 e.funcname() == 'bool___unbox__'):
             result = e.args().head()
         else:
             prim_bool = ctx.module.global_module.classes[PRIMITIVE_BOOL_TYPE]
             result = self.get_function_call(prim_bool, '__box__',
                                             [result], [None], None, ctx,
                                             position=e.pos())
     return result
Ejemplo n.º 4
0
 def _combine_names(self, prefix: Expr, name: Expr, pos: Position, info: Info) -> Expr:
     """
     Returns an expression that combines the prefix-name and the name to a new name
     that represents 'prefix.name'.
     """
     name_type = self.viper.DomainType(NAME_DOMAIN, {}, [])
     if name.typ() == self.viper.Int:
         boxed_name = self.viper.DomainFuncApp(SINGLE_NAME, [name], name_type, pos,
                                               info, NAME_DOMAIN)
     else:
         boxed_name = name
     if prefix.typ() == self.viper.Int:
         boxed_prefix = self.viper.DomainFuncApp(SINGLE_NAME, [prefix], name_type, pos,
                                                 info, NAME_DOMAIN)
     else:
         boxed_prefix = prefix
     return self.viper.DomainFuncApp(COMBINE_NAME_FUNC, [boxed_prefix, boxed_name],
                                     name_type, pos, info, NAME_DOMAIN)
Ejemplo n.º 5
0
 def _is_defined(self, name: Expr, module: Expr, pos: Position, info: Info) -> Expr:
     """
     Returns an expression that is true iff the name represented by the given
     expression is defined in the module represented by the other expression.
     """
     name_type = self.viper.DomainType(NAME_DOMAIN, {}, [])
     if name.typ() == self.viper.Int:
         boxed_name = self.viper.DomainFuncApp(SINGLE_NAME, [name], name_type, pos,
                                               info, NAME_DOMAIN)
     else:
         boxed_name = name
     return self.viper.AnySetContains(boxed_name, module, pos, info)
Ejemplo n.º 6
0
 def _set_global_defined(self, decl_int: Expr, module_var: Expr, pos: Position,
                         info: Info) -> Stmt:
     """
     Returns a statement that sets the name of represented by the integer decl_int to
     be defined in the given set of names.
     """
     if decl_int.typ() == self.viper.Int:
         decl_int = self.viper.DomainFuncApp(SINGLE_NAME, [decl_int], self.name_type(),
                                             pos, info, NAME_DOMAIN)
     new_set = self.viper.ExplicitSet([decl_int], pos, info)
     union = self.viper.AnySetUnion(module_var, new_set, pos, info)
     return self.viper.LocalVarAssign(module_var, union, pos, info)
Ejemplo n.º 7
0
 def to_bool(self, e: Expr, ctx: Context, node: ast.AST = None) -> Expr:
     """
     Converts the given expression to an expression of the Silver type Bool
     if it isn't already, either by calling __bool__ on an object and
     possibly unboxing the result, or by undoing a previous boxing operation.
     """
     # Avoid wrapping non-pure expressions (leads to errors within Silver's
     # Consistency object)
     if not self._is_pure(e):
         return e
     if e.typ() == self.viper.Bool:
         return e
     if e.typ() != self.viper.Ref:
         e = self.to_ref(e, ctx)
     if (isinstance(e, self.viper.ast.FuncApp) and
             e.funcname() == '__prim__bool___box__'):
         return e.args().head()
     result = e
     call_bool = True
     if node:
         node_type = self.get_type(node, ctx)
         if node_type.name == 'bool':
             call_bool = False
         if call_bool:
             result = self.get_function_call(node_type, '__bool__',
                                             [result], [None], node, ctx,
                                             position=e.pos())
     if result.typ() != self.viper.Bool:
         bool_type = ctx.module.global_module.classes['bool']
         result = self.get_function_call(bool_type, '__unbox__',
                                         [result], [None], node, ctx,
                                         position=e.pos())
     return result
Ejemplo n.º 8
0
 def unwrap(self, e: Expr) -> Expr:
     if isinstance(e, self.viper.ast.FuncApp):
         if (e.funcname().endswith('__box__') or
                 e.funcname().endswith('__unbox__')):
             return e.args().head()
     return e
Ejemplo n.º 9
0
 def _is_pure(self, e: Expr) -> bool:
     e = self.unwrap(e)
     if isinstance(e, (self.viper.ast.And, self.viper.ast.Or)):
         return self._is_pure(e.left()) and self._is_pure(e.right())
     return e.isPure()