// Copyright (c) 2016, 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.md file.

import 'dart:async';
import 'dart:collection' show Queue;

import 'package:kernel/ast.dart' as ir;
import 'package:kernel/verifier.dart' show CheckParentPointers;

import '../common.dart';
import '../common/names.dart';
import '../compiler.dart' show Compiler;
import '../constants/expressions.dart'
    show ConstantExpression, TypeConstantExpression;
import '../dart_types.dart'
    show DartType, FunctionType, InterfaceType, TypeKind, TypeVariableType;
import '../diagnostics/messages.dart' show MessageKind;
import '../diagnostics/spannable.dart' show Spannable;
import '../elements/elements.dart'
    show
        ClassElement,
        ConstructorElement,
        Element,
        ExportElement,
        FieldElement,
        FunctionElement,
        ImportElement,
        LibraryElement,
        LocalFunctionElement,
        MetadataAnnotation,
        MixinApplicationElement,
        TypeVariableElement;
import '../elements/modelx.dart' show ErroneousFieldElementX;
import '../tree/tree.dart' show FunctionExpression, Node;
import 'constant_visitor.dart';
import 'kernel_visitor.dart' show IrFunction, KernelVisitor;

typedef void WorkAction();

class WorkItem {
  final Element element;
  final WorkAction action;

  WorkItem(this.element, this.action);
}

class Kernel {
  final Compiler compiler;

  final Map<LibraryElement, ir.Library> libraries =
      <LibraryElement, ir.Library>{};

  final Map<ClassElement, ir.Class> classes = <ClassElement, ir.Class>{};

  final Map<FunctionElement, ir.Member> functions =
      <FunctionElement, ir.Member>{};

  final Map<LocalFunctionElement, ir.Node> localFunctions =
      <LocalFunctionElement, ir.Node>{};

  final Map<FieldElement, ir.Field> fields = <FieldElement, ir.Field>{};

  final Map<TypeVariableElement, ir.TypeParameter> typeParameters =
      <TypeVariableElement, ir.TypeParameter>{};

  final Map<TypeVariableElement, ir.TypeParameter> factoryTypeParameters =
      <TypeVariableElement, ir.TypeParameter>{};

  final Set<ir.TreeNode> checkedNodes = new Set<ir.TreeNode>();

  final Map<LibraryElement, Map<String, int>> mixinApplicationNamesByLibrary =
      <LibraryElement, Map<String, int>>{};

  final Map<ir.Node, Element> nodeToElement = <ir.Node, Element>{};
  final Map<ir.Node, Node> nodeToAst = <ir.Node, Node>{};
  final Map<ir.Node, Node> nodeToAstOperator = <ir.Node, Node>{};
  // Synthetic nodes are nodes we generated that do not correspond to
  // [ast.Node]s. A node should be in one of nodeToAst or syntheticNodes but not
  // both.
  final Set<ir.Node> syntheticNodes = new Set<ir.Node>();

  final Map<ir.Node, ConstantExpression> parameterInitializerNodeToConstant =
      <ir.Node, ConstantExpression>{};

  /// FIFO queue of work that needs to be completed before the returned AST
  /// nodes are correct.
  final Queue<WorkItem> workQueue = new Queue<WorkItem>();

  Kernel(this.compiler);

  void addWork(Element element, WorkAction action) {
    workQueue.addLast(new WorkItem(element, action));
  }

  void checkMember(Element key, ir.TreeNode value) {
    if (!checkedNodes.add(value)) return;
    if (value.parent == null) {
      internalError(key, "Missing parent on IR node.");
    }
    try {
      CheckParentPointers.check(value);
    } catch (e, s) {
      internalError(key, "$e\n$s");
    }
  }

  void checkLibrary(Element key, ir.Library library) {
    if (!checkedNodes.add(library)) return;
    CheckParentPointers.check(library);
  }

