// Copyright 2020 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.

#include "src/ast/ast.h"

namespace runtime {
extern runtime CreateArrayLiteral(
    Context, FeedbackVector, TaggedIndex, ArrayBoilerplateDescription,
    Smi): HeapObject;
extern runtime CreateObjectLiteral(
    Context, FeedbackVector, TaggedIndex, ObjectBoilerplateDescription,
    Smi): HeapObject;
}

namespace constructor {

extern builtin FastNewObject(Context, JSFunction, JSReceiver): JSObject;

extern enum AllocationSiteMode constexpr 'AllocationSiteMode' {
  DONT_TRACK_ALLOCATION_SITE,
  TRACK_ALLOCATION_SITE
}

const kIsShallowAndDisableMementos: constexpr int31
    generates 'AggregateLiteral::Flags::kIsShallowAndDisableMementos';
const kEvalScope: constexpr ScopeType generates 'ScopeType::EVAL_SCOPE';
const kFunctionScope:
    constexpr ScopeType generates 'ScopeType::FUNCTION_SCOPE';

extern macro ConstructorBuiltinsAssembler::FastNewFunctionContext(
    ScopeInfo, uint32, Context, constexpr ScopeType): Context;
extern macro ConstructorBuiltinsAssembler::CreateRegExpLiteral(
    HeapObject, TaggedIndex, Object, Smi, Context): JSRegExp;
extern macro ConstructorBuiltinsAssembler::CreateShallowArrayLiteral(
    FeedbackVector, TaggedIndex, Context,
    constexpr AllocationSiteMode): HeapObject labels CallRuntime;
extern macro ConstructorBuiltinsAssembler::CreateEmptyArrayLiteral(
    FeedbackVector, TaggedIndex, Context): HeapObject;
extern macro ConstructorBuiltinsAssembler::CreateShallowObjectLiteral(
    FeedbackVector, TaggedIndex): HeapObject labels CallRuntime;
extern macro ConstructorBuiltinsAssembler::CreateEmptyObjectLiteral(Context):
    JSObject;

builtin FastNewFunctionContextEval(implicit context: Context)(
    scopeInfo: ScopeInfo, slots: uint32): Context {
  return FastNewFunctionContext(scopeInfo, slots, context, kEvalScope);
}

builtin FastNewFunctionContextFunction(implicit context: Context)(
    scopeInfo: ScopeInfo, slots: uint32): Context {
  return FastNewFunctionContext(scopeInfo, slots, context, kFunctionScope);
}

builtin CreateRegExpLiteral(implicit context: Context)(
    maybeFeedbackVector: HeapObject, slot: TaggedIndex, pattern: Object,
    flags: Smi): JSRegExp {
  return CreateRegExpLiteral(
      maybeFeedbackVector, slot, pattern, flags, context);
}

builtin CreateShallowArrayLiteral(implicit context: Context)(
    feedbackVector: FeedbackVector, slot: TaggedIndex,
    constantElements: ArrayBoilerplateDescription): HeapObject {
  try {
    return CreateShallowArrayLiteral(
        feedbackVector, slot, context,
        AllocationSiteMode::DONT_TRACK_ALLOCATION_SITE)
        otherwise CallRuntime;
  } label CallRuntime deferred {
    tail runtime::CreateArrayLiteral(
        context, feedbackVector, slot, constantElements,
        SmiConstant(kIsShallowAndDisableMementos));
  }
}

builtin CreateEmptyArrayLiteral(implicit context: Context)(
    feedbackVector: FeedbackVector, slot: TaggedIndex): HeapObject {
  return CreateEmptyArrayLiteral(feedbackVector, slot, context);
}

builtin CreateShallowObjectLiteral(implicit context: Context)(
    feedbackVector: FeedbackVector, slot: TaggedIndex,
    desc: ObjectBoilerplateDescription, flags: Smi): HeapObject {
  try {
    return CreateShallowObjectLiteral(feedbackVector, slot)
        otherwise CallRuntime;
  } label CallRuntime deferred {
    tail runtime::CreateObjectLiteral(
        context, feedbackVector, slot, desc, flags);
  }
}

// ES #sec-object-constructor
transitioning javascript builtin
ObjectConstructor(
    js-implicit context: NativeContext, receiver: JSAny, newTarget: JSAny,
    target: JSFunction)(...arguments): JSAny {
  if (newTarget == Undefined || newTarget == target) {
    // Not Subclass.
    const value = arguments[0];
    if (arguments.length <= 0 || value == Undefined || value == Null) {
      // New object.
      return CreateEmptyObjectLiteral(context);
    } else {
      return ToObject(context, value);
    }
  } else {
    // Subclass.
    return FastNewObject(context, target, UnsafeCast<JSReceiver>(newTarget));
  }
}

builtin CreateEmptyLiteralObject(implicit context: Context)(): JSAny {
  return CreateEmptyObjectLiteral(context);
}

// ES #sec-number-constructor
transitioning javascript builtin
NumberConstructor(
    js-implicit context: NativeContext, receiver: JSAny, newTarget: JSAny,
    target: JSFunction)(...arguments): JSAny {
  // 1. If no arguments were passed to this function invocation, let n be +0.
  let n: Number = 0;
  if (arguments.length > 0) {
    // 2. Else,
    //    a. Let prim be ? ToNumeric(value).
    //    b. If Type(prim) is BigInt, let n be the Number value for prim.
    //    c. Otherwise, let n be prim.
    const value = arguments[0];
    n = ToNumber(value, BigIntHandling::kConvertToNumber);
  }

  // 3. If NewTarget is undefined, return n.
  if (newTarget == Undefined) return n;

  // 4. Let O be ? OrdinaryCreateFromConstructor(NewTarget,
  //    "%NumberPrototype%", « [[NumberData]] »).
  // 5. Set O.[[NumberData]] to n.
  // 6. Return O.

  // We ignore the normal target parameter and load the value from the
  // current frame here in order to reduce register pressure on the fast path.
  const target: JSFunction = LoadTargetFromFrame();
  const result = UnsafeCast<JSPrimitiveWrapper>(
      FastNewObject(context, target, UnsafeCast<JSReceiver>(newTarget)));
  result.value = n;
  return result;
}

javascript builtin
GenericLazyDeoptContinuation(js-implicit context: NativeContext)(result: JSAny):
    JSAny {
  return result;
}

}  // namespace constructor
