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

#include "src/ast/modules.h"
#include "src/ast/ast-value-factory.h"
#include "src/ast/scopes.h"

namespace v8 {
namespace internal {

void ModuleDescriptor::AddImport(
    const AstRawString* import_name, const AstRawString* local_name,
    const AstRawString* module_request, Scanner::Location loc, Zone* zone) {
  Entry* entry = new (zone) Entry(loc);
  entry->local_name = local_name;
  entry->import_name = import_name;
  entry->module_request = AddModuleRequest(module_request);
  AddRegularImport(entry);
}


void ModuleDescriptor::AddStarImport(
    const AstRawString* local_name, const AstRawString* module_request,
    Scanner::Location loc, Zone* zone) {
  DCHECK_NOT_NULL(local_name);
  Entry* entry = new (zone) Entry(loc);
  entry->local_name = local_name;
  entry->module_request = AddModuleRequest(module_request);
  AddSpecialImport(entry, zone);
}


void ModuleDescriptor::AddEmptyImport(
    const AstRawString* module_request, Scanner::Location loc, Zone* zone) {
  Entry* entry = new (zone) Entry(loc);
  entry->module_request = AddModuleRequest(module_request);
  AddSpecialImport(entry, zone);
}


void ModuleDescriptor::AddExport(
    const AstRawString* local_name, const AstRawString* export_name,
    Scanner::Location loc, Zone* zone) {
  Entry* entry = new (zone) Entry(loc);
  entry->export_name = export_name;
  entry->local_name = local_name;
  AddRegularExport(entry);
}


void ModuleDescriptor::AddExport(
    const AstRawString* import_name, const AstRawString* export_name,
    const AstRawString* module_request, Scanner::Location loc, Zone* zone) {
  DCHECK_NOT_NULL(import_name);
  DCHECK_NOT_NULL(export_name);
  Entry* entry = new (zone) Entry(loc);
  entry->export_name = export_name;
  entry->import_name = import_name;
  entry->module_request = AddModuleRequest(module_request);
  AddSpecialExport(entry, zone);
}


void ModuleDescriptor::AddStarExport(
    const AstRawString* module_request, Scanner::Location loc, Zone* zone) {
  Entry* entry = new (zone) Entry(loc);
  entry->module_request = AddModuleRequest(module_request);
  AddSpecialExport(entry, zone);
}

namespace {

Handle<Object> ToStringOrUndefined(Isolate* isolate, const AstRawString* s) {
  return (s == nullptr)
             ? Handle<Object>::cast(isolate->factory()->undefined_value())
             : Handle<Object>::cast(s->string());
}

const AstRawString* FromStringOrUndefined(Isolate* isolate,
                                          AstValueFactory* avfactory,
                                          Handle<Object> object) {
  if (object->IsUndefined(isolate)) return nullptr;
  return avfactory->GetString(Handle<String>::cast(object));
}

}  // namespace

Handle<ModuleInfoEntry> ModuleDescriptor::Entry::Serialize(
    Isolate* isolate) const {
  CHECK(Smi::IsValid(module_request));  // TODO(neis): Check earlier?
  return ModuleInfoEntry::New(
      isolate, ToStringOrUndefined(isolate, export_name),
      ToStringOrUndefined(isolate, local_name),
      ToStringOrUndefined(isolate, import_name),
      Handle<Object>(Smi::FromInt(module_request), isolate));
}

ModuleDescriptor::Entry* ModuleDescriptor::Entry::Deserialize(
    Isolate* isolate, AstValueFactory* avfactory,
    Handle<ModuleInfoEntry> entry) {
  Entry* result = new (avfactory->zone()) Entry(Scanner::Location::invalid());
  result->export_name = FromStringOrUndefined(
      isolate, avfactory, handle(entry->export_name(), isolate));
  result->local_name = FromStringOrUndefined(
      isolate, avfactory, handle(entry->local_name(), isolate));
  result->import_name = FromStringOrUndefined(
      isolate, avfactory, handle(entry->import_name(), isolate));
  result->module_request = Smi::cast(entry->module_request())->value();
  return result;
}

Handle<FixedArray> ModuleDescriptor::SerializeRegularExports(Isolate* isolate,
                                                             Zone* zone) const {
  // We serialize regular exports in a way that lets us later iterate over their
  // local names and for each local name immediately access all its export
  // names.  (Regular exports have neither import name nor module request.)

  ZoneVector<Handle<Object>> data(zone);
  data.reserve(2 * regular_exports_.size());

  for (auto it = regular_exports_.begin(); it != regular_exports_.end();) {
    // Find out how many export names this local name has.
    auto next = it;
    int size = 0;
    do {
      ++next;
      ++size;
    } while (next != regular_exports_.end() && next->first == it->first);

    Handle<FixedArray> export_names = isolate->factory()->NewFixedArray(size);
    data.push_back(it->second->local_name->string());
    data.push_back(export_names);

    // Collect the export names.
    int i = 0;
    for (; it != next; ++it) {
      export_names->set(i++, *it->second->export_name->string());
    }
    DCHECK_EQ(i, size);

    // Continue with the next distinct key.
    DCHECK(it == next);
  }

  // We cannot create the FixedArray earlier because we only now know the
  // precise size (the number of unique keys in regular_exports).
  int size = static_cast<int>(data.size());
  Handle<FixedArray> result = isolate->factory()->NewFixedArray(size);
  for (int i = 0; i < size; ++i) {
    result->set(i, *data[i]);
  }
  return result;
}

void ModuleDescriptor::DeserializeRegularExports(Isolate* isolate,
                                                 AstValueFactory* avfactory,
                                                 Handle<FixedArray> data) {
  for (int i = 0, length_i = data->length(); i < length_i;) {
    Handle<String> local_name(String::cast(data->get(i++)), isolate);
    Handle<FixedArray> export_names(FixedArray::cast(data->get(i++)), isolate);

    for (int j = 0, length_j = export_names->length(); j < length_j; ++j) {
      Handle<String> export_name(String::cast(export_names->get(j)), isolate);

      Entry* entry =
          new (avfactory->zone()) Entry(Scanner::Location::invalid());
      entry->local_name = avfactory->GetString(local_name);
      entry->export_name = avfactory->GetString(export_name);

      AddRegularExport(entry);
    }
  }
}

void ModuleDescriptor::MakeIndirectExportsExplicit(Zone* zone) {
  for (auto it = regular_exports_.begin(); it != regular_exports_.end();) {
    Entry* entry = it->second;
    DCHECK_NOT_NULL(entry->local_name);
    auto import = regular_imports_.find(entry->local_name);
    if (import != regular_imports_.end()) {
      // Found an indirect export.  Patch export entry and move it from regular
      // to special.
      DCHECK_NULL(entry->import_name);
      DCHECK_LT(entry->module_request, 0);
      DCHECK_NOT_NULL(import->second->import_name);
      DCHECK_LE(0, import->second->module_request);
      DCHECK_LT(import->second->module_request,
                static_cast<int>(module_requests_.size()));
      entry->import_name = import->second->import_name;
      entry->module_request = import->second->module_request;
      entry->local_name = nullptr;
      AddSpecialExport(entry, zone);
      it = regular_exports_.erase(it);
    } else {
      it++;
    }
  }
}

namespace {

const ModuleDescriptor::Entry* BetterDuplicate(
    const ModuleDescriptor::Entry* candidate,
    ZoneMap<const AstRawString*, const ModuleDescriptor::Entry*>& export_names,
    const ModuleDescriptor::Entry* current_duplicate) {
  DCHECK_NOT_NULL(candidate->export_name);
  DCHECK(candidate->location.IsValid());
  auto insert_result =
      export_names.insert(std::make_pair(candidate->export_name, candidate));
  if (insert_result.second) return current_duplicate;
  if (current_duplicate == nullptr) {
    current_duplicate = insert_result.first->second;
  }
  return (candidate->location.beg_pos > current_duplicate->location.beg_pos)
             ? candidate
             : current_duplicate;
}

}  // namespace

const ModuleDescriptor::Entry* ModuleDescriptor::FindDuplicateExport(
    Zone* zone) const {
  const ModuleDescriptor::Entry* duplicate = nullptr;
  ZoneMap<const AstRawString*, const ModuleDescriptor::Entry*> export_names(
      zone);
  for (const auto& elem : regular_exports_) {
    duplicate = BetterDuplicate(elem.second, export_names, duplicate);
  }
  for (auto entry : special_exports_) {
    if (entry->export_name == nullptr) continue;  // Star export.
    duplicate = BetterDuplicate(entry, export_names, duplicate);
  }
  return duplicate;
}

bool ModuleDescriptor::Validate(ModuleScope* module_scope,
                                PendingCompilationErrorHandler* error_handler,
                                Zone* zone) {
  DCHECK_EQ(this, module_scope->module());
  DCHECK_NOT_NULL(error_handler);

  // Report error iff there are duplicate exports.
  {
    const Entry* entry = FindDuplicateExport(zone);
    if (entry != nullptr) {
      error_handler->ReportMessageAt(
          entry->location.beg_pos, entry->location.end_pos,
          MessageTemplate::kDuplicateExport, entry->export_name);
      return false;
    }
  }

  // Report error iff there are exports of non-existent local names.
  for (const auto& elem : regular_exports_) {
    const Entry* entry = elem.second;
    DCHECK_NOT_NULL(entry->local_name);
    if (module_scope->LookupLocal(entry->local_name) == nullptr) {
      error_handler->ReportMessageAt(
          entry->location.beg_pos, entry->location.end_pos,
          MessageTemplate::kModuleExportUndefined, entry->local_name);
      return false;
    }
  }

  MakeIndirectExportsExplicit(zone);
  return true;
}

}  // namespace internal
}  // namespace v8
