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

namespace array_splice {
  // Given {elements}, we want to create a non-zero length array of type
  // FixedArrayType. Most of this behavior is outsourced to ExtractFixedArray(),
  // but the special case of wanting to have a FixedDoubleArray when given a
  // zero-length input FixedArray is handled here.
  macro Extract<FixedArrayType: type>(
      elements: FixedArrayBase, first: Smi, count: Smi,
      capacity: Smi): FixedArrayType;

  Extract<FixedArray>(implicit context: Context)(
      elements: FixedArrayBase, first: Smi, count: Smi,
      capacity: Smi): FixedArray {
    return UnsafeCast<FixedArray>(
        ExtractFixedArray(elements, first, count, capacity));
  }

  Extract<FixedDoubleArray>(implicit context: Context)(
      elements: FixedArrayBase, first: Smi, count: Smi,
      capacity: Smi): FixedDoubleArray {
    if (elements == kEmptyFixedArray) {
      return AllocateZeroedFixedDoubleArray(Convert<intptr>(capacity));
    }
    return UnsafeCast<FixedDoubleArray>(
        ExtractFixedArray(elements, first, count, capacity));
  }

  macro DoMoveElements<FixedArrayType: type>(
      elements: FixedArrayType, dstIndex: Smi, srcIndex: Smi,
      count: Smi): void {
    TorqueMoveElements(
        elements, Convert<intptr>(dstIndex), Convert<intptr>(srcIndex),
        Convert<intptr>(count));
  }

  macro StoreHoles<FixedArrayType: type>(
      elements: FixedArrayType, holeStartIndex: Smi, holeEndIndex: Smi): void {
    for (let i: Smi = holeStartIndex; i < holeEndIndex; i++) {
      array::StoreArrayHole(elements, i);
    }
  }

  macro DoCopyElements<FixedArrayType: type>(
      dstElements: FixedArrayType, dstIndex: Smi, srcElements: FixedArrayType,
      srcIndex: Smi, count: Smi): void {
    TorqueCopyElements(
        dstElements, Convert<intptr>(dstIndex), srcElements,
        Convert<intptr>(srcIndex), Convert<intptr>(count));
  }

  macro FastSplice<FixedArrayType: type, ElementType: type>(implicit context:
                                                                  Context)(
      args: Arguments, a: JSArray, length: Smi, newLength: Smi,
      actualStart: Smi, insertCount: Smi, actualDeleteCount: Smi): void {
    // Make sure elements are writable.
    array::EnsureWriteableFastElements(a);

    if (insertCount != actualDeleteCount) {
      const elements: FixedArrayBase = a.elements;
      const dstIndex: Smi = actualStart + insertCount;
      const srcIndex: Smi = actualStart + actualDeleteCount;
      const count: Smi = length - actualDeleteCount - actualStart;
      if (insertCount < actualDeleteCount) {
        // Shrink.
        DoMoveElements<FixedArrayType>(
            UnsafeCast<FixedArrayType>(elements), dstIndex, srcIndex, count);
        StoreHoles<FixedArrayType>(
            UnsafeCast<FixedArrayType>(elements), newLength, length);
      } else if (insertCount > actualDeleteCount) {
        // If the backing store is big enough, then moving elements is enough.
        if (newLength <= elements.length) {
          DoMoveElements<FixedArrayType>(
              UnsafeCast<FixedArrayType>(elements), dstIndex, srcIndex, count);
        } else {
          // Grow.
          const capacity: Smi = CalculateNewElementsCapacity(newLength);
          const newElements: FixedArrayType =
              Extract<FixedArrayType>(elements, 0, actualStart, capacity);
          a.elements = newElements;
          if (elements.length > 0) {
            DoCopyElements<FixedArrayType>(
                newElements, dstIndex, UnsafeCast<FixedArrayType>(elements),
                srcIndex, count);
          }
        }
      }
    }

    // Copy arguments.
    let k: Smi = actualStart;
    if (insertCount > 0) {
      const typedNewElements: FixedArrayType =
          UnsafeCast<FixedArrayType>(a.elements);
      for (let i: intptr = 2; i < args.length; ++i) {
        const e: Object = args[i];
        // The argument elements were already validated to be an appropriate
        // {ElementType} to store in {FixedArrayType}.
        typedNewElements[k++] = UnsafeCast<ElementType>(e);
      }
    }

    // Update the array's length after all the FixedArray shuffling is done.
    a.length = newLength;
  }

