// Copyright (C) 2020-2025 Free Software Foundation, Inc.

// This file is part of GCC.

// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.

// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.

// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3.  If not see
// <http://www.gnu.org/licenses/>.

#include "rust-compile-pattern.h"
#include "rust-compile-expr.h"
#include "rust-compile-resolve-path.h"
#include "rust-constexpr.h"
#include "rust-compile-type.h"
#include "print-tree.h"

namespace Rust {
namespace Compile {

void
CompilePatternCheckExpr::visit (HIR::PathInExpression &pattern)
{
  // lookup the type
  TyTy::BaseType *lookup = nullptr;
  bool ok
    = ctx->get_tyctx ()->lookup_type (pattern.get_mappings ().get_hirid (),
				      &lookup);
  rust_assert (ok);

  // must be an ADT (?)
  rust_assert (lookup->get_kind () == TyTy::TypeKind::ADT);
  TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup);

  // if this isn't an enum, always succeed
  if (!adt->is_enum ())
    {
      check_expr = boolean_true_node;
      return;
    }

  // lookup the variant
  HirId variant_id;
  ok = ctx->get_tyctx ()->lookup_variant_definition (
    pattern.get_mappings ().get_hirid (), &variant_id);
  rust_assert (ok);

  TyTy::VariantDef *variant = nullptr;
  ok = adt->lookup_variant_by_id (variant_id, &variant);
  rust_assert (ok);

  // find discriminant field of scrutinee
  tree scrutinee_expr_qualifier_expr
    = Backend::struct_field_expression (match_scrutinee_expr, 0,
					pattern.get_locus ());

  // must be enum
  match_scrutinee_expr = scrutinee_expr_qualifier_expr;

  HIR::Expr &discrim_expr = variant->get_discriminant ();
  tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx);

  check_expr
    = Backend::comparison_expression (ComparisonOperator::EQUAL,
				      match_scrutinee_expr, discrim_expr_node,
				      pattern.get_locus ());
}

void
CompilePatternCheckExpr::visit (HIR::LiteralPattern &pattern)
{
  // Compile the literal
  auto litexpr = std::make_unique<HIR::LiteralExpr> (
    HIR::LiteralExpr (pattern.get_mappings (), pattern.get_literal (),
		      pattern.get_locus (), std::vector<AST::Attribute> ()));

  // Note: Floating point literals are currently accepted but will likely be
  // forbidden in LiteralPatterns in a future version of Rust.
  // See: https://github.com/rust-lang/rust/issues/41620
  // For now, we cannot compile them anyway as CASE_LABEL_EXPR does not support
  // floating point types.
  if (pattern.get_literal ().get_lit_type () == HIR::Literal::LitType::FLOAT)
    {
      rust_sorry_at (pattern.get_locus (), "floating-point literal in pattern");
    }

  tree lit = CompileExpr::Compile (*litexpr, ctx);

  check_expr = Backend::comparison_expression (ComparisonOperator::EQUAL,
					       match_scrutinee_expr, lit,
					       pattern.get_locus ());
}

static tree
compile_range_pattern_bound (HIR::RangePatternBound &bound,
			     Analysis::NodeMapping mappings, location_t locus,
			     Context *ctx)
{
  tree result = NULL_TREE;
  switch (bound.get_bound_type ())
    {
      case HIR::RangePatternBound::RangePatternBoundType::LITERAL: {
	auto &ref = static_cast<HIR::RangePatternBoundLiteral &> (bound);

	HIR::LiteralExpr litexpr (mappings, ref.get_literal (), locus,
				  std::vector<AST::Attribute> ());

	result = CompileExpr::Compile (litexpr, ctx);
      }
      break;

      case HIR::RangePatternBound::RangePatternBoundType::PATH: {
	auto &ref = static_cast<HIR::RangePatternBoundPath &> (bound);

	result = ResolvePathRef::Compile (ref.get_path (), ctx);

	// If the path resolves to a const expression, fold it.
	result = fold_expr (result);
      }
      break;

      case HIR::RangePatternBound::RangePatternBoundType::QUALPATH: {
	auto &ref = static_cast<HIR::RangePatternBoundQualPath &> (bound);

	result = ResolvePathRef::Compile (ref.get_qualified_path (), ctx);

	// If the path resolves to a const expression, fold it.
	result = fold_expr (result);
      }
    }

  return result;
}

