// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_AST_MODULES_H_
#define V8_AST_MODULES_H_

#include "src/parsing/scanner.h"  // Only for Scanner::Location.
#include "src/zone/zone-containers.h"

namespace v8 {
namespace internal {


class AstRawString;
class ModuleRequest;
class SourceTextModuleInfo;
class SourceTextModuleInfoEntry;
class PendingCompilationErrorHandler;

class SourceTextModuleDescriptor : public ZoneObject {
 public:
  explicit SourceTextModuleDescriptor(Zone* zone)
      : module_requests_(zone),
        special_exports_(zone),
        namespace_imports_(zone),
        regular_exports_(zone),
        regular_imports_(zone) {}

  using ImportAssertions =
      ZoneMap<const AstRawString*,
              std::pair<const AstRawString*, Scanner::Location>>;

  // The following Add* methods are high-level convenience functions for use by
  // the parser.

  // import x from "foo.js";
  // import {x} from "foo.js";
  // import {x as y} from "foo.js";
  void AddImport(const AstRawString* import_name,
                 const AstRawString* local_name,
                 const AstRawString* module_request,
                 const ImportAssertions* import_assertions,
                 const Scanner::Location loc,
                 const Scanner::Location specifier_loc, Zone* zone);

  // import * as x from "foo.js";
  void AddStarImport(const AstRawString* local_name,
                     const AstRawString* module_request,
                     const ImportAssertions* import_assertions,
                     const Scanner::Location loc,
                     const Scanner::Location specifier_loc, Zone* zone);

  // import "foo.js";
  // import {} from "foo.js";
  // export {} from "foo.js";  (sic!)
  void AddEmptyImport(const AstRawString* module_request,
                      const ImportAssertions* import_assertions,
                      const Scanner::Location specifier_loc, Zone* zone);

  // export {x};
  // export {x as y};
  // export VariableStatement
  // export Declaration
  // export default ...
  void AddExport(
    const AstRawString* local_name, const AstRawString* export_name,
    const Scanner::Location loc, Zone* zone);

  // export {x} from "foo.js";
  // export {x as y} from "foo.js";
  void AddExport(const AstRawString* export_name,
                 const AstRawString* import_name,
                 const AstRawString* module_request,
                 const ImportAssertions* import_assertions,
                 const Scanner::Location loc,
                 const Scanner::Location specifier_loc, Zone* zone);

  // export * from "foo.js";
  void AddStarExport(const AstRawString* module_request,
                     const ImportAssertions* import_assertions,
                     const Scanner::Location loc,
                     const Scanner::Location specifier_loc, Zone* zone);

  // Check if module is well-formed and report error if not.
  // Also canonicalize indirect exports.
  bool Validate(ModuleScope* module_scope,
                PendingCompilationErrorHandler* error_handler, Zone* zone);

  struct Entry : public ZoneObject {
    Scanner::Location location;
    const AstRawString* export_name;
    const AstRawString* local_name;
    const AstRawString* import_name;

    // The module_request value records the order in which modules are
    // requested. It also functions as an index into the SourceTextModuleInfo's
    // array of module specifiers and into the Module's array of requested
    // modules.  A negative value means no module request.
    int module_request;

    // Import/export entries that are associated with a MODULE-allocated
    // variable (i.e. regular_imports and regular_exports after Validate) use
    // the cell_index value to encode the location of their cell.  During
    // variable allocation, this will be be copied into the variable's index
    // field.
    // Entries that are not associated with a MODULE-allocated variable have
    // GetCellIndexKind(cell_index) == kInvalid.
    int cell_index;

    // TODO(neis): Remove local_name component?
    explicit Entry(Scanner::Location loc)
        : location(loc),
          export_name(nullptr),
          local_name(nullptr),
          import_name(nullptr),
          module_request(-1),
          cell_index(0) {}

    template <typename LocalIsolate>
    Handle<SourceTextModuleInfoEntry> Serialize(LocalIsolate* isolate) const;
  };

  enum CellIndexKind { kInvalid, kExport, kImport };
  static CellIndexKind GetCellIndexKind(int cell_index);

  class AstModuleRequest : public ZoneObject {
   public:
    // TODO(v8:10958): Consider storing module request location here
    // instead of using separate ModuleRequestLocation struct.
    AstModuleRequest(const AstRawString* specifier,
                     const ImportAssertions* import_assertions)
        : specifier_(specifier), import_assertions_(import_assertions) {}

    template <typename LocalIsolate>
    Handle<v8::internal::ModuleRequest> Serialize(LocalIsolate* isolate) const;

    const AstRawString* specifier() const { return specifier_; }
    const ImportAssertions* import_assertions() const {
      return import_assertions_;
    }

   private:
    const AstRawString* specifier_;
    const ImportAssertions* import_assertions_;
  };

  struct ModuleRequestLocation {
    // The index at which we will place the request in SourceTextModuleInfo's
    // module_requests FixedArray.
    int index;

    // The JS source code position of the request, used for reporting errors.
    int position;

    ModuleRequestLocation(int index, int position)
        : index(index), position(position) {}
  };

