// Copyright 2018 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/codegen/string-constants.h"

#include "src/base/functional.h"
#include "src/numbers/dtoa.h"
#include "src/objects/objects.h"
#include "src/objects/string-inl.h"

namespace v8 {
namespace internal {

Handle<String> StringConstantBase::AllocateStringConstant(
    Isolate* isolate) const {
  if (!flattened_.is_null()) {
    return flattened_;
  }

  Handle<String> result;
  switch (kind()) {
    case StringConstantKind::kStringLiteral: {
      result = static_cast<const StringLiteral*>(this)->str();
      CHECK(!result.is_null());
      break;
    }
    case StringConstantKind::kNumberToStringConstant: {
      auto num_constant = static_cast<const NumberToStringConstant*>(this);
      Handle<Object> num_obj =
          isolate->factory()->NewNumber(num_constant->num());
      result = isolate->factory()->NumberToString(num_obj);
      CHECK(!result.is_null());
      break;
    }
    case StringConstantKind::kStringCons: {
      Handle<String> lhs =
          static_cast<const StringCons*>(this)->lhs()->AllocateStringConstant(
              isolate);
      Handle<String> rhs =
          static_cast<const StringCons*>(this)->rhs()->AllocateStringConstant(
              isolate);
      result = isolate->factory()->NewConsString(lhs, rhs).ToHandleChecked();
      break;
    }
  }

  // TODO(mslekova): Normally we'd want to flatten the string here
  // but that results in OOM for too long strings.
  Memoize(result);
  return flattened_;
}

bool StringConstantBase::operator==(const StringConstantBase& other) const {
  if (kind() != other.kind()) return false;

  switch (kind()) {
    case StringConstantKind::kStringLiteral: {
      return static_cast<const StringLiteral*>(this) ==
             static_cast<const StringLiteral*>(&other);
    }
    case StringConstantKind::kNumberToStringConstant: {
      return static_cast<const NumberToStringConstant*>(this) ==
             static_cast<const NumberToStringConstant*>(&other);
    }
    case StringConstantKind::kStringCons: {
      return static_cast<const StringCons*>(this) ==
             static_cast<const StringCons*>(&other);
    }
  }
  UNREACHABLE();
}

size_t hash_value(StringConstantBase const& base) {
  switch (base.kind()) {
    case StringConstantKind::kStringLiteral: {
      return hash_value(*static_cast<const StringLiteral*>(&base));
    }
    case StringConstantKind::kNumberToStringConstant: {
      return hash_value(*static_cast<const NumberToStringConstant*>(&base));
    }
    case StringConstantKind::kStringCons: {
      return hash_value(*static_cast<const StringCons*>(&base));
    }
  }
  UNREACHABLE();
}

bool operator==(StringLiteral const& lhs, StringLiteral const& rhs) {
  return lhs.str().address() == rhs.str().address();
}

bool operator!=(StringLiteral const& lhs, StringLiteral const& rhs) {
  return !(lhs == rhs);
}

size_t hash_value(StringLiteral const& p) {
  return base::hash_combine(p.str().address());
}

std::ostream& operator<<(std::ostream& os, StringLiteral const& p) {
  return os << Brief(*p.str());
}

bool operator==(NumberToStringConstant const& lhs,
                NumberToStringConstant const& rhs) {
  return lhs.num() == rhs.num();
}

bool operator!=(NumberToStringConstant const& lhs,
                NumberToStringConstant const& rhs) {
  return !(lhs == rhs);
}

size_t hash_value(NumberToStringConstant const& p) {
  return base::hash_combine(p.num());
}

std::ostream& operator<<(std::ostream& os, NumberToStringConstant const& p) {
  return os << p.num();
}

bool operator==(StringCons const& lhs, StringCons const& rhs) {
  // TODO(mslekova): Think if we can express this in a more readable manner
  return *(lhs.lhs()) == *(rhs.lhs()) && *(lhs.rhs()) == *(rhs.rhs());
}

bool operator!=(StringCons const& lhs, StringCons const& rhs) {
  return !(lhs == rhs);
}

size_t hash_value(StringCons const& p) {
  return base::hash_combine(*(p.lhs()), *(p.rhs()));
}

std::ostream& operator<<(std::ostream& os, const StringConstantBase* base) {
  os << "DelayedStringConstant: ";
  switch (base->kind()) {
    case StringConstantKind::kStringLiteral: {
      os << *static_cast<const StringLiteral*>(base);
      break;
    }
    case StringConstantKind::kNumberToStringConstant: {
      os << *static_cast<const NumberToStringConstant*>(base);
      break;
    }
    case StringConstantKind::kStringCons: {
      os << *static_cast<const StringCons*>(base);
      break;
    }
  }
  return os;
}

std::ostream& operator<<(std::ostream& os, StringCons const& p) {
  return os << p.lhs() << ", " << p.rhs();
}

size_t StringConstantBase::GetMaxStringConstantLength() const {
  switch (kind()) {
    case StringConstantKind::kStringLiteral: {
      return static_cast<const StringLiteral*>(this)
          ->GetMaxStringConstantLength();
    }
    case StringConstantKind::kNumberToStringConstant: {
      return static_cast<const NumberToStringConstant*>(this)
          ->GetMaxStringConstantLength();
    }
    case StringConstantKind::kStringCons: {
      return static_cast<const StringCons*>(this)->GetMaxStringConstantLength();
    }
  }
  UNREACHABLE();
}

size_t StringLiteral::GetMaxStringConstantLength() const { return length_; }

size_t NumberToStringConstant::GetMaxStringConstantLength() const {
  return kBase10MaximalLength + 1;
}

size_t StringCons::GetMaxStringConstantLength() const {
  return lhs()->GetMaxStringConstantLength() +
         rhs()->GetMaxStringConstantLength();
}

}  // namespace internal
}  // namespace v8