void
CompilePatternCheckExpr::visit (HIR::RangePattern &pattern)
{
  tree upper = compile_range_pattern_bound (pattern.get_upper_bound (),
					    pattern.get_mappings (),
					    pattern.get_locus (), ctx);
  tree lower = compile_range_pattern_bound (pattern.get_lower_bound (),
					    pattern.get_mappings (),
					    pattern.get_locus (), ctx);

  tree check_lower
    = Backend::comparison_expression (ComparisonOperator::GREATER_OR_EQUAL,
				      match_scrutinee_expr, lower,
				      pattern.get_locus ());
  tree check_upper
    = Backend::comparison_expression (ComparisonOperator::LESS_OR_EQUAL,
				      match_scrutinee_expr, upper,
				      pattern.get_locus ());
  check_expr = Backend::arithmetic_or_logical_expression (
    ArithmeticOrLogicalOperator::BITWISE_AND, check_lower, check_upper,
    pattern.get_locus ());
}

void
CompilePatternCheckExpr::visit (HIR::ReferencePattern &pattern)
{
  match_scrutinee_expr
    = indirect_expression (match_scrutinee_expr, pattern.get_locus ());
  pattern.get_referenced_pattern ().accept_vis (*this);
}

void
CompilePatternCheckExpr::visit (HIR::AltPattern &pattern)
{
  auto &alts = pattern.get_alts ();

  check_expr = CompilePatternCheckExpr::Compile (*alts.at (0),
						 match_scrutinee_expr, ctx);
  auto end = alts.end ();
  for (auto i = alts.begin () + 1; i != end; i++)
    {
      tree next_expr
	= CompilePatternCheckExpr::Compile (**i, match_scrutinee_expr, ctx);
      check_expr = Backend::arithmetic_or_logical_expression (
	ArithmeticOrLogicalOperator::BITWISE_OR, check_expr, next_expr,
	(*i)->get_locus ());
    }
}

void
CompilePatternCheckExpr::visit (HIR::StructPattern &pattern)
{
  // lookup the type
  TyTy::BaseType *lookup = nullptr;
  bool ok = ctx->get_tyctx ()->lookup_type (
    pattern.get_path ().get_mappings ().get_hirid (), &lookup);
  rust_assert (ok);

  // this might be an enum
  rust_assert (lookup->get_kind () == TyTy::TypeKind::ADT);
  TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup);

  rust_assert (adt->number_of_variants () > 0);
  TyTy::VariantDef *variant = nullptr;
  if (adt->is_enum ())
    {
      // lookup the variant
      HirId variant_id;
      ok = ctx->get_tyctx ()->lookup_variant_definition (
	pattern.get_path ().get_mappings ().get_hirid (), &variant_id);
      rust_assert (ok);

      int variant_index = 0;
      ok = adt->lookup_variant_by_id (variant_id, &variant, &variant_index);
      rust_assert (ok);

      // find expected discriminant
      // // need to access qualifier the field, if we use QUAL_UNION_TYPE this
      // // would be DECL_QUALIFIER i think. For now this will just access the
      // // first record field and its respective qualifier because it will
      // // always be set because this is all a big special union
      HIR::Expr &discrim_expr = variant->get_discriminant ();
      tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx);

      // find discriminant field of scrutinee
      tree scrutinee_expr_qualifier_expr
	= Backend::struct_field_expression (match_scrutinee_expr, 0,
					    pattern.get_path ().get_locus ());

      check_expr
	= Backend::comparison_expression (ComparisonOperator::EQUAL,
					  scrutinee_expr_qualifier_expr,
					  discrim_expr_node,
					  pattern.get_path ().get_locus ());

      match_scrutinee_expr = scrutinee_expr_qualifier_expr;
    }
  else
    {
      variant = adt->get_variants ().at (0);
      check_expr = boolean_true_node;
    }

  auto &struct_pattern_elems = pattern.get_struct_pattern_elems ();
  for (auto &field : struct_pattern_elems.get_struct_pattern_fields ())
    {
      switch (field->get_item_type ())
	{
	  case HIR::StructPatternField::ItemType::TUPLE_PAT: {
	    // TODO
	    rust_unreachable ();
	  }
	  break;

	  case HIR::StructPatternField::ItemType::IDENT_PAT: {
	    HIR::StructPatternFieldIdentPat &ident
	      = static_cast<HIR::StructPatternFieldIdentPat &> (*field.get ());

	    size_t offs = 0;
	    ok = variant->lookup_field (ident.get_identifier ().as_string (),
					nullptr, &offs);
	    rust_assert (ok);

	    // we may be offsetting by + 1 here since the first field in the
	    // record is always the discriminator
	    offs += adt->is_enum ();
	    tree field_expr
	      = Backend::struct_field_expression (match_scrutinee_expr, offs,
						  ident.get_locus ());

	    tree check_expr_sub
	      = CompilePatternCheckExpr::Compile (ident.get_pattern (),
						  field_expr, ctx);
	    check_expr = Backend::arithmetic_or_logical_expression (
	      ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
	      check_expr_sub, ident.get_pattern ().get_locus ());
	  }
	  break;

	  case HIR::StructPatternField::ItemType::IDENT: {
	    // ident pattern always matches - do nothing
	  }
	  break;
	}
    }
}

