// Copyright (c) 2018, 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.

// @dart=2.12

// This transformation annotates call sites with the receiver type.
// This is done to avoid reimplementing [Expression.getStaticType] in
// C++.
// We don't annotate all call-sites, but only those where VM could benefit from
// knowing static type of the receiver.
library vm.transformations.call_site_annotator;

import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import 'package:kernel/core_types.dart' show CoreTypes;
import 'package:kernel/type_environment.dart'
    show StaticTypeContext, TypeEnvironment;

import '../metadata/call_site_attributes.dart';

CallSiteAttributesMetadataRepository addRepositoryTo(Component component) {
  return component.metadata.putIfAbsent(
          CallSiteAttributesMetadataRepository.repositoryTag,
          () => new CallSiteAttributesMetadataRepository())
      as CallSiteAttributesMetadataRepository;
}

void transformLibraries(Component component, List<Library> libraries,
    CoreTypes coreTypes, ClassHierarchy hierarchy) {
  final transformer =
      new AnnotateWithStaticTypes(component, coreTypes, hierarchy);
  libraries.forEach(transformer.visitLibrary);
}

class AnnotateWithStaticTypes extends RecursiveVisitor {
  final CallSiteAttributesMetadataRepository _metadata;
  final TypeEnvironment env;
  StaticTypeContext? _staticTypeContext;

  AnnotateWithStaticTypes(
      Component component, CoreTypes coreTypes, ClassHierarchy hierarchy)
      : _metadata = addRepositoryTo(component),
        env = new TypeEnvironment(coreTypes, hierarchy);

  @override
  defaultMember(Member node) {
    _staticTypeContext = new StaticTypeContext(node, env);
    super.defaultMember(node);
    _staticTypeContext = null;
  }

  void annotateWithReceiver(TreeNode node, Expression receiver) {
    annotateWithReceiverType(node, receiver.getStaticType(_staticTypeContext!));
  }

  void annotateWithReceiverType(TreeNode node, DartType receiverType) {
    _metadata.mapping[node] =
        new CallSiteAttributesMetadata(receiverType: receiverType);
  }

  @override
  visitPropertyGet(PropertyGet node) =>
      throw 'Unexpected node ${node.runtimeType}: $node at ${node.location}';

  @override
  visitPropertySet(PropertySet node) =>
      throw 'Unexpected node ${node.runtimeType}: $node at ${node.location}';

  @override
  visitMethodInvocation(MethodInvocation node) =>
      throw 'Unexpected node ${node.runtimeType}: $node at ${node.location}';

  @override
  visitInstanceSet(InstanceSet node) {
    super.visitInstanceSet(node);

    if (hasGenericCovariantParameters(node.interfaceTarget)) {
      annotateWithReceiver(node, node.receiver);
    }
  }

  @override
  visitInstanceInvocation(InstanceInvocation node) {
    super.visitInstanceInvocation(node);

    final DartType receiverType =
        node.receiver.getStaticType(_staticTypeContext!);
    if (receiverType is FunctionType && node.name.text == 'call') {
      throw 'Node ${node.runtimeType}: $node at ${node.location} has receiver'
          ' static type $receiverType and selector \'call\'';
    }

    // TODO(34162): We don't need to save the type here for calls, just whether
    // or not it's a statically-checked call.
    if (hasGenericCovariantParameters(node.interfaceTarget)) {
      annotateWithReceiverType(node, receiverType);
    }
  }

  @override
  visitFunctionInvocation(FunctionInvocation node) {
    super.visitFunctionInvocation(node);

    final DartType receiverType =
        node.receiver.getStaticType(_staticTypeContext!);
    if (receiverType is FunctionType &&
        node.kind == FunctionAccessKind.Function) {
      throw 'Node ${node.runtimeType}: $node at ${node.location} has receiver'
          ' static type $receiverType, but kind ${node.kind}';
    }
  }

  @override
  visitEqualsCall(EqualsCall node) {
    super.visitEqualsCall(node);

    // TODO(34162): We don't need to save the type here for calls, just whether
    // or not it's a statically-checked call.
    if (hasGenericCovariantParameters(node.interfaceTarget)) {
      annotateWithReceiver(node, node.left);
    }
  }

  /// Return [true] if the given list of [VariableDeclaration] contains
  /// any annotated with generic-covariant-impl.
  static bool containsGenericCovariantImpl(List<VariableDeclaration> decls) =>
      decls.any((p) => p.isGenericCovariantImpl);

  /// Returns [true] if the given [member] has any parameters annotated with
  /// generic-covariant-impl attribute.
  static bool hasGenericCovariantParameters(Member? member) {
    if (member is Procedure) {
      return containsGenericCovariantImpl(
              member.function.positionalParameters) ||
          containsGenericCovariantImpl(member.function.namedParameters);
    } else if (member is Field) {
      return member.isGenericCovariantImpl;
    }

    return false;
  }
}
