// Copyright 2020 The Bazel Authors. All rights reserved.
//
// 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.

package net.starlark.java.eval;

import java.math.BigInteger;
import net.starlark.java.annot.StarlarkBuiltin;

/** The Starlark int data type. */
@StarlarkBuiltin(
    name = "int",
    category = "core",
    doc =
        "The type of integers in Starlark. Starlark integers may be of any magnitude; arithmetic"
            + " is exact. Examples of integer expressions:<br>"
            + "<pre class=\"language-python\">153\n"
            + "0x2A  # hexadecimal literal\n"
            + "0o54  # octal literal\n"
            + "23 * 2 + 5\n"
            + "100 / -7\n"
            + "100 % -7  # -5 (unlike in some other languages)\n"
            + "int(\"18\")\n"
            + "</pre>")
public abstract class StarlarkInt implements StarlarkValue, Comparable<StarlarkInt> {

  // A cache of small integers >= LEAST_SMALLINT.
  private static final int LEAST_SMALLINT = -128;
  private static final Int32[] smallints = new Int32[100_000];

  static final StarlarkInt ZERO = StarlarkInt.of(0);
  private static final StarlarkInt ONE = StarlarkInt.of(1);
  private static final StarlarkInt MINUS_ONE = StarlarkInt.of(-1);

  /** Only nested classes of {@code StarlarkInt} are allowed to inherit it. */
  private StarlarkInt() {}

  /** Returns the Starlark int value that represents x. */
  public static StarlarkInt of(int x) {
    int index = x - LEAST_SMALLINT; // (may overflow)
    if (0 <= index && index < smallints.length) {
      Int32 xi = smallints[index];
      if (xi == null) {
        xi = new Int32(x);
        smallints[index] = xi;
      }
      return xi;
    }
    return new Int32(x);
  }

  /** Returns the Starlark int value that represents x. */
  public static StarlarkInt of(long x) {
    if ((long) (int) x == x) {
      return StarlarkInt.of((int) x);
    }
    return new Int64(x);
  }

  /** Returns the Starlark int value that represents x. */
  public static StarlarkInt of(BigInteger x) {
    if (x.bitLength() < 64) {
      return StarlarkInt.of(x.longValue());
    }
    return new Big(x);
  }

  /**
   * Returns the StarlarkInt value that most closely approximates x.
   *
   * @throws IllegalArgumentException is x is not finite.
   */
  static StarlarkInt ofFiniteDouble(double x) {
    return StarlarkFloat.finiteDoubleToIntExact(x);
  }

  /**
   * Returns the int denoted by a literal string in the specified base, as if by the Starlark
   * expression {@code int(s, base)}.
   *
   * @throws NumberFormatException if the input is invalid.
   */
  public static StarlarkInt parse(String s, int base) {
    String stringForErrors = s;

    if (s.isEmpty()) {
      throw new NumberFormatException("empty string");
    }

    // +/- prefix?
    boolean isNegative = false;
    char c = s.charAt(0);
    if (c == '+') {
      s = s.substring(1);
    } else if (c == '-') {
      s = s.substring(1);
      isNegative = true;
    }

    String digits = s;

    // 0b 0o 0x prefix?
    if (s.length() > 1 && s.charAt(0) == '0') {
      int prefixBase = 0;
      c = s.charAt(1);
      if (c == 'b' || c == 'B') {
        prefixBase = 2;
      } else if (c == 'o' || c == 'O') {
        prefixBase = 8;
      } else if (c == 'x' || c == 'X') {
        prefixBase = 16;
      }
      if (prefixBase != 0) {
        digits = s.substring(2); // strip prefix
        if (base == 0) {
          base = prefixBase;
        } else if (base != prefixBase) {
          throw new NumberFormatException(
              String.format(
                  "invalid base-%d literal: %s (%s prefix wants base %d)",
                  base, Starlark.repr(stringForErrors), s.substring(0, 2), prefixBase));
        }
      }
    }

    // No prefix, no base? Use decimal.
    if (digits == s && base == 0) {
      // Don't infer base when input starts with '0' due to octal/decimal ambiguity.
      if (s.length() > 1 && s.charAt(0) == '0') {
        throw new NumberFormatException(
            "cannot infer base when string begins with a 0: " + Starlark.repr(stringForErrors));
      }
      base = 10;
    }
    if (base < 2 || base > 36) {
      throw new NumberFormatException(
          String.format("invalid base %d (want 2 <= base <= 36)", base));
    }

    // Do not allow Long.parseLong and new BigInteger to accept another +/- sign.
    if (digits.startsWith("+") || digits.startsWith("-")) {
      throw new NumberFormatException(
          String.format("invalid base-%d literal: %s", base, Starlark.repr(stringForErrors)));
    }

    StarlarkInt result;
    try {
      result = StarlarkInt.of(Long.parseLong(digits, base));
    } catch (NumberFormatException unused1) {
      try {
        result = StarlarkInt.of(new BigInteger(digits, base));
      } catch (NumberFormatException unused2) {
        throw new NumberFormatException(
            String.format("invalid base-%d literal: %s", base, Starlark.repr(stringForErrors)));
      }
    }
    return isNegative ? StarlarkInt.uminus(result) : result;
  }