void
CompilePatternCheckExpr::visit (HIR::TupleStructPattern &pattern)
{
  // lookup the type
  TyTy::BaseType *lookup = nullptr;
  bool ok = ctx->get_tyctx ()->lookup_type (
    pattern.get_path ().get_mappings ().get_hirid (), &lookup);
  rust_assert (ok);

  // this might be an enum
  rust_assert (lookup->get_kind () == TyTy::TypeKind::ADT);
  TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup);

  int variant_index = 0;
  rust_assert (adt->number_of_variants () > 0);
  TyTy::VariantDef *variant = nullptr;
  if (adt->is_enum ())
    {
      // lookup the variant
      HirId variant_id;
      ok = ctx->get_tyctx ()->lookup_variant_definition (
	pattern.get_path ().get_mappings ().get_hirid (), &variant_id);
      rust_assert (ok);

      ok = adt->lookup_variant_by_id (variant_id, &variant, &variant_index);
      rust_assert (ok);

      // find expected discriminant
      HIR::Expr &discrim_expr = variant->get_discriminant ();
      tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx);

      // find discriminant field of scrutinee
      tree scrutinee_expr_qualifier_expr
	= Backend::struct_field_expression (match_scrutinee_expr, 0,
					    pattern.get_path ().get_locus ());

      check_expr
	= Backend::comparison_expression (ComparisonOperator::EQUAL,
					  scrutinee_expr_qualifier_expr,
					  discrim_expr_node,
					  pattern.get_path ().get_locus ());
    }
  else
    {
      variant = adt->get_variants ().at (0);
      check_expr = boolean_true_node;
    }

  HIR::TupleStructItems &items = pattern.get_items ();
  switch (items.get_item_type ())
    {
      case HIR::TupleStructItems::RANGED: {
	// TODO
	rust_unreachable ();
      }
      break;

      case HIR::TupleStructItems::MULTIPLE: {
	HIR::TupleStructItemsNoRange &items_no_range
	  = static_cast<HIR::TupleStructItemsNoRange &> (items);

	rust_assert (items_no_range.get_patterns ().size ()
		     == variant->num_fields ());

	size_t tuple_field_index = 0;
	for (auto &pattern : items_no_range.get_patterns ())
	  {
	    // find payload union field of scrutinee
	    tree payload_ref
	      = Backend::struct_field_expression (match_scrutinee_expr, 1,
						  pattern->get_locus ());

	    tree variant_ref
	      = Backend::struct_field_expression (payload_ref, variant_index,
						  pattern->get_locus ());

	    tree field_expr
	      = Backend::struct_field_expression (variant_ref,
						  tuple_field_index++,
						  pattern->get_locus ());

	    tree check_expr_sub
	      = CompilePatternCheckExpr::Compile (*pattern, field_expr, ctx);
	    check_expr = Backend::arithmetic_or_logical_expression (
	      ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
	      check_expr_sub, pattern->get_locus ());
	  }
      }
      break;
    }
}

void
CompilePatternCheckExpr::visit (HIR::TuplePattern &pattern)
{
  check_expr = boolean_true_node;

  switch (pattern.get_items ().get_item_type ())
    {
      case HIR::TuplePatternItems::RANGED: {
	// TODO
	gcc_unreachable ();
      }
      break;

      case HIR::TuplePatternItems::MULTIPLE: {
	auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
	  pattern.get_items ());
	size_t tuple_field_index = 0;

	for (auto &pat : items.get_patterns ())
	  {
	    tree field_expr
	      = Backend::struct_field_expression (match_scrutinee_expr,
						  tuple_field_index++,
						  pat->get_locus ());

	    tree check_expr_sub
	      = CompilePatternCheckExpr::Compile (*pat, field_expr, ctx);
	    check_expr = Backend::arithmetic_or_logical_expression (
	      ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
	      check_expr_sub, pat->get_locus ());
	  }
      }
    }
}

