// Copyright (C) 2025-2026 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-readonly-check.h"
#include "rust-hir-expr.h"
#include "rust-hir-node.h"
#include "rust-hir-path.h"
#include "rust-hir-map.h"
#include "rust-hir-pattern.h"
#include "rust-mapping-common.h"
#include "rust-system.h"
#include "rust-immutable-name-resolution-context.h"
#include "rust-tyty.h"

namespace Rust {
namespace HIR {

static std::set<HirId> already_assigned_variables = {};

ReadonlyChecker::ReadonlyChecker ()
  : resolver (*Resolver::Resolver::get ()),
    mappings (Analysis::Mappings::get ()),
    context (*Resolver::TypeCheckContext::get ())
{}

void
ReadonlyChecker::go (Crate &crate)
{
  for (auto &item : crate.get_items ())
    item->accept_vis (*this);
}

void
ReadonlyChecker::visit (AssignmentExpr &expr)
{
  Expr &lhs = expr.get_lhs ();
  mutable_context.enter (expr.get_mappings ().get_hirid ());
  lhs.accept_vis (*this);
  mutable_context.exit ();
}

void
ReadonlyChecker::visit (PathInExpression &expr)
{
  if (!mutable_context.is_in_context ())
    return;

  NodeId ast_node_id = expr.get_mappings ().get_nodeid ();
  NodeId def_id;

  auto &nr_ctx
    = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
  if (auto id = nr_ctx.lookup (ast_node_id))
    def_id = *id;
  else
    return;

  auto hir_id = mappings.lookup_node_to_hir (def_id);
  if (!hir_id)
    return;

  // Check if the local variable is mutable.
  auto maybe_pattern = mappings.lookup_hir_pattern (*hir_id);
  if (maybe_pattern
      && maybe_pattern.value ()->get_pattern_type ()
	   == HIR::Pattern::PatternType::IDENTIFIER)
    check_variable (static_cast<IdentifierPattern *> (maybe_pattern.value ()),
		    expr.get_locus ());

  // Check if the static item is mutable.
  auto maybe_item = mappings.lookup_hir_item (*hir_id);
  if (maybe_item
      && maybe_item.value ()->get_item_kind () == HIR::Item::ItemKind::Static)
    {
      auto static_item = static_cast<HIR::StaticItem *> (*maybe_item);
      if (!static_item->is_mut ())
	rust_error_at (expr.get_locus (),
		       "assignment of read-only location '%s'",
		       static_item->get_identifier ().as_string ().c_str ());
    }

  // Check if the constant item is mutable.
  if (maybe_item
      && maybe_item.value ()->get_item_kind () == HIR::Item::ItemKind::Constant)
    {
      auto const_item = static_cast<HIR::ConstantItem *> (*maybe_item);
      rust_error_at (expr.get_locus (), "assignment of read-only location '%s'",
		     const_item->get_identifier ().as_string ().c_str ());
    }
}

void
ReadonlyChecker::check_variable (IdentifierPattern *pattern,
				 location_t assigned_loc)
{
  if (!mutable_context.is_in_context ())
    return;

  TyTy::BaseType *type;
  if (context.lookup_type (pattern->get_mappings ().get_hirid (), &type)
      && is_mutable_type (type))
    return;
  if (pattern->is_mut ())
    return;

  auto hir_id = pattern->get_mappings ().get_hirid ();
  if (already_assigned_variables.count (hir_id) > 0)
    rust_error_at (assigned_loc, "assignment of read-only variable '%s'",
		   pattern->to_string ().c_str ());
  already_assigned_variables.insert (hir_id);
}

void
ReadonlyChecker::collect_assignment_identifier (IdentifierPattern &pattern,
						bool has_init_expr)
{
  if (has_init_expr)
    {
      HirId pattern_id = pattern.get_mappings ().get_hirid ();
      already_assigned_variables.insert (pattern_id);
    }
}

void
ReadonlyChecker::collect_assignment_tuple (TuplePattern &tuple_pattern,
					   bool has_init_expr)
{
  switch (tuple_pattern.get_items ().get_item_type ())
    {
    case HIR::TuplePatternItems::ItemType::NO_REST:
      {
	auto &items_no_rest = static_cast<HIR::TuplePatternItemsNoRest &> (
	  tuple_pattern.get_items ());
	for (auto &sub : items_no_rest.get_patterns ())
	  {
	    collect_assignment (*sub, has_init_expr);
	  }
      }
      break;
    case HIR::TuplePatternItems::ItemType::HAS_REST:
      {
	auto &items_has_rest = static_cast<HIR::TuplePatternItemsHasRest &> (
	  tuple_pattern.get_items ());
	for (auto &sub : items_has_rest.get_lower_patterns ())
	  collect_assignment (*sub, has_init_expr);
	for (auto &sub : items_has_rest.get_upper_patterns ())
	  collect_assignment (*sub, has_init_expr);
      }
      break;
    default:
      break;
    }
}

void
ReadonlyChecker::collect_assignment (Pattern &pattern, bool has_init_expr)
{
  switch (pattern.get_pattern_type ())
    {
    case HIR::Pattern::PatternType::IDENTIFIER:
      {
	collect_assignment_identifier (static_cast<IdentifierPattern &> (
					 pattern),
				       has_init_expr);
      }
      break;
    case HIR::Pattern::PatternType::TUPLE:
      {
	auto &tuple_pattern = static_cast<HIR::TuplePattern &> (pattern);
	collect_assignment_tuple (tuple_pattern, has_init_expr);
      }
      break;
    default:
      break;
    }
}

void
ReadonlyChecker::visit (LetStmt &stmt)
{
  HIR::Pattern &pattern = stmt.get_pattern ();
  collect_assignment (pattern, stmt.has_init_expr ());
}

void
ReadonlyChecker::visit (FieldAccessExpr &expr)
{
  if (mutable_context.is_in_context ())
    {
      expr.get_receiver_expr ().accept_vis (*this);
    }
}

void
ReadonlyChecker::visit (TupleIndexExpr &expr)
{
  if (mutable_context.is_in_context ())
    {
      expr.get_tuple_expr ().accept_vis (*this);
    }
}

void
ReadonlyChecker::visit (ArrayIndexExpr &expr)
{
  if (mutable_context.is_in_context ())
    {
      expr.get_array_expr ().accept_vis (*this);
    }
}

void
ReadonlyChecker::visit (TupleExpr &expr)
{
  if (mutable_context.is_in_context ())
    {
      // TODO: Add check for tuple expression
    }
}

void
ReadonlyChecker::visit (LiteralExpr &expr)
{
  if (mutable_context.is_in_context ())
    {
      rust_error_at (expr.get_locus (), "assignment of read-only location");
    }
}

void
ReadonlyChecker::visit (DereferenceExpr &expr)
{
  if (!mutable_context.is_in_context ())
    return;
  TyTy::BaseType *to_deref_type;
  auto to_deref = expr.get_expr ().get_mappings ().get_hirid ();
  if (!context.lookup_type (to_deref, &to_deref_type))
    return;
  if (!is_mutable_type (to_deref_type))
    rust_error_at (expr.get_locus (), "assignment of read-only location");
}

bool
ReadonlyChecker::is_mutable_type (TyTy::BaseType *type)
{
  if (type->get_kind () == TyTy::TypeKind::REF)
    return static_cast<TyTy::ReferenceType *> (type)->is_mutable ();
  if (type->get_kind () == TyTy::TypeKind::POINTER)
    return static_cast<TyTy::PointerType *> (type)->is_mutable ();
  return false;
}
} // namespace HIR
} // namespace Rust