  void processWorkQueue() {
    while (workQueue.isNotEmpty) {
      WorkItem work = workQueue.removeFirst();
      work.action();
    }
    assert(() {
      libraries.forEach(checkLibrary);
      classes.forEach(checkMember);
      functions.forEach(checkMember);
      fields.forEach(checkMember);
      return true;
    });
  }

  ir.Name irName(String name, Element element) {
    ir.Library irLibrary = null;
    if (name.startsWith("_")) {
      ClassElement cls = element.enclosingClass;
      if (cls != null && cls.isMixinApplication) {
        MixinApplicationElement mixinApplication = cls;
        element = mixinApplication.mixin;
      }
      irLibrary = libraryToIr(element.library);
    }
    return new ir.Name(name, irLibrary);
  }

  Future<ir.Library> loadLibrary(Uri uri) async {
    return libraryToIr(await compiler.libraryLoader.loadLibrary(uri));
  }

  ir.Library libraryToIr(LibraryElement library) {
    library = library.declaration;
    return libraries.putIfAbsent(library, () {
      String name = library.hasLibraryName ? library.libraryName : null;
      ir.Library libraryNode = new ir.Library(library.canonicalUri,
          name: name, classes: null, procedures: null, fields: null);
      addWork(library, () {
        Queue<ir.Class> classes = new Queue<ir.Class>();
        Queue<ir.Member> members = new Queue<ir.Member>();
        library.implementation.forEachLocalMember((Element e) {
          if (e.isClass) {
            classes.addFirst(classToIr(e));
          } else if (e.isFunction || e.isAccessor) {
            members.addFirst(functionToIr(e));
          } else if (e.isField) {
            members.addFirst(fieldToIr(e));
          } else if (e.isTypedef) {
            // Ignored, typedefs are unaliased on use.
          } else {
            internalError(e, "Unhandled library member: $e");
          }
        });
        // The elements were inserted in reverse order as forEachLocalMember
        // above gives them in reversed order.
        classes.forEach(libraryNode.addClass);
        members.forEach(libraryNode.addMember);
      });
      return libraryNode;
    });
  }

  /// Compute a name for [cls]. We want to have unique names in a library, but
  /// mixin applications can lead to multiple classes with the same name. So
  /// for those we append `#` and a number.
  String computeName(ClassElement cls) {
    String name = cls.name;
    if (!cls.isUnnamedMixinApplication) return name;
    Map<String, int> mixinApplicationNames = mixinApplicationNamesByLibrary
        .putIfAbsent(cls.library.implementation, () => <String, int>{});
    int count = mixinApplicationNames.putIfAbsent(name, () => 0);
    mixinApplicationNames[name] = count + 1;
    return "$name#$count";
  }

  ir.Class classToIr(ClassElement cls) {
    cls = cls.declaration;
    return classes.putIfAbsent(cls, () {
      cls.ensureResolved(compiler.resolution);
      compiler.enqueuer.resolution.emptyDeferredQueueForTesting();
      String name = computeName(cls);
      ir.Class classNode = new ir.Class(
          name: name,
          isAbstract: cls.isAbstract,
          typeParameters: null,
          implementedTypes: null,
          constructors: null,
          procedures: null,
          fields: null);
      addWork(cls, () {
        if (cls.supertype != null) {
          classNode.supertype = supertypeToIr(cls.supertype);
        }
        if (cls.isMixinApplication) {
          MixinApplicationElement mixinApplication = cls;
          classNode.mixedInType = supertypeToIr(mixinApplication.mixinType);
        }
        classNode.parent = libraryToIr(cls.library);
        if (cls.isUnnamedMixinApplication) {
          classNode.enclosingLibrary.addClass(classNode);
        }
        cls.implementation
            .forEachMember((ClassElement enclosingClass, Element member) {
          if (member.enclosingClass.declaration != cls) {
            // TODO(het): figure out why impact_test triggers this
            //internalError(cls, "`$member` isn't mine.");
          } else if (member.isConstructor) {
            ConstructorElement constructor = member;
            ir.Member memberNode = functionToIr(member);
            if (!constructor.isRedirectingFactory) {
              classNode.addMember(memberNode);
            }
          } else if (member.isFunction || member.isAccessor) {
            classNode.addMember(functionToIr(member));
          } else if (member.isField) {
            classNode.addMember(fieldToIr(member));
          } else {
            internalError(member, "Unhandled class member: $member");
          }
        });
        classNode.typeParameters.addAll(typeVariablesToIr(cls.typeVariables));
        for (ir.Supertype supertype
            in supertypesToIr(cls.interfaces.reverse().toList())) {
          if (supertype != classNode.mixedInType) {
            classNode.implementedTypes.add(supertype);
          }
        }
        addWork(cls, () {
          addDefaultInstanceFieldInitializers(classNode);
        });
      });
      addWork(cls.declaration, () {
        for (MetadataAnnotation metadata in cls.declaration.metadata) {
          classNode.addAnnotation(
              const ConstantVisitor().visit(metadata.constant, this));
        }
      });
      return classNode;
    });
  }