  // Subclass for values exactly representable in a Java int.
  private static final class Int32 extends StarlarkInt {
    final int v;

    Int32(int v) {
      this.v = v;
    }

    @Override
    public int toInt(String what) {
      return v;
    }

    @Override
    public long toLong(String what) {
      return (long) v;
    }

    @Override
    protected long toLongFast() {
      return (long) v;
    }

    @Override
    public BigInteger toBigInteger() {
      return BigInteger.valueOf(v);
    }

    @Override
    public Number toNumber() {
      return v;
    }

    @Override
    public int signum() {
      return Integer.signum(v);
    }

    @Override
    public void repr(Printer printer) {
      printer.append(v);
    }

    @Override
    public int hashCode() {
      return 0x316c5239 * Integer.hashCode(v) ^ 0x67c4a7d5;
    }

    @Override
    public boolean equals(Object that) {
      return (that instanceof Int32 && this.v == ((Int32) that).v)
          || (that instanceof StarlarkFloat && intEqualsFloat(this, (StarlarkFloat) that));
    }
  }

  // Subclass for values exactly representable in a Java long.
  private static final class Int64 extends StarlarkInt {
    final long v;

    Int64(long v) {
      this.v = v;
    }

    @Override
    public long toLong(String what) {
      return v;
    }

    @Override
    protected long toLongFast() {
      return v;
    }

    @Override
    public BigInteger toBigInteger() {
      return BigInteger.valueOf(v);
    }

    @Override
    public Number toNumber() {
      return v;
    }

    @Override
    public int signum() {
      return Long.signum(v);
    }

    @Override
    public void repr(Printer printer) {
      printer.append(v);
    }

    @Override
    public int hashCode() {
      return 0x67c4a7d5 * Long.hashCode(v) ^ 0xee914a1b;
    }

    @Override
    public boolean equals(Object that) {
      return (that instanceof Int64 && this.v == ((Int64) that).v)
          || (that instanceof StarlarkFloat && intEqualsFloat(this, (StarlarkFloat) that));
    }
  }

  // Subclass for values not exactly representable in a long.
  private static final class Big extends StarlarkInt {
    final BigInteger v;

    Big(BigInteger v) {
      this.v = v;
    }

    @Override
    public BigInteger toBigInteger() {
      return v;
    }

    @Override
    public Number toNumber() {
      return v;
    }

    @Override
    public int signum() {
      return v.signum();
    }

    @Override
    public void repr(Printer printer) {
      printer.append(v.toString());
    }

    @Override
    public int hashCode() {
      return 0xee914a1b * v.hashCode() ^ 0x6406918f;
    }

    @Override
    public boolean equals(Object that) {
      return (that instanceof Big && this.v.equals(((Big) that).v))
          || (that instanceof StarlarkFloat && intEqualsFloat(this, (StarlarkFloat) that));
    }
  }

