//===--- FrontendActions.cpp ----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "flang/Frontend/FrontendActions.h"
#include "flang/Common/default-kinds.h"
#include "flang/Frontend/CompilerInstance.h"
#include "flang/Parser/parsing.h"
#include "flang/Parser/provenance.h"
#include "flang/Parser/source.h"
#include "flang/Semantics/semantics.h"

using namespace Fortran::frontend;

void InputOutputTestAction::ExecuteAction() {

  // Get the name of the file from FrontendInputFile current.
  std::string path{GetCurrentFileOrBufferName()};
  std::string buf;
  llvm::raw_string_ostream error_stream{buf};
  bool binaryMode = true;

  // Set/store input file info into CompilerInstance.
  CompilerInstance &ci = instance();
  Fortran::parser::AllSources &allSources{ci.allSources()};
  const Fortran::parser::SourceFile *sf;
  sf = allSources.Open(path, error_stream);
  llvm::ArrayRef<char> fileContent = sf->content();

  // Output file descriptor to receive the content of input file.
  std::unique_ptr<llvm::raw_ostream> os;

  // Do not write on the output file if using outputStream_.
  if (ci.IsOutputStreamNull()) {
    os = ci.CreateDefaultOutputFile(
        binaryMode, GetCurrentFileOrBufferName(), "txt");
    if (!os)
      return;
    (*os) << fileContent.data();
  } else {
    ci.WriteOutputStream(fileContent.data());
  }
}

void PrintPreprocessedAction::ExecuteAction() {
  std::string buf;
  llvm::raw_string_ostream outForPP{buf};

  // Run the preprocessor
  CompilerInstance &ci = this->instance();
  ci.parsing().DumpCookedChars(outForPP);

  // If a pre-defined output stream exists, dump the preprocessed content there
  if (!ci.IsOutputStreamNull()) {
    // Send the output to the pre-defined output buffer.
    ci.WriteOutputStream(outForPP.str());
    return;
  }

  // Print diagnostics from the preprocessor
  ci.parsing().messages().Emit(llvm::errs(), ci.allCookedSources());

  // Create a file and save the preprocessed output there
  if (auto os{ci.CreateDefaultOutputFile(
          /*Binary=*/true, /*InFile=*/GetCurrentFileOrBufferName())}) {
    (*os) << outForPP.str();
  } else {
    llvm::errs() << "Unable to create the output file\n";
    return;
  }
}

void ParseSyntaxOnlyAction::ExecuteAction() {
  CompilerInstance &ci = this->instance();

  // TODO: These should be specifiable by users. For now just use the defaults.
  common::LanguageFeatureControl features;
  Fortran::common::IntrinsicTypeDefaultKinds defaultKinds;

  // Parse. In case of failure, report and return.
  ci.parsing().Parse(llvm::outs());

  if (ci.parsing().messages().AnyFatalError()) {
    unsigned diagID = ci.diagnostics().getCustomDiagID(
        clang::DiagnosticsEngine::Error, "Could not parse %0");
    ci.diagnostics().Report(diagID) << GetCurrentFileOrBufferName();

    ci.parsing().messages().Emit(
        llvm::errs(), this->instance().allCookedSources());
    return;
  }

  auto &parseTree{*ci.parsing().parseTree()};

  // Prepare semantics
  Fortran::semantics::SemanticsContext semanticsContext{
      defaultKinds, features, ci.allCookedSources()};
  Fortran::semantics::Semantics semantics{
      semanticsContext, parseTree, ci.parsing().cooked().AsCharBlock()};

  // Run semantic checks
  semantics.Perform();

  // Report the diagnostics from the semantic checks
  semantics.EmitMessages(ci.semaOutputStream());

  if (semantics.AnyFatalError()) {
    unsigned DiagID = ci.diagnostics().getCustomDiagID(
        clang::DiagnosticsEngine::Error, "Semantic errors in %0");
    ci.diagnostics().Report(DiagID) << GetCurrentFileOrBufferName();
  }
}

void EmitObjAction::ExecuteAction() {
  CompilerInstance &ci = this->instance();
  unsigned DiagID = ci.diagnostics().getCustomDiagID(
      clang::DiagnosticsEngine::Error, "code-generation is not available yet");
  ci.diagnostics().Report(DiagID);
}