  transitioning macro FastArraySplice(
      context: Context, args: Arguments, o: JSReceiver,
      originalLengthNumber: Number, actualStartNumber: Number, insertCount: Smi,
      actualDeleteCountNumber: Number): Object
      labels Bailout {
    const originalLength: Smi =
        Cast<Smi>(originalLengthNumber) otherwise Bailout;
    const actualStart: Smi = Cast<Smi>(actualStartNumber) otherwise Bailout;
    const actualDeleteCount: Smi =
        Cast<Smi>(actualDeleteCountNumber) otherwise Bailout;
    const lengthDelta: Smi = insertCount - actualDeleteCount;
    const newLength: Smi = originalLength + lengthDelta;

    const a: JSArray = Cast<JSArray>(o) otherwise Bailout;

    const map: Map = a.map;
    if (!IsPrototypeInitialArrayPrototype(map)) goto Bailout;
    if (IsNoElementsProtectorCellInvalid()) goto Bailout;
    if (IsArraySpeciesProtectorCellInvalid()) goto Bailout;

    // Fast path only works on fast elements kind and with writable length.
    let elementsKind: ElementsKind = EnsureArrayPushable(map) otherwise Bailout;
    if (!IsFastElementsKind(elementsKind)) goto Bailout;

    const oldElementsKind: ElementsKind = elementsKind;
    for (let i: intptr = 2; i < args.length; ++i) {
      const e: Object = args[i];
      if (IsFastSmiElementsKind(elementsKind)) {
        if (TaggedIsNotSmi(e)) {
          const heapObject: HeapObject = UnsafeCast<HeapObject>(e);
          elementsKind = IsHeapNumber(heapObject) ?
              AllowDoubleElements(elementsKind) :
              AllowNonNumberElements(elementsKind);
        }
      } else if (IsDoubleElementsKind(elementsKind)) {
        if (!IsNumber(e)) {
          elementsKind = AllowNonNumberElements(elementsKind);
        }
      }
    }

    if (elementsKind != oldElementsKind) {
      const smiElementsKind: Smi = Convert<Smi>(Convert<int32>(elementsKind));
      TransitionElementsKindWithKind(context, a, smiElementsKind);
    }

    // Make sure that the length hasn't been changed by side-effect.
    const length: Smi = Cast<Smi>(a.length) otherwise Bailout;
    if (originalLength != length) goto Bailout;

    const deletedResult: JSArray =
        ExtractFastJSArray(context, a, actualStart, actualDeleteCount);

    if (newLength == 0) {
      a.elements = kEmptyFixedArray;
      a.length = 0;
      return deletedResult;
    }

    if (IsFastSmiOrTaggedElementsKind(elementsKind)) {
      FastSplice<FixedArray, Object>(
          args, a, length, newLength, actualStart, insertCount,
          actualDeleteCount);
    } else {
      FastSplice<FixedDoubleArray, Number>(
          args, a, length, newLength, actualStart, insertCount,
          actualDeleteCount);
    }

    return deletedResult;
  }

  transitioning macro FillDeletedElementsArray(
      context: Context, o: JSReceiver, actualStart: Number,
      actualDeleteCount: Number, a: JSReceiver): Object {
    // 10. Let k be 0.
    let k: Number = 0;

    // 11. Repeat, while k < actualDeleteCount
    while (k < actualDeleteCount) {
      // a. Let from be ! ToString(actualStart + k).
      const from: Number = actualStart + k;

      // b. Let fromPresent be ? HasProperty(O, from).
      const fromPresent: Boolean = HasProperty(o, from);

      // c. If fromPresent is true, then
      if (fromPresent == True) {
        // i. Let fromValue be ? Get(O, from).
        const fromValue: Object = GetProperty(o, from);

        // ii. Perform ? CreateDataPropertyOrThrow(A, ! ToString(k), fromValue).
        FastCreateDataProperty(a, k, fromValue);
      }

      // d. Increment k by 1.
      k++;
    }
    // 12. Perform ? Set(A, "length", actualDeleteCount, true).
    SetProperty(a, kLengthString, actualDeleteCount);
    return a;
  }