  /** Returns the value of this StarlarkInt as a Number (Integer, Long, or BigInteger). */
  public abstract Number toNumber();

  /** Returns the signum of this StarlarkInt (-1, 0, or +1). */
  public abstract int signum();

  /** Returns this StarlarkInt as a string of decimal digits. */
  @Override
  public String toString() {
    if (this instanceof Int32) {
      return Integer.toString(((Int32) this).v);
    } else if (this instanceof Int64) {
      return Long.toString(((Int64) this).v);
    } else {
      return toBigInteger().toString();
    }
  }

  @Override
  public abstract void repr(Printer printer);

  /** Returns the signed int32 value of this StarlarkInt, or fails if not exactly representable. */
  public int toInt(String what) throws EvalException {
    throw Starlark.errorf("got %s for %s, want value in signed 32-bit range", this, what);
  }

  /** Returns the signed int64 value of this StarlarkInt, or fails if not exactly representable. */
  public long toLong(String what) throws EvalException {
    throw Starlark.errorf("got %s for %s, want value in the signed 64-bit range", this, what);
  }

  // A preallocated exception used to indicate overflow errors without the cost of allocation.
  private static final Overflow OVERFLOW = new Overflow();

  private static final class Overflow extends Exception {}

  /**
   * Similar to {@link #toLong(String)}, but faster: exception is not allocated and stack trace is
   * not collected.
   */
  protected long toLongFast() throws Overflow {
    throw OVERFLOW;
  }

  /** Returns the nearest IEEE-754 double-precision value closest to this int, which may be ±Inf. */
  public double toDouble() {
    if (this instanceof Int32) {
      return ((Int32) this).v;
    } else if (this instanceof Int64) {
      return ((Int64) this).v;
    } else {
      return toBigInteger().doubleValue(); // may be ±Inf
    }
  }

  /**
   * Returns the nearest IEEE-754 double-precision value closest to this int.
   *
   * @throws EvalException is the int is to large to represent as a finite float value.
   */
  public double toFiniteDouble() throws EvalException {
    double d = toDouble();
    if (!Double.isFinite(d)) {
      throw Starlark.errorf("int too large to convert to float");
    }
    return d;
  }

  /** Returns the BigInteger value of this StarlarkInt. */
  public abstract BigInteger toBigInteger();

  /**
   * Returns the the value of this StarlarkInt as a Java signed 32-bit int.
   *
   * @throws IllegalArgumentException if this int is not in that value range.
   */
  public final int toIntUnchecked() throws IllegalArgumentException {
    if (this instanceof Int32) {
      return ((Int32) this).v;
    }
    // Use a constant exception to avoid allocation.
    // This operator is provided for fast access and case discrimination.
    // Use toInt(String) for user-visible errors.
    throw NOT_INT32;
  }

  private static final IllegalArgumentException NOT_INT32 =
      new IllegalArgumentException("not a signed 32-bit value");

  /** Returns the result of truncating this value into the signed 32-bit range. */
  public int truncateToInt() {
    if (this instanceof Int32) {
      return ((Int32) this).v;
    } else if (this instanceof Int64) {
      return (int) ((Int64) this).v;
    } else {
      return toBigInteger().intValue();
    }
  }

  @Override
  public boolean isImmutable() {
    return true;
  }

  @Override
  public boolean truth() {
    return this != ZERO;
  }

  @Override
  public int compareTo(StarlarkInt x) {
    return compare(this, x);
  }

  // binary operators

  /** Returns signum(x - y). */
  public static int compare(StarlarkInt x, StarlarkInt y) {
    // If both arguments are big, we compare BigIntegers.
    // If neither argument is big, we compare longs.
    // If only one argument is big, its magnitude is greater
    // than the other operand, so only its sign matters.
    //
    // We avoid unnecessary branches.
    try {
      long xl = x.toLongFast();
      try {
        long yl = y.toLongFast();
        return Long.compare(xl, yl); // (long, long)
      } catch (Overflow unused) {
        return -((Big) y).v.signum(); // (long, big)
      }
    } catch (Overflow unused) {
      return y instanceof Big
          ? ((Big) x).v.compareTo(((Big) y).v) // (big, big)
          : ((Big) x).v.signum(); // (big, long)
    }
  }

