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