  /// Adds initializers to instance fields that are have no initializer and are
  /// not initialized by all constructors in the class.
  ///
  /// This is more or less copied directly from `ast_from_analyzer.dart` in
  /// dartk.
  void addDefaultInstanceFieldInitializers(ir.Class node) {
    List<ir.Field> uninitializedFields = new List<ir.Field>();
    for (ir.Field field in node.fields) {
      if (field.initializer != null || field.isStatic) continue;
      uninitializedFields.add(field);
    }
    if (uninitializedFields.isEmpty) return;
    constructorLoop:
    for (ir.Constructor constructor in node.constructors) {
      Set<ir.Field> remainingFields = uninitializedFields.toSet();
      for (ir.Initializer initializer in constructor.initializers) {
        if (initializer is ir.FieldInitializer) {
          remainingFields.remove(initializer.field);
        } else if (initializer is ir.RedirectingInitializer) {
          // The target constructor will be checked in another iteration.
          continue constructorLoop;
        }
      }
      for (ir.Field field in remainingFields) {
        if (field.initializer == null) {
          field.initializer = new ir.NullLiteral()..parent = field;
        }
      }
    }
  }

  bool hasHierarchyProblem(ClassElement cls) => cls.hasIncompleteHierarchy;

  ir.InterfaceType interfaceTypeToIr(InterfaceType type) {
    ir.Class cls = classToIr(type.element);
    if (type.typeArguments.isEmpty) {
      return cls.rawType;
    } else {
      return new ir.InterfaceType(cls, typesToIr(type.typeArguments));
    }
  }

  ir.Supertype supertypeToIr(InterfaceType type) {
    ir.Class cls = classToIr(type.element);
    if (type.typeArguments.isEmpty) {
      return cls.asRawSupertype;
    } else {
      return new ir.Supertype(cls, typesToIr(type.typeArguments));
    }
  }

  // TODO(ahe): Remove this method when dart2js support generic type arguments.
  List<ir.TypeParameter> typeParametersNotImplemented() {
    return const <ir.TypeParameter>[];
  }

  ir.FunctionType functionTypeToIr(FunctionType type) {
    List<ir.TypeParameter> typeParameters = typeParametersNotImplemented();
    int requiredParameterCount = type.parameterTypes.length;
    List<ir.DartType> positionalParameters =
        new List<ir.DartType>.from(typesToIr(type.parameterTypes))
          ..addAll(typesToIr(type.optionalParameterTypes));
    List<ir.NamedType> namedParameters = new List<ir.NamedType>.generate(
        type.namedParameters.length,
        (i) => new ir.NamedType(
            type.namedParameters[i], typeToIr(type.namedParameterTypes[i])));
    ir.DartType returnType = typeToIr(type.returnType);

    return new ir.FunctionType(positionalParameters, returnType,
        namedParameters: namedParameters,
        typeParameters: typeParameters,
        requiredParameterCount: requiredParameterCount);
  }

