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

library kernel.transformations.method_call;

import 'dart:math' as math;

import '../ast.dart';
import '../class_hierarchy.dart';
import '../core_types.dart';
import '../kernel.dart';
import '../visitor.dart';

/// Problems with the method rewrite transformation:
///
/// * Cannot rewrite invocations to things called "call" because of tear-offs
///   and whatnot that when invoked turns into variableName.call(...).
///
/// * Cannot rewrite invocations to things sharing a name with a field because
///   one could have called clazz.fieldName(...).
///
/// * Rewrites will make stacktraces look weird.
///
/// * Rewrites will make noSuchMethod look weird --- e.g. calling a non-existing
///   function foo(a: 42) turns into foo%0%a(42), i.e. the method name has
///   changed ("foo" vs "foo%0%a") and the arguments has changed (named "a" vs
///   positional).
///   NOTE: At least for now this can be fixed by changing the
///   invocation_mirror_patch file. Doing this I can make all dill, language
///   and co19 tests pass!
///
/// Somewhat weird:
///
/// * Inserts methods that redirect to the correct noSuchMethod invocation
///   so that program #1 example below will work.
///   The reason it otherwise wouldn't is that b.foo(499, named1: 88) is
///   rewritten to b.foo%1%named1(499, 88) which is not legal for class B
///   (thus the method would not be create there) but IS legal for Bs parent
///   class (A), so it would be created there. The call will thus go to the
///   super (A) but shouldn't as foo was overwritten in B.
///
/// Program #1 example:
/// class A {
///   foo(required1, { named1: 499}) => print("Hello from class A");
/// }
///
/// class B extends A {
///   foo(required1) => print("Hello from class B");
/// }
///
/// main() {
///   var b = new B();
///   b.foo(499, named1: 88);
/// }
Program transformProgram(Program program, [debug = false]) {
  new MethodCallTransformer(debug).visitProgram(program);
  return program;
}

class MethodCallTransformer extends Transformer {
  /// Keep track of "visited" procedures and constructors to not visit already
  /// visited stuff, nor visit newly created stubs.
  Set<Member> _visited = new Set<Member>();

  /// Some things currently cannot be rewritten. Calls to methods called "call"
  /// (because invoking tear-offs and closures and whatnot becomes .call)
  /// as well as clashes with field names as a field can contain a function
  /// and one can then do a clazz.fieldName(...).
  Set<String> blacklistedSelectors = new Set<String>.from(["call"]);

  /// Map from a "originally named" procedure to the "%original" procedure
  /// for procedures that was moved.
  Map<Procedure, Procedure> _movedBodies = {};

  /// Map from a "originally named" constructor to the "%original"
  /// constructor for constructors that was moved.
  Map<Constructor, Constructor> _movedConstructors = {};

  /// For static method transformations:
  /// Maps a procedure to the mapping of argument signature to procedure stub.
  Map<Procedure, Map<String, Procedure>> _staticProcedureCalls = {};

  /// For constructor transformations:
  /// Maps a constructor to a mapping of argument signature to constructor stub.
  Map<Constructor, Map<String, Constructor>> _constructorCalls = {};

  /// For non-static method transformations:
  /// Maps from method name to the set of legal number of positional arguments.
  Map<String, Set<int>> _methodToLegalPositionalArgumentCount = {};

  /// For non-static method transformations:
  /// Maps from name of method to the set of new target names seen for at least
  /// one instance (i.e. rewriting has been performed from key to all values in
  /// the mapped to set at least once).
  Map<Name, Set<String>> _rewrittenMethods = {};

  /// For non-static method transformations:
  /// Maps a procedure to the mapping of argument signature to procedure stub.
  Map<Procedure, Map<String, Procedure>> _superProcedureCalls = {};

  /// Whether in debug mode, i.e. if we can insert extra print statements for
  /// debugging purposes.
  bool _debug;

  /// For noSuchMethod calls.
  ClassHierarchy hierarchy;
  CoreTypes coreTypes;
  Constructor _invocationMirrorConstructor; // cached
  Procedure _listFrom; // cached

  MethodCallTransformer(this._debug);

  @override
  TreeNode visitProgram(Program node) {
    hierarchy = new ClassHierarchy(node);
    coreTypes = new CoreTypes(node);

    // First move body of all procedures that takes optional positional or named
    // parameters and record which non-static procedure names have optional
    // positional arguments.
    // Do the same for constructors. Then also rewrite constructor initializers
    // using LocalInitializer and sort named arguments in those initializers
    for (final library in node.libraries) {
      for (final procedure in new List<Procedure>.from(library.procedures)) {
        _moveAndTransformProcedure(procedure);
      }

      for (final clazz in library.classes) {
        for (final field in clazz.fields) {
          blacklistedSelectors.add(field.name.name);
        }

        for (final procedure in new List<Procedure>.from(clazz.procedures)) {
          // This call creates new procedures
          _moveAndTransformProcedure(procedure);
          _recordNonStaticProcedureAndVariableArguments(procedure);
        }

        for (final constructor
            in new List<Constructor>.from(clazz.constructors)) {
          // This call creates new constructors
          _moveAndTransformConstructor(constructor);
        }

        for (final constructor in clazz.constructors) {
          _rewriteConstructorInitializations(constructor);
        }
      }
    }

    // Rewrite calls
    node.transformChildren(this);

    // Now for all method calls that was rewritten, make sure those call
    // destinations actually exist, i.e. for each method with a matching name
    // where the called-with-arguments is legal, create a stub
    for (final library in node.libraries) {
      for (final clazz in library.classes) {
        for (final procedure in new List<Procedure>.from(clazz.procedures)) {
          // This call creates new procedures
          _createNeededNonStaticStubs(procedure);
        }
      }
    }

    return node;
  }

  @override
  TreeNode visitProcedure(Procedure node) {
    if (!_visited.contains(node)) {
      _visited.add(node);
      node.transformChildren(this);
    }
    return node;
  }

  @override
  TreeNode visitConstructor(Constructor node) {
    if (!_visited.contains(node)) {
      _visited.add(node);
      node.transformChildren(this);
    }
    return node;
  }

