// 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(path);
  if (!maybe_content) {
    if (auto maybe_path = FileUriDecode(path)) {
      maybe_content = ReadFile(*maybe_path);
    }
  }

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

  ParseTorque(*maybe_content);
}

void CompileCurrentAst(TorqueCompilerOptions options) {
  GlobalContext::Scope global_context(std::move(CurrentAst::Get()));
  if (options.verbose) GlobalContext::SetVerbose();
  if (options.collect_language_server_data) {
    GlobalContext::SetCollectLanguageServerData();
  }
  if (options.force_assert_statements) {
    GlobalContext::SetForceAssertStatements();
  }
  TypeOracle::Scope type_oracle;

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

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

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

  ImplementationVisitor implementation_visitor;
  for (Namespace* n : GlobalContext::Get().GetNamespaces()) {
    implementation_visitor.BeginNamespaceFile(n);
  }

  implementation_visitor.VisitAllDeclarables();

  std::string output_directory = options.output_directory;
  if (output_directory.length() != 0) {
    std::string output_header_path = output_directory;
    output_header_path += "/builtin-definitions-from-dsl.h";
    implementation_visitor.GenerateBuiltinDefinitions(output_header_path);

    output_header_path = output_directory + "/class-definitions-from-dsl.h";
    implementation_visitor.GenerateClassDefinitions(output_header_path);

    std::string output_source_path =
        output_directory + "/objects-printer-from-dsl.cc";
    implementation_visitor.GeneratePrintDefinitions(output_source_path);

    for (Namespace* n : GlobalContext::Get().GetNamespaces()) {
      implementation_visitor.EndNamespaceFile(n);
      implementation_visitor.GenerateImplementation(output_directory, n);
    }
  }
}

TorqueCompilerResult CollectResultFromContextuals() {
  TorqueCompilerResult result;
  result.source_file_map = SourceFileMap::Get();
  result.language_server_data = LanguageServerData::Get();
  result.lint_errors = LintErrors::Get();
  return result;
}

TorqueCompilerResult ResultFromError(TorqueError& error) {
  TorqueCompilerResult result = CollectResultFromContextuals();
  result.error = error;
  return result;
}

}  // namespace

TorqueCompilerResult CompileTorque(const std::string& source,
                                   TorqueCompilerOptions options) {
  SourceFileMap::Scope source_map_scope;
  CurrentSourceFile::Scope no_file_scope(SourceFileMap::AddSource("<torque>"));
  CurrentAst::Scope ast_scope;
  LintErrors::Scope lint_errors_scope;
  LanguageServerData::Scope server_data_scope;

  try {
    ParseTorque(source);
    CompileCurrentAst(options);
  } catch (TorqueError& error) {
    return ResultFromError(error);
  }

  return CollectResultFromContextuals();
}

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

  try {
    for (const auto& path : files) ReadAndParseTorqueFile(path);
    CompileCurrentAst(options);
  } catch (TorqueError& error) {
    return ResultFromError(error);
  }
  return CollectResultFromContextuals();
}

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