// Copyright (c) 2024, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

part of '../../ast.dart';

// ------------------------------------------------------------------------
//                            FUNCTIONS
// ------------------------------------------------------------------------

/// A function declares parameters and has a body.
///
/// This may occur in a procedure, constructor, function expression, or local
/// function declaration.
class FunctionNode extends TreeNode implements ScopeProvider, ContextConsumer {
  /// End offset in the source file it comes from. Valid values are from 0 and
  /// up, or -1 ([TreeNode.noOffset]) if the file end offset is not available
  /// (this is the default if none is specifically set).
  int fileEndOffset = TreeNode.noOffset;

  @override
  List<int>? get fileOffsetsIfMultiple => [fileOffset, fileEndOffset];

  /// Kernel async marker for the function.
  ///
  /// See also [dartAsyncMarker].
  AsyncMarker asyncMarker;

  /// Dart async marker for the function.
  ///
  /// See also [asyncMarker].
  ///
  /// A Kernel function can represent a Dart function with a different async
  /// marker.
  ///
  /// For example, when async/await is translated away,
  /// a Dart async function might be represented by a Kernel sync function.
  AsyncMarker dartAsyncMarker;

  List<TypeParameter> typeParameters;
  int requiredParameterCount;
  List<PositionalParameter> positionalParameters;
  List<NamedParameter> namedParameters;
  ThisVariable? thisVariable;
  DartType returnType; // Not null.
  Statement? _body;

  @override
  Scope? scope;

  @override
  List<VariableContext>? capturedContexts;

  /// The emitted value of non-sync functions
  ///
  /// For `async` functions [emittedValueType] is the future value type, that
  /// is, the returned element type. For instance
  ///
  ///     Future<Foo> method1() async => new Foo();
  ///     FutureOr<Foo> method2() async => new Foo();
  ///
  /// here the return types are `Future<Foo>` and `FutureOr<Foo>` for `method1`
  /// and `method2`, respectively, but the future value type is in both cases
  /// `Foo`.
  ///
  /// For pre-nnbd libraries, this is set to `flatten(T)` of the return type
  /// `T`, which can be seen as the pre-nnbd equivalent of the future value
  /// type.
  ///
  /// For `sync*` functions [emittedValueType] is the type of the element of the
  /// iterable returned by the function.
  ///
  /// For `async*` functions [emittedValueType] is the type of the element of
  /// the stream returned by the function.
  ///
  /// For sync functions (those not marked with one of `async`, `sync*`, or
  /// `async*`) the value of [emittedValueType] is null.
  DartType? emittedValueType;

  /// If the function is a redirecting factory constructor, this holds
  /// the target and type arguments of the redirection.
  RedirectingFactoryTarget? redirectingFactoryTarget;

  void Function()? lazyBuilder;

  void _buildLazy() {
    void Function()? lazyBuilderLocal = lazyBuilder;
    if (lazyBuilderLocal != null) {
      lazyBuilder = null;
      lazyBuilderLocal();
    }
  }

  Statement? get body {
    _buildLazy();
    return _body;
  }

  void set body(Statement? body) {
    _buildLazy();
    _body = body;
  }

  new(
    this._body, {
    List<TypeParameter>? typeParameters,
    List<PositionalParameter>? positionalParameters,
    List<NamedParameter>? namedParameters,
    int? requiredParameterCount,
    this.returnType = const DynamicType(),
    this.asyncMarker = AsyncMarker.Sync,
    AsyncMarker? dartAsyncMarker,
    this.emittedValueType,
    this.thisVariable,
  }) : this.positionalParameters = positionalParameters ?? [],
       this.requiredParameterCount =
           requiredParameterCount ?? positionalParameters?.length ?? 0,
       this.namedParameters = namedParameters ?? [],
       this.typeParameters = typeParameters ?? <TypeParameter>[],
       this.dartAsyncMarker = dartAsyncMarker ?? asyncMarker {
    setParents(this.typeParameters, this);
    setParents(this.positionalParameters, this);
    setParents(this.namedParameters, this);
    thisVariable?.parent = this;
    _body?.parent = this;
  }

  static DartType _getTypeOfVariable(Variable node) => node.type;

  static NamedType _getNamedTypeOfVariable(
    NamedParameter node, [
    Substitution? substitution,
  ]) {
    return new NamedType(
      node.parameterName,
      substitution != null ? substitution.substituteType(node.type) : node.type,
      isRequired: node.isRequired,
    );
  }

  /// Returns the function type of the node reusing its type parameters.
  ///
  /// This getter works similarly to [functionType], but reuses type parameters
  /// of the function node (or the class enclosing it -- see the comment on
  /// [functionType] about constructors of generic classes) in the result.  It
  /// is useful in some contexts, especially when reasoning about the function
  /// type of the enclosing generic function and in combination with
  /// [FunctionType.withoutTypeParameters].
  FunctionType computeThisFunctionType(Nullability nullability) {
    TreeNode? parent = this.parent;

    List<TypeParameter> typeParametersToCopy = parent is Constructor
        ? parent.enclosingClass.typeParameters
        : typeParameters;

    // TODO(johnniwinther,cstefantsova): Cache the function type here and use
    // [DartType.withDeclaredNullability] to handle the variants.
    return computeFunctionTypeFromData(
      returnType: returnType,
      typeParameters: typeParametersToCopy,
      positionalParameters: positionalParameters,
      namedParameters: namedParameters,
      nullability: nullability,
      requiredParameterCount: requiredParameterCount,
    );
  }

