// 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: Context,
      receiver: Object)(callback: Object, length: Object): Object {
    // 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 Object 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: Context, receiver: Object)(
      callback: Object, initialK: Object, length: Object,
      accumulator: Object): Object {
    // 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 Object 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: Context, receiver: Object)(
      callback: Object, initialK: Object, length: Object,
      result: Object): Object {
    // 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: Object,
      o: JSReceiver, initialK: Number, length: Number): Object {
    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: Object = GetProperty(o, k);

        if (accumulator == TheHole) {
          // 8b.
          accumulator = value;
        } else {
          // 9c. ii. Set accumulator to ? Call(callbackfn, undefined,
          //         <accumulator, kValue, k, O>).
          accumulator =
              Call(context, callbackfn, Undefined, accumulator, 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.
    if (accumulator == TheHole) {
      ThrowTypeError(kReduceNoInitial, 'Array.prototype.reduce');
    }
    return accumulator;
  }

  transitioning macro FastArrayReduce(implicit context: Context)(
      o: JSReceiver, len: Number, callbackfn: Callable,
      initialAccumulator: Object): Object
      labels Bailout(Number, Object) {
    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: Object = fastOW.LoadElementNoHole(k) otherwise continue;
      if (accumulator == TheHole) {
        accumulator = value;
      } else {
        accumulator = Call(
            context, callbackfn, Undefined, accumulator, value, k,
            fastOW.Get());
      }
    }
    if (accumulator == TheHole) {
      ThrowTypeError(kReduceNoInitial, 'Array.prototype.reduce');
    }
    return accumulator;
  }

  // https://tc39.github.io/ecma262/#sec-array.prototype.reduce
  transitioning javascript builtin
  ArrayReduce(js-implicit context: Context, receiver: Object)(...arguments):
      Object {
    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: Object =
          arguments.length > 1 ? arguments[1] : TheHole;

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