// setup the bindings

void
CompilePatternBindings::visit (HIR::TupleStructPattern &pattern)
{
  // lookup the type
  TyTy::BaseType *lookup = nullptr;
  bool ok = ctx->get_tyctx ()->lookup_type (
    pattern.get_path ().get_mappings ().get_hirid (), &lookup);
  rust_assert (ok);

  // this must be an enum
  rust_assert (lookup->get_kind () == TyTy::TypeKind::ADT);
  TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup);
  rust_assert (adt->number_of_variants () > 0);

  int variant_index = 0;
  TyTy::VariantDef *variant = adt->get_variants ().at (0);
  if (adt->is_enum ())
    {
      HirId variant_id = UNKNOWN_HIRID;
      bool ok = ctx->get_tyctx ()->lookup_variant_definition (
	pattern.get_path ().get_mappings ().get_hirid (), &variant_id);
      rust_assert (ok);

      ok = adt->lookup_variant_by_id (variant_id, &variant, &variant_index);
      rust_assert (ok);
    }

  rust_assert (variant->get_variant_type ()
	       == TyTy::VariantDef::VariantType::TUPLE);

  HIR::TupleStructItems &items = pattern.get_items ();
  switch (items.get_item_type ())
    {
      case HIR::TupleStructItems::RANGED: {
	// TODO
	rust_unreachable ();
      }
      break;

      case HIR::TupleStructItems::MULTIPLE: {
	HIR::TupleStructItemsNoRange &items_no_range
	  = static_cast<HIR::TupleStructItemsNoRange &> (items);

	rust_assert (items_no_range.get_patterns ().size ()
		     == variant->num_fields ());

	if (adt->is_enum ())
	  {
	    size_t tuple_field_index = 0;
	    for (auto &pattern : items_no_range.get_patterns ())
	      {
		tree payload_accessor_union
		  = Backend::struct_field_expression (match_scrutinee_expr, 1,
						      pattern->get_locus ());

		tree variant_accessor
		  = Backend::struct_field_expression (payload_accessor_union,
						      variant_index,
						      pattern->get_locus ());

		tree binding
		  = Backend::struct_field_expression (variant_accessor,
						      tuple_field_index++,
						      pattern->get_locus ());

		CompilePatternBindings::Compile (*pattern, binding, ctx);
	      }
	  }
	else
	  {
	    size_t tuple_field_index = 0;
	    for (auto &pattern : items_no_range.get_patterns ())
	      {
		tree variant_accessor = match_scrutinee_expr;

		tree binding
		  = Backend::struct_field_expression (variant_accessor,
						      tuple_field_index++,
						      pattern->get_locus ());

		CompilePatternBindings::Compile (*pattern, binding, ctx);
	      }
	  }
      }
      break;
    }
}

void
CompilePatternBindings::visit (HIR::StructPattern &pattern)
{
  // lookup the type
  TyTy::BaseType *lookup = nullptr;
  bool ok = ctx->get_tyctx ()->lookup_type (
    pattern.get_path ().get_mappings ().get_hirid (), &lookup);
  rust_assert (ok);

  // this must be an enum
  rust_assert (lookup->get_kind () == TyTy::TypeKind::ADT);
  TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup);
  rust_assert (adt->number_of_variants () > 0);

  int variant_index = 0;
  TyTy::VariantDef *variant = adt->get_variants ().at (0);
  if (adt->is_enum ())
    {
      HirId variant_id = UNKNOWN_HIRID;
      bool ok = ctx->get_tyctx ()->lookup_variant_definition (
	pattern.get_path ().get_mappings ().get_hirid (), &variant_id);
      rust_assert (ok);

      ok = adt->lookup_variant_by_id (variant_id, &variant, &variant_index);
      rust_assert (ok);
    }

  rust_assert (variant->get_variant_type ()
	       == TyTy::VariantDef::VariantType::STRUCT);

  auto &struct_pattern_elems = pattern.get_struct_pattern_elems ();
  for (auto &field : struct_pattern_elems.get_struct_pattern_fields ())
    {
      switch (field->get_item_type ())
	{
	  case HIR::StructPatternField::ItemType::TUPLE_PAT: {
	    // TODO
	    rust_unreachable ();
	  }
	  break;

	  case HIR::StructPatternField::ItemType::IDENT_PAT: {
	    // TODO
	    rust_unreachable ();
	  }
	  break;

	  case HIR::StructPatternField::ItemType::IDENT: {
	    HIR::StructPatternFieldIdent &ident
	      = static_cast<HIR::StructPatternFieldIdent &> (*field.get ());

	    size_t offs = 0;
	    ok = variant->lookup_field (ident.get_identifier ().as_string (),
					nullptr, &offs);
	    rust_assert (ok);

	    tree binding = error_mark_node;
	    if (adt->is_enum ())
	      {
		tree payload_accessor_union
		  = Backend::struct_field_expression (match_scrutinee_expr, 1,
						      ident.get_locus ());

		tree variant_accessor
		  = Backend::struct_field_expression (payload_accessor_union,
						      variant_index,
						      ident.get_locus ());

		binding
		  = Backend::struct_field_expression (variant_accessor, offs,
						      ident.get_locus ());
	      }
	    else
	      {
		tree variant_accessor = match_scrutinee_expr;
		binding
		  = Backend::struct_field_expression (variant_accessor, offs,
						      ident.get_locus ());
	      }

	    ctx->insert_pattern_binding (ident.get_mappings ().get_hirid (),
					 binding);
	  }
	  break;
	}
    }
}