  /** Returns x + y. */
  public static StarlarkInt add(StarlarkInt x, StarlarkInt y) {
    if (x instanceof Int32 && y instanceof Int32) {
      long xl = ((Int32) x).v;
      long yl = ((Int32) y).v;
      return StarlarkInt.of(xl + yl);
    }

    // We avoid Math.addExact and its overheads of exception allocation.
    try {
      long xl = x.toLongFast();
      long yl = y.toLongFast();
      long zl = xl + yl;
      boolean overflow = ((xl ^ zl) & (yl ^ zl)) < 0; // see Hacker's Delight, chapter 2
      if (!overflow) {
        return StarlarkInt.of(zl);
      }
    } catch (Overflow unused) {
      /* fall through */
    }

    BigInteger xbig = x.toBigInteger();
    BigInteger ybig = y.toBigInteger();
    BigInteger zbig = xbig.add(ybig);
    return StarlarkInt.of(zbig);
  }

  /** Returns x - y. */
  public static StarlarkInt subtract(StarlarkInt x, StarlarkInt y) {
    if (x instanceof Int32 && y instanceof Int32) {
      long xl = ((Int32) x).v;
      long yl = ((Int32) y).v;
      return StarlarkInt.of(xl - yl);
    }

    // We avoid Math.subtractExact and its overhead of exception allocation.
    try {
      long xl = x.toLongFast();
      long yl = y.toLongFast();
      long zl = xl - yl;
      boolean overflow = ((xl ^ yl) & (xl ^ zl)) < 0; // see Hacker's Delight, chapter 2
      if (!overflow) {
        return StarlarkInt.of(zl);
      }
    } catch (Overflow unused) {
      /* fall through */
    }

    BigInteger xbig = x.toBigInteger();
    BigInteger ybig = y.toBigInteger();
    BigInteger zbig = xbig.subtract(ybig);
    return StarlarkInt.of(zbig);
  }

  /** Returns x * y. */
  public static StarlarkInt multiply(StarlarkInt x, StarlarkInt y) {
    // Fast path for common case: int32 * int32.
    if (x instanceof Int32 && y instanceof Int32) {
      long xl = ((Int32) x).v;
      long yl = ((Int32) y).v;
      return StarlarkInt.of(xl * yl);
    }

    try {
      long xl = x.toLongFast();
      long yl = y.toLongFast();

      // Signed int128 multiplication, using Hacker's Delight 8-2
      // (High-Order Half of 64-Bit Product) extended to 128 bits.
      // TODO(adonovan): use Math.multiplyHigh when Java 9 becomes available.
      long xlo = xl & 0xFFFFFFFFL;
      long xhi = xl >> 32;
      long ylo = yl & 0xFFFFFFFFL;
      long yhi = yl >> 32;
      long zlo = xlo * ylo;
      long t = xhi * ylo + (zlo >>> 32);
      long z1 = t & 0xFFFFFFFFL;
      long z2 = t >> 32;
      z1 += xlo * yhi;

      // high and low arms of result
      long z128hi = xhi * yhi + z2 + (z1 >> 32);
      long z128lo = xl * yl;

      // Check int128 result is within int64 range.
      if (z128hi == (z128lo & Long.MIN_VALUE) >> 63) {
        return StarlarkInt.of(z128lo);
      }

      /* overflow */

    } catch (Overflow unused) {
      /* fall through */
    }

    // Avoid unnecessary conversion to BigInteger if the other operand is -1, 0, 1.
    // (Also makes self-test below faster.)
    if (x == ZERO || y == ONE) {
      return x;
    } else if (y == ZERO || x == ONE) {
      return y;
    } else if (x == MINUS_ONE) {
      return StarlarkInt.uminus(y);
    } else if (y == MINUS_ONE) {
      return StarlarkInt.uminus(x);
    }

    BigInteger xbig = x.toBigInteger();
    BigInteger ybig = y.toBigInteger();
    BigInteger zbig = xbig.multiply(ybig);
    StarlarkInt z = StarlarkInt.of(zbig);
    // cheap self-test
    if (!(z instanceof Big)) {
      throw new AssertionError(
          String.format(
              "bug in multiplication: %s * %s = %s, must be long multiplication", x, y, z));
    }
    return z;
  }