  ir.TypeParameterType typeVariableTypeToIr(TypeVariableType type) {
    return new ir.TypeParameterType(typeVariableToIr(type.element));
  }

  List<ir.DartType> typesToIr(List<DartType> types) {
    List<ir.DartType> result = new List<ir.DartType>(types.length);
    for (int i = 0; i < types.length; i++) {
      result[i] = typeToIr(types[i]);
    }
    return result;
  }

  List<ir.Supertype> supertypesToIr(List<DartType> types) {
    List<ir.Supertype> result = new List<ir.Supertype>(types.length);
    for (int i = 0; i < types.length; i++) {
      result[i] = supertypeToIr(types[i]);
    }
    return result;
  }

  ir.DartType typeToIr(DartType type) {
    switch (type.kind) {
      case TypeKind.FUNCTION:
        return functionTypeToIr(type);

      case TypeKind.INTERFACE:
        return interfaceTypeToIr(type);

      case TypeKind.STATEMENT:
        throw "Internal error: statement type: $type.";

      case TypeKind.TYPEDEF:
        type.computeUnaliased(compiler.resolution);
        return typeToIr(type.unaliased);

      case TypeKind.TYPE_VARIABLE:
        return typeVariableTypeToIr(type);

      case TypeKind.MALFORMED_TYPE:
        return const ir.InvalidType();

      case TypeKind.DYNAMIC:
        return const ir.DynamicType();

      case TypeKind.VOID:
        return const ir.VoidType();
    }
  }

  ir.DartType typeLiteralToIr(TypeConstantExpression constant) {
    return typeToIr(constant.type);
  }

  void setParent(ir.Member member, Element element) {
    if (element.isLocal) {
      member.parent = elementToIr(element.enclosingElement);
    } else if (element.isTopLevel) {
      member.parent = elementToIr(element.library);
    } else if (element.isClassMember) {
      member.parent = elementToIr(element.enclosingClass);
    } else {
      member.parent = elementToIr(element.enclosingElement);
    }
  }

  bool isNativeMethod(FunctionElement element) {
    // This method is a (modified) copy of the same method in
    // `pkg/compiler/lib/src/native/enqueue.dart`.
    if (!compiler.backend.canLibraryUseNative(element.library)) return false;
    return compiler.reporter.withCurrentElement(element, () {
      FunctionExpression functionExpression =
          element.node?.asFunctionExpression();
      if (functionExpression == null) return false;
      Node body = functionExpression.body;
      if (body == null) return false;
      if (identical(body.getBeginToken().stringValue, 'native')) return true;
      return false;
    });
  }

  ir.Member functionToIr(FunctionElement function) {
    if (function.isDeferredLoaderGetter) {
      internalError(function, "Deferred loader.");
    }
    if (function.isLocal) {
      internalError(function, "Local function.");
    }
    if (isSyntheticError(function)) {
      internalError(function, "Synthetic error function: $function.");
    }
    function = function.declaration;
    return functions.putIfAbsent(function, () {
      compiler.resolution.ensureResolved(function);
      compiler.enqueuer.resolution.emptyDeferredQueueForTesting();
      function = function.implementation;
      ir.Member member;
      ir.Constructor constructor;
      ir.Procedure procedure;
      ir.Name name = irName(function.name, function);
      bool isNative = isNativeMethod(function);
      if (function.isGenerativeConstructor) {
        member = constructor = new ir.Constructor(null,
            name: name,
            isConst: function.isConst,
            isExternal: isNative || function.isExternal,
            initializers: null);
      } else {
        member = procedure = new ir.Procedure(name, null, null,
            isAbstract: function.isAbstract,
            isStatic: function.isStatic ||
                function.isTopLevel ||
                function.isFactoryConstructor,
            isExternal: isNative || function.isExternal,
            isConst: false); // TODO(ahe): When is this true?
      }
      addWork(function, () {
        setParent(member, function);
        KernelVisitor visitor =
            new KernelVisitor(function, function.treeElements, this);
        beginFactoryScope(function);
        IrFunction irFunction = visitor.buildFunction();
        // TODO(ahe): Add addFunction/set function to [ir.Procedure].
        irFunction.node.parent = member;
        if (irFunction.isConstructor) {
          assert(irFunction.kind == null);
          constructor.function = irFunction.node;
          constructor.initializers = irFunction.initializers;
          // TODO(ahe): Add setInitializers to [ir.Constructor].
          for (ir.Initializer initializer in irFunction.initializers) {
            initializer.parent = constructor;
          }
        } else {
          assert(irFunction.kind != null);
          procedure.function = irFunction.node;
          procedure.kind = irFunction.kind;
        }
        endFactoryScope(function);
        member.transformerFlags = visitor.transformerFlags;
        assert(() {
          visitor.locals.forEach(checkMember);
          return true;
        });
      });
      addWork(function.declaration, () {
        for (MetadataAnnotation metadata in function.declaration.metadata) {
          member.addAnnotation(
              const ConstantVisitor().visit(metadata.constant, this));
        }
      });
      return member;
    });
  }

