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
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
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)
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
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