// Copyright 2017 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.

#ifndef V8_TORQUE_UTILS_H_
#define V8_TORQUE_UTILS_H_

#include <algorithm>
#include <ostream>
#include <queue>
#include <streambuf>
#include <string>
#include <unordered_set>

#include "src/base/functional.h"
#include "src/base/optional.h"
#include "src/torque/contextual.h"
#include "src/torque/source-positions.h"

namespace v8 {
namespace internal {
namespace torque {

std::string StringLiteralUnquote(const std::string& s);
std::string StringLiteralQuote(const std::string& s);

// Decodes "file://" URIs into file paths which can then be used
// with the standard stream API.
V8_EXPORT_PRIVATE base::Optional<std::string> FileUriDecode(
    const std::string& s);

struct TorqueMessage {
  enum class Kind { kError, kLint };

  std::string message;
  base::Optional<SourcePosition> position;
  Kind kind;
};

DECLARE_CONTEXTUAL_VARIABLE(TorqueMessages, std::vector<TorqueMessage>);

template <class... Args>
std::string ToString(Args&&... args) {
  std::stringstream stream;
  USE((stream << std::forward<Args>(args))...);
  return stream.str();
}

class V8_EXPORT_PRIVATE MessageBuilder {
 public:
  MessageBuilder() = delete;
  MessageBuilder(const std::string& message, TorqueMessage::Kind kind);

  MessageBuilder& Position(SourcePosition position) {
    message_.position = position;
    return *this;
  }

  [[noreturn]] void Throw() const;

  ~MessageBuilder() {
    // This will also get called in case the error is thrown.
    Report();
  }

 private:
  void Report() const;

  TorqueMessage message_;
  std::vector<TorqueMessage> extra_messages_;
};

// Used for throwing exceptions. Retrieve TorqueMessage from the contextual
// for specific error information.
struct TorqueAbortCompilation {};

template <class... Args>
static MessageBuilder Message(TorqueMessage::Kind kind, Args&&... args) {
  return MessageBuilder(ToString(std::forward<Args>(args)...), kind);
}

template <class... Args>
MessageBuilder Error(Args&&... args) {
  return Message(TorqueMessage::Kind::kError, std::forward<Args>(args)...);
}
template <class... Args>
MessageBuilder Lint(Args&&... args) {
  return Message(TorqueMessage::Kind::kLint, std::forward<Args>(args)...);
}

bool IsLowerCamelCase(const std::string& s);
bool IsUpperCamelCase(const std::string& s);
bool IsSnakeCase(const std::string& s);
bool IsValidNamespaceConstName(const std::string& s);
bool IsValidTypeName(const std::string& s);

template <class... Args>
[[noreturn]] void ReportError(Args&&... args) {
  Error(std::forward<Args>(args)...).Throw();
}

std::string CapifyStringWithUnderscores(const std::string& camellified_string);
std::string CamelifyString(const std::string& underscore_string);
std::string SnakeifyString(const std::string& camel_string);
std::string DashifyString(const std::string& underscore_string);
std::string UnderlinifyPath(std::string path);

void ReplaceFileContentsIfDifferent(const std::string& file_path,
                                    const std::string& contents);

std::string CurrentPositionAsString();

template <class T>
class Deduplicator {
 public:
  const T* Add(T x) { return &*(storage_.insert(std::move(x)).first); }

 private:
  std::unordered_set<T, base::hash<T>> storage_;
};

template <class T>
T& DereferenceIfPointer(T* x) {
  return *x;
}
template <class T>
T&& DereferenceIfPointer(T&& x) {
  return std::forward<T>(x);
}

template <class T, class L>
struct ListPrintAdaptor {
  const T& list;
  const std::string& separator;
  L transformer;