void
CompilePatternBindings::visit (HIR::ReferencePattern &pattern)
{
  tree derefed
    = indirect_expression (match_scrutinee_expr, pattern.get_locus ());

  CompilePatternBindings::Compile (pattern.get_referenced_pattern (), derefed,
				   ctx);
}

void
CompilePatternBindings::visit (HIR::IdentifierPattern &pattern)
{
  if (!pattern.get_is_ref ())
    {
      ctx->insert_pattern_binding (pattern.get_mappings ().get_hirid (),
				   match_scrutinee_expr);
      return;
    }

  tree ref = address_expression (match_scrutinee_expr,
				 EXPR_LOCATION (match_scrutinee_expr));
  ctx->insert_pattern_binding (pattern.get_mappings ().get_hirid (), ref);
}

void
CompilePatternBindings::visit (HIR::TuplePattern &pattern)
{
  rust_assert (pattern.has_tuple_pattern_items ());

  // lookup the type
  TyTy::BaseType *ty = nullptr;
  bool ok
    = ctx->get_tyctx ()->lookup_type (pattern.get_mappings ().get_hirid (),
				      &ty);
  rust_assert (ok);

  switch (pattern.get_items ().get_item_type ())
    {
      case HIR::TuplePatternItems::ItemType::RANGED: {
	size_t tuple_idx = 0;
	auto &items
	  = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ());

	auto &items_lower = items.get_lower_patterns ();
	auto &items_upper = items.get_upper_patterns ();

	for (auto &sub : items_lower)
	  {
	    TyTy::BaseType *ty_sub = nullptr;
	    HirId sub_id = sub->get_mappings ().get_hirid ();
	    bool ok = ctx->get_tyctx ()->lookup_type (sub_id, &ty_sub);
	    rust_assert (ok);

	    tree sub_init
	      = Backend::struct_field_expression (match_scrutinee_expr,
						  tuple_idx, sub->get_locus ());

	    CompilePatternBindings::Compile (*sub.get (), sub_init, ctx);
	    tuple_idx++;
	  }

	rust_assert (ty->get_kind () == TyTy::TypeKind::TUPLE);
	tuple_idx = static_cast<TyTy::TupleType &> (*ty).num_fields ()
		    - items_upper.size ();

	for (auto &sub : items_upper)
	  {
	    TyTy::BaseType *ty_sub = nullptr;
	    HirId sub_id = sub->get_mappings ().get_hirid ();
	    bool ok = ctx->get_tyctx ()->lookup_type (sub_id, &ty_sub);
	    rust_assert (ok);

	    tree sub_init
	      = Backend::struct_field_expression (match_scrutinee_expr,
						  tuple_idx, sub->get_locus ());
	    CompilePatternBindings::Compile (*sub.get (), sub_init, ctx);
	    tuple_idx++;
	  }

	return;
      }
      case HIR::TuplePatternItems::ItemType::MULTIPLE: {
	size_t tuple_idx = 0;
	auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
	  pattern.get_items ());

	for (auto &sub : items.get_patterns ())
	  {
	    TyTy::BaseType *ty_sub = nullptr;
	    HirId sub_id = sub->get_mappings ().get_hirid ();
	    bool ok = ctx->get_tyctx ()->lookup_type (sub_id, &ty_sub);
	    rust_assert (ok);

	    tree sub_init
	      = Backend::struct_field_expression (match_scrutinee_expr,
						  tuple_idx, sub->get_locus ());
	    CompilePatternBindings::Compile (*sub.get (), sub_init, ctx);
	    tuple_idx++;
	  }

	return;
      }
      default: {
	rust_unreachable ();
      }
    }
}

