// Copyright 2019 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/builtins/builtins-bigint-gen.h'

// TODO(nicohartmann): Discuss whether types used by multiple builtins should be
// in global namespace
@noVerifier
extern class BigIntBase extends HeapObject generates 'TNode<BigInt>' {
}

type BigInt extends BigIntBase;

@noVerifier
@hasSameInstanceTypeAsParent
extern class MutableBigInt extends BigIntBase generates 'TNode<BigInt>' {
}

Convert<BigInt, MutableBigInt>(i: MutableBigInt): BigInt {
  assert(bigint::IsCanonicalized(i));
  return %RawDownCast<BigInt>(Convert<BigIntBase>(i));
}

namespace bigint {

  const kPositiveSign: uint32 = 0;
  const kNegativeSign: uint32 = 1;

  extern macro BigIntBuiltinsAssembler::CppAbsoluteAddAndCanonicalize(
      MutableBigInt, BigIntBase, BigIntBase): void;
  extern macro BigIntBuiltinsAssembler::CppAbsoluteSubAndCanonicalize(
      MutableBigInt, BigIntBase, BigIntBase): void;
  extern macro BigIntBuiltinsAssembler::CppAbsoluteCompare(
      BigIntBase, BigIntBase): int32;

  extern macro BigIntBuiltinsAssembler::ReadBigIntSign(BigIntBase): uint32;
  extern macro BigIntBuiltinsAssembler::ReadBigIntLength(BigIntBase): intptr;
  extern macro BigIntBuiltinsAssembler::WriteBigIntSignAndLength(
      MutableBigInt, uint32, intptr): void;

  extern macro CodeStubAssembler::AllocateBigInt(intptr): MutableBigInt;
  extern macro CodeStubAssembler::StoreBigIntDigit(
      MutableBigInt, intptr, uintptr): void;
  extern macro CodeStubAssembler::LoadBigIntDigit(BigIntBase, intptr): uintptr;

  @export  // Silence unused warning.
           // TODO(szuend): Remove @export once macros that are only used in
           //               asserts are no longer detected as unused.
  macro IsCanonicalized(bigint: BigIntBase): bool {
    const length = ReadBigIntLength(bigint);

    if (length == 0) {
      return ReadBigIntSign(bigint) == kPositiveSign;
    }

    return LoadBigIntDigit(bigint, length - 1) != 0;
  }

  macro InvertSign(sign: uint32): uint32 {
    return sign == kPositiveSign ? kNegativeSign : kPositiveSign;
  }

  macro AllocateEmptyBigIntNoThrow(implicit context: Context)(
      sign: uint32, length: intptr): MutableBigInt labels BigIntTooBig {
    if (length > kBigIntMaxLength) {
      goto BigIntTooBig;
    }
    const result: MutableBigInt = AllocateBigInt(length);

    WriteBigIntSignAndLength(result, sign, length);
    return result;
  }

  macro AllocateEmptyBigInt(implicit context: Context)(
      sign: uint32, length: intptr): MutableBigInt {
    try {
      return AllocateEmptyBigIntNoThrow(sign, length) otherwise BigIntTooBig;
    }
    label BigIntTooBig {
      ThrowRangeError(kBigIntTooBig);
    }
  }

  macro MutableBigIntAbsoluteCompare(x: BigIntBase, y: BigIntBase): int32 {
    return CppAbsoluteCompare(x, y);
  }

  macro MutableBigIntAbsoluteSub(implicit context: Context)(
      x: BigInt, y: BigInt, resultSign: uint32): BigInt {
    const xlength = ReadBigIntLength(x);
    const ylength = ReadBigIntLength(y);
    const xsign = ReadBigIntSign(x);

    assert(MutableBigIntAbsoluteCompare(x, y) >= 0);
    if (xlength == 0) {
      assert(ylength == 0);
      return x;
    }

    if (ylength == 0) {
      return resultSign == xsign ? x : BigIntUnaryMinus(x);
    }

    const result = AllocateEmptyBigInt(resultSign, xlength);
    CppAbsoluteSubAndCanonicalize(result, x, y);
    return Convert<BigInt>(result);
  }

  macro MutableBigIntAbsoluteAdd(implicit context: Context)(
      xBigint: BigInt, yBigint: BigInt,
      resultSign: uint32): BigInt labels BigIntTooBig {
    let xlength = ReadBigIntLength(xBigint);
    let ylength = ReadBigIntLength(yBigint);

    let x = xBigint;
    let y = yBigint;
    if (xlength < ylength) {
      // Swap x and y so that x is longer.
      x = yBigint;
      y = xBigint;
      const tempLength = xlength;
      xlength = ylength;
      ylength = tempLength;
    }

    // case: 0n + 0n
    if (xlength == 0) {
      assert(ylength == 0);
      return x;
    }

    // case: x + 0n
    if (ylength == 0) {
      return resultSign == ReadBigIntSign(x) ? x : BigIntUnaryMinus(x);
    }

    // case: x + y
    const result = AllocateEmptyBigIntNoThrow(resultSign, xlength + 1)
        otherwise BigIntTooBig;
    CppAbsoluteAddAndCanonicalize(result, x, y);
    return Convert<BigInt>(result);
  }

  macro BigIntAddImpl(implicit context: Context)(x: BigInt, y: BigInt): BigInt
      labels BigIntTooBig {
    const xsign = ReadBigIntSign(x);
    const ysign = ReadBigIntSign(y);
    if (xsign == ysign) {
      // x + y == x + y
      // -x + -y == -(x + y)
      return MutableBigIntAbsoluteAdd(x, y, xsign) otherwise BigIntTooBig;
    }

    // x + -y == x - y == -(y - x)
    // -x + y == y - x == -(x - y)
    if (MutableBigIntAbsoluteCompare(x, y) >= 0) {
      return MutableBigIntAbsoluteSub(x, y, xsign);
    }
    return MutableBigIntAbsoluteSub(y, x, InvertSign(xsign));
  }

  builtin BigIntAddNoThrow(implicit context: Context)(x: BigInt, y: BigInt):
      Numeric {
    try {
      return BigIntAddImpl(x, y) otherwise BigIntTooBig;
    }
    label BigIntTooBig {
      // Smi sentinal is used to signal BigIntTooBig exception.
      return Convert<Smi>(0);
    }
  }

  builtin BigIntAdd(implicit context: Context)(xNum: Numeric, yNum: Numeric):
      BigInt {
    try {
      const x = Cast<BigInt>(xNum) otherwise MixedTypes;
      const y = Cast<BigInt>(yNum) otherwise MixedTypes;

      return BigIntAddImpl(x, y) otherwise BigIntTooBig;
    }
    label MixedTypes {
      ThrowTypeError(kBigIntMixedTypes);
    }
    label BigIntTooBig {
      ThrowRangeError(kBigIntTooBig);
    }
  }

  builtin BigIntUnaryMinus(implicit context: Context)(bigint: BigInt): BigInt {
    const length = ReadBigIntLength(bigint);

    // There is no -0n.
    if (length == 0) {
      return bigint;
    }

    const result =
        AllocateEmptyBigInt(InvertSign(ReadBigIntSign(bigint)), length);
    for (let i: intptr = 0; i < length; ++i) {
      StoreBigIntDigit(result, i, LoadBigIntDigit(bigint, i));
    }
    return Convert<BigInt>(result);
  }

}  // namespace bigint
