// 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_reverse {
  macro LoadElement<ElementsAccessor: type, T: type>(
      elements: FixedArrayBase, index: Smi): T;

  LoadElement<array::FastPackedSmiElements, Smi>(implicit context: Context)(
      elements: FixedArrayBase, index: Smi): Smi {
    const elements: FixedArray = UnsafeCast<FixedArray>(elements);
    return UnsafeCast<Smi>(elements.objects[index]);
  }

  LoadElement<array::FastPackedObjectElements, Object>(
      implicit context: Context)(elements: FixedArrayBase, index: Smi): Object {
    const elements: FixedArray = UnsafeCast<FixedArray>(elements);
    return elements.objects[index];
  }

  LoadElement<array::FastPackedDoubleElements, float64>(
      implicit context: Context)(elements: FixedArrayBase, index: Smi):
      float64 {
    const elements: FixedDoubleArray = UnsafeCast<FixedDoubleArray>(elements);
    // This macro is only used for PACKED_DOUBLE, loading the hole should
    // be impossible.
    return LoadDoubleWithHoleCheck(elements, index)
        otherwise unreachable;
  }

  macro StoreElement<ElementsAccessor: type, T: type>(
      implicit context:
          Context)(elements: FixedArrayBase, index: Smi, value: T);

  StoreElement<array::FastPackedSmiElements, Smi>(implicit context: Context)(
      elements: FixedArrayBase, index: Smi, value: Smi) {
    const elems: FixedArray = UnsafeCast<FixedArray>(elements);
    StoreFixedArrayElement(elems, index, value, SKIP_WRITE_BARRIER);
  }

  StoreElement<array::FastPackedObjectElements, Object>(
      implicit context:
          Context)(elements: FixedArrayBase, index: Smi, value: Object) {
    const elements: FixedArray = UnsafeCast<FixedArray>(elements);
    elements.objects[index] = value;
  }

  StoreElement<array::FastPackedDoubleElements, float64>(
      implicit context:
          Context)(elements: FixedArrayBase, index: Smi, value: float64) {
    const elems: FixedDoubleArray = UnsafeCast<FixedDoubleArray>(elements);
    StoreFixedDoubleArrayElementSmi(elems, index, value);
  }

  // Fast-path for all PACKED_* elements kinds. These do not need to check
  // whether a property is present, so we can simply swap them using fast
  // FixedArray loads/stores.
  macro FastPackedArrayReverse<Accessor: type, T: type>(
      implicit context: Context)(elements: FixedArrayBase, length: Smi) {
    let lower: Smi = 0;
    let upper: Smi = length - 1;

    while (lower < upper) {
      const lowerValue: T = LoadElement<Accessor, T>(elements, lower);
      const upperValue: T = LoadElement<Accessor, T>(elements, upper);
      StoreElement<Accessor>(elements, lower, upperValue);
      StoreElement<Accessor>(elements, upper, lowerValue);
      ++lower;
      --upper;
    }
  }

  transitioning macro GenericArrayReverse(context: Context, receiver: Object):
      Object {
    // 1. Let O be ? ToObject(this value).
    const object: JSReceiver = ToObject_Inline(context, receiver);

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

    // 3. Let middle be floor(len / 2).
    // 4. Let lower be 0.
    // 5. Repeat, while lower != middle.
    //   a. Let upper be len - lower - 1.

    // Instead of calculating the middle value, we simply initialize upper
    // with len - 1 and decrement it after each iteration.
    let lower: Number = 0;
    let upper: Number = length - 1;

    while (lower < upper) {
      let lowerValue: Object = Undefined;
      let upperValue: Object = Undefined;

      // b. Let upperP be ! ToString(upper).
      // c. Let lowerP be ! ToString(lower).
      // d. Let lowerExists be ? HasProperty(O, lowerP).
      const lowerExists: Boolean = HasProperty(object, lower);

      // e. If lowerExists is true, then.
      if (lowerExists == True) {
        // i. Let lowerValue be ? Get(O, lowerP).
        lowerValue = GetProperty(object, lower);
      }

      // f. Let upperExists be ? HasProperty(O, upperP).
      const upperExists: Boolean = HasProperty(object, upper);

      // g. If upperExists is true, then.
      if (upperExists == True) {
        // i. Let upperValue be ? Get(O, upperP).
        upperValue = GetProperty(object, upper);
      }

      // h. If lowerExists is true and upperExists is true, then
      if (lowerExists == True && upperExists == True) {
        // i. Perform ? Set(O, lowerP, upperValue, true).
        SetProperty(object, lower, upperValue);

        // ii. Perform ? Set(O, upperP, lowerValue, true).
        SetProperty(object, upper, lowerValue);
      } else if (lowerExists == False && upperExists == True) {
        // i. Perform ? Set(O, lowerP, upperValue, true).
        SetProperty(object, lower, upperValue);

        // ii. Perform ? DeletePropertyOrThrow(O, upperP).
        DeleteProperty(object, upper, kStrict);
      } else if (lowerExists == True && upperExists == False) {
        // i. Perform ? DeletePropertyOrThrow(O, lowerP).
        DeleteProperty(object, lower, kStrict);

        // ii. Perform ? Set(O, upperP, lowerValue, true).
        SetProperty(object, upper, lowerValue);
      }

      // l. Increase lower by 1.
      ++lower;
      --upper;
    }

    // 6. Return O.
    return object;
  }

  macro TryFastPackedArrayReverse(implicit context: Context)(receiver: Object)
      labels Slow {
    const array: FastJSArray = Cast<FastJSArray>(receiver) otherwise Slow;

    const kind: ElementsKind = array.map.elements_kind;
    if (kind == PACKED_SMI_ELEMENTS) {
      array::EnsureWriteableFastElements(array);
      FastPackedArrayReverse<array::FastPackedSmiElements, Smi>(
          array.elements, array.length);
    } else if (kind == PACKED_ELEMENTS) {
      array::EnsureWriteableFastElements(array);
      FastPackedArrayReverse<array::FastPackedObjectElements, Object>(
          array.elements, array.length);
    } else if (kind == PACKED_DOUBLE_ELEMENTS) {
      FastPackedArrayReverse<array::FastPackedDoubleElements, float64>(
          array.elements, array.length);
    } else {
      goto Slow;
    }
  }

  // https://tc39.github.io/ecma262/#sec-array.prototype.reverse
  transitioning javascript builtin ArrayPrototypeReverse(
      js-implicit context: Context, receiver: Object)(...arguments): Object {
    try {
      TryFastPackedArrayReverse(receiver) otherwise Baseline;
      return receiver;
    }
    label Baseline {
      return GenericArrayReverse(context, receiver);
    }
  }
}