  // HandleForwardCase implements step 15. "If itemCount < actualDeleteCount,
  // then...""
  transitioning macro HandleForwardCase(
      context: Context, o: JSReceiver, len: Number, itemCount: Number,
      actualStart: Number, actualDeleteCount: Number): void {
    // 15. If itemCount < actualDeleteCount, then
    // a. Let k be actualStart.
    let k: Number = actualStart;

    // b. Repeat, while k < (len - actualDeleteCount)
    while (k < (len - actualDeleteCount)) {
      // i. Let from be ! ToString(k + actualDeleteCount).
      const from: Number = k + actualDeleteCount;
      // ii. Let to be ! ToString(k + itemCount).
      const to: Number = k + itemCount;

      // iii. Let fromPresent be ? HasProperty(O, from).
      const fromPresent: Boolean = HasProperty(o, from);

      // iv. If fromPresent is true, then
      if (fromPresent == True) {
        // 1. Let fromValue be ? Get(O, from).
        const fromValue: Object = GetProperty(o, from);

        // 2. Perform ? Set(O, to, fromValue, true).
        SetProperty(o, to, fromValue);

        // v. Else fromPresent is false,
      } else {
        // 1. Perform ? DeletePropertyOrThrow(O, to).
        DeleteProperty(o, to, kStrict);
      }
      // vi. Increase k by 1.
      k++;
    }

    // c. Let k be len.
    k = len;

    // d. Repeat, while k > (len - actualDeleteCount + itemCount)
    while (k > (len - actualDeleteCount + itemCount)) {
      // i. Perform ? DeletePropertyOrThrow(O, ! ToString(k - 1)).
      DeleteProperty(o, k - 1, kStrict);
      // ii. Decrease k by 1.
      k--;
    }
  }

  // HandleBackwardCase implements step 16. "Else if itemCount >
  // actualDeleteCount, then..."
  transitioning macro HandleBackwardCase(
      context: Context, o: JSReceiver, len: Number, itemCount: Number,
      actualStart: Number, actualDeleteCount: Number): void {
    // 16. Else if itemCount > actualDeleteCount, then
    // a. Let k be (len - actualDeleteCount).
    let k: Number = len - actualDeleteCount;

    // b. Repeat, while k > actualStart
    while (k > actualStart) {
      // i. Let from be ! ToString(k + actualDeleteCount - 1).
      const from: Number = k + actualDeleteCount - 1;

      // ii. Let to be ! ToString(k + itemCount - 1).
      const to: Number = k + itemCount - 1;

      // iii. Let fromPresent be ? HasProperty(O, from).
      const fromPresent: Boolean = HasProperty(o, from);

      // iv. If fromPresent is true, then
      if (fromPresent == True) {
        // 1. Let fromValue be ? Get(O, from).
        const fromValue: Object = GetProperty(o, from);

        // 2. Perform ? Set(O, to, fromValue, true).
        SetProperty(o, to, fromValue);

        // v. Else fromPresent is false,
      } else {
        // 1. Perform ? DeletePropertyOrThrow(O, to).
        DeleteProperty(o, to, kStrict);
      }

      // vi. Decrease k by 1.
      k--;
    }
  }