  @override
  TreeNode visitStaticInvocation(StaticInvocation node) {
    node.transformChildren(this);
    if (!_isMethod(node.target)) return node;
    if (!_hasAnyOptionalParameters(node.target.function)) return node;
    if (!_callIsLegal(node.target.function, node.arguments)) return node;

    // Rewrite with let if needed (without named arguments it won't do anything)
    Expression rewrittenNode = _rewriteWithLetAndSort(node, node.arguments);

    // Create/lookup target and set it as the new target
    node.target = _getNewTargetForStaticLikeInvocation(
        node.target, node.arguments, _staticProcedureCalls);

    // Now turn any named parameters into positional parameters
    _turnNamedArgumentsIntoPositional(node.arguments);
    return rewrittenNode;
  }

  @override
  TreeNode visitDirectMethodInvocation(DirectMethodInvocation node) {
    node.transformChildren(this);
    if (!_isMethod(node.target)) return node;
    if (!_hasAnyOptionalParameters(node.target.function)) return node;
    if (!_callIsLegal(node.target.function, node.arguments)) return node;

    // Rewrite with let if needed (without named arguments it won't do anything)
    Expression rewrittenNode = _rewriteWithLetAndSort(node, node.arguments);

    // Create/lookup target and set it as the new target
    node.target = _getNewTargetForStaticLikeInvocation(
        node.target, node.arguments, _superProcedureCalls);

    // Now turn any named parameters into positional parameters instead
    _turnNamedArgumentsIntoPositional(node.arguments);
    return rewrittenNode;
  }

  @override
  TreeNode visitSuperMethodInvocation(SuperMethodInvocation node) {
    // SuperMethodInvocation was changed since I originally wrote this,
    // and now it seems to never be called anyway.
    throw "visitSuperMethodInvocation is not implemented!";
  }

  @override
  TreeNode visitMethodInvocation(MethodInvocation node) {
    node.transformChildren(this);
    final name = node.name.name;

    // Don't renamed calls to methods that clashes in name with a field
    // or is called "call".
    if (blacklistedSelectors.contains(name)) return node;

    // Rewrite with let if needed (without named arguments it won't do anything)
    Expression rewrittenNode = _rewriteWithLetAndSort(node, node.arguments);

    String argumentsSignature = _createArgumentsSignature(node.arguments);
    if (node.arguments.named.isEmpty) {
      // Positional: Don't rewrite if no procedure with that name can be called
      // with a variable number of arguments, or where the number of arguments
      // called with here isn't a legal number of arguments to any such
      // procedure.
      // Note for named arguments: Named arguments are always rewritten
      // (except for 'call' methods) so there's no such check
      final okCounts = _methodToLegalPositionalArgumentCount[name];

      if (okCounts == null ||
          !okCounts.contains(node.arguments.positional.length)) {
        return node;
      }
    }

    // Rewrite this call
    final originalName = node.name;
    node.name = _createName(node.name, argumentsSignature);

    // Remember that we rewrote this call
    _rewrittenMethods
        .putIfAbsent(originalName, () => new Set<String>())
        .add(argumentsSignature);

    // Now turn any named parameters into positional parameters instead
    _turnNamedArgumentsIntoPositional(node.arguments);
    return rewrittenNode;
  }

  @override
  TreeNode visitConstructorInvocation(ConstructorInvocation node) {
    node.transformChildren(this);
    if (!_callIsLegal(node.target.function, node.arguments)) return node;

    Expression rewrittenNode;
    if (node.isConst) {
      // Sort named arguments by name => it's const so there's no side-effects!
      // but DO NOT rewrite with let!
      node.arguments.named.sort((a, b) => a.name.compareTo(b.name));
      rewrittenNode = node;
    } else {
      rewrittenNode = _rewriteWithLetAndSort(node, node.arguments);
    }
    node.target = _getNewTargetForConstructor(node.target, node.arguments);

    // Now turn named parameters into positional parameters instead
    _turnNamedArgumentsIntoPositional(node.arguments);
    return rewrittenNode;
  }

  @override
  TreeNode visitSuperInitializer(SuperInitializer node) {
    // Note that sorting was done in _rewriteConstructorInitializations
    node.transformChildren(this);
    if (!_callIsLegal(node.target.function, node.arguments)) return node;

    node.target = _getNewTargetForConstructor(node.target, node.arguments);

    // Now turn named parameters into positional parameters instead
    _turnNamedArgumentsIntoPositional(node.arguments);
    return node;
  }

  @override
  TreeNode visitRedirectingInitializer(RedirectingInitializer node) {
    // Note that sorting was done in _rewriteConstructorInitializations
    node.transformChildren(this);
    if (!_callIsLegal(node.target.function, node.arguments)) return node;

    node.target = _getNewTargetForConstructor(node.target, node.arguments);

    // Now turn named parameters into positional parameters instead
    _turnNamedArgumentsIntoPositional(node.arguments);
    return node;
  }

  /// Gets the new target for an invocation, using cache or creating a new one.
  ///
  /// Assumes that any let-rewrite, named argument sorting etc has been done
  /// already.
  Procedure _getNewTargetForStaticLikeInvocation(Procedure target,
      Arguments arguments, Map<Procedure, Map<String, Procedure>> cache) {
    final createdProcedures = cache.putIfAbsent(target, () => {});

    // Rewrite target
    final argumentsSignature = _createArgumentsSignature(arguments);
    return createdProcedures[argumentsSignature] ??
        _createAndCacheInvocationProcedure(
            argumentsSignature,
            arguments.positional.length,
            arguments.named.map((e) => e.name).toList(),
            target,
            _movedBodies[target],
            createdProcedures,
            true);
  }

  /// Rewrite the [Argument]s turning named arguments into positional arguments.
  ///
  /// Note that if the [Argument]s does not take any named parameters this
  /// method does nothing.
  void _turnNamedArgumentsIntoPositional(Arguments arguments) {
    for (final named in arguments.named) {
      arguments.positional.add(named.value..parent = arguments);
    }
    arguments.named.clear();
  }

