// 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-typed-array-gen.h'

namespace typed_array {
const kBuiltinNameSort: constexpr string = '%TypedArray%.prototype.sort';

extern runtime TypedArraySortFast(Context, JSAny): JSTypedArray;

transitioning macro CallCompare(
    implicit context: Context, array: JSTypedArray, comparefn: Callable)(
    a: JSAny, b: JSAny): Number {
  // a. Let v be ? ToNumber(? Call(comparefn, undefined, x, y)).
  const v: Number = ToNumber_Inline(Call(context, comparefn, Undefined, a, b));

  // b. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
  if (IsDetachedBuffer(array.buffer)) {
    ThrowTypeError(MessageTemplate::kDetachedOperation, kBuiltinNameSort);
  }

  // c. If v is NaN, return +0.
  if (NumberIsNaN(v)) return 0;

  // d. return v.
  return v;
}

// Merges two sorted runs [from, middle) and [middle, to)
// from "source" into "target".
transitioning macro
TypedArrayMerge(
    implicit context: Context, array: JSTypedArray, comparefn: Callable)(
    source: FixedArray, from: uintptr, middle: uintptr, to: uintptr,
    target: FixedArray) {
  let left: uintptr = from;
  let right: uintptr = middle;

  for (let targetIndex: uintptr = from; targetIndex < to; ++targetIndex) {
    if (left < middle && right >= to) {
      // If the left run has elements, but the right does not, we take
      // from the left.
      target.objects[targetIndex] = source.objects[left++];
    } else if (left < middle) {
      // If both have elements, we need to compare.
      const leftElement = UnsafeCast<JSAny>(source.objects[left]);
      const rightElement = UnsafeCast<JSAny>(source.objects[right]);
      if (CallCompare(leftElement, rightElement) <= 0) {
        target.objects[targetIndex] = leftElement;
        left++;
      } else {
        target.objects[targetIndex] = rightElement;
        right++;
      }
    } else {
      // No elements on the left, but the right does, so we take
      // from the right.
      assert(left == middle);
      target.objects[targetIndex] = source.objects[right++];
    }
  }
}

transitioning builtin
TypedArrayMergeSort(implicit context: Context)(
    source: FixedArray, from: uintptr, to: uintptr, target: FixedArray,
    array: JSTypedArray, comparefn: Callable): JSAny {
  assert(to - from > 1);
  const middle: uintptr = from + ((to - from) >>> 1);

  // On the next recursion step source becomes target and vice versa.
  // This saves the copy of the relevant range from the original
  // array into a work array on each recursion step.
  if (middle - from > 1) {
    TypedArrayMergeSort(target, from, middle, source, array, comparefn);
  }
  if (to - middle > 1) {
    TypedArrayMergeSort(target, middle, to, source, array, comparefn);
  }

  TypedArrayMerge(source, from, middle, to, target);

  return Undefined;
}

// https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.sort
transitioning javascript builtin TypedArrayPrototypeSort(
    js-implicit context: NativeContext,
    receiver: JSAny)(...arguments): JSTypedArray {
  // 1. If comparefn is not undefined and IsCallable(comparefn) is false,
  //    throw a TypeError exception.
  const comparefnObj: JSAny = arguments[0];
  if (comparefnObj != Undefined && !Is<Callable>(comparefnObj)) {
    ThrowTypeError(MessageTemplate::kBadSortComparisonFunction, comparefnObj);
  }

  // 2. Let obj be the this value.
  const obj: JSAny = receiver;

  // 3. Let buffer be ? ValidateTypedArray(obj).
  //    ValidateTypedArray currently returns the array, not the ViewBuffer.
  const array: JSTypedArray =
      ValidateTypedArray(context, obj, kBuiltinNameSort);

  // 4. Let len be obj.[[ArrayLength]].
  const len: uintptr = array.length;

  // Arrays of length 1 or less are considered sorted.
  if (len < 2) return array;

  // Default sorting is done in C++ using std::sort
  if (comparefnObj == Undefined) {
    return TypedArraySortFast(context, obj);
  }

  // Throw rather than crash if the TypedArray's size exceeds max FixedArray
  // size (which we need below).
  // TODO(4153): Consider redesigning the sort implementation such that we
  // don't have such a limit.
  if (len > kFixedArrayMaxLength) {
    ThrowTypeError(MessageTemplate::kTypedArrayTooLargeToSort);
  }

  const comparefn: Callable =
      Cast<Callable>(comparefnObj) otherwise unreachable;
  const accessor: TypedArrayAccessor =
      GetTypedArrayAccessor(array.elements_kind);

  // Prepare the two work arrays. All numbers are converted to tagged
  // objects first, and merge sorted between the two FixedArrays.
  // The result is then written back into the JSTypedArray.
  const work1: FixedArray = AllocateZeroedFixedArray(Convert<intptr>(len));
  const work2: FixedArray = AllocateZeroedFixedArray(Convert<intptr>(len));

  for (let i: uintptr = 0; i < len; ++i) {
    const element: Numeric = accessor.LoadNumeric(array, i);
    work1.objects[i] = element;
    work2.objects[i] = element;
  }

  TypedArrayMergeSort(work2, 0, len, work1, array, comparefn);

  // work1 contains the sorted numbers. Write them back.
  for (let i: uintptr = 0; i < len; ++i) {
    accessor.StoreNumeric(
        context, array, i, UnsafeCast<Numeric>(work1.objects[i]));
  }

  return array;
}
}