  /// Adds the type parameters of the enclosing class of [function] to
  /// [factoryTypeParameters]. This serves as a local scope for type variables
  /// resolved inside the factory.
  ///
  /// This method solves the problem that a factory method really is a generic
  /// method that has its own type parameters, one for each type parameter in
  /// the enclosing class.
  void beginFactoryScope(FunctionElement function) {
    assert(factoryTypeParameters.isEmpty);
    if (!function.isFactoryConstructor) return;
    ClassElement cls = function.enclosingClass;
    for (DartType type in cls.typeVariables) {
      if (type.isTypeVariable) {
        TypeVariableElement variable = type.element;
        factoryTypeParameters[variable] =
            new ir.TypeParameter(variable.name, null);
      }
    }
    for (DartType type in cls.typeVariables) {
      if (type.isTypeVariable) {
        TypeVariableElement variable = type.element;
        factoryTypeParameters[variable].bound = typeToIr(variable.bound);
      }
    }
  }

  /// Ends the local scope started by [beginFactoryScope].
  void endFactoryScope(FunctionElement function) {
    factoryTypeParameters.clear();
  }

  ir.Field fieldToIr(FieldElement field) {
    if (isSyntheticError(field)) {
      internalError(field, "Synthetic error field: $field.");
    }
    field = field.declaration;
    return fields.putIfAbsent(field, () {
      compiler.resolution.ensureResolved(field);
      compiler.enqueuer.resolution.emptyDeferredQueueForTesting();
      field = field.implementation;
      ir.DartType type =
          field.isMalformed ? const ir.InvalidType() : typeToIr(field.type);
      ir.Field fieldNode = new ir.Field(irName(field.memberName.text, field),
          type: type,
          initializer: null,
          isFinal: field.isFinal,
          isStatic: field.isStatic || field.isTopLevel,
          isConst: field.isConst);
      addWork(field, () {
        setParent(fieldNode, field);
        if (!field.isMalformed) {
          if (field.initializer != null) {
            KernelVisitor visitor =
                new KernelVisitor(field, field.treeElements, this);
            fieldNode.initializer = visitor.buildInitializer()
              ..parent = fieldNode;
          } else if (!field.isInstanceMember) {
            fieldNode.initializer = new ir.NullLiteral()..parent = fieldNode;
          }
        }
      });
      addWork(field.declaration, () {
        for (MetadataAnnotation metadata in field.declaration.metadata) {
          fieldNode.addAnnotation(
              const ConstantVisitor().visit(metadata.constant, this));
        }
      });
      return fieldNode;
    });
  }

