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

#ifndef V8_OBJECTS_SMI_H_
#define V8_OBJECTS_SMI_H_

#include "src/common/globals.h"
#include "src/objects/heap-object.h"

// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"

namespace v8 {
namespace internal {

// Smi represents integer Numbers that can be stored in 31 bits.
// Smis are immediate which means they are NOT allocated in the heap.
// The ptr_ value has the following format: [31 bit signed int] 0
// For long smis it has the following format:
//     [32 bit signed int] [31 bits zero padding] 0
// Smi stands for small integer.
class Smi : public Object {
 public:
  // This replaces the OBJECT_CONSTRUCTORS macro, because Smis are special
  // in that we want them to be constexprs.
  constexpr Smi() : Object() {}
  explicit constexpr Smi(Address ptr) : Object(ptr) {
#if V8_CAN_HAVE_DCHECK_IN_CONSTEXPR
    DCHECK(HAS_SMI_TAG(ptr));
#endif
  }
  Smi* operator->() { return this; }
  const Smi* operator->() const { return this; }

  // Returns the integer value.
  inline int value() const { return Internals::SmiValue(ptr()); }
  inline Smi ToUint32Smi() {
    if (value() <= 0) return Smi::FromInt(0);
    return Smi::FromInt(static_cast<uint32_t>(value()));
  }

  // Convert a Smi object to an int.
  static inline int ToInt(const Object object) {
    return Smi::cast(object).value();
  }

  // Convert a value to a Smi object.
  static inline constexpr Smi FromInt(int value) {
#if V8_CAN_HAVE_DCHECK_IN_CONSTEXPR
    DCHECK(Smi::IsValid(value));
#endif
    return Smi(Internals::IntToSmi(value));
  }

  static inline Smi FromIntptr(intptr_t value) {
    DCHECK(Smi::IsValid(value));
    int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
    return Smi((static_cast<Address>(value) << smi_shift_bits) | kSmiTag);
  }

  // Given {value} in [0, 2^31-1], force it into Smi range by changing at most
  // the MSB (leaving the lower 31 bit unchanged).
  static inline Smi From31BitPattern(int value) {
    return Smi::FromInt((value << (32 - kSmiValueSize)) >>
                        (32 - kSmiValueSize));
  }

  template <typename E,
            typename = typename std::enable_if<std::is_enum<E>::value>::type>
  static inline Smi FromEnum(E value) {
    STATIC_ASSERT(sizeof(E) <= sizeof(int));
    return FromInt(static_cast<int>(value));
  }

  // Returns whether value can be represented in a Smi.
  static inline bool constexpr IsValid(intptr_t value) {
#if V8_CAN_HAVE_DCHECK_IN_CONSTEXPR
    DCHECK(Internals::IsValidSmi(value) ==
           (value >= kMinValue && value <= kMaxValue));
#endif
    return Internals::IsValidSmi(value);
  }

  // Compare two Smis x, y as if they were converted to strings and then
  // compared lexicographically. Returns:
  // -1 if x < y.
  //  0 if x == y.
  //  1 if x > y.
  // Returns the result (a tagged Smi) as a raw Address for ExternalReference
  // usage.
  V8_EXPORT_PRIVATE static Address LexicographicCompare(Isolate* isolate, Smi x,
                                                        Smi y);

  DECL_CAST(Smi)

  // Dispatched behavior.
  V8_EXPORT_PRIVATE void SmiPrint(std::ostream& os) const;  // NOLINT
  DECL_VERIFIER(Smi)

  // C++ does not allow us to have an object of type Smi within class Smi,
  // so the kZero value has type Object. Consider it deprecated; new code
  // should use zero() instead.
  V8_EXPORT_PRIVATE static constexpr Object kZero = Object(0);
  // If you need something with type Smi, call zero() instead. Since it is
  // a constexpr, "calling" it is just as efficient as reading kZero.
  static inline constexpr Smi zero() { return Smi::FromInt(0); }
  static constexpr int kMinValue = kSmiMinValue;
  static constexpr int kMaxValue = kSmiMaxValue;
};

CAST_ACCESSOR(Smi)

}  // namespace internal
}  // namespace v8

#include "src/objects/object-macros-undef.h"

#endif  // V8_OBJECTS_SMI_H_
