// Copyright (C) 2020-2024 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-session-manager.h"

#ifndef RUST_SESSION_MANAGER_H
#define RUST_SESSION_MANAGER_H

#include "rust-linemap.h"
#include "rust-backend.h"
#include "rust-hir-map.h"
#include "safe-ctype.h"

#include "config.h"
#include "rust-system.h"
#include "coretypes.h"
#include "options.h"

#include "optional.h"

namespace Rust {
// parser forward decl
template <typename ManagedTokenSource> class Parser;
class Lexer;
// crate forward decl
namespace AST {
struct Crate;
}
// crate forward decl
namespace HIR {
class Crate;
}

/* Data related to target, most useful for conditional compilation and
 * whatever. */
struct TargetOptions
{
  /* TODO: maybe make private and access through helpers to allow changes to
   * impl */
  std::unordered_map<std::string, std::unordered_set<tl::optional<std::string>>>
    features;

  enum class CrateType
  {
    BIN = 0,
    LIB,
    RLIB,
    DYLIB,
    CDYLIB,
    STATICLIB,
    PROC_MACRO
  } crate_type
    = CrateType::BIN;

public:
  void set_crate_type (int raw_type)
  {
    crate_type = static_cast<CrateType> (raw_type);
  }

  const CrateType &get_crate_type () const { return crate_type; }

  // Returns whether a key is defined in the feature set.
  bool has_key (std::string key) const
  {
    auto it = features.find (key);
    return it != features.end ()
	   && it->second.find (tl::nullopt) != it->second.end ();
  }

  // Returns whether a key exists with the given value in the feature set.
  bool has_key_value_pair (std::string key, std::string value) const
  {
    auto it = features.find (key);
    if (it != features.end ())
      {
	auto set = it->second;
	auto it2 = set.find (value);
	if (it2 != set.end ())
	  return true;
      }
    return false;
  }

  /* Returns the singular value from the key, or if the key has multiple, an
   * empty string. */
  std::string get_singular_value (std::string key) const
  {
    auto it = features.find (key);
    if (it != features.end ())
      {
	auto set = it->second;
	if (set.size () == 1 && set.begin ()->has_value ())
	  return set.begin ()->value ();
      }
    return "";
  }

  /* Returns all values associated with a key (including none), or an empty
   * set if no key is found. */
  std::unordered_set<std::string> get_values_for_key (std::string key) const
  {
    std::unordered_set<std::string> ret;

    auto it = features.find (key);
    if (it == features.end ())
      return {};

    for (auto &val : it->second)
      if (val.has_value ())
	ret.insert (val.value ());

    return ret;
  }

  /* Inserts a key (no value) into the feature set. This will do nothing if
   * the key already exists. This returns whether the insertion was successful
   * (i.e. whether key already existed). */
  bool insert_key (std::string key)
  {
    auto it = features.find (key);

    if (it == features.end ())
      it
	= features
	    .insert (
	      std::make_pair (std::move (key),
			      std::unordered_set<tl::optional<std::string>> ()))
	    .first;

    return it->second.insert (tl::nullopt).second;
  }

  // Inserts a key-value pair into the feature set.
  void insert_key_value_pair (std::string key, std::string value)
  {
    auto it = features.find (key);

    if (it == features.end ())
      it
	= features
	    .insert (
	      std::make_pair (std::move (key),
			      std::unordered_set<tl::optional<std::string>> ()))
	    .first;

    it->second.insert (std::move (value));
  }

  // Dump all target options to stderr.
  void dump_target_options () const;

  /* Creates derived values and implicit enables after all target info is
   * added (e.g. "unix"). */
  void init_derived_values ();

  /* Enables all requirements for the feature given, and will enable feature
   * itself if not enabled. */
  void enable_implicit_feature_reqs (std::string feature);