  ir.TypeParameter typeVariableToIr(TypeVariableElement variable) {
    variable = variable.declaration;
    ir.TypeParameter parameter = factoryTypeParameters[variable];
    if (parameter != null) return parameter;
    return typeParameters.putIfAbsent(variable, () {
      ir.TypeParameter parameter = new ir.TypeParameter(variable.name, null);
      addWork(variable, () {
        // TODO(ahe): This assignment will probably not be correct when dart2js
        // supports generic methods.
        ClassElement cls = variable.typeDeclaration;
        cls.ensureResolved(compiler.resolution);
        parameter.parent = classToIr(cls);
        parameter.bound = typeToIr(variable.bound);
      });
      return parameter;
    });
  }

  List<ir.TypeParameter> typeVariablesToIr(List<DartType> variables) {
    List<ir.TypeParameter> result =
        new List<ir.TypeParameter>(variables.length);
    for (int i = 0; i < variables.length; i++) {
      TypeVariableType type = variables[i];
      result[i] = typeVariableToIr(type.element);
    }
    return result;
  }

  ir.TreeNode elementToIr(Element element) {
    if (element.isLibrary) return libraryToIr(element);
    if (element.isClass) return classToIr(element);
    if (element.isFunction || element.isAccessor) return functionToIr(element);
    if (element.isField) return fieldToIr(element);
    throw "unhandled element: $element";
  }

  void debugMessage(Spannable spannable, String message) {
    compiler.reporter
        .reportHintMessage(spannable, MessageKind.GENERIC, {'text': message});
  }

  void internalError(Spannable spannable, String message) {
    compiler.reporter.internalError(spannable, message);
    throw message;
  }

  forEachLibraryElement(f(LibraryElement library)) {
    return compiler.libraryLoader.libraries.forEach(f);
  }

  ConstructorTarget computeEffectiveTarget(
      ConstructorElement constructor, DartType type) {
    constructor = constructor.implementation;
    Set<ConstructorElement> seen = new Set<ConstructorElement>();
    functionToIr(constructor);
    while (constructor != constructor.effectiveTarget) {
      type = constructor.computeEffectiveTargetType(type);
      if (constructor.isGenerativeConstructor) break;
      if (!seen.add(constructor)) break;
      constructor = constructor.effectiveTarget.implementation;
      if (isSyntheticError(constructor)) break;
      functionToIr(constructor);
    }
    return new ConstructorTarget(constructor, type);
  }

  /// Compute all the dependencies on the library with [uri] (including the
  /// library itself). This is useful for creating a Kernel IR `Program`.
  List<ir.Library> libraryDependencies(Uri uri) {
    List<ir.Library> result = <ir.Library>[];
    Queue<LibraryElement> notProcessed = new Queue<LibraryElement>();
    Set<LibraryElement> seen = new Set<LibraryElement>();
    LibraryElement library = compiler.libraryLoader.lookupLibrary(uri);
    void processLater(LibraryElement library) {
      if (library != null) {
        notProcessed.addLast(library);
      }
    }

    processLater(library);
    seen.add(library);
    LibraryElement core =
        compiler.libraryLoader.lookupLibrary(Uri.parse("dart:core"));
    if (seen.add(core)) {
      // `dart:core` is implicitly imported by most libraries, and for some
      // reason not included in `library.imports` below.
      processLater(core);
    }
    while (notProcessed.isNotEmpty) {
      LibraryElement library = notProcessed.removeFirst();
      ir.Library irLibrary = libraryToIr(library);
      for (ImportElement import in library.imports) {
        if (seen.add(import.importedLibrary)) {
          processLater(import.importedLibrary);
        }
      }
      for (ExportElement export in library.exports) {
        if (seen.add(export.exportedLibrary)) {
          processLater(export.exportedLibrary);
        }
      }
      for (ImportElement import in library.implementation.imports) {
        if (seen.add(import.importedLibrary)) {
          processLater(import.importedLibrary);
        }
      }
      for (ExportElement export in library.implementation.exports) {
        if (seen.add(export.exportedLibrary)) {
          processLater(export.exportedLibrary);
        }
      }
      if (irLibrary != null) {
        result.add(irLibrary);
      }
    }
    processWorkQueue();
    return result;
  }

