// 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-ast-lower-pattern.h"
#include "rust-ast-lower-expr.h"
#include "rust-system.h"

namespace Rust {
namespace HIR {

ASTLoweringPattern::ASTLoweringPattern () : translated (nullptr) {}

HIR::Pattern *
ASTLoweringPattern::translate (AST::Pattern &pattern, bool is_let_top_level)
{
  ASTLoweringPattern resolver;
  resolver.is_let_top_level = is_let_top_level;
  pattern.accept_vis (resolver);

  rust_assert (resolver.translated != nullptr);

  resolver.mappings.insert_hir_pattern (resolver.translated);
  resolver.mappings.insert_location (
    resolver.translated->get_mappings ().get_hirid (), pattern.get_locus ());

  return resolver.translated;
}

void
ASTLoweringPattern::visit (AST::IdentifierPattern &pattern)
{
  auto crate_num = mappings.get_current_crate ();
  Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
				 mappings.get_next_hir_id (crate_num),
				 UNKNOWN_LOCAL_DEFID);

  std::unique_ptr<Pattern> to_bind;
  translated
    = new HIR::IdentifierPattern (mapping, pattern.get_ident (),
				  pattern.get_locus (), pattern.get_is_ref (),
				  pattern.get_is_mut () ? Mutability::Mut
							: Mutability::Imm,
				  std::move (to_bind));
}

void
ASTLoweringPattern::visit (AST::PathInExpression &pattern)
{
  translated = ASTLowerPathInExpression::translate (pattern);
}

void
ASTLoweringPattern::visit (AST::TupleStructPattern &pattern)
{
  HIR::PathInExpression *path
    = ASTLowerPathInExpression::translate (pattern.get_path ());

  TupleStructItems *lowered = nullptr;
  auto &items = pattern.get_items ();
  switch (items.get_item_type ())
    {
      case AST::TupleStructItems::RANGE: {
	// TODO
	rust_unreachable ();
      }
      break;

      case AST::TupleStructItems::NO_RANGE: {
	AST::TupleStructItemsNoRange &items_no_range
	  = static_cast<AST::TupleStructItemsNoRange &> (items);

	std::vector<std::unique_ptr<HIR::Pattern>> patterns;
	for (auto &inner_pattern : items_no_range.get_patterns ())
	  {
	    HIR::Pattern *p = ASTLoweringPattern::translate (*inner_pattern);
	    patterns.push_back (std::unique_ptr<HIR::Pattern> (p));
	  }

	lowered = new HIR::TupleStructItemsNoRange (std::move (patterns));
      }
      break;
    }

  auto crate_num = mappings.get_current_crate ();
  Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
				 mappings.get_next_hir_id (crate_num),
				 UNKNOWN_LOCAL_DEFID);

  translated = new HIR::TupleStructPattern (
    mapping, *path, std::unique_ptr<HIR::TupleStructItems> (lowered));
}

void
ASTLoweringPattern::visit (AST::StructPattern &pattern)
{
  HIR::PathInExpression *path
    = ASTLowerPathInExpression::translate (pattern.get_path ());

  auto &raw_elems = pattern.get_struct_pattern_elems ();
  rust_assert (!raw_elems.has_etc ());

  std::vector<std::unique_ptr<HIR::StructPatternField>> fields;
  for (auto &field : raw_elems.get_struct_pattern_fields ())
    {
      HIR::StructPatternField *f = nullptr;
      switch (field->get_item_type ())
	{
	  case AST::StructPatternField::ItemType::TUPLE_PAT: {
	    auto &tuple
	      = static_cast<AST::StructPatternFieldTuplePat &> (*field);

	    auto crate_num = mappings.get_current_crate ();
	    Analysis::NodeMapping mapping (crate_num, tuple.get_node_id (),
					   mappings.get_next_hir_id (crate_num),
					   UNKNOWN_LOCAL_DEFID);

	    std::unique_ptr<HIR::Pattern> pat (
	      ASTLoweringPattern::translate (tuple.get_index_pattern ()));

	    f = new HIR::StructPatternFieldTuplePat (mapping,
						     tuple.get_index (),
						     std::move (pat),
						     tuple.get_outer_attrs (),
						     tuple.get_locus ());
	  }
	  break;

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

	    auto crate_num = mappings.get_current_crate ();
	    Analysis::NodeMapping mapping (crate_num, ident.get_node_id (),
					   mappings.get_next_hir_id (crate_num),
					   UNKNOWN_LOCAL_DEFID);

	    std::unique_ptr<HIR::Pattern> pat (
	      ASTLoweringPattern::translate (ident.get_ident_pattern ()));

	    f = new HIR::StructPatternFieldIdentPat (mapping,
						     ident.get_identifier (),
						     std::move (pat),
						     ident.get_outer_attrs (),
						     ident.get_locus ());
	  }
	  break;

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

	    auto crate_num = mappings.get_current_crate ();
	    Analysis::NodeMapping mapping (crate_num, ident.get_node_id (),
					   mappings.get_next_hir_id (crate_num),
					   UNKNOWN_LOCAL_DEFID);

	    f = new HIR::StructPatternFieldIdent (
	      mapping, ident.get_identifier (), ident.is_ref (),
	      ident.is_mut () ? Mutability::Mut : Mutability::Imm,
	      ident.get_outer_attrs (), ident.get_locus ());
	  }
	  break;
	}

      // insert the reverse mappings and locations
      auto field_id = f->get_mappings ().get_hirid ();
      auto field_node_id = f->get_mappings ().get_nodeid ();
      mappings.insert_location (field_id, f->get_locus ());
      mappings.insert_node_to_hir (field_node_id, field_id);

      // add it to the lowered fields list
      fields.push_back (std::unique_ptr<HIR::StructPatternField> (f));
    }

  auto crate_num = mappings.get_current_crate ();
  Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
				 mappings.get_next_hir_id (crate_num),
				 UNKNOWN_LOCAL_DEFID);

  HIR::StructPatternElements elems (std::move (fields));
  translated = new HIR::StructPattern (mapping, *path, std::move (elems));
}

