def translate_AnnAssign(self, node: ast.AnnAssign, res: List[Expr], ctx: Context): pos = self.to_position(node, ctx) self._add_local_var(node.target, ctx) lhs = ctx.all_vars[node.target.id] if node.value is None: vyper_type = node.target.type rhs = self.type_translator.default_value(None, vyper_type, res, ctx) elif types.is_numeric(node.value.type): rhs = self.expression_translator.translate_top_level_expression( node.value, res, ctx) else: # Ignore the $wrap information, if the node is not numeric rhs = self.expression_translator.translate(node.value, res, ctx) if self.arithmetic_translator.is_wrapped(rhs): if types.is_numeric(node.value.type): lhs.new_idx() lhs.is_local = False else: rhs = helpers.w_unwrap(self.viper_ast, rhs) assign = self.viper_ast.EqCmp(lhs.local_var(ctx, pos), rhs, pos) expr = self.viper_ast.Implies(ctx.pure_conds, assign, pos) if ctx.pure_conds else assign res.append(expr)
def assign_to_Name(self, node: ast.Name, value: Expr, res: List[Expr], ctx: Context): pos = self.to_position(node, ctx) var = ctx.locals.get(node.id) w_value = value if var: if isinstance(var, TranslatedPureIndexedVar): var.new_idx() if (types.is_numeric(node.type) and not var.is_local and self.expression_translator.arithmetic_translator. is_unwrapped(value)): w_value = helpers.w_wrap(self.viper_ast, value) elif (types.is_numeric(node.type) and var.is_local and self.expression_translator.arithmetic_translator. is_wrapped(value)): var.is_local = False elif (types.is_numeric(node.type) and self._always_wrap and var.is_local and self.expression_translator. arithmetic_translator.is_unwrapped(value)): var.is_local = False w_value = helpers.w_wrap(self.viper_ast, value) elif (not types.is_numeric(node.type) and self.expression_translator.arithmetic_translator. is_wrapped(value)): w_value = helpers.w_unwrap(self.viper_ast, value) lhs = self.expression_translator.translate(node, res, ctx) assign = self.viper_ast.EqCmp(lhs, w_value, pos) expr = self.viper_ast.Implies(ctx.pure_conds, assign, pos) if ctx.pure_conds else assign res.append(expr)
def _wrapped_decimal_div(self, lhs, rhs, pos=None, info=None) -> Expr: scaling_factor = self.viper_ast.IntLit( types.VYPER_DECIMAL.scaling_factor, pos) uw_lhs = helpers.w_unwrap(self.viper_ast, lhs, pos) uw_mult = self.viper_ast.Mul(uw_lhs, scaling_factor, pos) mult = helpers.w_wrap(self.viper_ast, uw_mult, pos) return helpers.w_div(self.viper_ast, mult, rhs, pos, info)
def add_model_var(name, var_type, rhs, components): new_var_name = ctx.new_local_var_name( mangled.model_var_name(*components)) vtype = self.type_translator.translate(var_type, ctx) new_var = self.viper_ast.LocalVarDecl(new_var_name, vtype, pos) ctx.new_local_vars.append(new_var) transform[new_var_name] = name type_map[new_var_name] = var_type if hasattr(rhs, 'isSubtype') and rhs.isSubtype( helpers.wrapped_int_type(self.viper_ast)): rhs = helpers.w_unwrap(self.viper_ast, rhs) res.append( self.viper_ast.LocalVarAssign(new_var.localVar(), rhs, pos))
def translate_Return(self, node: ast.Return, res: List[Expr], ctx: Context): assert node.value assert isinstance(ctx.result_var, TranslatedPureIndexedVar) assert isinstance(ctx.success_var, TranslatedPureIndexedVar) pos = self.to_position(node, ctx) expr = self.expression_translator.translate_top_level_expression( node.value, res, ctx) if (self.arithmetic_translator.is_unwrapped( ctx.result_var.local_var(ctx)) and self.arithmetic_translator.is_wrapped(expr)): expr = helpers.w_unwrap(self.viper_ast, expr) ctx.result_var.new_idx() assign = self.viper_ast.EqCmp(ctx.result_var.local_var(ctx), expr, pos) expr = self.viper_ast.Implies(ctx.pure_conds, assign, pos) if ctx.pure_conds else assign res.append(expr) cond = ctx.pure_conds or self.viper_ast.TrueLit(pos) ctx.pure_returns.append((cond, ctx.result_var.evaluate_idx(ctx))) ctx.pure_success.append((cond, ctx.success_var.evaluate_idx(ctx)))
def unwrap(a: Expr) -> Expr: if hasattr(a, 'isSubtype') and a.isSubtype(wrapped_int_type): nonlocal had_wrapped_integers had_wrapped_integers = True return helpers.w_unwrap(_self.viper_ast, a, pos, info) return a
def arithmetic_op(self, lhs, op: ast.ArithmeticOperator, rhs, otype: PrimitiveType, res: List[Stmt], ctx: Context, pos=None) -> Expr: ast_op = ast.ArithmeticOperator left_is_wrapped = self.is_wrapped(lhs) right_is_wrapped = self.is_wrapped(rhs) if ctx.inside_interpreted: if left_is_wrapped: left_is_wrapped = False lhs = helpers.w_unwrap(self.viper_ast, lhs, pos) if right_is_wrapped: right_is_wrapped = False rhs = helpers.w_unwrap(self.viper_ast, rhs, pos) elif ctx.inside_lemma: if not left_is_wrapped: left_is_wrapped = True lhs = helpers.w_wrap(self.viper_ast, lhs, pos) if not right_is_wrapped: right_is_wrapped = True rhs = helpers.w_wrap(self.viper_ast, rhs, pos) with switch(op, otype) as case: from twovyper.utils import _ if (case(ast_op.DIV, _) or case(ast_op.MOD, _)) and not self.no_reverts: expr = rhs if right_is_wrapped: expr = helpers.w_unwrap(self.viper_ast, rhs, pos) cond = self.viper_ast.EqCmp(expr, self.viper_ast.IntLit(0, pos), pos) self.fail_if(cond, [], res, ctx, pos) if left_is_wrapped and right_is_wrapped: # Both are wrapped if case(ast_op.MUL, types.VYPER_DECIMAL): expr = self._wrapped_decimal_mul(lhs, rhs, pos) elif case(ast_op.DIV, types.VYPER_DECIMAL): expr = self._wrapped_decimal_div(lhs, rhs, pos) else: expr = self._wrapped_arithmetic_ops[op](lhs, rhs, pos) else: if case(ast_op.MUL, types.VYPER_DECIMAL): expr = self._decimal_mul(lhs, rhs, pos) elif case(ast_op.DIV, types.VYPER_DECIMAL): expr = self._decimal_div(lhs, rhs, pos) else: expr = self._arithmetic_ops[op](lhs, rhs, pos) if types.is_bounded(otype): assert isinstance(otype, BoundedType) if is_compatible_version('<=0.1.0-beta.17') and op == ast_op.POW: # In certain versions of Vyper there was no overflow check for POW. self.check_underflow(expr, otype, res, ctx, pos) else: self.check_under_overflow(expr, otype, res, ctx, pos) return expr