  /// Gets the new target for an invocation, using cache or creating a new one.
  ///
  /// Assumes that any let-rewrite, named argument sorting etc has been done
  /// already.
  Constructor _getNewTargetForConstructor(
      Constructor target, Arguments arguments) {
    if (!_isNotExternal(target)) return target;
    if (!_hasAnyOptionalParameters(target.function)) return target;

    final argumentsSignature = _createArgumentsSignature(arguments);
    final createdConstructor = _constructorCalls.putIfAbsent(target, () => {});
    return createdConstructor[argumentsSignature] ??
        _createAndCacheInvocationConstructor(
            argumentsSignature,
            arguments.positional.length,
            arguments.named.map((e) => e.name).toList(),
            target,
            _movedConstructors[target],
            createdConstructor,
            true);
  }

  /// Create a signature for the [Arguments].
  ///
  /// Assumes that any needed sorting etc has already been done.
  ///
  /// Looks like x%positionalCount%named --- but it shouldn't matter if always
  /// using these methods
  String _createArgumentsSignature(Arguments arguments) {
    String namedString = arguments.named.map((e) => e.name).join("%");
    return "${arguments.positional.length}%$namedString";
  }

  /// Parse the argument signature.
  ///
  /// First element will be the string representation of the number of
  /// positional arguments used.
  /// The rest will be the named arguments, except that with no named arguments
  /// there still is a 2nd entry: the empty string...
  List<String> _parseArgumentsSignature(String argumentsSignature) {
    return argumentsSignature.split("%");
  }

  /// Rewrites an expression with let, replacing expressions in the [Arguments].
  ///
  /// Sorts the named arguments after rewriting with let.
  ///
  /// Note that this method does nothing if there are no named arguments, or the
  /// named arguments list contain only a single named argument as any sorting
  /// would have no effect. As such, the let-rewrite will also have no effect.
  /// In such a case the return value is [original].
  Expression _rewriteWithLetAndSort(Expression original, Arguments arguments) {
    final named = arguments.named;

    // Only bother if names can be unordered
    if (named.length < 2) return original;

    // Rewrite named with let in given order
    Let let;
    for (int i = named.length - 1; i >= 0; i--) {
      VariableDeclaration letDeclaration =
          new VariableDeclaration.forValue(named[i].value);
      named[i].value = new VariableGet(letDeclaration)..parent = arguments;
      let = new Let(letDeclaration, let ?? original);
    }

    // Sort named arguments by name
    named.sort((a, b) => a.name.compareTo(b.name));

    // Now also add the given positional arguments into the let
    final expressions = arguments.positional;
    for (int i = expressions.length - 1; i >= 0; i--) {
      VariableDeclaration letDeclaration =
          new VariableDeclaration.forValue(expressions[i]);
      expressions[i] = new VariableGet(letDeclaration)..parent = arguments;
      let = new Let(letDeclaration, let ?? original);
    }

    return let;
  }

  /// Creates all needed stubs for non static procedures.
  ///
  /// More specifically: If calls have been made to a procedure with the same
  /// name as this procedure with both 1 and 2 arguments, where both of these
  /// are legal inputs to this procedure, create stubs for both of them,
  /// each of which calls with whatever default parameter values are defined for
  /// the non-given arguments.
  void _createNeededNonStaticStubs(Procedure procedure) {
    final incomingCalls = _rewrittenMethods[procedure.name];
    if (incomingCalls != null &&
        procedure.kind == ProcedureKind.Method &&
        !procedure.isStatic) {
      final createdOnSuper = _superProcedureCalls[procedure];
      final names =
          procedure.function.namedParameters.map((e) => e.name).toSet();

      // A procedure with this name was called on at least one object with
      // an argument signature like any in [incomingCalls]
      nextArgumentSignature:
      for (final argumentsSignature in incomingCalls) {
        // Skip if it was created in a super call already
        if (createdOnSuper != null &&
            createdOnSuper.containsKey(argumentsSignature)) {
          continue;
        }

        final elements = _parseArgumentsSignature(argumentsSignature);
        int positional = int.parse(elements[0]);

        if (positional < procedure.function.requiredParameterCount ||
            positional > procedure.function.positionalParameters.length) {
          // We don't take that number of positional parameters!
          // Call noSuchMethod in case anyone called on object with wrong
          // parameters, but where superclass does take these parameters.
          _createNoSuchMethodStub(
              argumentsSignature, positional, elements.sublist(1), procedure);
          continue;
        }

        if (elements.length > 2 || elements[1] != "") {
          // Named: Could the call be for this method?
          for (int i = 1; i < elements.length; i++) {
            String name = elements[i];
            // Using a name that we don't have?
            if (!names.contains(name)) {
              // Call noSuchMethod in case anyone called on object with wrong
              // parameters, but where superclass does take these parameters.
              _createNoSuchMethodStub(argumentsSignature, positional,
                  elements.sublist(1), procedure);
              continue nextArgumentSignature;
            }
          }
        }

        // Potential legal call => make stub
        // Note the ?? here: E.g. contains on list doesn't take optionals so it
        // wasn't moved, but calls were rewritten because contains on string
        // takes either 1 or 2 arguments.
        final destination = _movedBodies[procedure] ?? procedure;
        _createAndCacheInvocationProcedure(argumentsSignature, positional,
            elements.sublist(1), procedure, destination, {}, false);
      }
    }
  }

  /// Records how this procedure can be called (if it is non-static).
  ///
  /// More specifically: Assuming that the procedure given is non-static taking
  /// a variable number of positional parameters, record all number of arguments
  /// that is legal, e.g. foo(int a, [int b]) is legal for 1 and 2 parameters.
  /// If it takes named parameters, remember how many positional there is so
  /// we also know to rewrite calls without the named arguments.
  void _recordNonStaticProcedureAndVariableArguments(Procedure procedure) {
    if (_isMethod(procedure) &&
        !procedure.isStatic &&
        _hasAnyOptionalParameters(procedure.function)) {
      final name = procedure.name.name;
      final okCounts = _methodToLegalPositionalArgumentCount.putIfAbsent(
          name, () => new Set<int>());
      for (int i = procedure.function.requiredParameterCount;
          i <= procedure.function.positionalParameters.length;
          i++) {
        okCounts.add(i);
      }
    }
  }

