// Copyright 2019 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/torque/torque-compiler.h"

#include <fstream>
#include "src/torque/declarable.h"
#include "src/torque/declaration-visitor.h"
#include "src/torque/global-context.h"
#include "src/torque/implementation-visitor.h"
#include "src/torque/torque-parser.h"
#include "src/torque/type-oracle.h"

namespace v8 {
namespace internal {
namespace torque {

namespace {

base::Optional<std::string> ReadFile(const std::string& path) {
  std::ifstream file_stream(path);
  if (!file_stream.good()) return base::nullopt;

  return std::string{std::istreambuf_iterator<char>(file_stream),
                     std::istreambuf_iterator<char>()};
}

void ReadAndParseTorqueFile(const std::string& path) {
  SourceId source_id = SourceFileMap::AddSource(path);
  CurrentSourceFile::Scope source_id_scope(source_id);

  // path might be either a normal file path or an encoded URI.
  auto maybe_content = ReadFile(SourceFileMap::AbsolutePath(source_id));
  if (!maybe_content) {
    if (auto maybe_path = FileUriDecode(path)) {
      maybe_content = ReadFile(*maybe_path);
    }
  }

  if (!maybe_content) {
    Error("Cannot open file path/uri: ", path).Throw();
  }

  ParseTorque(*maybe_content);
}

void CompileCurrentAst(TorqueCompilerOptions options) {
  GlobalContext::Scope global_context(std::move(CurrentAst::Get()));
  if (options.collect_language_server_data) {
    GlobalContext::SetCollectLanguageServerData();
  }
  if (options.force_assert_statements) {
    GlobalContext::SetForceAssertStatements();
  }
  TargetArchitecture::Scope target_architecture(options.force_32bit_output);
  TypeOracle::Scope type_oracle;
  CurrentScope::Scope current_namespace(GlobalContext::GetDefaultNamespace());

  // Two-step process of predeclaration + resolution allows to resolve type
  // declarations independent of the order they are given.
  PredeclarationVisitor::Predeclare(GlobalContext::ast());
  PredeclarationVisitor::ResolvePredeclarations();

  // Process other declarations.
  DeclarationVisitor::Visit(GlobalContext::ast());

  // A class types' fields are resolved here, which allows two class fields to
  // mutually refer to each others.
  TypeOracle::FinalizeAggregateTypes();

  std::string output_directory = options.output_directory;

  ImplementationVisitor implementation_visitor;
  implementation_visitor.SetDryRun(output_directory.length() == 0);

  implementation_visitor.GenerateInstanceTypes(output_directory);
  implementation_visitor.BeginGeneratedFiles();
  implementation_visitor.BeginRuntimeMacrosFile();

  implementation_visitor.VisitAllDeclarables();

  ReportAllUnusedMacros();

  implementation_visitor.GenerateBuiltinDefinitionsAndInterfaceDescriptors(
      output_directory);
  implementation_visitor.GenerateClassFieldOffsets(output_directory);
  implementation_visitor.GenerateBitFields(output_directory);
  implementation_visitor.GeneratePrintDefinitions(output_directory);
  implementation_visitor.GenerateClassDefinitions(output_directory);
  implementation_visitor.GenerateClassVerifiers(output_directory);
  implementation_visitor.GenerateClassDebugReaders(output_directory);
  implementation_visitor.GenerateEnumVerifiers(output_directory);
  implementation_visitor.GenerateBodyDescriptors(output_directory);
  implementation_visitor.GenerateExportedMacrosAssembler(output_directory);
  implementation_visitor.GenerateCSATypes(output_directory);

  implementation_visitor.EndGeneratedFiles();
  implementation_visitor.EndRuntimeMacrosFile();
  implementation_visitor.GenerateImplementation(output_directory);

  if (GlobalContext::collect_language_server_data()) {
    LanguageServerData::SetGlobalContext(std::move(GlobalContext::Get()));
    LanguageServerData::SetTypeOracle(std::move(TypeOracle::Get()));
  }
}

}  // namespace

TorqueCompilerResult CompileTorque(const std::string& source,
                                   TorqueCompilerOptions options) {
  SourceFileMap::Scope source_map_scope(options.v8_root);
  CurrentSourceFile::Scope no_file_scope(
      SourceFileMap::AddSource("dummy-filename.tq"));
  CurrentAst::Scope ast_scope;
  TorqueMessages::Scope messages_scope;
  LanguageServerData::Scope server_data_scope;

  TorqueCompilerResult result;
  try {
    ParseTorque(source);
    CompileCurrentAst(options);
  } catch (TorqueAbortCompilation&) {
    // Do nothing. The relevant TorqueMessage is part of the
    // TorqueMessages contextual.
  }

  result.source_file_map = SourceFileMap::Get();
  result.language_server_data = std::move(LanguageServerData::Get());
  result.messages = std::move(TorqueMessages::Get());

  return result;
}

TorqueCompilerResult CompileTorque(std::vector<std::string> files,
                                   TorqueCompilerOptions options) {
  SourceFileMap::Scope source_map_scope(options.v8_root);
  CurrentSourceFile::Scope unknown_source_file_scope(SourceId::Invalid());
  CurrentAst::Scope ast_scope;
  TorqueMessages::Scope messages_scope;
  LanguageServerData::Scope server_data_scope;

  TorqueCompilerResult result;
  try {
    for (const auto& path : files) {
      ReadAndParseTorqueFile(path);
    }
    CompileCurrentAst(options);
  } catch (TorqueAbortCompilation&) {
    // Do nothing. The relevant TorqueMessage is part of the
    // TorqueMessages contextual.
  }

  result.source_file_map = SourceFileMap::Get();
  result.language_server_data = std::move(LanguageServerData::Get());
  result.messages = std::move(TorqueMessages::Get());

  return result;
}

}  // namespace torque
}  // namespace internal
}  // namespace v8