  friend std::ostream& operator<<(std::ostream& os, const ListPrintAdaptor& l) {
    bool first = true;
    for (auto& e : l.list) {
      if (first) {
        first = false;
      } else {
        os << l.separator;
      }
      os << DereferenceIfPointer(l.transformer(e));
    }
    return os;
  }
};

template <class T>
auto PrintList(const T& list, const std::string& separator = ", ") {
  using ElementType = decltype(*list.begin());
  auto id = [](ElementType el) { return el; };
  return ListPrintAdaptor<T, decltype(id)>{list, separator, id};
}

template <class T, class L>
auto PrintList(const T& list, const std::string& separator, L&& transformer) {
  return ListPrintAdaptor<T, L&&>{list, separator,
                                  std::forward<L>(transformer)};
}

template <class C, class T>
void PrintCommaSeparatedList(std::ostream& os, const T& list, C&& transform) {
  os << PrintList(list, ", ", std::forward<C>(transform));
}

template <class T>
void PrintCommaSeparatedList(std::ostream& os, const T& list) {
  os << PrintList(list, ", ");
}

struct BottomOffset {
  size_t offset;

  BottomOffset& operator=(std::size_t offset) {
    this->offset = offset;
    return *this;
  }
  BottomOffset& operator++() {
    ++offset;
    return *this;
  }
  BottomOffset operator+(size_t x) const { return BottomOffset{offset + x}; }
  BottomOffset operator-(size_t x) const {
    DCHECK_LE(x, offset);
    return BottomOffset{offset - x};
  }
  bool operator<(const BottomOffset& other) const {
    return offset < other.offset;
  }
  bool operator<=(const BottomOffset& other) const {
    return offset <= other.offset;
  }
  bool operator==(const BottomOffset& other) const {
    return offset == other.offset;
  }
  bool operator!=(const BottomOffset& other) const {
    return offset != other.offset;
  }
};

inline std::ostream& operator<<(std::ostream& out, BottomOffset from_bottom) {
  return out << "BottomOffset{" << from_bottom.offset << "}";
}

// An iterator-style range of stack slots.
class StackRange {
 public:
  StackRange(BottomOffset begin, BottomOffset end) : begin_(begin), end_(end) {
    DCHECK_LE(begin_, end_);
  }

  bool operator==(const StackRange& other) const {
    return begin_ == other.begin_ && end_ == other.end_;
  }

  void Extend(StackRange adjacent) {
    DCHECK_EQ(end_, adjacent.begin_);
    end_ = adjacent.end_;
  }

  size_t Size() const { return end_.offset - begin_.offset; }
  BottomOffset begin() const { return begin_; }
  BottomOffset end() const { return end_; }

 private:
  BottomOffset begin_;
  BottomOffset end_;
};

inline std::ostream& operator<<(std::ostream& out, StackRange range) {
  return out << "StackRange{" << range.begin() << ", " << range.end() << "}";
}

template <class T>
class Stack {
 public:
  using value_type = T;
  Stack() = default;
  Stack(std::initializer_list<T> initializer)
      : Stack(std::vector<T>(initializer)) {}
  explicit Stack(std::vector<T> v) : elements_(std::move(v)) {}
  size_t Size() const { return elements_.size(); }
  const T& Peek(BottomOffset from_bottom) const {
    return elements_.at(from_bottom.offset);
  }
  void Poke(BottomOffset from_bottom, T x) {
    elements_.at(from_bottom.offset) = std::move(x);
  }
  void Push(T x) {
    elements_.push_back(std::move(x));
  }
  StackRange TopRange(size_t slot_count) const {
    DCHECK_GE(Size(), slot_count);
    return StackRange{AboveTop() - slot_count, AboveTop()};
  }
  StackRange PushMany(const std::vector<T>& v) {
    for (const T& x : v) {
      Push(x);
    }
    return TopRange(v.size());
  }
  const T& Top() const { return Peek(AboveTop() - 1); }
  T Pop() {
    T result = std::move(elements_.back());
    elements_.pop_back();
    return result;
  }
  std::vector<T> PopMany(size_t count) {
    DCHECK_GE(elements_.size(), count);
    std::vector<T> result;
    result.reserve(count);
    for (auto it = elements_.end() - count; it != elements_.end(); ++it) {
      result.push_back(std::move(*it));
    }
    elements_.resize(elements_.size() - count);
    return result;
  }
  // The invalid offset above the top element. This is useful for StackRange.
  BottomOffset AboveTop() const { return BottomOffset{Size()}; }
  // Delete the slots in {range}, moving higher slots to fill the gap.
  void DeleteRange(StackRange range) {
    DCHECK_LE(range.end(), AboveTop());
    if (range.Size() == 0) return;
    for (BottomOffset i = range.end(); i < AboveTop(); ++i) {
      elements_[i.offset - range.Size()] = std::move(elements_[i.offset]);
    }
    elements_.resize(elements_.size() - range.Size());
  }