  /// Move body of procedure to new procedure and call that from this procedure.
  ///
  /// More specifically: For all procedures with optional positional parameters,
  /// or named parameters, create a new procedure without optional positional
  /// parameters and named parameters and move the body of the original
  /// procedure into this new procedure.
  /// Then make the body of the original procedure call the new procedure.
  ///
  /// The idea is that all rewrites should call the moved procedure instead,
  /// bypassing the optional/named arguments entirely.
  void _moveAndTransformProcedure(Procedure procedure) {
    if (_isMethod(procedure) && _hasAnyOptionalParameters(procedure.function)) {
      final function = procedure.function;

      // Create variable lists
      final newParameterDeclarations = <VariableDeclaration>[];
      final newNamedParameterDeclarations = <VariableDeclaration>[];
      final newParameterVariableGets = <Expression>[];
      final targetParameters = function.positionalParameters;
      final targetNamedParameters = function.namedParameters;
      _moveVariableInitialization(
          targetParameters,
          targetNamedParameters,
          newParameterDeclarations,
          newNamedParameterDeclarations,
          newParameterVariableGets,
          procedure.function);

      // Create new procedure looking like the old one
      // (with the old body and parameters)
      FunctionNode functionNode = _createShallowFunctionCopy(function);
      final newProcedure = new Procedure(
          _createOriginalName(procedure), ProcedureKind.Method, functionNode,
          isAbstract: procedure.isAbstract,
          isStatic: procedure.isStatic,
          isConst: procedure.isConst,
          fileUri: procedure.fileUri);

      // Add procedure to the code
      _addMember(procedure, newProcedure);

      // Map moved body
      _movedBodies[procedure] = newProcedure;

      // Transform original procedure
      if (procedure.isAbstract && procedure.function.body == null) {
        // do basically nothing then
        procedure.function.positionalParameters = newParameterDeclarations;
        procedure.function.namedParameters = newNamedParameterDeclarations;
      } else if (procedure.isStatic) {
        final expression = new StaticInvocation(
            newProcedure, new Arguments(newParameterVariableGets));
        final statement = new ReturnStatement(expression)
          ..parent = procedure.function;
        procedure.function.body = statement;
        procedure.function.positionalParameters = newParameterDeclarations;
        procedure.function.namedParameters = newNamedParameterDeclarations;
      } else {
        final expression = new DirectMethodInvocation(new ThisExpression(),
            newProcedure, new Arguments(newParameterVariableGets));
        final statement = new ReturnStatement(expression)
          ..parent = procedure.function;
        procedure.function.body = statement;
        procedure.function.positionalParameters = newParameterDeclarations;
        procedure.function.namedParameters = newNamedParameterDeclarations;
      }

      if (_debug) {
        // Debug flag set: Print something to the terminal before returning to
        // easily detect if rewrites are missing.
        Expression debugPrint = _getPrintExpression(
            "DEBUG! Procedure shouldn't have been called...", procedure);
        procedure.function.body = new Block(
            [new ExpressionStatement(debugPrint), procedure.function.body])
          ..parent = procedure.function;
      }

      // Mark original procedure as seen (i.e. don't transform it further)
      _visited.add(procedure);
    }
  }

  /// Rewrite constructor initializers by introducing variables and sorting.
  ///
  /// For any* [SuperInitializer] or [RedirectingInitializer], extract the
  /// parameters, put them into variables, then sorting the named parameters.
  /// The idea is to sort the named parameters without changing any invocation
  /// order.
  ///
  /// * only with at least 2 named arguments, otherwise sorting would do nothing
  void _rewriteConstructorInitializations(Constructor constructor) {
    if (_isNotExternal(constructor)) {
      // Basically copied from "super_calls.dart"
      List<Initializer> initializers = constructor.initializers;
      int foundIndex = -1;
      Arguments arguments;
      for (int i = initializers.length - 1; i >= 0; --i) {
        Initializer initializer = initializers[i];
        if (initializer is SuperInitializer) {
          foundIndex = i;
          arguments = initializer.arguments;
          break;
        } else if (initializer is RedirectingInitializer) {
          foundIndex = i;
          arguments = initializer.arguments;
          break;
        }
      }
      if (foundIndex == -1) return;

      // Rewrite using variables if using named parameters (so we can sort them)
      // (note that with 1 named it cannot be unsorted so we don't bother)
      if (arguments.named.length < 2) return;

      int argumentCount = arguments.positional.length + arguments.named.length;

      // Make room for [argumentCount] [LocalInitializer]s before the
      // super/redirector call.
      initializers.length += argumentCount;
      initializers.setRange(
          foundIndex + argumentCount, // destination start (inclusive)
          initializers.length, // destination end (exclusive)
          initializers, // source list
          foundIndex); // source start index

      // Fill in the [argumentCount] reserved slots with the evaluation
      // expressions of the arguments to the super/redirector constructor call
      int storeIndex = foundIndex;
      for (int i = 0; i < arguments.positional.length; ++i) {
        var variable =
            new VariableDeclaration.forValue(arguments.positional[i]);
        arguments.positional[i] = new VariableGet(variable)..parent = arguments;
        initializers[storeIndex++] = new LocalInitializer(variable)
          ..parent = constructor;
      }
      for (int i = 0; i < arguments.named.length; ++i) {
        NamedExpression argument = arguments.named[i];
        var variable = new VariableDeclaration.forValue(argument.value);
        arguments.named[i].value = new VariableGet(variable)..parent = argument;
        initializers[storeIndex++] = new LocalInitializer(variable)
          ..parent = constructor;
      }

      // Sort the named arguments
      arguments.named.sort((a, b) => a.name.compareTo(b.name));
    }
  }

