/*
 * Copyright 2010, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "slang_rs_pragma_handler.h"

#include <map>
#include <sstream>
#include <string>

#include "clang/AST/ASTContext.h"

#include "clang/Basic/TokenKinds.h"

#include "clang/Lex/LiteralSupport.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/Token.h"

#include "slang_assert.h"
#include "slang_rs_context.h"
#include "slang_rs_export_reduce.h"
#include "slang_version.h"

namespace slang {

namespace {  // Anonymous namespace

class RSExportTypePragmaHandler : public RSPragmaHandler {
 private:
  void handleItem(const std::string &Item) {
    mContext->addPragma(this->getName(), Item);
    mContext->addExportType(Item);
  }

 public:
  RSExportTypePragmaHandler(llvm::StringRef Name, RSContext *Context)
      : RSPragmaHandler(Name, Context) { }

  void HandlePragma(clang::Preprocessor &PP,
                    clang::PragmaIntroducerKind Introducer,
                    clang::Token &FirstToken) {
    this->handleItemListPragma(PP, FirstToken);
  }
};

class RSJavaPackageNamePragmaHandler : public RSPragmaHandler {
 public:
  RSJavaPackageNamePragmaHandler(llvm::StringRef Name, RSContext *Context)
      : RSPragmaHandler(Name, Context) { }

  void HandlePragma(clang::Preprocessor &PP,
                    clang::PragmaIntroducerKind Introducer,
                    clang::Token &FirstToken) {
    // FIXME: Need to validate the extracted package name from pragma.
    // Currently "all chars" specified in pragma will be treated as package
    // name.
    //
    // 18.1 The Grammar of the Java Programming Language
    // (http://java.sun.com/docs/books/jls/third_edition/html/syntax.html#18.1)
    //
    // CompilationUnit:
    //     [[Annotations] package QualifiedIdentifier   ;  ] {ImportDeclaration}
    //     {TypeDeclaration}
    //
    // QualifiedIdentifier:
    //     Identifier { . Identifier }
    //
    // Identifier:
    //     IDENTIFIER
    //
    // 3.8 Identifiers
    // (http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.8)
    //
    //

    clang::Token &PragmaToken = FirstToken;
    std::string PackageName;

    // Skip first token, "java_package_name"
    PP.LexUnexpandedToken(PragmaToken);

    // Now, the current token must be clang::tok::lpara
    if (PragmaToken.isNot(clang::tok::l_paren))
      return;

    while (PragmaToken.isNot(clang::tok::eod)) {
      // Lex package name
      PP.LexUnexpandedToken(PragmaToken);

      bool Invalid;
      std::string Spelling = PP.getSpelling(PragmaToken, &Invalid);
      if (!Invalid)
        PackageName.append(Spelling);

      // Pre-mature end (syntax error will be triggered by preprocessor later)
      if (PragmaToken.is(clang::tok::eod) || PragmaToken.is(clang::tok::eof)) {
        break;
      } else {
        // Next token is ')' (end of pragma)
        const clang::Token &NextTok = PP.LookAhead(0);
        if (NextTok.is(clang::tok::r_paren)) {
          mContext->addPragma(this->getName(), PackageName);
          mContext->setReflectJavaPackageName(PackageName);
          // Lex until meets clang::tok::eod
          do {
            PP.LexUnexpandedToken(PragmaToken);
          } while (PragmaToken.isNot(clang::tok::eod));
          break;
        }
      }
    }
  }
};

class RSReducePragmaHandler : public RSPragmaHandler {
 public:
  RSReducePragmaHandler(llvm::StringRef Name, RSContext *Context)
      : RSPragmaHandler(Name, Context) { }

  void HandlePragma(clang::Preprocessor &PP,
                    clang::PragmaIntroducerKind Introducer,
                    clang::Token &FirstToken) override {
    // #pragma rs reduce(name)
    //   initializer(initializename)
    //   accumulator(accumulatename)
    //   combiner(combinename)
    //   outconverter(outconvertname)
    //   halter(haltname)

    const clang::SourceLocation PragmaLocation = FirstToken.getLocation();

    clang::Token &PragmaToken = FirstToken;

    // Grab "reduce(name)" ("reduce" is already known to be the first
    // token) and all the "keyword(value)" contributions
    //
    // TODO: Remove halter from initial release
    KeywordValueMapType KeywordValueMap({std::make_pair(RSExportReduceNew::KeyReduce, ""),
                                         std::make_pair(RSExportReduceNew::KeyInitializer, ""),
                                         std::make_pair(RSExportReduceNew::KeyAccumulator, ""),
                                         std::make_pair(RSExportReduceNew::KeyCombiner, ""),
                                         std::make_pair(RSExportReduceNew::KeyOutConverter, ""),
                                         std::make_pair(RSExportReduceNew::KeyHalter, "")});
    while (PragmaToken.is(clang::tok::identifier)) {
      if (!ProcessKeywordAndValue(PP, PragmaToken, KeywordValueMap))
        return;
    }

    // Make sure there's no end-of-line garbage
    if (PragmaToken.isNot(clang::tok::eod)) {
      PP.Diag(PragmaToken.getLocation(),
              PP.getDiagnostics().getCustomDiagID(
                clang::DiagnosticsEngine::Error,
                "did not expect '%0' here for '#pragma rs %1'"))
          << PP.getSpelling(PragmaToken) << getName();
      return;
    }

    // Make sure we have an accumulator
    if (KeywordValueMap[RSExportReduceNew::KeyAccumulator].empty()) {
      PP.Diag(PragmaLocation, PP.getDiagnostics().getCustomDiagID(
                                clang::DiagnosticsEngine::Error,
                                "missing '%0' for '#pragma rs %1'"))
          << RSExportReduceNew::KeyAccumulator << getName();
      return;
    }

    // Make sure the reduction kernel name is unique.  (If we were
    // worried there might be a VERY large number of pragmas, then we
    // could do something more efficient than walking a list to search
    // for duplicates.)
    for (auto I = mContext->export_reduce_new_begin(),
              E = mContext->export_reduce_new_end();
         I != E; ++I) {
      if ((*I)->getNameReduce() == KeywordValueMap[RSExportReduceNew::KeyReduce]) {
        PP.Diag(PragmaLocation, PP.getDiagnostics().getCustomDiagID(
                                  clang::DiagnosticsEngine::Error,
                                  "reduction kernel '%0' declared multiple "
                                  "times (first one is at %1)"))
            << KeywordValueMap[RSExportReduceNew::KeyReduce]
            << (*I)->getLocation().printToString(PP.getSourceManager());
        return;
      }
    }

    // Check API version.
    if (mContext->getTargetAPI() != RS_DEVELOPMENT_API) {
      PP.Diag(PragmaLocation,
              PP.getDiagnostics().getCustomDiagID(
                clang::DiagnosticsEngine::Error,
                "reduction kernels are not supported in SDK level %0"))
          << mContext->getTargetAPI();
      return;
    }

    // Handle backward reference from pragma (see Backend::HandleTopLevelDecl for forward reference).
    MarkUsed(PP, KeywordValueMap[RSExportReduceNew::KeyInitializer]);
    MarkUsed(PP, KeywordValueMap[RSExportReduceNew::KeyAccumulator]);
    MarkUsed(PP, KeywordValueMap[RSExportReduceNew::KeyCombiner]);
    MarkUsed(PP, KeywordValueMap[RSExportReduceNew::KeyOutConverter]);
    MarkUsed(PP, KeywordValueMap[RSExportReduceNew::KeyHalter]);

    mContext->addExportReduceNew(RSExportReduceNew::Create(mContext, PragmaLocation,
                                                           KeywordValueMap[RSExportReduceNew::KeyReduce],
                                                           KeywordValueMap[RSExportReduceNew::KeyInitializer],
                                                           KeywordValueMap[RSExportReduceNew::KeyAccumulator],
                                                           KeywordValueMap[RSExportReduceNew::KeyCombiner],
                                                           KeywordValueMap[RSExportReduceNew::KeyOutConverter],
                                                           KeywordValueMap[RSExportReduceNew::KeyHalter]));
  }

 private:
  typedef std::map<std::string, std::string> KeywordValueMapType;

  void MarkUsed(clang::Preprocessor &PP, const std::string &FunctionName) {
    if (FunctionName.empty())
      return;

    clang::ASTContext &ASTC = mContext->getASTContext();
    clang::TranslationUnitDecl *TUDecl = ASTC.getTranslationUnitDecl();
    slangAssert(TUDecl);
    if (const clang::IdentifierInfo *II = PP.getIdentifierInfo(FunctionName)) {
      for (auto Decl : TUDecl->lookup(II)) {
        clang::FunctionDecl *FDecl = Decl->getAsFunction();
        if (!FDecl || !FDecl->isThisDeclarationADefinition())
          continue;
        // Handle backward reference from pragma (see
        // Backend::HandleTopLevelDecl for forward reference).
        mContext->markUsedByReducePragma(FDecl, RSContext::CheckNameNo);
      }
    }
  }

  // Return comma-separated list of all keys in the map
  static std::string ListKeywords(const KeywordValueMapType &KeywordValueMap) {
    std::string Ret;
    bool First = true;
    for (auto const &entry : KeywordValueMap) {
      if (First)
        First = false;
      else
        Ret += ", ";
      Ret += "'";
      Ret += entry.first;
      Ret += "'";
    }
    return Ret;
  }

  // Parse "keyword(value)" and set KeywordValueMap[keyword] = value.  (Both
  // "keyword" and "value" are identifiers.)
  // Does both syntactic validation and the following semantic validation:
  // - The keyword must be present in the map.
  // - The map entry for the keyword must not contain a value.
  bool ProcessKeywordAndValue(clang::Preprocessor &PP,
                              clang::Token &PragmaToken,
                              KeywordValueMapType &KeywordValueMap) {
    // The current token must be an identifier in KeywordValueMap
    KeywordValueMapType::iterator Entry;
    if (PragmaToken.isNot(clang::tok::identifier) ||
        ((Entry = KeywordValueMap.find(
            PragmaToken.getIdentifierInfo()->getName())) ==
         KeywordValueMap.end())) {
      // Note that we should never get here for the "reduce" token
      // itself, which should already have been recognized.
      PP.Diag(PragmaToken.getLocation(),
              PP.getDiagnostics().getCustomDiagID(
                clang::DiagnosticsEngine::Error,
                "did not recognize '%0' for '#pragma %1'; expected one of "
                "the following keywords: %2"))
          << PragmaToken.getIdentifierInfo()->getName() << getName()
          << ListKeywords(KeywordValueMap);
      return false;
    }
    // ... and there must be no value for this keyword yet
    if (!Entry->second.empty()) {
      PP.Diag(PragmaToken.getLocation(),
              PP.getDiagnostics().getCustomDiagID(
                clang::DiagnosticsEngine::Error,
                "more than one '%0' for '#pragma rs %1'"))
          << Entry->first << getName();
      return false;
    }
    PP.LexUnexpandedToken(PragmaToken);

    // The current token must be clang::tok::l_paren
    if (PragmaToken.isNot(clang::tok::l_paren)) {
      PP.Diag(PragmaToken.getLocation(),
              PP.getDiagnostics().getCustomDiagID(
                clang::DiagnosticsEngine::Error,
                "missing '(' after '%0' for '#pragma rs %1'"))
          << Entry->first << getName();
      return false;
    }
    PP.LexUnexpandedToken(PragmaToken);

    // The current token must be an identifier (a name)
    if (PragmaToken.isNot(clang::tok::identifier)) {
      PP.Diag(PragmaToken.getLocation(),
              PP.getDiagnostics().getCustomDiagID(
                clang::DiagnosticsEngine::Error,
                "missing name after '%0(' for '#pragma rs %1'"))
          << Entry->first << getName();
      return false;
    }
    const std::string Name = PragmaToken.getIdentifierInfo()->getName();
    PP.LexUnexpandedToken(PragmaToken);

    // The current token must be clang::tok::r_paren
    if (PragmaToken.isNot(clang::tok::r_paren)) {
      PP.Diag(PragmaToken.getLocation(),
              PP.getDiagnostics().getCustomDiagID(
                clang::DiagnosticsEngine::Error,
                "missing ')' after '%0(%1' for '#pragma rs %2'"))
          << Entry->first << Name << getName();
      return false;
    }
    PP.LexUnexpandedToken(PragmaToken);

    // Success
    Entry->second = Name;
    return true;
  }
};

class RSReflectLicensePragmaHandler : public RSPragmaHandler {
 private:
  void handleItem(const std::string &Item) {
    mContext->addPragma(this->getName(), Item);
    mContext->setLicenseNote(Item);
  }

 public:
  RSReflectLicensePragmaHandler(llvm::StringRef Name, RSContext *Context)
      : RSPragmaHandler(Name, Context) { }

  void HandlePragma(clang::Preprocessor &PP,
                    clang::PragmaIntroducerKind Introducer,
                    clang::Token &FirstToken) {
    this->handleOptionalStringLiteralParamPragma(PP, FirstToken);
  }
};

class RSVersionPragmaHandler : public RSPragmaHandler {
 private:
  void handleInt(clang::Preprocessor &PP,
                 clang::Token &Tok,
                 const int v) {
    if (v != 1) {
      PP.Diag(Tok,
              PP.getDiagnostics().getCustomDiagID(
                  clang::DiagnosticsEngine::Error,
                  "pragma for version in source file must be set to 1"));
      mContext->setVersion(1);
      return;
    }
    std::stringstream ss;
    ss << v;
    mContext->addPragma(this->getName(), ss.str());
    mContext->setVersion(v);
  }

 public:
  RSVersionPragmaHandler(llvm::StringRef Name, RSContext *Context)
      : RSPragmaHandler(Name, Context) { }

  void HandlePragma(clang::Preprocessor &PP,
                    clang::PragmaIntroducerKind Introducer,
                    clang::Token &FirstToken) {
    this->handleIntegerParamPragma(PP, FirstToken);
  }
};

// Handles the pragmas rs_fp_full, rs_fp_relaxed, and rs_fp_imprecise.
// There's one instance of this handler for each of the above values.
// Only getName() differs between the instances.
class RSPrecisionPragmaHandler : public RSPragmaHandler {
public:
  RSPrecisionPragmaHandler(llvm::StringRef Name, RSContext *Context)
      : RSPragmaHandler(Name, Context) {}

  void HandlePragma(clang::Preprocessor &PP,
                    clang::PragmaIntroducerKind Introducer,
                    clang::Token &Token) {
    std::string Precision = getName();
    // We are deprecating rs_fp_imprecise.
    if (Precision == "rs_fp_imprecise") {
      PP.Diag(Token, PP.getDiagnostics().getCustomDiagID(
                         clang::DiagnosticsEngine::Warning,
                         "rs_fp_imprecise is deprecated.  Assuming "
                         "rs_fp_relaxed instead."));
      Precision = "rs_fp_relaxed";
    }
    // Check if we have already encountered a precision pragma already.
    std::string PreviousPrecision = mContext->getPrecision();
    if (!PreviousPrecision.empty()) {
      // If the previous specified a different value, it's an error.
      if (PreviousPrecision != Precision) {
        PP.Diag(Token, PP.getDiagnostics().getCustomDiagID(
                           clang::DiagnosticsEngine::Error,
                           "Multiple float precisions specified.  Encountered "
                           "%0 previously."))
            << PreviousPrecision;
      }
      // Otherwise we ignore redundant entries.
      return;
    }

    mContext->addPragma(Precision, "");
    mContext->setPrecision(Precision);
  }
};

}  // namespace

void RSPragmaHandler::handleItemListPragma(clang::Preprocessor &PP,
                                           clang::Token &FirstToken) {
  clang::Token &PragmaToken = FirstToken;

  // Skip first token, like "export_var"
  PP.LexUnexpandedToken(PragmaToken);

  // Now, the current token must be clang::tok::lpara
  if (PragmaToken.isNot(clang::tok::l_paren))
    return;

  while (PragmaToken.isNot(clang::tok::eod)) {
    // Lex variable name
    PP.LexUnexpandedToken(PragmaToken);
    if (PragmaToken.is(clang::tok::identifier))
      this->handleItem(PP.getSpelling(PragmaToken));
    else
      break;

    slangAssert(PragmaToken.isNot(clang::tok::eod));

    PP.LexUnexpandedToken(PragmaToken);

    if (PragmaToken.isNot(clang::tok::comma))
      break;
  }
}

void RSPragmaHandler::handleNonParamPragma(clang::Preprocessor &PP,
                                           clang::Token &FirstToken) {
  clang::Token &PragmaToken = FirstToken;

  // Skip first token, like "export_var_all"
  PP.LexUnexpandedToken(PragmaToken);

  // Should be end immediately
  if (PragmaToken.isNot(clang::tok::eod))
    if (PragmaToken.isNot(clang::tok::r_paren)) {
      PP.Diag(PragmaToken,
              PP.getDiagnostics().getCustomDiagID(
                  clang::DiagnosticsEngine::Error,
                  "expected a ')'"));
      return;
    }
}

void RSPragmaHandler::handleOptionalStringLiteralParamPragma(
    clang::Preprocessor &PP, clang::Token &FirstToken) {
  clang::Token &PragmaToken = FirstToken;

  // Skip first token, like "set_reflect_license"
  PP.LexUnexpandedToken(PragmaToken);

  // Now, the current token must be clang::tok::lpara
  if (PragmaToken.isNot(clang::tok::l_paren))
    return;

  // If not ')', eat the following string literal as the license
  PP.LexUnexpandedToken(PragmaToken);
  if (PragmaToken.isNot(clang::tok::r_paren)) {
    // Eat the whole string literal
    clang::StringLiteralParser StringLiteral(PragmaToken, PP);
    if (StringLiteral.hadError) {
      // Diagnostics will be generated automatically
      return;
    } else {
      this->handleItem(std::string(StringLiteral.GetString()));
    }

    // The current token should be clang::tok::r_para
    PP.LexUnexpandedToken(PragmaToken);
    if (PragmaToken.isNot(clang::tok::r_paren)) {
      PP.Diag(PragmaToken,
              PP.getDiagnostics().getCustomDiagID(
                  clang::DiagnosticsEngine::Error,
                  "expected a ')'"));
      return;
    }
  } else {
    // If no argument, remove the license
    this->handleItem("");
  }
}

void RSPragmaHandler::handleIntegerParamPragma(
    clang::Preprocessor &PP, clang::Token &FirstToken) {
  clang::Token &PragmaToken = FirstToken;

  // Skip first token, like "version"
  PP.LexUnexpandedToken(PragmaToken);

  // Now, the current token must be clang::tok::lpara
  if (PragmaToken.isNot(clang::tok::l_paren)) {
    // If no argument, set the version to 0
    this->handleInt(PP, PragmaToken, 0);
    return;
  }
  PP.LexUnexpandedToken(PragmaToken);

  if (PragmaToken.is(clang::tok::numeric_constant)) {
    llvm::SmallString<128> SpellingBuffer;
    SpellingBuffer.resize(PragmaToken.getLength() + 1);
    llvm::StringRef TokSpelling = PP.getSpelling(PragmaToken, SpellingBuffer);
    clang::NumericLiteralParser NumericLiteral(TokSpelling,
        PragmaToken.getLocation(), PP);
    if (NumericLiteral.hadError) {
      // Diagnostics will be generated automatically
      return;
    } else {
      llvm::APInt Val(32, 0);
      NumericLiteral.GetIntegerValue(Val);
      this->handleInt(PP, PragmaToken, static_cast<int>(Val.getSExtValue()));
    }
    PP.LexUnexpandedToken(PragmaToken);
  } else {
    // If no argument, set the version to 0
    this->handleInt(PP, PragmaToken, 0);
  }

  if (PragmaToken.isNot(clang::tok::r_paren)) {
    PP.Diag(PragmaToken,
            PP.getDiagnostics().getCustomDiagID(
                clang::DiagnosticsEngine::Error,
                "expected a ')'"));
    return;
  }

  do {
    PP.LexUnexpandedToken(PragmaToken);
  } while (PragmaToken.isNot(clang::tok::eod));
}

void AddPragmaHandlers(clang::Preprocessor &PP, RSContext *RsContext) {
  // For #pragma rs export_type
  PP.AddPragmaHandler("rs",
                      new RSExportTypePragmaHandler("export_type", RsContext));

  // For #pragma rs java_package_name
  PP.AddPragmaHandler(
      "rs", new RSJavaPackageNamePragmaHandler("java_package_name", RsContext));

  // For #pragma rs reduce
  PP.AddPragmaHandler(
      "rs", new RSReducePragmaHandler(RSExportReduceNew::KeyReduce, RsContext));

  // For #pragma rs set_reflect_license
  PP.AddPragmaHandler(
      "rs", new RSReflectLicensePragmaHandler("set_reflect_license", RsContext));

  // For #pragma version
  PP.AddPragmaHandler(new RSVersionPragmaHandler("version", RsContext));

  // For #pragma rs_fp*
  PP.AddPragmaHandler(new RSPrecisionPragmaHandler("rs_fp_full", RsContext));
  PP.AddPragmaHandler(new RSPrecisionPragmaHandler("rs_fp_relaxed", RsContext));
  PP.AddPragmaHandler(new RSPrecisionPragmaHandler("rs_fp_imprecise", RsContext));
}


}  // namespace slang