  bool operator==(const Stack& other) const {
    return elements_ == other.elements_;
  }
  bool operator!=(const Stack& other) const {
    return elements_ != other.elements_;
  }

  T* begin() { return elements_.data(); }
  T* end() { return begin() + elements_.size(); }
  const T* begin() const { return elements_.data(); }
  const T* end() const { return begin() + elements_.size(); }

 private:
  std::vector<T> elements_;
};

template <class T>
T* CheckNotNull(T* x) {
  CHECK_NOT_NULL(x);
  return x;
}

template <class T>
inline std::ostream& operator<<(std::ostream& os, const Stack<T>& t) {
  os << "Stack{";
  PrintCommaSeparatedList(os, t);
  os << "}";
  return os;
}

static const char* const kBaseNamespaceName = "base";
static const char* const kTestNamespaceName = "test";

// Erase elements of a container that has a constant-time erase function, like
// std::set or std::list. Calling this on std::vector would have quadratic
// complexity.
template <class Container, class F>
void EraseIf(Container* container, F f) {
  for (auto it = container->begin(); it != container->end();) {
    if (f(*it)) {
      it = container->erase(it);
    } else {
      ++it;
    }
  }
}

class NullStreambuf : public std::streambuf {
 public:
  int overflow(int c) override {
    setp(buffer_, buffer_ + sizeof(buffer_));
    return (c == traits_type::eof()) ? '\0' : c;
  }

 private:
  char buffer_[64];
};

class NullOStream : public std::ostream {
 public:
  NullOStream() : std::ostream(&buffer_) {}

 private:
  NullStreambuf buffer_;
};

inline bool StringStartsWith(const std::string& s, const std::string& prefix) {
  if (s.size() < prefix.size()) return false;
  return s.substr(0, prefix.size()) == prefix;
}
inline bool StringEndsWith(const std::string& s, const std::string& suffix) {
  if (s.size() < suffix.size()) return false;
  return s.substr(s.size() - suffix.size()) == suffix;
}

class IfDefScope {
 public:
  IfDefScope(std::ostream& os, std::string d);
  ~IfDefScope();
  IfDefScope(const IfDefScope&) = delete;
  IfDefScope& operator=(const IfDefScope&) = delete;

 private:
  std::ostream& os_;
  std::string d_;
};

class NamespaceScope {
 public:
  NamespaceScope(std::ostream& os,
                 std::initializer_list<std::string> namespaces);
  ~NamespaceScope();
  NamespaceScope(const NamespaceScope&) = delete;
  NamespaceScope& operator=(const NamespaceScope&) = delete;

 private:
  std::ostream& os_;
  std::vector<std::string> d_;
};

class IncludeGuardScope {
 public:
  IncludeGuardScope(std::ostream& os, std::string file_name);
  ~IncludeGuardScope();
  IncludeGuardScope(const IncludeGuardScope&) = delete;
  IncludeGuardScope& operator=(const IncludeGuardScope&) = delete;

 private:
  std::ostream& os_;
  std::string d_;
};

class IncludeObjectMacrosScope {
 public:
  explicit IncludeObjectMacrosScope(std::ostream& os);
  ~IncludeObjectMacrosScope();
  IncludeObjectMacrosScope(const IncludeObjectMacrosScope&) = delete;
  IncludeObjectMacrosScope& operator=(const IncludeObjectMacrosScope&) = delete;