  /// Move body of constructor to new one and call that from this one.
  ///
  /// More specifically: For all constructors with optional positional
  /// parameters, or named parameters, create a new constructor without optional
  /// positional parameters and named parameters, and move the body of the
  /// original constructor into this new constructor.
  /// Then make the original constructor redirect to the new constructor.
  ///
  /// The idea is that all rewrites should call the moved constructor instead,
  /// bypassing the optional/named arguments entirely.
  ///
  /// This method is very similar to _moveAndTransformProcedure
  void _moveAndTransformConstructor(Constructor constructor) {
    if (_isNotExternal(constructor) &&
        _hasAnyOptionalParameters(constructor.function)) {
      final function = constructor.function;

      // Create variable lists
      final newParameterDeclarations = <VariableDeclaration>[];
      final newNamedParameterDeclarations = <VariableDeclaration>[];
      final newParameterVariableGets = <Expression>[];
      final targetParameters = function.positionalParameters;
      final targetNamedParameters = function.namedParameters;
      _moveVariableInitialization(
          targetParameters,
          targetNamedParameters,
          newParameterDeclarations,
          newNamedParameterDeclarations,
          newParameterVariableGets,
          constructor.function);

      // Create new constructor looking like the old one
      // (with the old body, parameters and initializers)
      FunctionNode functionNode = _createShallowFunctionCopy(function);
      final newConstructor = new Constructor(functionNode,
          name: _createOriginalName(constructor),
          isConst: constructor.isConst,
          isExternal: constructor.isExternal,
          initializers: constructor.initializers);

      // Add constructor to the code
      _addMember(constructor, newConstructor);

      // Map moved body
      _movedConstructors[constructor] = newConstructor;

      // Transform original constructor
      constructor.function.body = null;
      constructor.function.positionalParameters = newParameterDeclarations;
      constructor.function.namedParameters = newNamedParameterDeclarations;
      constructor.initializers = [
        new RedirectingInitializer(
            newConstructor, new Arguments(newParameterVariableGets))
          ..parent = constructor
      ];

      if (_debug) {
        // Debug flag set: Print something to the terminal before returning to
        // easily detect if rewrites are missing.
        Expression debugPrint = _getPrintExpression(
            "DEBUG! Constructor shouldn't have been called...", constructor);
        var variable = new VariableDeclaration.forValue(debugPrint);
        final debugInitializer = new LocalInitializer(variable)
          ..parent = constructor;
        final redirector = constructor.initializers[0];
        constructor.initializers = [debugInitializer, redirector];
      }

      // Mark original procedure as seen (i.e. don't transform it further)
      _visited.add(constructor);
    }
  }

  /// Creates a new [FunctionNode] based on the given one.
  ///
  /// Parameters are taken directly (i.e. after returning the parameters will
  /// have a new parent (the returned value), but still be referenced in the
  /// original [FunctionNode].
  /// The same goes for the body of the function.
  /// The caller should take steps to remedy this after this call.
  ///
  /// The parameters are no longer optional and named parameters have been
  /// sorted and turned into regular parameters in the returned [FunctionNode].
  FunctionNode _createShallowFunctionCopy(FunctionNode function) {
    final newParameters =
        new List<VariableDeclaration>.from(function.positionalParameters);
    final named = new List<VariableDeclaration>.from(function.namedParameters);
    named.sort((a, b) => a.name.compareTo(b.name));
    newParameters.addAll(named);
    final functionNode = new FunctionNode(function.body,
        positionalParameters: newParameters,
        namedParameters: [],
        requiredParameterCount: newParameters.length,
        returnType: function.returnType,
        asyncMarker: function.asyncMarker,
        dartAsyncMarker: function.dartAsyncMarker);
    return functionNode;
  }

  /// Creates new variables, moving old initializers into them
  ///
  /// Specifically: Given lists for output, create new variables based on
  /// original parameters. Any new variable will receive the original variables
  /// initializer, and the original variable will have its initializer set to
  /// null.
  /// Named parameters have been sorted in [newParameterVariableGets].
  void _moveVariableInitialization(
      List<VariableDeclaration> originalParameters,
      List<VariableDeclaration> originalNamedParameters,
      List<VariableDeclaration> newParameterDeclarations,
      List<VariableDeclaration> newNamedParameterDeclarations,
      List<Expression> newParameterVariableGets,
      TreeNode newStuffParent) {
    for (final orgVar in originalParameters) {
      final variableDeclaration = new VariableDeclaration(orgVar.name,
          initializer: orgVar.initializer,
          type: orgVar.type,
          isFinal: orgVar.isFinal,
          isConst: orgVar.isConst)
        ..parent = newStuffParent;
      variableDeclaration.initializer?.parent = variableDeclaration;
      newParameterDeclarations.add(variableDeclaration);
      orgVar.initializer = null;
      newParameterVariableGets.add(new VariableGet(variableDeclaration));
    }

    // Named expressions in newParameterVariableGets should be sorted
    final tmp = new List<_Pair<String, Expression>>();
    for (final orgVar in originalNamedParameters) {
      final variableDeclaration = new VariableDeclaration(orgVar.name,
          initializer: orgVar.initializer,
          type: orgVar.type,
          isFinal: orgVar.isFinal,
          isConst: orgVar.isConst)
        ..parent = newStuffParent;
      variableDeclaration.initializer?.parent = variableDeclaration;
      newNamedParameterDeclarations.add(variableDeclaration);
      orgVar.initializer = null;
      tmp.add(new _Pair(orgVar.name, new VariableGet(variableDeclaration)));
    }
    tmp.sort((a, b) => a.key.compareTo(b.key));
    for (final item in tmp) {
      newParameterVariableGets.add(item.value);
    }
  }

