// 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_filter {
  transitioning javascript builtin
  ArrayFilterLoopEagerDeoptContinuation(implicit context: Context)(
      receiver: Object, callback: Object, thisArg: Object, array: Object,
      initialK: Object, length: Object, initialTo: Object): Object {
    // All continuation points in the optimized filter 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 outputArray = Cast<JSReceiver>(array) otherwise unreachable;
    const numberK = Cast<Number>(initialK) otherwise unreachable;
    const numberTo = Cast<Number>(initialTo) otherwise unreachable;
    const numberLength = Cast<Number>(length) otherwise unreachable;

    return ArrayFilterLoopContinuation(
        jsreceiver, callbackfn, thisArg, outputArray, jsreceiver, numberK,
        numberLength, numberTo);
  }

  transitioning javascript builtin
  ArrayFilterLoopLazyDeoptContinuation(implicit context: Context)(
      receiver: Object, callback: Object, thisArg: Object, array: Object,
      initialK: Object, length: Object, valueK: Object, initialTo: Object,
      result: Object): Object {
    // All continuation points in the optimized filter 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 outputArray = Cast<JSReceiver>(array) otherwise unreachable;
    let numberK = Cast<Number>(initialK) otherwise unreachable;
    let numberTo = Cast<Number>(initialTo) otherwise unreachable;
    const numberLength = Cast<Number>(length) otherwise unreachable;

    // This custom lazy deopt point is right after the callback. filter() needs
    // to pick up at the next step, which is setting the callback result in
    // the output array. After incrementing k and to, we can glide into the loop
    // continuation builtin.
    if (ToBoolean(result)) {
      FastCreateDataProperty(outputArray, numberTo, valueK);
      numberTo = numberTo + 1;
    }

    numberK = numberK + 1;

    return ArrayFilterLoopContinuation(
        jsreceiver, callbackfn, thisArg, outputArray, jsreceiver, numberK,
        numberLength, numberTo);
  }

  transitioning builtin ArrayFilterLoopContinuation(implicit context: Context)(
      receiver: JSReceiver, callbackfn: Callable, thisArg: Object,
      array: JSReceiver, o: JSReceiver, initialK: Number, length: Number,
      initialTo: Number): Object {
    let to: Number = initialTo;
    // 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. 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: Object = GetProperty(o, k);

        // 6c. ii. Perform ? Call(callbackfn, T, <kValue, k, O>).
        const result: Object = Call(context, callbackfn, thisArg, kValue, k, o);

        // iii. If selected is true, then...
        if (ToBoolean(result)) {
          // 1. Perform ? CreateDataPropertyOrThrow(A, ToString(to), kValue).
          FastCreateDataProperty(array, to, kValue);
          // 2. Increase to by 1.
          to = to + 1;
        }
      }

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

  transitioning macro FastArrayFilter(implicit context: Context)(
      fastO: FastJSArray, len: Smi, callbackfn: Callable, thisArg: Object,
      output: FastJSArray) labels Bailout(Number, Number) {
    let k: Smi = 0;
    let to: Smi = 0;
    let fastOW = NewFastJSArrayWitness(fastO);
    let fastOutputW = NewFastJSArrayWitness(output);

    fastOutputW.EnsureArrayPushable() otherwise goto Bailout(k, to);

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

      // Ensure that we haven't walked beyond a possibly updated length.
      if (k >= fastOW.Get().length) goto Bailout(k, to);
      const value: Object = fastOW.LoadElementNoHole(k) otherwise continue;
      const result: Object =
          Call(context, callbackfn, thisArg, value, k, fastOW.Get());
      if (ToBoolean(result)) {
        try {
          // Since the call to {callbackfn} is observable, we can't
          // use the Bailout label until we've successfully stored.
          // Hence the {SlowStore} label.
          fastOutputW.Recheck() otherwise SlowStore;
          if (fastOutputW.Get().length != to) goto SlowStore;
          fastOutputW.Push(value) otherwise SlowStore;
        }
        label SlowStore {
          FastCreateDataProperty(fastOutputW.stable, to, value);
        }
        to = to + 1;
      }
    }
  }

  // This method creates a 0-length array with the ElementsKind of the
  // receiver if possible, otherwise, bails out. It makes sense for the
  // caller to know that the slow case needs to be invoked.
  macro FastFilterSpeciesCreate(implicit context: Context)(
      receiver: JSReceiver): JSReceiver labels Slow {
    const len: Smi = 0;
    if (IsArraySpeciesProtectorCellInvalid()) goto Slow;
    const o = Cast<FastJSArray>(receiver) otherwise Slow;
    const newMap: Map =
        LoadJSArrayElementsMap(o.map.elements_kind, LoadNativeContext(context));
    return AllocateJSArray(PACKED_SMI_ELEMENTS, newMap, len, len);
  }

  // https://tc39.github.io/ecma262/#sec-array.prototype.filter
  transitioning javascript builtin
  ArrayFilter(implicit context: Context)(receiver: Object, ...arguments):
      Object {
    try {
      if (IsNullOrUndefined(receiver)) {
        goto NullOrUndefinedError;
      }

      // 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: Object = arguments.length > 1 ? arguments[1] : Undefined;
      let output: JSReceiver;

      // Special cases.
      let k: Number = 0;
      let to: Number = 0;
      try {
        output = FastFilterSpeciesCreate(o) otherwise SlowSpeciesCreate;

        try {
          const smiLen: Smi = Cast<Smi>(len) otherwise goto Bailout(k, to);
          const fastOutput =
              Cast<FastJSArray>(output) otherwise goto Bailout(k, to);
          const fastO = Cast<FastJSArray>(o) otherwise goto Bailout(k, to);

          FastArrayFilter(fastO, smiLen, callbackfn, thisArg, fastOutput)
              otherwise Bailout;
          return output;
        }
        label Bailout(kValue: Number, toValue: Number) deferred {
          k = kValue;
          to = toValue;
        }
      }
      label SlowSpeciesCreate {
        output = ArraySpeciesCreate(context, receiver, 0);
      }

      return ArrayFilterLoopContinuation(
          o, callbackfn, thisArg, output, o, k, len, to);
    }
    label TypeError deferred {
      ThrowTypeError(kCalledNonCallable, arguments[0]);
    }
    label NullOrUndefinedError deferred {
      ThrowTypeError(kCalledOnNullOrUndefined, 'Array.prototype.filter');
    }
  }
}
