def try_rehom(rhs: Expression, expected_type: AnnotatedTypeName): if rhs.annotated_type.is_public(): raise ValueError( 'Cannot change the homomorphism of a public value') if rhs.annotated_type.is_private_at_me(rhs.analysis): # The value is @me, so we can just insert a ReclassifyExpr to change # the homomorphism of this value, just like we do for public values. return TypeCheckVisitor.make_rehom(rhs, expected_type) if isinstance(rhs, ReclassifyExpr) and not isinstance(rhs, RehomExpr): # rhs is a valid ReclassifyExpr, i.e. the argument is public or @me-private # To create an expression with the correct homomorphism, # just change the ReclassifyExpr's output homomorphism rhs.homomorphism = expected_type.homomorphism elif isinstance(rhs, PrimitiveCastExpr): # Ignore primitive cast & recurse rhs.expr = TypeCheckVisitor.try_rehom(rhs.expr, expected_type) elif isinstance(rhs, FunctionCallExpr) and isinstance(rhs.func, BuiltinFunction) and rhs.func.is_ite() \ and rhs.args[0].annotated_type.is_public(): # Argument is public_cond ? true_val : false_val. Try to rehom both true_val and false_val rhs.args[1] = TypeCheckVisitor.try_rehom(rhs.args[1], expected_type) rhs.args[2] = TypeCheckVisitor.try_rehom(rhs.args[2], expected_type) else: raise TypeMismatchException(expected_type, rhs.annotated_type, rhs) # Rehom worked without throwing, change annotated_type and return rhs.annotated_type = rhs.annotated_type.with_homomorphism( expected_type.homomorphism) return rhs
def implicitly_converted_to(expr: Expression, t: TypeName) -> Expression: if isinstance(expr, ReclassifyExpr) and not expr.privacy.is_all_expr(): # Cast the argument of the ReclassifyExpr instead expr.expr = TypeCheckVisitor.implicitly_converted_to(expr.expr, t) expr.annotated_type.type_name = expr.expr.annotated_type.type_name return expr assert expr.annotated_type.type_name.is_primitive_type() cast = PrimitiveCastExpr(t.clone(), expr, is_implicit=True).override( parent=expr.parent, statement=expr.statement, line=expr.line, column=expr.column) cast.elem_type.parent = cast expr.parent = cast cast.annotated_type = AnnotatedTypeName( t.clone(), expr.annotated_type.privacy_annotation.clone(), expr.annotated_type.homomorphism).override(parent=cast) return cast