  /// Creates a stub redirecting to noSuchMethod.
  ///
  /// Needed because if B extends A, both have a foo method, but taking
  /// different optional parameters, a call on an instance of B with parameters
  /// for A should actually result in a noSuchMethod call, but if only A has
  /// the rewritten method name, that method will be called...
  /// TODO: We only have to create these stubs for arguments that a procedures
  /// super allows, otherwise it will become a noSuchMethod automatically!
  Procedure _createNoSuchMethodStub(
      String argumentsSignature,
      int positionalCount,
      List<String> givenNamedParameters,
      Procedure existing) {
    // Build parameter lists
    final newParameterDeclarations = <VariableDeclaration>[];
    final newParameterVariableGets = <Expression>[];
    for (int i = 0; i < positionalCount + givenNamedParameters.length; i++) {
      final variableDeclaration = new VariableDeclaration("v%$i");
      newParameterDeclarations.add(variableDeclaration);
      newParameterVariableGets.add(new VariableGet(variableDeclaration));
    }

    var procedureName = _createName(existing.name, argumentsSignature);

    // Find noSuchMethod to call
    Member noSuchMethod = hierarchy.getDispatchTarget(
        existing.enclosingClass, new Name("noSuchMethod"));
    Arguments argumentsToNoSuchMethod;

    if (noSuchMethod.function.positionalParameters.length == 1 &&
        noSuchMethod.function.namedParameters.isEmpty) {
      // We have a correct noSuchMethod method.
      ConstructorInvocation invocation = _createInvocation(
          procedureName.name, new Arguments(newParameterVariableGets));
      argumentsToNoSuchMethod = new Arguments([invocation]);
    } else {
      // Get noSuchMethod on Object then...
      noSuchMethod = hierarchy.getDispatchTarget(
          hierarchy.rootClass, new Name("noSuchMethod"));
      ConstructorInvocation invocation = _createInvocation(
          procedureName.name, new Arguments(newParameterVariableGets));
      ConstructorInvocation invocationPrime =
          _createInvocation("noSuchMethod", new Arguments([invocation]));
      argumentsToNoSuchMethod = new Arguments([invocationPrime]);
    }

    // Create return statement to call noSuchMethod
    ReturnStatement statement;
    final expression = new DirectMethodInvocation(
        new ThisExpression(), noSuchMethod, argumentsToNoSuchMethod);
    statement = new ReturnStatement(expression);

    // Build procedure
    final functionNode = new FunctionNode(statement,
        positionalParameters: newParameterDeclarations,
        namedParameters: [],
        requiredParameterCount: newParameterDeclarations.length,
        returnType: existing.function.returnType,
        asyncMarker: existing.function.asyncMarker,
        dartAsyncMarker: existing.function.dartAsyncMarker);
    final procedure = new Procedure(
        procedureName, ProcedureKind.Method, functionNode,
        isStatic: existing.isStatic, fileUri: existing.fileUri);

    // Add procedure to the code
    _addMember(existing, procedure);

    // Mark the new procedure as visited already (i.e. don't rewrite it again!)
    _visited.add(procedure);

    return procedure;
  }

  /// Creates an "new _InvocationMirror(...)" invocation.
  ConstructorInvocation _createInvocation(
      String methodName, Arguments callArguments) {
    if (_invocationMirrorConstructor == null) {
      Class clazz = coreTypes.invocationMirrorClass;
      _invocationMirrorConstructor = clazz.constructors[0];
    }

    // The _InvocationMirror constructor takes the following arguments:
    // * Method name (a string).
    // * An arguments descriptor - a list consisting of:
    //   - number of arguments (including receiver).
    //   - number of positional arguments (including receiver).
    //   - pairs (2 entries in the list) of
    //     * named arguments name.
    //     * index of named argument in arguments list.
    // * A list of arguments, where the first ones are the positional arguments.
    // * Whether it's a super invocation or not.

    int numPositionalArguments = callArguments.positional.length + 1;
    int numArguments = numPositionalArguments + callArguments.named.length;
    List<Expression> argumentsDescriptor = [
      new IntLiteral(numArguments),
      new IntLiteral(numPositionalArguments)
    ];
    List<Expression> arguments = [];
    arguments.add(new ThisExpression());
    for (Expression pos in callArguments.positional) {
      arguments.add(pos);
    }
    for (NamedExpression named in callArguments.named) {
      argumentsDescriptor.add(new StringLiteral(named.name));
      argumentsDescriptor.add(new IntLiteral(arguments.length));
      arguments.add(named.value);
    }

    return new ConstructorInvocation(
        _invocationMirrorConstructor,
        new Arguments([
          new StringLiteral(methodName),
          _fixedLengthList(argumentsDescriptor),
          _fixedLengthList(arguments),
          new BoolLiteral(false)
        ]));
  }

  /// Create a fixed length list containing given expressions.
  Expression _fixedLengthList(List<Expression> list) {
    _listFrom ??= coreTypes.listFromConstructor;
    return new StaticInvocation(
        _listFrom,
        new Arguments([new ListLiteral(list)],
            named: [new NamedExpression("growable", new BoolLiteral(false))],
            types: [const DynamicType()]));
  }

  /// Creates a new procedure taking given arguments, caching it.
  ///
  /// Copies any non-given default values for parameters into the new procedure
  /// to be able to call the [realTarget] without using optionals and named
  /// parameters.
  Procedure _createAndCacheInvocationProcedure(
      String argumentsSignature,
      int positionalCount,
      List<String> givenNamedParameters,
      Procedure target,
      Procedure realTarget,
      Map<String, Procedure> createdProcedures,
      bool doSpecialCaseForAllParameters) {
    // Special case: Calling with all parameters
    if (doSpecialCaseForAllParameters &&
        positionalCount == target.function.positionalParameters.length &&
        givenNamedParameters.length == target.function.namedParameters.length) {
      // We don't cache this procedure as this could make it look like
      // something with name argumentsSignature actually exists
      // while it doesn't (which is bad as we could then decide that we don't
      // need to create a stub even though we do!)
      return realTarget;
    }

    // Create and cache (save) constructor

    // Build parameter lists
    final newParameterDeclarations = <VariableDeclaration>[];
    final newParameterVariableGets = <Expression>[];
    _extractAndCreateParameters(positionalCount, newParameterDeclarations,
        newParameterVariableGets, target, givenNamedParameters);

    // Create return statement to call real target
    ReturnStatement statement;
    if (target.isAbstract && target.function?.body == null) {
      // statement should just be null then
    } else if (target.isStatic) {
      final expression = new StaticInvocation(
          realTarget, new Arguments(newParameterVariableGets));
      statement = new ReturnStatement(expression);
    } else {
      final expression = new DirectMethodInvocation(new ThisExpression(),
          realTarget, new Arguments(newParameterVariableGets));
      statement = new ReturnStatement(expression);
    }

    // Build procedure
    final functionNode = new FunctionNode(statement,
        positionalParameters: newParameterDeclarations,
        namedParameters: [],
        requiredParameterCount: newParameterDeclarations.length,
        returnType: target.function.returnType,
        asyncMarker: target.function.asyncMarker,
        dartAsyncMarker: target.function.dartAsyncMarker);
    final procedure = new Procedure(
        _createName(target.name, argumentsSignature),
        ProcedureKind.Method,
        functionNode,
        isAbstract: target.isAbstract,
        isStatic: target.isStatic,
        isConst: target.isConst,
        fileUri: target.fileUri);

    // Add procedure to the code
    _addMember(target, procedure);

    // Cache it for future reference
    createdProcedures[argumentsSignature] = procedure;

    // Mark the new procedure as visited already (i.e. don't rewrite it again!)
    _visited.add(procedure);

    return procedure;
  }

