// 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
ArrayFindLoopEagerDeoptContinuation(
    js-implicit context: NativeContext, receiver: JSAny)(
    callback: JSAny, thisArg: JSAny, initialK: JSAny, length: JSAny): JSAny {
  // All continuation points in the optimized find 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 ArrayFindLoopContinuation(
      jsreceiver, callbackfn, thisArg, jsreceiver, numberK, numberLength);
}

transitioning javascript builtin
ArrayFindLoopLazyDeoptContinuation(
    js-implicit context: NativeContext, receiver: JSAny)(
    _callback: JSAny, _thisArg: JSAny, _initialK: JSAny, _length: JSAny,
    _result: JSAny): JSAny {
  // This deopt continuation point is never actually called, it just
  // exists to make stack traces correct from a ThrowTypeError if the
  // callback was found to be non-callable.
  unreachable;
}

// Continuation that is called after a lazy deoptimization from TF that
// happens right after the callback and it's returned value must be handled
// before iteration continues.
transitioning javascript builtin
ArrayFindLoopAfterCallbackLazyDeoptContinuation(
    js-implicit context: NativeContext, receiver: JSAny)(
    callback: JSAny, thisArg: JSAny, initialK: JSAny, length: JSAny,
    foundValue: JSAny, isFound: JSAny): JSAny {
  // All continuation points in the optimized find 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;

  // This custom lazy deopt point is right after the callback. find() needs
  // to pick up at the next step, which is returning the element if the
  // callback value is truthy.  Otherwise, continue the search by calling the
  // continuation.

  if (ToBoolean(isFound)) {
    return foundValue;
  }

  return ArrayFindLoopContinuation(
      jsreceiver, callbackfn, thisArg, jsreceiver, numberK, numberLength);
}

transitioning builtin ArrayFindLoopContinuation(implicit context: Context)(
    _receiver: JSReceiver, callbackfn: Callable, thisArg: JSAny, o: JSReceiver,
    initialK: Number, length: Number): JSAny {
  // 5. Let k be 0.
  // 6. Repeat, while k < len
  for (let k: Number = initialK; k < length; k++) {
    // 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. i. Let kValue be ? Get(O, Pk).
    const value: JSAny = GetProperty(o, k);

    // 6c. Let testResult be ToBoolean(? Call(predicate, T, <<kValue, k,
    // O>>)).
    const testResult: JSAny = Call(context, callbackfn, thisArg, value, k, o);

    // 6d. If testResult is true, return kValue.
    if (ToBoolean(testResult)) {
      return value;
    }

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

transitioning macro FastArrayFind(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.LoadElementOrUndefined(k);
    const testResult: JSAny =
        Call(context, callbackfn, thisArg, value, k, fastOW.Get());
    if (ToBoolean(testResult)) {
      return value;
    }
  }
  return Undefined;
}

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

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

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

    // Special cases.
    try {
      return FastArrayFind(o, len, callbackfn, thisArg)
          otherwise Bailout;
    } label Bailout(k: Smi) deferred {
      return ArrayFindLoopContinuation(o, callbackfn, thisArg, o, k, len);
    }
  } label NotCallableError deferred {
    ThrowTypeError(MessageTemplate::kCalledNonCallable, arguments[0]);
  }
}
}
