// 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 {
transitioning javascript builtin
ArrayReducePreLoopEagerDeoptContinuation(
    js-implicit context: NativeContext, receiver: JSAny)(
    callback: JSAny, length: JSAny): JSAny {
  // All continuation points in the optimized every implementation are
  // after the ToObject(O) call that ensures we are dealing with a
  // JSReceiver.
  //
  // Also, this great mass of casts is necessary because the signature
  // of Torque javascript builtins requires JSAny type for all parameters
  // other than {context}.
  const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable;
  const callbackfn = Cast<Callable>(callback) otherwise unreachable;
  const numberLength = Cast<Number>(length) otherwise unreachable;

  // Simulate starting the loop at 0, but ensuring that the accumulator is
  // the hole. The continuation stub will search for the initial non-hole
  // element, rightly throwing an exception if not found.
  return ArrayReduceLoopContinuation(
      jsreceiver, callbackfn, TheHole, jsreceiver, 0, numberLength);
}

transitioning javascript builtin
ArrayReduceLoopEagerDeoptContinuation(
    js-implicit context: NativeContext, receiver: JSAny)(
    callback: JSAny, initialK: JSAny, length: JSAny,
    accumulator: JSAny): JSAny {
  // All continuation points in the optimized every implementation are
  // after the ToObject(O) call that ensures we are dealing with a
  // JSReceiver.
  //
  // Also, this great mass of casts is necessary because the signature
  // of Torque javascript builtins requires JSAny type for all parameters
  // other than {context}.
  const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable;
  const callbackfn = Cast<Callable>(callback) otherwise unreachable;
  const numberK = Cast<Number>(initialK) otherwise unreachable;
  const numberLength = Cast<Number>(length) otherwise unreachable;

  return ArrayReduceLoopContinuation(
      jsreceiver, callbackfn, accumulator, jsreceiver, numberK, numberLength);
}

transitioning javascript builtin
ArrayReduceLoopLazyDeoptContinuation(
    js-implicit context: NativeContext, receiver: JSAny)(
    callback: JSAny, initialK: JSAny, length: JSAny, result: JSAny): JSAny {
  // All continuation points in the optimized every implementation are
  // after the ToObject(O) call that ensures we are dealing with a
  // JSReceiver.
  const jsreceiver = Cast<JSReceiver>(receiver) otherwise unreachable;
  const callbackfn = Cast<Callable>(callback) otherwise unreachable;
  const numberK = Cast<Number>(initialK) otherwise unreachable;
  const numberLength = Cast<Number>(length) otherwise unreachable;

  // The accumulator is the result from the callback call which just occured.
  const r = ArrayReduceLoopContinuation(
      jsreceiver, callbackfn, result, jsreceiver, numberK, numberLength);
  return r;
}

transitioning builtin ArrayReduceLoopContinuation(implicit context: Context)(
    _receiver: JSReceiver, callbackfn: Callable,
    initialAccumulator: JSAny|TheHole, o: JSReceiver, initialK: Number,
    length: Number): JSAny {
  let accumulator = initialAccumulator;

  // 8b and 9. Repeat, while k < len
  for (let k: Number = initialK; k < length; k++) {
    // 8b i and 9a. Let Pk be ! ToString(k).
    // k is guaranteed to be a positive integer, hence ToString is
    // side-effect free and HasProperty/GetProperty do the conversion inline.

    // 8b ii and 9b. Set kPresent to ? HasProperty(O, Pk).
    const present: Boolean = HasProperty_Inline(o, k);

    // 6c. If kPresent is true, then
    if (present == True) {
      // 6c. i. Let kValue be ? Get(O, Pk).
      const value: JSAny = GetProperty(o, k);

      typeswitch (accumulator) {
        case (TheHole): {
          // 8b.
          accumulator = value;
        }
        case (accumulatorNotHole: JSAny): {
          // 9c. ii. Set accumulator to ? Call(callbackfn, undefined,
          //         <accumulator, kValue, k, O>).
          accumulator = Call(
              context, callbackfn, Undefined, accumulatorNotHole, value, k, o);
        }
      }
    }

    // 8b iv and 9d. Increase k by 1. (done by the loop).
  }

  // 8c. if kPresent is false, throw a TypeError exception.
  // If the accumulator is discovered with the sentinel hole value,
  // this means kPresent is false.
  typeswitch (accumulator) {
    case (TheHole): {
      ThrowTypeError(
          MessageTemplate::kReduceNoInitial, 'Array.prototype.reduce');
    }
    case (accumulator: JSAny): {
      return accumulator;
    }
  }
}

transitioning macro FastArrayReduce(implicit context: Context)(
    o: JSReceiver, len: Number, callbackfn: Callable,
    initialAccumulator: JSAny|TheHole): JSAny
    labels Bailout(Number, JSAny | TheHole) {
  const k = 0;
  let accumulator = initialAccumulator;
  Cast<Smi>(len) otherwise goto Bailout(k, accumulator);
  const fastO =
      Cast<FastJSArrayForRead>(o) otherwise goto Bailout(k, accumulator);
  let fastOW = NewFastJSArrayForReadWitness(fastO);

  // Build a fast loop over the array.
  for (let k: Smi = 0; k < len; k++) {
    fastOW.Recheck() otherwise goto Bailout(k, accumulator);

    // Ensure that we haven't walked beyond a possibly updated length.
    if (k >= fastOW.Get().length) goto Bailout(k, accumulator);

    const value: JSAny = fastOW.LoadElementNoHole(k) otherwise continue;
    typeswitch (accumulator) {
      case (TheHole): {
        accumulator = value;
      }
      case (accumulatorNotHole: JSAny): {
        accumulator = Call(
            context, callbackfn, Undefined, accumulatorNotHole, value, k,
            fastOW.Get());
      }
    }
  }
  typeswitch (accumulator) {
    case (TheHole): {
      ThrowTypeError(
          MessageTemplate::kReduceNoInitial, 'Array.prototype.reduce');
    }
    case (accumulator: JSAny): {
      return accumulator;
    }
  }
}

// https://tc39.github.io/ecma262/#sec-array.prototype.reduce
transitioning javascript builtin
ArrayReduce(
    js-implicit context: NativeContext, receiver: JSAny)(...arguments): JSAny {
  try {
    RequireObjectCoercible(receiver, 'Array.prototype.reduce');

    // 1. Let O be ? ToObject(this value).
    const o: JSReceiver = ToObject_Inline(context, receiver);

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

    // 3. If IsCallable(callbackfn) is false, throw a TypeError exception.
    if (arguments.length == 0) {
      goto NoCallableError;
    }
    const callbackfn = Cast<Callable>(arguments[0]) otherwise NoCallableError;

    // 4. If len is 0 and initialValue is not present, throw a TypeError
    // exception. (This case is handled at the end of
    // ArrayReduceLoopContinuation).

    const initialValue: JSAny|TheHole =
        arguments.length > 1 ? arguments[1] : TheHole;

    try {
      return FastArrayReduce(o, len, callbackfn, initialValue)
          otherwise Bailout;
    } label Bailout(value: Number, accumulator: JSAny|TheHole) {
      return ArrayReduceLoopContinuation(
          o, callbackfn, accumulator, o, value, len);
    }
  } label NoCallableError deferred {
    ThrowTypeError(MessageTemplate::kCalledNonCallable, arguments[0]);
  }
}
}