  /// Creates a new constructor taking given arguments, caching it.
  ///
  /// Copies any non-given default values for parameters into the new
  /// constructor to be able to call the [realTarget] without using optionals
  /// and named parameters.
  Constructor _createAndCacheInvocationConstructor(
      String argumentsSignature,
      int positionalCount,
      List<String> givenNamedParameters,
      Constructor target,
      Constructor realTarget,
      Map<String, Constructor> createdConstructor,
      bool doSpecialCaseForAllParameters) {
    // Special case: Calling with all parameters
    if (doSpecialCaseForAllParameters &&
        positionalCount == target.function.positionalParameters.length &&
        givenNamedParameters.length == target.function.namedParameters.length) {
      createdConstructor[argumentsSignature] = realTarget;
      return realTarget;
    }

    // Create and cache (save) constructor

    // Build parameter lists
    final newParameterDeclarations = <VariableDeclaration>[];
    final newParameterVariableGets = <Expression>[];
    _extractAndCreateParameters(positionalCount, newParameterDeclarations,
        newParameterVariableGets, target, givenNamedParameters);

    // Build constructor
    final functionNode = new FunctionNode(null,
        positionalParameters: newParameterDeclarations,
        namedParameters: [],
        requiredParameterCount: newParameterDeclarations.length,
        returnType: target.function.returnType,
        asyncMarker: target.function.asyncMarker,
        dartAsyncMarker: target.function.dartAsyncMarker);
    final constructor = new Constructor(functionNode,
        name: _createName(target.name, argumentsSignature),
        isConst: target.isConst,
        isExternal: target.isExternal,
        initializers: [
          new RedirectingInitializer(
              realTarget, new Arguments(newParameterVariableGets))
        ]);

    // Add procedure to the code
    _addMember(target, constructor);

    // Cache it for future reference
    createdConstructor[argumentsSignature] = constructor;

    // Mark the new procedure as visited already (i.e. don't rewrite it again!)
    _visited.add(constructor);

    return constructor;
  }

  /// Extracts and creates parameters into the first two given lists.
  ///
  /// What is done:
  /// Step 1: Re-create the parameters given (i.e. the non-optional positional
  /// ones) - i.e. create a new variable with the same name etc, put it in
  /// [newParameterDeclarations]; create VariableGet for that and put it in
  /// [newParameterVariableGets]
  /// Step 2: Re-create the positional parameters NOT given, i.e. insert
  /// defaults and add to [newParameterVariableGets] only.
  /// Step 3: Re-create the named arguments (in sorted order). For actually
  /// given named parameters, do as in step 1, for not-given named parameters
  /// do as in step 2.
  ///
  /// NOTE: [newParameterDeclarations] and [newParameterVariableGets] are OUTPUT
  /// lists.
  void _extractAndCreateParameters(
      int positionalCount,
      List<VariableDeclaration> newParameterDeclarations,
      List<Expression> newParameterVariableGets,
      Member target,
      List<String> givenNamedParameters) {
    // First re-create the parameters given (i.e. the non-optional positional ones)
    final targetParameters = target.function.positionalParameters;
    positionalCount = math.min(positionalCount, targetParameters.length);
    for (int i = 0; i < positionalCount; i++) {
      final orgVar = targetParameters[i];
      final variableDeclaration = new VariableDeclaration(orgVar.name,
          type: orgVar.type, isFinal: orgVar.isFinal, isConst: orgVar.isConst);
      newParameterDeclarations.add(variableDeclaration);
      newParameterVariableGets.add(new VariableGet(variableDeclaration));
    }

    // Default parameters for the rest of them
    _fillInPositionalParameters(
        positionalCount, target, newParameterVariableGets);

    // Then all named parameters (given here or not)
    final orgNamed =
        new List<VariableDeclaration>.from(target.function.namedParameters);
    orgNamed.sort((a, b) => a.name.compareTo(b.name));
    final givenArgumentsIterator = givenNamedParameters.iterator;
    givenArgumentsIterator.moveNext();
    for (VariableDeclaration named in orgNamed) {
      if (givenArgumentsIterator.current == named.name) {
        // We have that one: Use it and move the iterator
        final variableDeclaration = new VariableDeclaration(named.name);
        newParameterDeclarations.add(variableDeclaration);
        newParameterVariableGets.add(new VariableGet(variableDeclaration));
        givenArgumentsIterator.moveNext();
      } else {
        // We don't have that one: Fill it in
        _fillInSingleParameter(named, newParameterVariableGets, target);
      }
    }
  }

  /// Adds the new member the same place as the existing member
  void _addMember(Member existingMember, Member newMember) {
    if (existingMember.enclosingClass != null) {
      existingMember.enclosingClass.addMember(newMember);
    } else {
      existingMember.enclosingLibrary.addMember(newMember);
    }
  }