//

void
CompilePatternLet::visit (HIR::IdentifierPattern &pattern)
{
  Bvariable *var = nullptr;
  rust_assert (
    ctx->lookup_var_decl (pattern.get_mappings ().get_hirid (), &var));

  auto fnctx = ctx->peek_fn ();
  if (ty->is_unit ())
    {
      ctx->add_statement (init_expr);

      auto unit_type_init_expr = unit_expression (rval_locus);
      auto s = Backend::init_statement (fnctx.fndecl, var, unit_type_init_expr);
      ctx->add_statement (s);
    }
  else
    {
      auto s = Backend::init_statement (fnctx.fndecl, var, init_expr);
      ctx->add_statement (s);
    }
}

void
CompilePatternLet::visit (HIR::WildcardPattern &pattern)
{
  tree init_stmt = NULL;
  tree stmt_type = TyTyResolveCompile::compile (ctx, ty);

  Backend::temporary_variable (ctx->peek_fn ().fndecl, NULL_TREE, stmt_type,
			       init_expr, false, pattern.get_locus (),
			       &init_stmt);

  ctx->add_statement (init_stmt);
}

void
CompilePatternLet::visit (HIR::TuplePattern &pattern)
{
  rust_assert (pattern.has_tuple_pattern_items ());

  tree tuple_type = TyTyResolveCompile::compile (ctx, ty);
  tree init_stmt;
  Bvariable *tmp_var
    = Backend::temporary_variable (ctx->peek_fn ().fndecl, NULL_TREE,
				   tuple_type, init_expr, false,
				   pattern.get_locus (), &init_stmt);
  tree access_expr = Backend::var_expression (tmp_var, pattern.get_locus ());
  ctx->add_statement (init_stmt);

  switch (pattern.get_items ().get_item_type ())
    {
      case HIR::TuplePatternItems::ItemType::RANGED: {
	size_t tuple_idx = 0;
	auto &items
	  = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ());

	auto &items_lower = items.get_lower_patterns ();
	auto &items_upper = items.get_upper_patterns ();

	for (auto &sub : items_lower)
	  {
	    TyTy::BaseType *ty_sub = nullptr;
	    HirId sub_id = sub->get_mappings ().get_hirid ();
	    bool ok = ctx->get_tyctx ()->lookup_type (sub_id, &ty_sub);
	    rust_assert (ok);

	    tree sub_init
	      = Backend::struct_field_expression (access_expr, tuple_idx,
						  sub->get_locus ());
	    CompilePatternLet::Compile (sub.get (), sub_init, ty_sub,
					rval_locus, ctx);
	    tuple_idx++;
	  }

	rust_assert (ty->get_kind () == TyTy::TypeKind::TUPLE);
	tuple_idx = static_cast<TyTy::TupleType &> (*ty).num_fields ()
		    - items_upper.size ();

	for (auto &sub : items_upper)
	  {
	    TyTy::BaseType *ty_sub = nullptr;
	    HirId sub_id = sub->get_mappings ().get_hirid ();
	    bool ok = ctx->get_tyctx ()->lookup_type (sub_id, &ty_sub);
	    rust_assert (ok);

	    tree sub_init
	      = Backend::struct_field_expression (access_expr, tuple_idx,
						  sub->get_locus ());
	    CompilePatternLet::Compile (sub.get (), sub_init, ty_sub,
					rval_locus, ctx);
	    tuple_idx++;
	  }

	return;
      }
      case HIR::TuplePatternItems::ItemType::MULTIPLE: {
	size_t tuple_idx = 0;
	auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
	  pattern.get_items ());

	for (auto &sub : items.get_patterns ())
	  {
	    TyTy::BaseType *ty_sub = nullptr;
	    HirId sub_id = sub->get_mappings ().get_hirid ();
	    bool ok = ctx->get_tyctx ()->lookup_type (sub_id, &ty_sub);
	    rust_assert (ok);

	    tree sub_init
	      = Backend::struct_field_expression (access_expr, tuple_idx,
						  sub->get_locus ());
	    CompilePatternLet::Compile (sub.get (), sub_init, ty_sub,
					rval_locus, ctx);
	    tuple_idx++;
	  }

	return;
      }
      default: {
	rust_unreachable ();
      }
    }
}

} // namespace Compile
} // namespace Rust