  /* According to reference, Rust uses either multi-map key-values or just
   * values (although values may be aliases for a key-value value). This seems
   * like overkill. Thus, depending on whether the attributes used in cfg are
   * fixed or not, I think I'll either put each non-multimap "key-value" as a
   * separate field and have the multimap "key-values" in a regular map for
   * that one key, or actually use a multimap.
   *
   * rustc itself uses a set of key-value tuples where the second tuple
   * element is optional. This gets rid of the requirement to make a
   * multi-map, I guess, but seems like it might make search slow (unless all
   * "is defined"-only ones have empty string as second element). */
  /* cfg attributes:
   * - target_arch: single value
   * - target_feature: multiple values possible
   * - target_os: single value
   * - target_family: single value (or no value?)
   * - unix: set when target_family = "unix"
   * - windows: set when target_family = "windows"
   *  - if these are just syntactic sugar, then maybe have a separate set or
   * map for this kind of stuff
   * - target_env: set when needed for disambiguation about ABI - usually
   * empty string for GNU, complicated
   *  - seems to be a single value (if any)
   * - target_endian: single value; "little" or "big"
   * - target_pointer_width: single value, "32" for 32-bit pointers, etc.
   * - target_vendor, single value
   * - test: set when testing is being done
   *  - again, seems similar to a "is defined" rather than "is equal to" like
   * unix
   * - debug_assertions: seems to "is defined"
   * - proc_macro: no idea, bad docs. seems to be boolean, so maybe "is
   * defined"
   */
};

// Defines compiler options (e.g. dump, etc.).
struct CompileOptions
{
  enum DumpOption
  {
    LEXER_DUMP,
    AST_DUMP_PRETTY,
    REGISTER_PLUGINS_DUMP,
    INJECTION_DUMP,
    EXPANSION_DUMP,
    RESOLUTION_DUMP,
    TARGET_OPTION_DUMP,
    HIR_DUMP,
    HIR_DUMP_PRETTY,
    BIR_DUMP,
  };

  std::set<DumpOption> dump_options;

  /* configuration options - actually useful for conditional compilation and
   * whatever data related to target arch, features, os, family, env, endian,
   * pointer width, vendor */
  TargetOptions target_data;
  std::string crate_name;
  bool crate_name_set_manually = false;
  bool enable_test = false;
  bool debug_assertions = false;
  std::string metadata_output_path;

  enum class Edition
  {
    E2015 = 0,
    E2018,
    E2021,
  } edition
    = Edition::E2015;

  enum class CompileStep
  {
    Ast,
    AttributeCheck,
    Expansion,
    ASTValidation,
    FeatureGating,
    NameResolution,
    Lowering,
    TypeCheck,
    Privacy,
    Unsafety,
    Const,
    BorrowCheck,
    Compilation,
    End,
  } compile_until
    = CompileStep::End;

  bool dump_option_enabled (DumpOption option) const
  {
    return dump_options.find (option) != dump_options.end ();
  }

  void enable_dump_option (DumpOption option) { dump_options.insert (option); }

  void enable_all_dump_options ()
  {
    enable_dump_option (DumpOption::LEXER_DUMP);
    enable_dump_option (DumpOption::AST_DUMP_PRETTY);
    enable_dump_option (DumpOption::REGISTER_PLUGINS_DUMP);
    enable_dump_option (DumpOption::INJECTION_DUMP);
    enable_dump_option (DumpOption::EXPANSION_DUMP);
    enable_dump_option (DumpOption::RESOLUTION_DUMP);
    enable_dump_option (DumpOption::TARGET_OPTION_DUMP);
    enable_dump_option (DumpOption::HIR_DUMP);
    enable_dump_option (DumpOption::HIR_DUMP_PRETTY);
    enable_dump_option (DumpOption::BIR_DUMP);
  }

  void set_crate_name (std::string name)
  {
    rust_assert (!name.empty ());

    crate_name = std::move (name);
  }

  const std::string &get_crate_name () const
  {
    rust_assert (!crate_name.empty ());
    return crate_name;
  }