  /** Returns x // y (floor of integer division). */
  public static StarlarkInt floordiv(StarlarkInt x, StarlarkInt y) throws EvalException {
    if (y == ZERO) {
      throw Starlark.errorf("integer division by zero");
    }
    try {
      long xl = x.toLongFast();
      long yl = y.toLongFast();
      // http://python-history.blogspot.com/2010/08/why-pythons-integer-division-floors.html
      if (xl == Long.MIN_VALUE && yl == -1) {
        /* sole case in which quotient doesn't fit in long */
      } else {
        long quo = Math.floorDiv(xl, yl);
        return StarlarkInt.of(quo);
      }
      /* overflow */
    } catch (Overflow unused) {
      /* fall through */
    }

    BigInteger xbig = x.toBigInteger();
    BigInteger ybig = y.toBigInteger();
    BigInteger[] quorem = xbig.divideAndRemainder(ybig);
    if ((xbig.signum() < 0) != (ybig.signum() < 0) && quorem[1].signum() != 0) {
      quorem[0] = quorem[0].subtract(BigInteger.ONE);
    }
    return StarlarkInt.of(quorem[0]);
  }

  /** Returns x % y. */
  public static StarlarkInt mod(StarlarkInt x, StarlarkInt y) throws EvalException {
    if (y == ZERO) {
      throw Starlark.errorf("integer modulo by zero");
    }
    try {
      long xl = x.toLongFast();
      long yl = y.toLongFast();
      // In Starlark, the sign of the result is the sign of the divisor.
      return StarlarkInt.of(Math.floorMod(xl, yl));
    } catch (Overflow unused) {
      /* fall through */
    }

    BigInteger xbig = x.toBigInteger();
    BigInteger ybig = y.toBigInteger();
    BigInteger zbig = xbig.remainder(ybig);
    if ((x.signum() < 0) != (y.signum() < 0) && zbig.signum() != 0) {
      zbig = zbig.add(ybig);
    }
    return StarlarkInt.of(zbig);
  }

  /** Returns x >> y. */
  public static StarlarkInt shiftRight(StarlarkInt x, StarlarkInt y) throws EvalException {
    int yi = y.toInt("shift count");
    if (yi < 0) {
      throw Starlark.errorf("negative shift count: %d", yi);
    }
    try {
      long xl = x.toLongFast();
      if (yi >= Long.SIZE) {
        return xl < 0 ? StarlarkInt.of(-1) : ZERO;
      }
      return StarlarkInt.of(xl >> yi);
    } catch (Overflow unused) {
      /* fall through */
    }

    BigInteger xbig = x.toBigInteger();
    BigInteger zbig = xbig.shiftRight(yi);
    return StarlarkInt.of(zbig);
  }

  /** Returns x << y. */
  public static StarlarkInt shiftLeft(StarlarkInt x, StarlarkInt y) throws EvalException {
    int yi = y.toInt("shift count");
    if (yi < 0) {
      throw Starlark.errorf("negative shift count: %d", yi);
    } else if (yi >= 512) {
      throw Starlark.errorf("shift count too large: %d", yi);
    }
    try {
      long xl = x.toLongFast();
      long z = xl << yi; // only uses low 6 bits of yi
      if ((z >> yi) == xl && yi < 64) {
        return StarlarkInt.of(z);
      }
      /* overflow */
    } catch (Overflow unused) {
      /* fall through */
    }

    BigInteger xbig = x.toBigInteger();
    BigInteger zbig = xbig.shiftLeft(yi);
    return StarlarkInt.of(zbig);
  }