void
ASTLoweringPattern::visit (AST::WildcardPattern &pattern)
{
  auto crate_num = mappings.get_current_crate ();
  Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
				 mappings.get_next_hir_id (crate_num),
				 UNKNOWN_LOCAL_DEFID);

  translated = new HIR::WildcardPattern (mapping, pattern.get_locus ());
}

void
ASTLoweringPattern::visit (AST::TuplePattern &pattern)
{
  std::unique_ptr<HIR::TuplePatternItems> items;
  switch (pattern.get_items ().get_pattern_type ())
    {
      case AST::TuplePatternItems::TuplePatternItemType::MULTIPLE: {
	AST::TuplePatternItemsMultiple &ref
	  = static_cast<AST::TuplePatternItemsMultiple &> (
	    pattern.get_items ());
	items = lower_tuple_pattern_multiple (ref);
      }
      break;

      case AST::TuplePatternItems::TuplePatternItemType::RANGED: {
	AST::TuplePatternItemsRanged &ref
	  = static_cast<AST::TuplePatternItemsRanged &> (pattern.get_items ());
	items = lower_tuple_pattern_ranged (ref);
      }
      break;
    }

  auto crate_num = mappings.get_current_crate ();
  Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
				 mappings.get_next_hir_id (crate_num),
				 UNKNOWN_LOCAL_DEFID);

  translated
    = new HIR::TuplePattern (mapping, std::move (items), pattern.get_locus ());
}

void
ASTLoweringPattern::visit (AST::LiteralPattern &pattern)
{
  auto crate_num = mappings.get_current_crate ();
  Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
				 mappings.get_next_hir_id (crate_num),
				 UNKNOWN_LOCAL_DEFID);

  HIR::Literal l = lower_literal (pattern.get_literal ());
  translated
    = new HIR::LiteralPattern (mapping, std::move (l), pattern.get_locus ());
}

void
ASTLoweringPattern::visit (AST::RangePattern &pattern)
{
  if (pattern.get_range_kind () == AST::RangeKind::EXCLUDED)
    rust_unreachable (); // Not supported yet
  auto upper_bound = lower_range_pattern_bound (pattern.get_upper_bound ());
  auto lower_bound = lower_range_pattern_bound (pattern.get_lower_bound ());

  auto crate_num = mappings.get_current_crate ();
  Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
				 mappings.get_next_hir_id (crate_num),
				 UNKNOWN_LOCAL_DEFID);

  translated
    = new HIR::RangePattern (mapping, std::move (lower_bound),
			     std::move (upper_bound), pattern.get_locus ());
}

void
ASTLoweringPattern::visit (AST::GroupedPattern &pattern)
{
  is_let_top_level = false;
  pattern.get_pattern_in_parens ().accept_vis (*this);
}

void
ASTLoweringPattern::visit (AST::ReferencePattern &pattern)
{
  auto crate_num = mappings.get_current_crate ();
  Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
				 mappings.get_next_hir_id (crate_num),
				 UNKNOWN_LOCAL_DEFID);

  HIR::Pattern *inner
    = ASTLoweringPattern::translate (pattern.get_referenced_pattern ());

  translated
    = new HIR::ReferencePattern (mapping, std::unique_ptr<HIR::Pattern> (inner),
				 pattern.get_is_mut () ? Mutability::Mut
						       : Mutability::Imm,
				 pattern.get_locus ());

  if (pattern.is_double_reference ())
    {
      Analysis::NodeMapping mapping2 (crate_num, pattern.get_node_id (),
				      mappings.get_next_hir_id (crate_num),
				      UNKNOWN_LOCAL_DEFID);
      translated
	= new HIR::ReferencePattern (mapping2,
				     std::unique_ptr<HIR::Pattern> (translated),
				     Mutability::Imm, pattern.get_locus ());
    }
}

void
ASTLoweringPattern::visit (AST::SlicePattern &pattern)
{
  std::vector<std::unique_ptr<HIR::Pattern>> items;
  for (auto &p : pattern.get_items ())
    {
      HIR::Pattern *item = ASTLoweringPattern::translate (*p);
      items.push_back (std::unique_ptr<HIR::Pattern> (item));
    }

  auto crate_num = mappings.get_current_crate ();
  Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
				 mappings.get_next_hir_id (crate_num),
				 UNKNOWN_LOCAL_DEFID);

  translated
    = new HIR::SlicePattern (mapping, std::move (items), pattern.get_locus ());
}

void
ASTLoweringPattern::visit (AST::AltPattern &pattern)
{
  auto crate_num = mappings.get_current_crate ();
  Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
				 mappings.get_next_hir_id (crate_num),
				 UNKNOWN_LOCAL_DEFID);

  std::vector<std::unique_ptr<HIR::Pattern>> alts;

  for (auto &alt : pattern.get_alts ())
    {
      alts.push_back (
	std::unique_ptr<HIR::Pattern> (ASTLoweringPattern::translate (*alt)));
    }

  translated
    = new HIR::AltPattern (mapping, std::move (alts), pattern.get_locus ());

  if (is_let_top_level)
    {
      rich_location richloc (line_table, pattern.get_locus ());
      richloc.add_fixit_replace ("use an outer grouped pattern");
      rust_error_at (
	richloc, "top level or-patterns are not allowed for %<let%> bindings");
    }
}

} // namespace HIR
} // namespace Rust