  /// Returns the function type of the function node.
  ///
  /// If the function node describes a generic function, the resulting function
  /// type will be generic.  If the function node describes a constructor of a
  /// generic class, the resulting function type will be generic with its type
  /// parameters constructed after those of the class.  In both cases, if the
  /// resulting function type is generic, a fresh set of type parameters is used
  /// in it.
  // TODO(johnniwinther,cstefantsova): Merge it with [computeThisFunctionType].
  FunctionType computeFunctionType(Nullability nullability) {
    return computeThisFunctionType(nullability);
  }

  static FunctionType computeFunctionTypeFromData({
    required DartType returnType,
    required List<TypeParameter> typeParameters,
    required List<PositionalParameter> positionalParameters,
    required List<NamedParameter> namedParameters,
    required Nullability nullability,
    required int requiredParameterCount,
  }) {
    List<StructuralParameter> structuralParameters;
    DartType functionReturnType;
    List<DartType> positionalParameterTypes;
    List<NamedType> namedParameterTypes;
    if (typeParameters.isEmpty) {
      structuralParameters = const <StructuralParameter>[];
      functionReturnType = returnType;
      positionalParameterTypes = List.generate(
        positionalParameters.length,
        (index) => _getTypeOfVariable(positionalParameters[index]),
        growable: false,
      );

      if (namedParameters.isEmpty) {
        namedParameterTypes = const <NamedType>[];
      } else {
        namedParameterTypes = List.generate(
          namedParameters.length,
          (index) => _getNamedTypeOfVariable(namedParameters[index]),
          growable: false,
        );
        namedParameterTypes.sort();
      }
    } else {
      // We need create a copy of the list of type parameters, otherwise
      // transformations like erasure don't work.
      FreshStructuralParametersFromTypeParameters freshStructuralParameters =
          getFreshStructuralParametersFromTypeParameters(typeParameters);
      structuralParameters = freshStructuralParameters.freshTypeParameters;
      Substitution substitution = freshStructuralParameters.substitution;
      functionReturnType = substitution.substituteType(returnType);

      positionalParameterTypes = List.generate(
        positionalParameters.length,
        (index) => substitution.substituteType(
          _getTypeOfVariable(positionalParameters[index]),
        ),
        growable: false,
      );
      if (namedParameters.isEmpty) {
        namedParameterTypes = const <NamedType>[];
      } else {
        namedParameterTypes = List.generate(
          namedParameters.length,
          (index) =>
              _getNamedTypeOfVariable(namedParameters[index], substitution),
          growable: false,
        );
        namedParameterTypes.sort();
      }
    }
    return new FunctionType(
      positionalParameterTypes,
      functionReturnType,
      nullability,
      namedParameters: namedParameterTypes,
      typeParameters: structuralParameters,
      requiredParameterCount: requiredParameterCount,
    );
  }

  @override
  R accept<R>(TreeVisitor<R> v) => v.visitFunctionNode(this);

  @override
  R accept1<R, A>(TreeVisitor1<R, A> v, A arg) =>
      v.visitFunctionNode(this, arg);

  @override
  void visitChildren(Visitor v) {
    visitList(typeParameters, v);
    visitList(positionalParameters, v);
    visitList(namedParameters, v);
    returnType.accept(v);
    thisVariable?.accept(v);
    emittedValueType?.accept(v);
    redirectingFactoryTarget?.target?.acceptReference(v);
    if (redirectingFactoryTarget?.typeArguments != null) {
      visitList(redirectingFactoryTarget!.typeArguments!, v);
    }
    body?.accept(v);
  }

  @override
  void transformChildren(Transformer v) {
    v.transformList(typeParameters, this);
    v.transformList(positionalParameters, this);
    v.transformList(namedParameters, this);
    returnType = v.visitDartType(returnType);
    if (thisVariable != null) {
      thisVariable = v.transform(thisVariable!)..parent = this;
    }
    if (emittedValueType != null) {
      emittedValueType = v.visitDartType(emittedValueType!);
    }
    if (redirectingFactoryTarget?.typeArguments != null) {
      v.transformDartTypeList(redirectingFactoryTarget!.typeArguments!);
    }
    if (body != null) {
      body = v.transform(body!);
      body?.parent = this;
    }
  }

  @override
  void transformOrRemoveChildren(RemovingTransformer v) {
    v.transformTypeParameterList(typeParameters, this);
    v.transformVariableList(positionalParameters, this);
    v.transformVariableList(namedParameters, this);
    returnType = v.visitDartType(returnType, cannotRemoveSentinel);
    if (thisVariable != null) {
      thisVariable = v.transformOrRemove(thisVariable!, dummyThisVariable)
        ?..parent = this;
    }
    if (emittedValueType != null) {
      emittedValueType = v.visitDartType(
        emittedValueType!,
        cannotRemoveSentinel,
      );
    }
    if (redirectingFactoryTarget?.typeArguments != null) {
      v.transformDartTypeList(redirectingFactoryTarget!.typeArguments!);
    }
    if (body != null) {
      body = v.transformOrRemoveStatement(body!);
      body?.parent = this;
    }
  }

  @override
  String toString() {
    return "FunctionNode(${toStringInternal()})";
  }

  @override
  void toTextInternal(AstPrinter printer) {
    // TODO(johnniwinther): Implement this.
  }
}

enum AsyncMarker {
  // Do not change the order of these, the frontends depend on it.
  Sync,
  SyncStar,
  Async,
  AsyncStar,
}