  /** Returns x ^ y. */
  public static StarlarkInt xor(StarlarkInt x, StarlarkInt y) {
    try {
      long xl = x.toLongFast();
      long yl = y.toLongFast();
      return StarlarkInt.of(xl ^ yl);
    } catch (Overflow unused) {
      /* fall through */
    }

    BigInteger xbig = x.toBigInteger();
    BigInteger ybig = y.toBigInteger();
    BigInteger zbig = xbig.xor(ybig);
    return StarlarkInt.of(zbig);
  }

  /** Returns x | y. */
  public static StarlarkInt or(StarlarkInt x, StarlarkInt y) {
    try {
      long xl = x.toLongFast();
      long yl = y.toLongFast();
      return StarlarkInt.of(xl | yl);
    } catch (Overflow unused) {
      /* fall through */
    }

    BigInteger xbig = x.toBigInteger();
    BigInteger ybig = y.toBigInteger();
    BigInteger zbig = xbig.or(ybig);
    return StarlarkInt.of(zbig);
  }

  /** Returns x & y. */
  public static StarlarkInt and(StarlarkInt x, StarlarkInt y) {
    try {
      long xl = x.toLongFast();
      long yl = y.toLongFast();
      return StarlarkInt.of(xl & yl);
    } catch (Overflow unused) {
      /* fall through */
    }

    BigInteger xbig = x.toBigInteger();
    BigInteger ybig = y.toBigInteger();
    BigInteger zbig = xbig.and(ybig);
    return StarlarkInt.of(zbig);
  }

  /** Returns ~x. */
  public static StarlarkInt bitnot(StarlarkInt x) {
    try {
      long xl = x.toLongFast();
      return StarlarkInt.of(~xl);
    } catch (Overflow unused) {
      /* fall through */
    }

    BigInteger xbig = ((Big) x).v;
    return StarlarkInt.of(xbig.not());
  }

  /** Returns -x. */
  public static StarlarkInt uminus(StarlarkInt x) {
    if (x instanceof Int32) {
      long xl = ((Int32) x).v;
      return StarlarkInt.of(-xl);
    }

    if (x instanceof Int64) {
      long xl = ((Int64) x).v;
      if (xl != Long.MIN_VALUE) {
        return StarlarkInt.of(-xl);
      }
    }

    BigInteger xbig = x.toBigInteger();
    BigInteger ybig = xbig.negate();
    return StarlarkInt.of(ybig);
  }

  /** Reports whether int x exactly equals float y. */
  static boolean intEqualsFloat(StarlarkInt x, StarlarkFloat y) {
    double yf = y.toDouble();
    return !Double.isNaN(yf) && compareIntAndDouble(x, yf) == 0;
  }

  /** Returns an exact three-valued comparison of int x with (non-NaN) double y. */
  static int compareIntAndDouble(StarlarkInt x, double y) {
    if (Double.isInfinite(y)) {
      return y > 0 ? -1 : +1;
    }

    // For Int32 and some Int64s, the toDouble conversion is exact.
    if (x instanceof StarlarkInt.Int32
        || (x instanceof StarlarkInt.Int64 && longHasExactDouble(((Int64) x).v))) {
      // Avoid Double.compare: it believes -0.0 < 0.0.
      double xf = x.toDouble();
      if (xf > y) {
        return +1;
      } else if (xf < y) {
        return -1;
      }
      return 0;
    }

    // If signs differ, we needn't look at magnitude.
    int xsign = x.signum();
    int ysign = (int) Math.signum(y);
    if (xsign > ysign) {
      return +1;
    } else if (xsign < ysign) {
      return -1;
    }

    // Left-shift either the int or the float mantissa,
    // then compare the resulting integers.
    int shift = StarlarkFloat.getShift(y);
    BigInteger xbig = x.toBigInteger();
    if (shift < 0) {
      xbig = xbig.shiftLeft(-shift);
    }
    BigInteger ybig = BigInteger.valueOf(StarlarkFloat.getMantissa(y));
    if (shift > 0) {
      ybig = ybig.shiftLeft(shift);
    }
    return xbig.compareTo(ybig);
  }

  private static boolean longHasExactDouble(long x) {
    return (long) (double) x == x;
  }
}
