// 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/>.

#ifndef RUST_RIB_H
#define RUST_RIB_H

#include "rust-system.h"
#include "rust-ast.h"
#include "optional.h"
#include "expected.h"

namespace Rust {
namespace Resolver2_0 {

/**

pub enum Namespace {
   /// The type namespace includes `struct`s, `enum`s, `union`s, `trait`s, and
`mod`s
   /// (and, by extension, crates).
   ///
   /// Note that the type namespace includes other items; this is not an
   /// exhaustive list.
   TypeNS,
   /// The value namespace includes `fn`s, `const`s, `static`s, and local
variables (including function arguments). ValueNS,
   /// The macro namespace includes `macro_rules!` macros, declarative `macro`s,
   /// procedural macros, attribute macros, `derive` macros, and non-macro
attributes
   /// like `#[inline]` and `#[rustfmt::skip]`.
   MacroNS,
}

*/

// FIXME: There's no `labels` namespace, not sure if we need one or how to keep
// one
// FIXME: And where are things like loop labels kept?

/**
 * All namespaces that Rust's name resolution needs to handle
 */
// TODO: Move to `rust-forever-stack.h`?
enum class Namespace
{
  Values,
  Types,
  Labels,
  Macros,
  // TODO: Which namespaces are we missing?
};

/**
 * Error returned by `Rib::insert` when the key was already present in the Rib's
 * map. The class contains the previously-inserted NodeId as well as the name of
 * the node.
 */
struct DuplicateNameError
{
  // TODO: We might need multiple kinds of errors later down the line
  DuplicateNameError (std::string name, NodeId existing);

  std::string name;
  NodeId existing;
};

/**
 * A rib is a container of nodes, either declaration or usages, as well as the
 * identifier each node uses. They are used to delimit lexical scopes, and have
 * an impact on name resolution - they restrict certain name accesses and serve
 * as boundaries between scopes.

 * For example, if we are resolving the following *variable* use:
 *
 * ```rust
 * fn outer() {
 *     let a = 15; // decl
 *     fn inner() -> i32 {
 *         a // use
 *     }
 * }
 * ```
 *
 * The `Function` rib we will have pushed will restrict the access to `outer`'s
 * `a` declaration: Variable uses cannot cross function boundaries. On the other
 * hand, if we were resolving a type usage, this would be perfectly allowed.
 */
class Rib
{
public:
  // TODO: Rename the class? to what? Binding? Declaration?
  // This is useful for items which are in namespaces where shadowing is not
  // allowed, but which are still shadowable! for example, when you do a glob
  // import, if a later import has the same name as an item imported in the glob
  // import, that glob imported item will need to get shadowed
  class Definition
  {
  public:
    static Definition NonShadowable (NodeId id, bool enum_variant = false);
    static Definition Shadowable (NodeId id);
    static Definition Globbed (NodeId id);

    // checked shadowable -> non_shadowable -> globbed
    // we have shadowable *and* globbed in order to control
    // resolution priority
    // we *could* use a single vector with 2 indices here
    // but it's probably not worth it for now
    std::vector<NodeId> ids_shadowable;
    std::vector<NodeId> ids_non_shadowable;
    std::vector<NodeId> ids_globbed;

    // Enum variant should be skipped when dealing with inner definition.
    // struct E2;
    //
    // enum MyEnum<T> /* <-- Should be kept */{
    //     E2 /* <-- Should be skipped */ (E2);
    // }
    bool enum_variant;

    Definition () = default;

    Definition &operator= (const Definition &) = default;
    Definition (Definition const &) = default;

    bool is_variant () const;

    bool is_ambiguous () const;

    NodeId get_node_id () const
    {
      if (!ids_shadowable.empty ())
	return ids_shadowable.back ();

      rust_assert (!is_ambiguous ());

      if (!ids_non_shadowable.empty ())
	return ids_non_shadowable.back ();

      rust_assert (!ids_globbed.empty ());
      return ids_globbed.back ();
    }

    std::string to_string () const;

  private:
    enum class Mode
    {
      SHADOWABLE,
      NON_SHADOWABLE,
      GLOBBED
    };

    Definition (NodeId id, Mode mode, bool enum_variant);
  };

  enum class Kind
  {
    Normal,
    Module,
    Function,
    ConstantItem, // -> this variant has a boolean
    TraitOrImpl,
    /* Any item other than a Module, Function, Constant, Trait or Impl block */
    Item,
    Closure,
    MacroDefinition,
    /* Ban the use of forward-declared generic parameters in defaults */
    ForwardTypeParamBan,
    /* Const generic, as in the following example: fn foo<T, const X: T>() {} */
    ConstParamType,
    /* Prelude rib, used for both the language prelude (i32,usize,etc) and the
     * (future) {std,core}::prelude::* import. A regular rib with the
     * restriction that you cannot `use` items from the Prelude
     */
    Prelude,
    /* Generic rib, used to store generics */
    Generics,
  } kind;

  static std::string kind_to_string (Rib::Kind kind)
  {
    switch (kind)
      {
      case Rib::Kind::Normal:
	return "Normal";
      case Rib::Kind::Module:
	return "Module";
      case Rib::Kind::Function:
	return "Function";
      case Rib::Kind::ConstantItem:
	return "ConstantItem";
      case Rib::Kind::TraitOrImpl:
	return "TraitOrImpl";
      case Rib::Kind::Item:
	return "Item";
      case Rib::Kind::Closure:
	return "Closure";
      case Rib::Kind::MacroDefinition:
	return "Macro definition";
      case Rib::Kind::ForwardTypeParamBan:
	return "Forward type param ban";
      case Rib::Kind::ConstParamType:
	return "Const Param Type";
      case Kind::Prelude:
	return "Prelude";
      case Kind::Generics:
	return "Generics";
      }

    rust_unreachable ();
  }

  Rib (Kind kind);
  Rib (Kind kind, std::string identifier, NodeId id);
  Rib (Kind kind, std::unordered_map<std::string, NodeId> values);

  // TODO: What's the correctbehavior if the key already exists? What if a decl
  // and use are in the same rib? Is that possible? Okay based on RibKind?

  /**
   * Insert a new node in the rib
   *
   * @param name The name associated with the AST node
   * @param def The `Definition` to insert
   *
   * @return `DuplicateNameError` if the node is already present in the rib. The
   *         `DuplicateNameError` class contains the NodeId of the existing
   * node. Returns the new NodeId on success.
   */
  tl::expected<NodeId, DuplicateNameError> insert (std::string name,
						   Definition def);

  /**
   * Access an inserted NodeId.
   *
   * @return tl::nullopt if the key does not exist, the NodeId otherwise
   */
  tl::optional<Rib::Definition> get (const std::string &name);

  /* View all the values stored in the rib */
  const std::unordered_map<std::string, Definition> &get_values () const;

private:
  // TODO: Switch this to (NodeId, shadowable = false);
  std::unordered_map<std::string, Definition> values;
};

} // namespace Resolver2_0
} // namespace Rust

#endif // !RUST_RIB_H