  /// Create expressions based on the default values from the given [Member].
  ///
  /// More specifically: static gets and nulls will be "copied" whereas other
  /// things (e.g. literals or things like "a+b") will be moved from the
  /// original member as argument initializers to const fields and both the
  /// original member and the expression-copy will use static gets to these.
  void _fillInPositionalParameters(
      int startFrom, Member copyFrom, List<Expression> fillInto) {
    final targetParameters = copyFrom.function.positionalParameters;
    for (int i = startFrom; i < targetParameters.length; i++) {
      final parameter = targetParameters[i];
      _fillInSingleParameter(parameter, fillInto, copyFrom);
    }
  }

  /// Create expression based on the default values from the given variable.
  ///
  /// More specifically: a static get or null will be "copied" whereas other
  /// things (e.g. literals or things like "a+b") will be moved from the
  /// original member as an argument initializer to a const field and both the
  /// original member and the expression-copy will use a static get to it.
  void _fillInSingleParameter(VariableDeclaration parameter,
      List<Expression> fillInto, Member copyFrom) {
    if (parameter.initializer is StaticGet) {
      // Reference to const => recreate it
      StaticGet staticGet = parameter.initializer;
      fillInto.add(new StaticGet(staticGet.target));
    } else if (parameter.initializer == null) {
      // No default given => output null
      fillInto.add(new NullLiteral());
    } else if (parameter.initializer is IntLiteral) {
      // Int literal => recreate (or else class ByteBuffer in typed_data will
      // get 2 fields and the C++ code will complain!)
      IntLiteral value = parameter.initializer;
      fillInto.add(new IntLiteral(value.value));
    } else {
      // Advanced stuff => move to static const field and reference that
      final initializer = parameter.initializer;
      final f = new Field(
          new Name('${copyFrom.name.name}%_${parameter.name}',
              copyFrom.enclosingLibrary),
          type: parameter.type,
          initializer: initializer,
          isFinal: false,
          isConst: true,
          isStatic: true,
          fileUri: copyFrom.enclosingClass?.fileUri ??
              copyFrom.enclosingLibrary.fileUri);
      initializer.parent = f;

      // Add field to the code
      if (copyFrom.enclosingClass != null) {
        copyFrom.enclosingClass.addMember(f);
      } else {
        copyFrom.enclosingLibrary.addMember(f);
      }

      // Use it at the call site
      fillInto.add(new StaticGet(f));

      // Now replace the initializer in the method to a StaticGet
      parameter.initializer = new StaticGet(f)..parent = parameter;
    }
  }

  /// Create an "original name" for a member.
  ///
  /// Specifically, for a member "x" just returns "x%original";
  Name _createOriginalName(Member member) {
    return new Name("${member.name.name}%original", member.enclosingLibrary);
  }

  /// Create a [Name] based on current name and argument signature.
  Name _createName(Name name, String argumentsSignature) {
    String nameString = '${name.name}%$argumentsSignature';
    return new Name(nameString, name.library);
  }

  /// Is the procedure a method?
  bool _isMethod(Procedure procedure) => procedure.kind == ProcedureKind.Method;

  /// Is the procedure NOT marked as external?
  bool _isNotExternal(Constructor constructor) => !constructor.isExternal;

  /// Does the target function have any optional arguments? (positional/named)
  bool _hasAnyOptionalParameters(FunctionNode targetFunction) =>
      _hasOptionalParameters(targetFunction) ||
      _hasNamedParameters(targetFunction);

  /// Does the target function have optional positional arguments?
  bool _hasOptionalParameters(FunctionNode targetFunction) =>
      targetFunction.positionalParameters.length >
      targetFunction.requiredParameterCount;

  /// Does the target function have named parameters?
  bool _hasNamedParameters(FunctionNode targetFunction) =>
      targetFunction.namedParameters.isNotEmpty;

  bool _callIsLegal(FunctionNode targetFunction, Arguments arguments) {
    if ((targetFunction.requiredParameterCount > arguments.positional.length) ||
        (targetFunction.positionalParameters.length <
            arguments.positional.length)) {
      // Given too few or too many positional arguments
      return false;
    }

    // Do we give named that we don't take?
    Set<String> givenNamed = arguments.named.map((v) => v.name).toSet();
    Set<String> takenNamed =
        targetFunction.namedParameters.map((v) => v.name).toSet();
    givenNamed.removeAll(takenNamed);
    return givenNamed.isEmpty;
  }

  // Below methods used to add debug prints etc

  Library _getDartCoreLibrary(Program program) {
    if (program == null) return null;
    return program.libraries.firstWhere((lib) =>
        lib.importUri.scheme == 'dart' && lib.importUri.path == 'core');
  }

  Procedure _getProcedureInLib(Library lib, String name) {
    if (lib == null) return null;
    return lib.procedures
        .firstWhere((procedure) => procedure.name.name == name);
  }

  Procedure _getProcedureInClassInLib(
      Library lib, String className, String procedureName) {
    if (lib == null) return null;
    Class clazz = lib.classes.firstWhere((clazz) => clazz.name == className);
    return clazz.procedures
        .firstWhere((procedure) => procedure.name.name == procedureName);
  }

  Expression _getPrintExpression(String msg, TreeNode treeNode) {
    TreeNode program = treeNode;
    while (program is! Program) program = program.parent;
    var finalMsg = msg;
    if (treeNode is Member) {
      finalMsg += " [ ${treeNode.name.name} ]";
      if (treeNode.enclosingClass != null) {
        finalMsg += " [ class ${treeNode.enclosingClass.name} ]";
      }
      if (treeNode.enclosingLibrary != null) {
        finalMsg += " [ lib ${treeNode.enclosingLibrary.name} ]";
      }
    }

    var stacktrace = new StaticGet(_getProcedureInClassInLib(
        _getDartCoreLibrary(program), 'StackTrace', 'current'));
    var printStackTrace = new StaticInvocation(
        _getProcedureInLib(_getDartCoreLibrary(program), 'print'),
        new Arguments([
          new StringConcatenation([
            new StringLiteral(finalMsg),
            new StringLiteral("\n"),
            stacktrace,
            new StringLiteral("\n")
          ])
        ]));

    return printStackTrace;
  }
}

class _Pair<K, V> {
  final K key;
  final V value;

  _Pair(this.key, this.value);
}