  void set_edition (int raw_edition)
  {
    edition = static_cast<Edition> (raw_edition);
  }

  const Edition &get_edition () const { return edition; }

  void set_crate_type (int raw_type) { target_data.set_crate_type (raw_type); }

  bool is_proc_macro () const
  {
    return target_data.get_crate_type ()
	   == TargetOptions::CrateType::PROC_MACRO;
  }

  void set_compile_step (int raw_step)
  {
    compile_until = static_cast<CompileStep> (raw_step);
  }

  const CompileStep &get_compile_until () const { return compile_until; }

  void set_metadata_output (const std::string &path)
  {
    metadata_output_path = path;
  }

  const std::string &get_metadata_output () const
  {
    return metadata_output_path;
  }

  bool metadata_output_path_set () const
  {
    return !metadata_output_path.empty ();
  }
};

/* Defines a compiler session. This is for a single compiler invocation, so
 * potentially includes parsing multiple crates. */
struct Session
{
  CompileOptions options;
  /* This should really be in a per-crate storage area but it is wiped with
   * every file so eh. */
  std::string injected_crate_name;
  std::map<std::string, std::string> extern_crates;

  /* extra files get included during late stages of compilation (e.g. macro
   * expansion) */
  std::vector<std::string> extra_files;

  // backend linemap
  Linemap *linemap;

  // mappings
  Analysis::Mappings *mappings;

public:
  /* Get a reference to the static session instance */
  static Session &get_instance ();

  Session () = default;
  ~Session () = default;

  /* This initializes the compiler session. Corresponds to langhook
   * grs_langhook_init(). Note that this is called after option handling. */
  void init ();

  // delete those constructors so we don't access the singleton in any
  // other way than via `get_instance()`
  Session (Session const &) = delete;
  void operator= (Session const &) = delete;

  bool handle_option (enum opt_code code, const char *arg, HOST_WIDE_INT value,
		      int kind, location_t loc,
		      const struct cl_option_handlers *handlers);
  void handle_input_files (int num_files, const char **files);
  void init_options ();
  void handle_crate_name (const AST::Crate &parsed_crate);

  /* This function saves the filename data into the session manager using the
   * `move` semantics, and returns a C-style string referencing the input
   * std::string */
  inline const char *include_extra_file (std::string filename)
  {
    extra_files.push_back (std::move (filename));
    return extra_files.back ().c_str ();
  }

  NodeId load_extern_crate (const std::string &crate_name, location_t locus);

private:
  void compile_crate (const char *filename);
  bool enable_dump (std::string arg);

  void dump_lex (Parser<Lexer> &parser) const;
  void dump_ast_pretty (AST::Crate &crate, bool expanded = false) const;
  void dump_hir (HIR::Crate &crate) const;
  void dump_hir_pretty (HIR::Crate &crate) const;

  // pipeline stages - TODO maybe move?
  /* Register plugins pipeline stage. TODO maybe move to another object?
   * Currently dummy stage. In future will handle attribute injection
   * (top-level inner attribute creation from command line arguments), setting
   * options maybe, registering lints maybe, loading plugins maybe. */
  void register_plugins (AST::Crate &crate);

  /* Injection pipeline stage. TODO maybe move to another object? Maybe have
   * some lint checks (in future, obviously), register builtin macros, crate
   * injection. */
  void injection (AST::Crate &crate);

  /* Expansion pipeline stage. TODO maybe move to another object? Expands all
   * macros, maybe build test harness in future, AST validation, maybe create
   * macro crate (if not rustdoc).*/
  void expansion (AST::Crate &crate);

  // handle cfg_option
  bool handle_cfg_option (std::string &data);

  bool handle_extern_option (std::string &data);
};

} // namespace Rust

#if CHECKING_P
namespace selftest {
extern void
rust_crate_name_validation_test (void);
}
#endif // CHECKING_P

#endif