  /// Returns true if [element] is synthesized to recover or represent a
  /// semantic error, for example, missing, duplicated, or ambiguous elements.
  /// However, returns false for elements that have an unrecoverable syntax
  /// error. Both kinds of element will return true from [Element.isMalformed],
  /// but they must be handled differently. For example, a static call to
  /// synthetic error element should be compiled to [ir.InvalidExpression],
  /// whereas a static call to a method which has a syntax error should be
  /// compiled to a static call to the method. The method itself will have a
  /// method body that is [ir.InvalidStatement].
  bool isSyntheticError(Element element) {
    if (element.isAmbiguous) return true;
    if (element.isError) return true;
    if (element.isField && element is ErroneousFieldElementX) {
      return true;
    }
    return false;
  }

  ir.Constructor getDartCoreConstructor(
      String className, String constructorName) {
    LibraryElement library =
        compiler.libraryLoader.lookupLibrary(Uris.dart_core);
    ClassElement cls = library.implementation.localLookup(className);
    assert(invariant(CURRENT_ELEMENT_SPANNABLE, cls != null,
        message: 'dart:core class $className not found.'));
    ConstructorElement constructor = cls.lookupConstructor(constructorName);
    assert(invariant(CURRENT_ELEMENT_SPANNABLE, constructor != null,
        message: "Constructor '$constructorName' not found "
            "in class '$className'."));
    return functionToIr(constructor);
  }

  ir.Procedure getDartCoreMethod(String name) {
    LibraryElement library =
        compiler.libraryLoader.lookupLibrary(Uris.dart_core);
    Element function = library.implementation.localLookup(name);
    assert(invariant(CURRENT_ELEMENT_SPANNABLE, function != null,
        message: "dart:core method '$name' not found."));
    return functionToIr(function);
  }

  ir.Procedure getMalformedTypeErrorBuilder() {
    return getDartCoreMethod('_malformedTypeError');
  }

  ir.Procedure getUnresolvedConstructorBuilder() {
    return getDartCoreMethod('_unresolvedConstructorError');
  }

  ir.Procedure getUnresolvedStaticGetterBuilder() {
    return getDartCoreMethod('_unresolvedStaticGetterError');
  }

  ir.Procedure getUnresolvedStaticSetterBuilder() {
    return getDartCoreMethod('_unresolvedStaticSetterError');
  }

  ir.Procedure getUnresolvedStaticMethodBuilder() {
    return getDartCoreMethod('_unresolvedStaticMethodError');
  }

  ir.Procedure getUnresolvedTopLevelGetterBuilder() {
    return getDartCoreMethod('_unresolvedTopLevelGetterError');
  }

  ir.Procedure getUnresolvedTopLevelSetterBuilder() {
    return getDartCoreMethod('_unresolvedTopLevelSetterError');
  }

  ir.Procedure getUnresolvedTopLevelMethodBuilder() {
    return getDartCoreMethod('_unresolvedTopLevelMethodError');
  }

  ir.Procedure getUnresolvedSuperGetterBuilder() {
    return getDartCoreMethod('_unresolvedSuperGetterError');
  }

  ir.Procedure getUnresolvedSuperSetterBuilder() {
    return getDartCoreMethod('_unresolvedSuperSetterError');
  }

  ir.Procedure getUnresolvedSuperMethodBuilder() {
    return getDartCoreMethod('_unresolvedSuperMethodError');
  }

  ir.Procedure getGenericNoSuchMethodBuilder() {
    return getDartCoreMethod('_genericNoSuchMethod');
  }

  ir.Constructor getFallThroughErrorConstructor() {
    return getDartCoreConstructor('FallThroughError', '');
  }
}

class ConstructorTarget {
  final ConstructorElement element;
  final DartType type;

  ConstructorTarget(this.element, this.type);

  String toString() => "ConstructorTarget($element, $type)";
}
