diff options
Diffstat (limited to 'gcc/rust/backend/rust-compile-expr.cc')
-rw-r--r-- | gcc/rust/backend/rust-compile-expr.cc | 746 |
1 files changed, 743 insertions, 3 deletions
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index bfaa7fc..9a8b779 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -16,15 +16,15 @@ // along with GCC; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. -#include "rust-compile.h" -#include "rust-compile-item.h" -#include "rust-compile-implitem.h" #include "rust-compile-expr.h" #include "rust-compile-struct-field-expr.h" #include "rust-hir-trait-resolve.h" #include "rust-hir-path-probe.h" #include "rust-hir-type-bounds.h" #include "rust-compile-pattern.h" +#include "rust-compile-resolve-path.h" +#include "rust-compile-block.h" +#include "rust-compile-implitem.h" #include "rust-constexpr.h" #include "fold-const.h" @@ -35,6 +35,97 @@ namespace Rust { namespace Compile { +CompileExpr::CompileExpr (Context *ctx) + : HIRCompileBase (ctx), translated (error_mark_node) +{} + +tree +CompileExpr::Compile (HIR::Expr *expr, Context *ctx) +{ + CompileExpr compiler (ctx); + expr->accept_vis (compiler); + return compiler.translated; +} + +void +CompileExpr::visit (HIR::TupleIndexExpr &expr) +{ + HIR::Expr *tuple_expr = expr.get_tuple_expr ().get (); + TupleIndex index = expr.get_tuple_index (); + + tree receiver_ref = CompileExpr::Compile (tuple_expr, ctx); + + TyTy::BaseType *tuple_expr_ty = nullptr; + bool ok + = ctx->get_tyctx ()->lookup_type (tuple_expr->get_mappings ().get_hirid (), + &tuple_expr_ty); + rust_assert (ok); + + // do we need to add an indirect reference + if (tuple_expr_ty->get_kind () == TyTy::TypeKind::REF) + { + tree indirect = indirect_expression (receiver_ref, expr.get_locus ()); + receiver_ref = indirect; + } + + translated + = ctx->get_backend ()->struct_field_expression (receiver_ref, index, + expr.get_locus ()); +} + +void +CompileExpr::visit (HIR::TupleExpr &expr) +{ + if (expr.is_unit ()) + { + translated = ctx->get_backend ()->unit_expression (); + return; + } + + TyTy::BaseType *tyty = nullptr; + if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), + &tyty)) + { + rust_fatal_error (expr.get_locus (), + "did not resolve type for this TupleExpr"); + return; + } + + tree tuple_type = TyTyResolveCompile::compile (ctx, tyty); + rust_assert (tuple_type != nullptr); + + // this assumes all fields are in order from type resolution + std::vector<tree> vals; + for (auto &elem : expr.get_tuple_elems ()) + { + auto e = CompileExpr::Compile (elem.get (), ctx); + vals.push_back (e); + } + + translated + = ctx->get_backend ()->constructor_expression (tuple_type, false, vals, -1, + expr.get_locus ()); +} + +void +CompileExpr::visit (HIR::ReturnExpr &expr) +{ + auto fncontext = ctx->peek_fn (); + + std::vector<tree> retstmts; + if (expr.has_return_expr ()) + { + tree compiled_expr = CompileExpr::Compile (expr.return_expr.get (), ctx); + rust_assert (compiled_expr != nullptr); + + retstmts.push_back (compiled_expr); + } + + auto s = ctx->get_backend ()->return_statement (fncontext.fndecl, retstmts, + expr.get_locus ()); + ctx->add_statement (s); +} + void CompileExpr::visit (HIR::ArithmeticOrLogicalExpr &expr) { @@ -120,6 +211,585 @@ CompileExpr::visit (HIR::NegationExpr &expr) } void +CompileExpr::visit (HIR::ComparisonExpr &expr) +{ + auto op = expr.get_expr_type (); + auto lhs = CompileExpr::Compile (expr.get_lhs (), ctx); + auto rhs = CompileExpr::Compile (expr.get_rhs (), ctx); + auto location = expr.get_locus (); + + translated + = ctx->get_backend ()->comparison_expression (op, lhs, rhs, location); +} + +void +CompileExpr::visit (HIR::LazyBooleanExpr &expr) +{ + auto op = expr.get_expr_type (); + auto lhs = CompileExpr::Compile (expr.get_lhs (), ctx); + auto rhs = CompileExpr::Compile (expr.get_rhs (), ctx); + auto location = expr.get_locus (); + + translated + = ctx->get_backend ()->lazy_boolean_expression (op, lhs, rhs, location); +} + +void +CompileExpr::visit (HIR::TypeCastExpr &expr) +{ + TyTy::BaseType *tyty = nullptr; + if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), + &tyty)) + { + translated = error_mark_node; + return; + } + + auto type_to_cast_to = TyTyResolveCompile::compile (ctx, tyty); + auto casted_expr = CompileExpr::Compile (expr.get_casted_expr ().get (), ctx); + translated + = type_cast_expression (type_to_cast_to, casted_expr, expr.get_locus ()); +} + +void +CompileExpr::visit (HIR::IfExpr &expr) +{ + auto stmt = CompileConditionalBlocks::compile (&expr, ctx, nullptr); + ctx->add_statement (stmt); +} + +void +CompileExpr::visit (HIR::IfExprConseqElse &expr) +{ + TyTy::BaseType *if_type = nullptr; + if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), + &if_type)) + { + rust_error_at (expr.get_locus (), + "failed to lookup type of IfExprConseqElse"); + return; + } + + Bvariable *tmp = NULL; + bool needs_temp = !if_type->is_unit (); + if (needs_temp) + { + fncontext fnctx = ctx->peek_fn (); + tree enclosing_scope = ctx->peek_enclosing_scope (); + tree block_type = TyTyResolveCompile::compile (ctx, if_type); + + bool is_address_taken = false; + tree ret_var_stmt = nullptr; + tmp = ctx->get_backend ()->temporary_variable ( + fnctx.fndecl, enclosing_scope, block_type, NULL, is_address_taken, + expr.get_locus (), &ret_var_stmt); + ctx->add_statement (ret_var_stmt); + } + + auto stmt = CompileConditionalBlocks::compile (&expr, ctx, tmp); + ctx->add_statement (stmt); + + if (tmp != NULL) + { + translated = ctx->get_backend ()->var_expression (tmp, expr.get_locus ()); + } +} + +void +CompileExpr::visit (HIR::IfExprConseqIf &expr) +{ + TyTy::BaseType *if_type = nullptr; + if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), + &if_type)) + { + rust_error_at (expr.get_locus (), + "failed to lookup type of IfExprConseqElse"); + return; + } + + Bvariable *tmp = NULL; + bool needs_temp = !if_type->is_unit (); + if (needs_temp) + { + fncontext fnctx = ctx->peek_fn (); + tree enclosing_scope = ctx->peek_enclosing_scope (); + tree block_type = TyTyResolveCompile::compile (ctx, if_type); + + bool is_address_taken = false; + tree ret_var_stmt = nullptr; + tmp = ctx->get_backend ()->temporary_variable ( + fnctx.fndecl, enclosing_scope, block_type, NULL, is_address_taken, + expr.get_locus (), &ret_var_stmt); + ctx->add_statement (ret_var_stmt); + } + + auto stmt = CompileConditionalBlocks::compile (&expr, ctx, tmp); + ctx->add_statement (stmt); + + if (tmp != NULL) + { + translated = ctx->get_backend ()->var_expression (tmp, expr.get_locus ()); + } +} + +void +CompileExpr::visit (HIR::BlockExpr &expr) +{ + TyTy::BaseType *block_tyty = nullptr; + if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), + &block_tyty)) + { + rust_error_at (expr.get_locus (), "failed to lookup type of BlockExpr"); + return; + } + + Bvariable *tmp = NULL; + bool needs_temp = !block_tyty->is_unit (); + if (needs_temp) + { + fncontext fnctx = ctx->peek_fn (); + tree enclosing_scope = ctx->peek_enclosing_scope (); + tree block_type = TyTyResolveCompile::compile (ctx, block_tyty); + + bool is_address_taken = false; + tree ret_var_stmt = nullptr; + tmp = ctx->get_backend ()->temporary_variable ( + fnctx.fndecl, enclosing_scope, block_type, NULL, is_address_taken, + expr.get_locus (), &ret_var_stmt); + ctx->add_statement (ret_var_stmt); + } + + auto block_stmt = CompileBlock::compile (&expr, ctx, tmp); + rust_assert (TREE_CODE (block_stmt) == BIND_EXPR); + ctx->add_statement (block_stmt); + + if (tmp != NULL) + { + translated = ctx->get_backend ()->var_expression (tmp, expr.get_locus ()); + } +} + +void +CompileExpr::visit (HIR::UnsafeBlockExpr &expr) +{ + expr.get_block_expr ()->accept_vis (*this); +} + +void +CompileExpr::visit (HIR::StructExprStruct &struct_expr) +{ + TyTy::BaseType *tyty = nullptr; + if (!ctx->get_tyctx ()->lookup_type (struct_expr.get_mappings ().get_hirid (), + &tyty)) + { + rust_error_at (struct_expr.get_locus (), "unknown type"); + return; + } + + rust_assert (tyty->is_unit ()); + translated = ctx->get_backend ()->unit_expression (); +} + +void +CompileExpr::visit (HIR::StructExprStructFields &struct_expr) +{ + TyTy::BaseType *tyty = nullptr; + if (!ctx->get_tyctx ()->lookup_type (struct_expr.get_mappings ().get_hirid (), + &tyty)) + { + rust_error_at (struct_expr.get_locus (), "unknown type"); + return; + } + + // it must be an ADT + rust_assert (tyty->get_kind () == TyTy::TypeKind::ADT); + TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (tyty); + + // what variant is it? + int union_disriminator = struct_expr.union_index; + TyTy::VariantDef *variant = nullptr; + if (!adt->is_enum ()) + { + rust_assert (adt->number_of_variants () == 1); + variant = adt->get_variants ().at (0); + } + else + { + HirId variant_id; + bool ok = ctx->get_tyctx ()->lookup_variant_definition ( + struct_expr.get_struct_name ().get_mappings ().get_hirid (), + &variant_id); + rust_assert (ok); + + ok + = adt->lookup_variant_by_id (variant_id, &variant, &union_disriminator); + rust_assert (ok); + } + + // compile it + tree compiled_adt_type = TyTyResolveCompile::compile (ctx, tyty); + + std::vector<tree> arguments; + if (adt->is_union ()) + { + rust_assert (struct_expr.get_fields ().size () == 1); + + // assignments are coercion sites so lets convert the rvalue if + // necessary + auto respective_field = variant->get_field_at_index (union_disriminator); + auto expected = respective_field->get_field_type (); + + // process arguments + auto &argument = struct_expr.get_fields ().at (0); + auto lvalue_locus + = ctx->get_mappings ()->lookup_location (expected->get_ty_ref ()); + auto rvalue_locus = argument->get_locus (); + auto rvalue = CompileStructExprField::Compile (argument.get (), ctx); + + TyTy::BaseType *actual = nullptr; + bool ok = ctx->get_tyctx ()->lookup_type ( + argument->get_mappings ().get_hirid (), &actual); + + if (ok) + { + rvalue + = coercion_site (argument->get_mappings ().get_hirid (), rvalue, + actual, expected, lvalue_locus, rvalue_locus); + } + + // add it to the list + arguments.push_back (rvalue); + } + else + { + // this assumes all fields are in order from type resolution and if a + // base struct was specified those fields are filed via accesors + for (size_t i = 0; i < struct_expr.get_fields ().size (); i++) + { + // assignments are coercion sites so lets convert the rvalue if + // necessary + auto respective_field = variant->get_field_at_index (i); + auto expected = respective_field->get_field_type (); + + // process arguments + auto &argument = struct_expr.get_fields ().at (i); + auto lvalue_locus + = ctx->get_mappings ()->lookup_location (expected->get_ty_ref ()); + auto rvalue_locus = argument->get_locus (); + auto rvalue = CompileStructExprField::Compile (argument.get (), ctx); + + TyTy::BaseType *actual = nullptr; + bool ok = ctx->get_tyctx ()->lookup_type ( + argument->get_mappings ().get_hirid (), &actual); + + // coerce it if required/possible see + // compile/torture/struct_base_init_1.rs + if (ok) + { + rvalue + = coercion_site (argument->get_mappings ().get_hirid (), rvalue, + actual, expected, lvalue_locus, rvalue_locus); + } + + // add it to the list + arguments.push_back (rvalue); + } + } + + // the constructor depends on whether this is actually an enum or not if + // its an enum we need to setup the discriminator + std::vector<tree> ctor_arguments; + if (adt->is_enum ()) + { + HIR::Expr *discrim_expr = variant->get_discriminant (); + tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx); + tree folded_discrim_expr = fold_expr (discrim_expr_node); + tree qualifier = folded_discrim_expr; + + ctor_arguments.push_back (qualifier); + } + for (auto &arg : arguments) + ctor_arguments.push_back (arg); + + translated = ctx->get_backend ()->constructor_expression ( + compiled_adt_type, adt->is_enum (), ctor_arguments, union_disriminator, + struct_expr.get_locus ()); +} + +void +CompileExpr::visit (HIR::GroupedExpr &expr) +{ + translated = CompileExpr::Compile (expr.get_expr_in_parens ().get (), ctx); +} + +void +CompileExpr::visit (HIR::FieldAccessExpr &expr) +{ + HIR::Expr *receiver_expr = expr.get_receiver_expr ().get (); + tree receiver_ref = CompileExpr::Compile (receiver_expr, ctx); + + // resolve the receiver back to ADT type + TyTy::BaseType *receiver = nullptr; + if (!ctx->get_tyctx ()->lookup_type ( + expr.get_receiver_expr ()->get_mappings ().get_hirid (), &receiver)) + { + rust_error_at (expr.get_receiver_expr ()->get_locus (), + "unresolved type for receiver"); + return; + } + + size_t field_index = 0; + if (receiver->get_kind () == TyTy::TypeKind::ADT) + { + TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (receiver); + rust_assert (!adt->is_enum ()); + rust_assert (adt->number_of_variants () == 1); + + TyTy::VariantDef *variant = adt->get_variants ().at (0); + bool ok + = variant->lookup_field (expr.get_field_name (), nullptr, &field_index); + rust_assert (ok); + } + else if (receiver->get_kind () == TyTy::TypeKind::REF) + { + TyTy::ReferenceType *r = static_cast<TyTy::ReferenceType *> (receiver); + TyTy::BaseType *b = r->get_base (); + rust_assert (b->get_kind () == TyTy::TypeKind::ADT); + + TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (b); + rust_assert (!adt->is_enum ()); + rust_assert (adt->number_of_variants () == 1); + + TyTy::VariantDef *variant = adt->get_variants ().at (0); + bool ok + = variant->lookup_field (expr.get_field_name (), nullptr, &field_index); + rust_assert (ok); + + tree indirect = indirect_expression (receiver_ref, expr.get_locus ()); + receiver_ref = indirect; + } + + translated + = ctx->get_backend ()->struct_field_expression (receiver_ref, field_index, + expr.get_locus ()); +} + +void +CompileExpr::visit (HIR::QualifiedPathInExpression &expr) +{ + translated = ResolvePathRef::Compile (expr, ctx); +} + +void +CompileExpr::visit (HIR::PathInExpression &expr) +{ + translated = ResolvePathRef::Compile (expr, ctx); +} + +void +CompileExpr::visit (HIR::LoopExpr &expr) +{ + TyTy::BaseType *block_tyty = nullptr; + if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), + &block_tyty)) + { + rust_error_at (expr.get_locus (), "failed to lookup type of BlockExpr"); + return; + } + + fncontext fnctx = ctx->peek_fn (); + tree enclosing_scope = ctx->peek_enclosing_scope (); + tree block_type = TyTyResolveCompile::compile (ctx, block_tyty); + + bool is_address_taken = false; + tree ret_var_stmt = NULL_TREE; + Bvariable *tmp = ctx->get_backend ()->temporary_variable ( + fnctx.fndecl, enclosing_scope, block_type, NULL, is_address_taken, + expr.get_locus (), &ret_var_stmt); + ctx->add_statement (ret_var_stmt); + ctx->push_loop_context (tmp); + + if (expr.has_loop_label ()) + { + HIR::LoopLabel &loop_label = expr.get_loop_label (); + tree label + = ctx->get_backend ()->label (fnctx.fndecl, + loop_label.get_lifetime ().get_name (), + loop_label.get_locus ()); + tree label_decl = ctx->get_backend ()->label_definition_statement (label); + ctx->add_statement (label_decl); + ctx->insert_label_decl ( + loop_label.get_lifetime ().get_mappings ().get_hirid (), label); + } + + tree loop_begin_label + = ctx->get_backend ()->label (fnctx.fndecl, "", expr.get_locus ()); + tree loop_begin_label_decl + = ctx->get_backend ()->label_definition_statement (loop_begin_label); + ctx->add_statement (loop_begin_label_decl); + ctx->push_loop_begin_label (loop_begin_label); + + tree code_block + = CompileBlock::compile (expr.get_loop_block ().get (), ctx, nullptr); + tree loop_expr + = ctx->get_backend ()->loop_expression (code_block, expr.get_locus ()); + ctx->add_statement (loop_expr); + + ctx->pop_loop_context (); + translated = ctx->get_backend ()->var_expression (tmp, expr.get_locus ()); + + ctx->pop_loop_begin_label (); +} + +void +CompileExpr::visit (HIR::WhileLoopExpr &expr) +{ + fncontext fnctx = ctx->peek_fn (); + if (expr.has_loop_label ()) + { + HIR::LoopLabel &loop_label = expr.get_loop_label (); + tree label + = ctx->get_backend ()->label (fnctx.fndecl, + loop_label.get_lifetime ().get_name (), + loop_label.get_locus ()); + tree label_decl = ctx->get_backend ()->label_definition_statement (label); + ctx->add_statement (label_decl); + ctx->insert_label_decl ( + loop_label.get_lifetime ().get_mappings ().get_hirid (), label); + } + + std::vector<Bvariable *> locals; + Location start_location = expr.get_loop_block ()->get_locus (); + Location end_location = expr.get_loop_block ()->get_locus (); // FIXME + + tree enclosing_scope = ctx->peek_enclosing_scope (); + tree loop_block + = ctx->get_backend ()->block (fnctx.fndecl, enclosing_scope, locals, + start_location, end_location); + ctx->push_block (loop_block); + + tree loop_begin_label + = ctx->get_backend ()->label (fnctx.fndecl, "", expr.get_locus ()); + tree loop_begin_label_decl + = ctx->get_backend ()->label_definition_statement (loop_begin_label); + ctx->add_statement (loop_begin_label_decl); + ctx->push_loop_begin_label (loop_begin_label); + + tree condition + = CompileExpr::Compile (expr.get_predicate_expr ().get (), ctx); + tree exit_expr + = ctx->get_backend ()->exit_expression (condition, expr.get_locus ()); + ctx->add_statement (exit_expr); + + tree code_block_stmt + = CompileBlock::compile (expr.get_loop_block ().get (), ctx, nullptr); + rust_assert (TREE_CODE (code_block_stmt) == BIND_EXPR); + ctx->add_statement (code_block_stmt); + + ctx->pop_loop_begin_label (); + ctx->pop_block (); + + tree loop_expr + = ctx->get_backend ()->loop_expression (loop_block, expr.get_locus ()); + ctx->add_statement (loop_expr); +} + +void +CompileExpr::visit (HIR::BreakExpr &expr) +{ + if (expr.has_break_expr ()) + { + tree compiled_expr = CompileExpr::Compile (expr.get_expr ().get (), ctx); + + Bvariable *loop_result_holder = ctx->peek_loop_context (); + tree result_reference + = ctx->get_backend ()->var_expression (loop_result_holder, + expr.get_expr ()->get_locus ()); + + tree assignment + = ctx->get_backend ()->assignment_statement (result_reference, + compiled_expr, + expr.get_locus ()); + ctx->add_statement (assignment); + } + + if (expr.has_label ()) + { + NodeId resolved_node_id = UNKNOWN_NODEID; + if (!ctx->get_resolver ()->lookup_resolved_label ( + expr.get_label ().get_mappings ().get_nodeid (), &resolved_node_id)) + { + rust_error_at ( + expr.get_label ().get_locus (), + "failed to resolve compiled label for label %s", + expr.get_label ().get_mappings ().as_string ().c_str ()); + return; + } + + HirId ref = UNKNOWN_HIRID; + if (!ctx->get_mappings ()->lookup_node_to_hir (resolved_node_id, &ref)) + { + rust_fatal_error (expr.get_locus (), "reverse lookup label failure"); + return; + } + + tree label = NULL_TREE; + if (!ctx->lookup_label_decl (ref, &label)) + { + rust_error_at (expr.get_label ().get_locus (), + "failed to lookup compiled label"); + return; + } + + tree goto_label + = ctx->get_backend ()->goto_statement (label, expr.get_locus ()); + ctx->add_statement (goto_label); + } + else + { + tree exit_expr = ctx->get_backend ()->exit_expression ( + ctx->get_backend ()->boolean_constant_expression (true), + expr.get_locus ()); + ctx->add_statement (exit_expr); + } +} + +void +CompileExpr::visit (HIR::ContinueExpr &expr) +{ + tree label = ctx->peek_loop_begin_label (); + if (expr.has_label ()) + { + NodeId resolved_node_id = UNKNOWN_NODEID; + if (!ctx->get_resolver ()->lookup_resolved_label ( + expr.get_label ().get_mappings ().get_nodeid (), &resolved_node_id)) + { + rust_error_at ( + expr.get_label ().get_locus (), + "failed to resolve compiled label for label %s", + expr.get_label ().get_mappings ().as_string ().c_str ()); + return; + } + + HirId ref = UNKNOWN_HIRID; + if (!ctx->get_mappings ()->lookup_node_to_hir (resolved_node_id, &ref)) + { + rust_fatal_error (expr.get_locus (), "reverse lookup label failure"); + return; + } + + if (!ctx->lookup_label_decl (ref, &label)) + { + rust_error_at (expr.get_label ().get_locus (), + "failed to lookup compiled label"); + return; + } + } + + translated = ctx->get_backend ()->goto_statement (label, expr.get_locus ()); +} + +void CompileExpr::visit (HIR::BorrowExpr &expr) { tree main_expr = CompileExpr::Compile (expr.get_expr ().get (), ctx); @@ -177,6 +847,76 @@ CompileExpr::visit (HIR::DereferenceExpr &expr) translated = indirect_expression (main_expr, expr.get_locus ()); } +void +CompileExpr::visit (HIR::LiteralExpr &expr) +{ + TyTy::BaseType *tyty = nullptr; + if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), + &tyty)) + return; + + switch (expr.get_lit_type ()) + { + case HIR::Literal::BOOL: + translated = compile_bool_literal (expr, tyty); + return; + + case HIR::Literal::INT: + translated = compile_integer_literal (expr, tyty); + return; + + case HIR::Literal::FLOAT: + translated = compile_float_literal (expr, tyty); + return; + + case HIR::Literal::CHAR: + translated = compile_char_literal (expr, tyty); + return; + + case HIR::Literal::BYTE: + translated = compile_byte_literal (expr, tyty); + return; + + case HIR::Literal::STRING: + translated = compile_string_literal (expr, tyty); + return; + + case HIR::Literal::BYTE_STRING: + translated = compile_byte_string_literal (expr, tyty); + return; + } +} + +void +CompileExpr::visit (HIR::AssignmentExpr &expr) +{ + auto lvalue = CompileExpr::Compile (expr.get_lhs (), ctx); + auto rvalue = CompileExpr::Compile (expr.get_rhs (), ctx); + + // assignments are coercion sites so lets convert the rvalue if necessary + TyTy::BaseType *expected = nullptr; + TyTy::BaseType *actual = nullptr; + + bool ok; + ok = ctx->get_tyctx ()->lookup_type ( + expr.get_lhs ()->get_mappings ().get_hirid (), &expected); + rust_assert (ok); + + ok = ctx->get_tyctx ()->lookup_type ( + expr.get_rhs ()->get_mappings ().get_hirid (), &actual); + rust_assert (ok); + + rvalue = coercion_site (expr.get_mappings ().get_hirid (), rvalue, actual, + expected, expr.get_lhs ()->get_locus (), + expr.get_rhs ()->get_locus ()); + + tree assignment + = ctx->get_backend ()->assignment_statement (lvalue, rvalue, + expr.get_locus ()); + + ctx->add_statement (assignment); +} + // Helper for sort_tuple_patterns. // Determine whether Patterns a and b are really the same pattern. // FIXME: This is a nasty hack to avoid properly implementing a comparison |