//===-- Arena.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 "clang/Analysis/FlowSensitive/Arena.h"
#include "clang/Analysis/FlowSensitive/Formula.h"
#include "clang/Analysis/FlowSensitive/Value.h"
#include "llvm/Support/Error.h"
#include <string>

namespace clang::dataflow {

static std::pair<const Formula *, const Formula *>
canonicalFormulaPair(const Formula &LHS, const Formula &RHS) {
  auto Res = std::make_pair(&LHS, &RHS);
  if (&RHS < &LHS) // FIXME: use a deterministic order instead
    std::swap(Res.first, Res.second);
  return Res;
}

template <class Key, class ComputeFunc>
static const Formula &cached(llvm::DenseMap<Key, const Formula *> &Cache, Key K,
                             ComputeFunc &&Compute) {
  auto [It, Inserted] = Cache.try_emplace(std::forward<Key>(K));
  if (Inserted)
    It->second = Compute();
  return *It->second;
}

const Formula &Arena::makeAtomRef(Atom A) {
  return cached(AtomRefs, A, [&] {
    return &Formula::create(Alloc, Formula::AtomRef, {},
                            static_cast<unsigned>(A));
  });
}

const Formula &Arena::makeAnd(const Formula &LHS, const Formula &RHS) {
  return cached(Ands, canonicalFormulaPair(LHS, RHS), [&] {
    if (&LHS == &RHS)
      return &LHS;
    if (LHS.kind() == Formula::Literal)
      return LHS.literal() ? &RHS : &LHS;
    if (RHS.kind() == Formula::Literal)
      return RHS.literal() ? &LHS : &RHS;

    return &Formula::create(Alloc, Formula::And, {&LHS, &RHS});
  });
}

const Formula &Arena::makeOr(const Formula &LHS, const Formula &RHS) {
  return cached(Ors, canonicalFormulaPair(LHS, RHS), [&] {
    if (&LHS == &RHS)
      return &LHS;
    if (LHS.kind() == Formula::Literal)
      return LHS.literal() ? &LHS : &RHS;
    if (RHS.kind() == Formula::Literal)
      return RHS.literal() ? &RHS : &LHS;

    return &Formula::create(Alloc, Formula::Or, {&LHS, &RHS});
  });
}

const Formula &Arena::makeNot(const Formula &Val) {
  return cached(Nots, &Val, [&] {
    if (Val.kind() == Formula::Not)
      return Val.operands()[0];
    if (Val.kind() == Formula::Literal)
      return &makeLiteral(!Val.literal());

    return &Formula::create(Alloc, Formula::Not, {&Val});
  });
}

const Formula &Arena::makeImplies(const Formula &LHS, const Formula &RHS) {
  return cached(Implies, std::make_pair(&LHS, &RHS), [&] {
    if (&LHS == &RHS)
      return &makeLiteral(true);
    if (LHS.kind() == Formula::Literal)
      return LHS.literal() ? &RHS : &makeLiteral(true);
    if (RHS.kind() == Formula::Literal)
      return RHS.literal() ? &RHS : &makeNot(LHS);

    return &Formula::create(Alloc, Formula::Implies, {&LHS, &RHS});
  });
}

const Formula &Arena::makeEquals(const Formula &LHS, const Formula &RHS) {
  return cached(Equals, canonicalFormulaPair(LHS, RHS), [&] {
    if (&LHS == &RHS)
      return &makeLiteral(true);
    if (LHS.kind() == Formula::Literal)
      return LHS.literal() ? &RHS : &makeNot(RHS);
    if (RHS.kind() == Formula::Literal)
      return RHS.literal() ? &LHS : &makeNot(LHS);

    return &Formula::create(Alloc, Formula::Equal, {&LHS, &RHS});
  });
}

IntegerValue &Arena::makeIntLiteral(llvm::APInt Value) {
  auto [It, Inserted] = IntegerLiterals.try_emplace(Value, nullptr);

  if (Inserted)
    It->second = &create<IntegerValue>();
  return *It->second;
}

BoolValue &Arena::makeBoolValue(const Formula &F) {
  auto [It, Inserted] = FormulaValues.try_emplace(&F);
  if (Inserted)
    It->second = (F.kind() == Formula::AtomRef)
                     ? (BoolValue *)&create<AtomicBoolValue>(F)
                     : &create<FormulaBoolValue>(F);
  return *It->second;
}

namespace {
const Formula *parse(Arena &A, llvm::StringRef &In) {
  auto EatSpaces = [&] { In = In.ltrim(' '); };
  EatSpaces();

  if (In.consume_front("!")) {
    if (auto *Arg = parse(A, In))
      return &A.makeNot(*Arg);
    return nullptr;
  }

  if (In.consume_front("(")) {
    auto *Arg1 = parse(A, In);
    if (!Arg1)
      return nullptr;

    EatSpaces();
    decltype(&Arena::makeOr) Op;
    if (In.consume_front("|"))
      Op = &Arena::makeOr;
    else if (In.consume_front("&"))
      Op = &Arena::makeAnd;
    else if (In.consume_front("=>"))
      Op = &Arena::makeImplies;
    else if (In.consume_front("="))
      Op = &Arena::makeEquals;
    else
      return nullptr;

    auto *Arg2 = parse(A, In);
    if (!Arg2)
      return nullptr;

    EatSpaces();
    if (!In.consume_front(")"))
      return nullptr;

    return &(A.*Op)(*Arg1, *Arg2);
  }

  // For now, only support unnamed variables V0, V1 etc.
  // FIXME: parse e.g. "X" by allocating an atom and storing a name somewhere.
  if (In.consume_front("V")) {
    std::underlying_type_t<Atom> At;
    if (In.consumeInteger(10, At))
      return nullptr;
    return &A.makeAtomRef(static_cast<Atom>(At));
  }

  if (In.consume_front("true"))
    return &A.makeLiteral(true);
  if (In.consume_front("false"))
    return &A.makeLiteral(false);

  return nullptr;
}

class FormulaParseError : public llvm::ErrorInfo<FormulaParseError> {
  std::string Formula;
  unsigned Offset;

public:
  static char ID;
  FormulaParseError(llvm::StringRef Formula, unsigned Offset)
      : Formula(Formula), Offset(Offset) {}

  void log(raw_ostream &OS) const override {
    OS << "bad formula at offset " << Offset << "\n";
    OS << Formula << "\n";
    OS.indent(Offset) << "^";
  }

  std::error_code convertToErrorCode() const override {
    return std::make_error_code(std::errc::invalid_argument);
  }
};

char FormulaParseError::ID = 0;

} // namespace

llvm::Expected<const Formula &> Arena::parseFormula(llvm::StringRef In) {
  llvm::StringRef Rest = In;
  auto *Result = parse(*this, Rest);
  if (!Result) // parse() hit something unparseable
    return llvm::make_error<FormulaParseError>(In, In.size() - Rest.size());
  Rest = Rest.ltrim();
  if (!Rest.empty()) // parse didn't consume all the input
    return llvm::make_error<FormulaParseError>(In, In.size() - Rest.size());
  return *Result;
}

} // namespace clang::dataflow
