// 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
ArrayForEachLoopEagerDeoptContinuation(
    js-implicit context: NativeContext, receiver: JSAny)(
    callback: JSAny, thisArg: JSAny, initialK: JSAny, length: JSAny): JSAny {
  // All continuation points in the optimized forEach 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;

  return ArrayForEachLoopContinuation(
      jsreceiver, callbackfn, thisArg, Undefined, jsreceiver, numberK,
      numberLength, Undefined);
}

transitioning javascript builtin
ArrayForEachLoopLazyDeoptContinuation(
    js-implicit context: NativeContext, receiver: JSAny)(
    callback: JSAny, thisArg: JSAny, initialK: JSAny, length: JSAny,
    _result: JSAny): JSAny {
  // All continuation points in the optimized forEach 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;

  return ArrayForEachLoopContinuation(
      jsreceiver, callbackfn, thisArg, Undefined, jsreceiver, numberK,
      numberLength, Undefined);
}

transitioning builtin ArrayForEachLoopContinuation(implicit context: Context)(
    _receiver: JSReceiver, callbackfn: Callable, thisArg: JSAny, _array: JSAny,
    o: JSReceiver, initialK: Number, len: Number, _to: JSAny): JSAny {
  // variables {array} and {to} are ignored.

  // 5. Let k be 0.
  // 6. Repeat, while k < len
  for (let k: Number = initialK; k < len; k = k + 1) {
    // 6a. 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.

    // 6b. Let kPresent be ? HasProperty(O, Pk).
    const kPresent: Boolean = HasProperty_Inline(o, k);

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

      // 6c. ii. Perform ? Call(callbackfn, T, <kValue, k, O>).
      Call(context, callbackfn, thisArg, kValue, k, o);
    }

    // 6d. Increase k by 1. (done by the loop).
  }
  return Undefined;
}

transitioning macro FastArrayForEach(implicit context: Context)(
    o: JSReceiver, len: Number, callbackfn: Callable, thisArg: JSAny): JSAny
    labels Bailout(Smi) {
  let k: Smi = 0;
  const smiLen = Cast<Smi>(len) otherwise goto Bailout(k);
  const fastO = Cast<FastJSArray>(o) otherwise goto Bailout(k);
  let fastOW = NewFastJSArrayWitness(fastO);

  // Build a fast loop over the smi array.
  for (; k < smiLen; k++) {
    fastOW.Recheck() otherwise goto Bailout(k);

    // Ensure that we haven't walked beyond a possibly updated length.
    if (k >= fastOW.Get().length) goto Bailout(k);
    const value: JSAny = fastOW.LoadElementNoHole(k)
        otherwise continue;
    Call(context, callbackfn, thisArg, value, k, fastOW.Get());
  }
  return Undefined;
}

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

    // 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 TypeError;
    }
    const callbackfn = Cast<Callable>(arguments[0]) otherwise TypeError;

    // 4. If thisArg is present, let T be thisArg; else let T be undefined.
    const thisArg: JSAny = arguments[1];

    // Special cases.
    let k: Number = 0;
    try {
      return FastArrayForEach(o, len, callbackfn, thisArg)
          otherwise Bailout;
    } label Bailout(kValue: Smi) deferred {
      k = kValue;
    }

    return ArrayForEachLoopContinuation(
        o, callbackfn, thisArg, Undefined, o, k, len, Undefined);
  } label TypeError deferred {
    ThrowTypeError(MessageTemplate::kCalledNonCallable, arguments[0]);
  }
}
}