 private:
  std::ostream& os_;
};

// A value of ResidueClass is a congruence class of integers modulo a power
// of 2.
// In contrast to common modulo arithmetic, we also allow addition and
// multiplication of congruence classes with different modulus. In this case, we
// do an abstract-interpretation style approximation to produce an as small as
// possible congruence class. ResidueClass is used to represent partial
// knowledge about offsets and sizes to validate alignment constraints.
// ResidueClass(x,m) = {y \in Z | x == y mod 2^m} = {x+k2^m | k \in Z} where Z
// is the set of all integers.
// Notation: 2^x is 2 to the power of x.
class ResidueClass {
 public:
  ResidueClass(size_t value, size_t modulus_log_2 =
                                 kMaxModulusLog2)  // NOLINT(runtime/explicit)
      : value_(value),
        modulus_log_2_(std::min(modulus_log_2, kMaxModulusLog2)) {
    if (modulus_log_2_ < kMaxModulusLog2) {
      value_ %= size_t{1} << modulus_log_2_;
    }
  }

  // 0 modulo 1, in other words, the class of all integers.
  static ResidueClass Unknown() { return ResidueClass{0, 0}; }

  // If the modulus corresponds to the size of size_t, it represents a concrete
  // value.
  base::Optional<size_t> SingleValue() const {
    if (modulus_log_2_ == kMaxModulusLog2) return value_;
    return base::nullopt;
  }

  friend ResidueClass operator+(const ResidueClass& a, const ResidueClass& b) {
    return ResidueClass{a.value_ + b.value_,
                        std::min(a.modulus_log_2_, b.modulus_log_2_)};
  }

  // Reasoning for the choice of the new modulus:
  // {x+k2^a | k \in Z} * {y+l2^b | l \in Z}
  // = {xy + xl2^b + yk2^a + kl2^(a+b)| k,l \in Z},
  // which is a subset of {xy + k2^c | k \in Z}
  // if 2^c is a common divisor of x2^b, y2^a and hence also of 2^(a+b) since
  // x<2^a and y<2^b.
  // So we use the gcd of x2^b and y2^a as the new modulus.
  friend ResidueClass operator*(const ResidueClass& a, const ResidueClass& b) {
    return ResidueClass{a.value_ * b.value_,
                        std::min(a.modulus_log_2_ + b.AlignmentLog2(),
                                 b.modulus_log_2_ + a.AlignmentLog2())};
  }

  friend std::ostream& operator<<(std::ostream& os, const ResidueClass& a);

  ResidueClass& operator+=(const ResidueClass& other) {
    *this = *this + other;
    return *this;
  }

  ResidueClass& operator*=(const ResidueClass& other) {
    *this = *this * other;
    return *this;
  }

  // 2^AlignmentLog2() is the larget power of 2 that divides all elements of the
  // congruence class.
  size_t AlignmentLog2() const;
  size_t Alignment() const {
    DCHECK_LT(AlignmentLog2(), kMaxModulusLog2);
    return size_t{1} << AlignmentLog2();
  }

 private:
  // The value is the representative of the congruence class. It's always
  // smaller than 2^modulus_log_2_.
  size_t value_;
  // Base 2 logarithm of the modulus.
  size_t modulus_log_2_;

  // size_t values are modulo 2^kMaxModulusLog2, so we don't consider larger
  // modulus.
  static const size_t kMaxModulusLog2 = 8 * sizeof(size_t);
};

template <typename T>
class Worklist {
 public:
  bool IsEmpty() const {
    DCHECK_EQ(queue_.size(), contained_.size());
    return queue_.empty();
  }

  bool Enqueue(T value) {
    if (contained_.find(value) != contained_.end()) return false;
    queue_.push(value);
    contained_.insert(value);
    DCHECK_EQ(queue_.size(), contained_.size());
    return true;
  }

  T Dequeue() {
    DCHECK(!IsEmpty());
    T value = queue_.front();
    queue_.pop();
    contained_.erase(value);
    DCHECK_EQ(queue_.size(), contained_.size());
    return value;
  }

 private:
  std::queue<T> queue_;
  std::unordered_set<T> contained_;
};

template <class T, class U, class F>
std::vector<T> TransformVector(const std::vector<U>& v, F f) {
  std::vector<T> result;
  std::transform(v.begin(), v.end(), std::back_inserter(result), f);
  return result;
}
template <class T, class U>
std::vector<T> TransformVector(const std::vector<U>& v) {
  return TransformVector<T>(v, [](const U& x) -> T { return x; });
}

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

#endif  // V8_TORQUE_UTILS_H_