  transitioning macro SlowSplice(
      context: Context, arguments: Arguments, o: JSReceiver, len: Number,
      actualStart: Number, insertCount: Smi,
      actualDeleteCount: Number): Object {
    // 9. Let A be ? ArraySpeciesCreate(O, actualDeleteCount).
    const a: JSReceiver = ArraySpeciesCreate(context, o, actualDeleteCount);
    const itemCount: Number = insertCount;

    // Steps 9 through 12: creating the array of deleted elements.
    FillDeletedElementsArray(context, o, actualStart, actualDeleteCount, a);

    // 13. Let items be a List whose elements are, in left-to-right order,
    //     the portion of the actual argument list starting with the third
    //     argument. The list is empty if fewer than three arguments were
    //     passed.
    // 14. Let itemCount be the Number of elements in items.
    // (done above).

    // 15. If itemCount < actualDeleteCount, then
    if (itemCount < actualDeleteCount) {
      HandleForwardCase(
          context, o, len, itemCount, actualStart, actualDeleteCount);
      // 16. Else if itemCount > actualDeleteCount, then
    } else if (itemCount > actualDeleteCount) {
      HandleBackwardCase(
          context, o, len, itemCount, actualStart, actualDeleteCount);
    }

    // 17. Let k be actualStart.
    let k: Number = actualStart;

    // 18. Repeat, while items is not empty
    //   a. Remove the first element from items and let E be the value of that
    //   element.
    if (arguments.length > 2) {
      for (let i: intptr = 2; i < arguments.length; ++i) {
        const e: Object = arguments[i];
        // b. Perform ? Set(O, ! ToString(k), E, true).
        SetProperty(o, k, e);

        // c. Increase k by 1.
        k = k + 1;
      }
    }

    // 19. Perform ? Set(O, "length", len - actualDeleteCount + itemCount,
    // true).
    SetProperty(o, kLengthString, len - actualDeleteCount + itemCount);

    return a;
  }

  // https://tc39.github.io/ecma262/#sec-array.prototype.splice
  transitioning javascript builtin
  ArrayPrototypeSplice(js-implicit context: Context, receiver: Object)(
      ...arguments): Object {
    // 1. Let O be ? ToObject(this value).
    const o: JSReceiver = ToObject(context, receiver);

    // 2. Let len be ? ToLength(? Get(O, "length")).
    const len: Number = GetLengthProperty(o);

    // 3. Let relativeStart be ? ToInteger(start).
    const start: Object = arguments[0];
    const relativeStart: Number = ToInteger_Inline(context, start);

    // 4. If relativeStart < 0, let actualStart be max((len + relativeStart),
    // 0);
    //    else let actualStart be min(relativeStart, len).
    const actualStart: Number = relativeStart < 0 ?
        Max((len + relativeStart), 0) :
        Min(relativeStart, len);

    let insertCount: Smi;
    let actualDeleteCount: Number;
    // 5. If the Number of actual arguments is 0, then
    if (arguments.length == 0) {
      // a. Let insertCount be 0.
      insertCount = 0;
      // b. Let actualDeleteCount be 0.
      actualDeleteCount = 0;
      // 6. Else if the Number of actual arguments is 1, then
    } else if (arguments.length == 1) {
      // a. Let insertCount be 0.
      insertCount = 0;
      // b. Let actualDeleteCount be len - actualStart.
      actualDeleteCount = len - actualStart;
      // 7. Else,
    } else {
      // a. Let insertCount be the Number of actual arguments minus 2.
      insertCount = Convert<Smi>(arguments.length) - 2;
      // b. Let dc be ? ToInteger(deleteCount).
      const deleteCount: Object = arguments[1];
      const dc: Number = ToInteger_Inline(context, deleteCount);
      // c. Let actualDeleteCount be min(max(dc, 0), len - actualStart).
      actualDeleteCount = Min(Max(dc, 0), len - actualStart);
    }

    // 8. If len + insertCount - actualDeleteCount > 2^53-1, throw a
    //    Bailout exception.
    const newLength: Number = len + insertCount - actualDeleteCount;
    if (newLength > kMaxSafeInteger) {
      ThrowTypeError(kInvalidArrayLength, start);
    }

    try {
      return FastArraySplice(
          context, arguments, o, len, actualStart, insertCount,
          actualDeleteCount) otherwise Bailout;
    }
    label Bailout {}

    // If the fast case fails, just continue with the slow, correct,
    // spec-compliant case.
    return SlowSplice(
        context, arguments, o, len, actualStart, insertCount,
        actualDeleteCount);
  }
}