  // Custom content-based comparer for the below maps, to keep them stable
  // across parses.
  struct V8_EXPORT_PRIVATE AstRawStringComparer {
    bool operator()(const AstRawString* lhs, const AstRawString* rhs) const;
    static int ThreeWayCompare(const AstRawString* lhs,
                               const AstRawString* rhs);
  };

  struct V8_EXPORT_PRIVATE ModuleRequestComparer {
    bool operator()(const AstModuleRequest* lhs,
                    const AstModuleRequest* rhs) const;
  };

  using ModuleRequestMap =
      ZoneMap<const AstModuleRequest*, ModuleRequestLocation,
              ModuleRequestComparer>;
  using RegularExportMap =
      ZoneMultimap<const AstRawString*, Entry*, AstRawStringComparer>;
  using RegularImportMap =
      ZoneMap<const AstRawString*, Entry*, AstRawStringComparer>;

  // Module requests.
  const ModuleRequestMap& module_requests() const { return module_requests_; }

  // Namespace imports.
  const ZoneVector<const Entry*>& namespace_imports() const {
    return namespace_imports_;
  }

  // All the remaining imports, indexed by local name.
  const RegularImportMap& regular_imports() const { return regular_imports_; }

  // Star exports and explicitly indirect exports.
  const ZoneVector<const Entry*>& special_exports() const {
    return special_exports_;
  }

  // All the remaining exports, indexed by local name.
  // After canonicalization (see Validate), these are exactly the local exports.
  const RegularExportMap& regular_exports() const { return regular_exports_; }

  void AddRegularExport(Entry* entry) {
    DCHECK_NOT_NULL(entry->export_name);
    DCHECK_NOT_NULL(entry->local_name);
    DCHECK_NULL(entry->import_name);
    DCHECK_LT(entry->module_request, 0);
    regular_exports_.insert(std::make_pair(entry->local_name, entry));
  }

  void AddSpecialExport(const Entry* entry, Zone* zone) {
    DCHECK_NULL(entry->local_name);
    DCHECK_LE(0, entry->module_request);
    special_exports_.push_back(entry);
  }

  void AddRegularImport(Entry* entry) {
    DCHECK_NOT_NULL(entry->import_name);
    DCHECK_NOT_NULL(entry->local_name);
    DCHECK_NULL(entry->export_name);
    DCHECK_LE(0, entry->module_request);
    regular_imports_.insert(std::make_pair(entry->local_name, entry));
    // We don't care if there's already an entry for this local name, as in that
    // case we will report an error when declaring the variable.
  }

  void AddNamespaceImport(const Entry* entry, Zone* zone) {
    DCHECK_NULL(entry->import_name);
    DCHECK_NULL(entry->export_name);
    DCHECK_NOT_NULL(entry->local_name);
    DCHECK_LE(0, entry->module_request);
    namespace_imports_.push_back(entry);
  }

  template <typename LocalIsolate>
  Handle<FixedArray> SerializeRegularExports(LocalIsolate* isolate,
                                             Zone* zone) const;

 private:
  ModuleRequestMap module_requests_;
  ZoneVector<const Entry*> special_exports_;
  ZoneVector<const Entry*> namespace_imports_;
  RegularExportMap regular_exports_;
  RegularImportMap regular_imports_;

  // If there are multiple export entries with the same export name, return the
  // last of them (in source order).  Otherwise return nullptr.
  const Entry* FindDuplicateExport(Zone* zone) const;

  // Find any implicitly indirect exports and make them explicit.
  //
  // An explicitly indirect export is an export entry arising from an export
  // statement of the following form:
  //   export {a as c} from "X";
  // An implicitly indirect export corresponds to
  //   export {b as c};
  // in the presence of an import statement of the form
  //   import {a as b} from "X";
  // This function finds such implicitly indirect export entries and rewrites
  // them by filling in the import name and module request, as well as nulling
  // out the local name.  Effectively, it turns
  //   import {a as b} from "X"; export {b as c};
  // into:
  //   import {a as b} from "X"; export {a as c} from "X";
  // (The import entry is never deleted.)
  void MakeIndirectExportsExplicit(Zone* zone);

  // Assign a cell_index of -1,-2,... to regular imports.
  // Assign a cell_index of +1,+2,... to regular (local) exports.
  // Assign a cell_index of 0 to anything else.
  void AssignCellIndices();

  int AddModuleRequest(const AstRawString* specifier,
                       const ImportAssertions* import_assertions,
                       Scanner::Location specifier_loc, Zone* zone) {
    DCHECK_NOT_NULL(specifier);
    int module_requests_count = static_cast<int>(module_requests_.size());
    auto it = module_requests_
                  .insert(std::make_pair(
                      zone->New<AstModuleRequest>(specifier, import_assertions),
                      ModuleRequestLocation(module_requests_count,
                                            specifier_loc.beg_pos)))
                  .first;
    return it->second.index;
  }
};

}  // namespace internal
}  // namespace v8

#endif  // V8_AST_MODULES_H_
