// Copyright (c) 2012, 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 dart2js.compiler_base;

import 'dart:async' show
    EventSink,
    Future;

import '../compiler_new.dart' as api;
import 'cache_strategy.dart' show
    CacheStrategy;
import 'closure.dart' as closureMapping show
    ClosureTask;
import 'common.dart';
import 'common/backend_api.dart' show
    Backend;
import 'common/codegen.dart' show
    CodegenImpact,
    CodegenWorkItem;
import 'common/names.dart' show
    Identifiers,
    Uris;
import 'common/registry.dart' show
    EagerRegistry,
    Registry;
import 'common/resolution.dart' show
    Parsing,
    Resolution,
    ResolutionWorkItem,
    ResolutionImpact;
import 'common/tasks.dart' show
    CompilerTask,
    GenericTask;
import 'common/work.dart' show
    ItemCompilationContext,
    WorkItem;
import 'compile_time_constants.dart';
import 'constants/values.dart';
import 'core_types.dart' show
    CoreClasses,
    CoreTypes;
import 'dart_backend/dart_backend.dart' as dart_backend;
import 'dart_types.dart' show
    DartType,
    DynamicType,
    InterfaceType,
    Types;
import 'deferred_load.dart' show DeferredLoadTask, OutputUnit;
import 'diagnostics/code_location.dart';
import 'diagnostics/diagnostic_listener.dart' show
    DiagnosticReporter;
import 'diagnostics/invariant.dart' show
    REPORT_EXCESS_RESOLUTION;
import 'diagnostics/messages.dart' show
    Message,
    MessageTemplate;
import 'dump_info.dart' show
    DumpInfoTask;
import 'elements/elements.dart';
import 'elements/modelx.dart' show
    ErroneousElementX,
    ClassElementX,
    CompilationUnitElementX,
    DeferredLoaderGetterElementX,
    MethodElementX,
    LibraryElementX,
    PrefixElementX;
import 'enqueue.dart' show
    CodegenEnqueuer,
    Enqueuer,
    EnqueueTask,
    ResolutionEnqueuer,
    QueueFilter;
import 'environment.dart';
import 'io/source_information.dart' show
    SourceInformation;
import 'js_backend/backend_helpers.dart' as js_backend show
    BackendHelpers;
import 'js_backend/js_backend.dart' as js_backend show
    JavaScriptBackend;
import 'library_loader.dart' show
    ElementScanner,
    LibraryLoader,
    LibraryLoaderTask,
    LoadedLibraries,
    LibraryLoaderListener,
    ResolvedUriTranslator,
    ScriptLoader;
import 'mirrors_used.dart' show
    MirrorUsageAnalyzerTask;
import 'common/names.dart' show
    Selectors;
import 'null_compiler_output.dart' show
    NullCompilerOutput,
    NullSink;
import 'options.dart' show
    CompilerOptions,
    DiagnosticOptions,
    ParserOptions;
import 'parser/diet_parser_task.dart' show
    DietParserTask;
import 'parser/element_listener.dart' show
    ScannerOptions;
import 'parser/parser_task.dart' show
    ParserTask;
import 'patch_parser.dart' show
    PatchParserTask;
import 'resolution/registry.dart' show
    ResolutionRegistry;
import 'resolution/resolution.dart' show
    ResolverTask;
import 'resolution/tree_elements.dart' show
    TreeElementMapping;
import 'scanner/scanner_task.dart' show
    ScannerTask;
import 'serialization/task.dart' show
    SerializationTask;
import 'script.dart' show
    Script;
import 'ssa/nodes.dart' show
    HInstruction;
import 'tracer.dart' show
    Tracer;
import 'tokens/token.dart' show
    StringToken,
    Token,
    TokenPair;
import 'tokens/token_constants.dart' as Tokens show
    COMMENT_TOKEN,
    EOF_TOKEN;
import 'tokens/token_map.dart' show
    TokenMap;
import 'tree/tree.dart' show
    Node,
    TypeAnnotation;
import 'typechecker.dart' show
    TypeCheckerTask;
import 'types/types.dart' as ti;
import 'universe/call_structure.dart' show
    CallStructure;
import 'universe/selector.dart' show
    Selector;
import 'universe/universe.dart' show
    Universe;
import 'universe/use.dart' show
    StaticUse;
import 'universe/world_impact.dart' show
    ImpactStrategy,
    WorldImpact;
import 'util/util.dart' show
    Link,
    Setlet;
import 'world.dart' show
    World;

abstract class Compiler implements LibraryLoaderListener {

  final Stopwatch totalCompileTime = new Stopwatch();
  int nextFreeClassId = 0;
  World world;
  Types types;
  _CompilerCoreTypes _coreTypes;
  _CompilerDiagnosticReporter _reporter;
  _CompilerResolution _resolution;
  _CompilerParsing _parsing;

  final CacheStrategy cacheStrategy;

  ImpactStrategy impactStrategy = const ImpactStrategy();

  /**
   * Map from token to the first preceding comment token.
   */
  final TokenMap commentMap = new TokenMap();

  /**
   * Records global dependencies, that is, dependencies that don't
   * correspond to a particular element.
   *
   * We should get rid of this and ensure that all dependencies are
   * associated with a particular element.
   */
  GlobalDependencyRegistry globalDependencies;

  /**
   * Dependencies that are only included due to mirrors.
   *
   * We should get rid of this and ensure that all dependencies are
   * associated with a particular element.
   */
  // TODO(johnniwinther): This should not be a [ResolutionRegistry].
  final Registry mirrorDependencies =
      new ResolutionRegistry(null, new TreeElementMapping(null));

  /// Options provided from command-line arguments.
  final CompilerOptions options;

  /**
   * If true, stop compilation after type inference is complete. Used for
   * debugging and testing purposes only.
   */
  bool stopAfterTypeInference = false;

  /// Output provider from user of Compiler API.
  api.CompilerOutput userOutputProvider;

  List<Uri> librariesToAnalyzeWhenRun;

  /// The set of platform libraries reported as unsupported.
  ///
  /// For instance when importing 'dart:io' without '--categories=Server'.
  Set<Uri> disallowedLibraryUris = new Setlet<Uri>();

  Tracer tracer;

  CompilerTask measuredTask;
  LibraryElement coreLibrary;
  LibraryElement asyncLibrary;

  LibraryElement mainApp;
  FunctionElement mainFunction;

  /// Initialized when dart:mirrors is loaded.
  LibraryElement mirrorsLibrary;

  /// Initialized when dart:typed_data is loaded.
  LibraryElement typedDataLibrary;

  DiagnosticReporter get reporter => _reporter;
  CoreClasses get coreClasses => _coreTypes;
  CoreTypes get coreTypes => _coreTypes;
  Resolution get resolution => _resolution;
  Parsing get parsing => _parsing;

  ClassElement typedDataClass;

  /// The constant for the [proxy] variable defined in dart:core.
  ConstantValue proxyConstant;

  // TODO(johnniwinther): Move this to the JavaScriptBackend.
  /// The class for patch annotation defined in dart:_js_helper.
  ClassElement patchAnnotationClass;

  // TODO(johnniwinther): Move this to the JavaScriptBackend.
  ClassElement nativeAnnotationClass;

  // Initialized after symbolClass has been resolved.
  FunctionElement symbolConstructor;

  // Initialized when dart:mirrors is loaded.
  ClassElement mirrorSystemClass;

  // Initialized when dart:mirrors is loaded.
  ClassElement mirrorsUsedClass;

  // Initialized after mirrorSystemClass has been resolved.
  FunctionElement mirrorSystemGetNameFunction;

  // Initialized when dart:_internal is loaded.
  ClassElement symbolImplementationClass;

  // Initialized when symbolImplementationClass has been resolved.
  // TODO(johnniwinther): Move this to [BackendHelpers].
  FunctionElement symbolValidatedConstructor;

  // Initialized when mirrorsUsedClass has been resolved.
  FunctionElement mirrorsUsedConstructor;

  // Initialized when dart:mirrors is loaded.
  ClassElement deferredLibraryClass;

  /// Document class from dart:mirrors.
  ClassElement documentClass;
  Element identicalFunction;
  Element loadLibraryFunction;
  Element functionApplyMethod;

  /// The [int.fromEnvironment] constructor.
  ConstructorElement intEnvironment;

  /// The [bool.fromEnvironment] constructor.
  ConstructorElement boolEnvironment;

  /// The [String.fromEnvironment] constructor.
  ConstructorElement stringEnvironment;

  /// Tracks elements with compile-time errors.
  final Set<Element> elementsWithCompileTimeErrors = new Set<Element>();

  final Environment environment;
  // TODO(sigmund): delete once we migrate the rest of the compiler to use
  // `environment` directly.
  @deprecated
  fromEnvironment(String name) => environment.valueOf(name);

  Element get currentElement => _reporter.currentElement;

  List<CompilerTask> tasks;
  ScannerTask scanner;
  DietParserTask dietParser;
  ParserTask parser;
  PatchParserTask patchParser;
  LibraryLoaderTask libraryLoader;
  SerializationTask serialization;
  ResolverTask resolver;
  closureMapping.ClosureTask closureToClassMapper;
  TypeCheckerTask checker;
  ti.TypesTask typesTask;
  Backend backend;

  GenericTask reuseLibraryTask;

  /// The constant environment for the frontend interpretation of compile-time
  /// constants.
  ConstantEnvironment constants;

  EnqueueTask enqueuer;
  DeferredLoadTask deferredLoadTask;
  MirrorUsageAnalyzerTask mirrorUsageAnalyzerTask;
  DumpInfoTask dumpInfoTask;

  /// A customizable filter that is applied to enqueued work items.
  QueueFilter enqueuerFilter = new QueueFilter();

  final Selector symbolValidatedConstructorSelector = new Selector.call(
      const PublicName('validated'), CallStructure.ONE_ARG);

  static const String CREATE_INVOCATION_MIRROR =
      'createInvocationMirror';

  bool enabledRuntimeType = false;
  bool enabledFunctionApply = false;
  bool enabledInvokeOn = false;
  bool hasIsolateSupport = false;

  bool get hasCrashed => _reporter.hasCrashed;

  Stopwatch progress;

  bool get shouldPrintProgress {
    return options.verbose && progress.elapsedMilliseconds > 500;
  }

  static const int PHASE_SCANNING = 0;
  static const int PHASE_RESOLVING = 1;
  static const int PHASE_DONE_RESOLVING = 2;
  static const int PHASE_COMPILING = 3;
  int phase;

  bool compilationFailedInternal = false;

  bool get compilationFailed => compilationFailedInternal;

  void set compilationFailed(bool value) {
    if (value) {
      elementsWithCompileTimeErrors.add(currentElement);
    }
    compilationFailedInternal = value;
  }

  Compiler({CompilerOptions options,
            api.CompilerOutput outputProvider,
            this.environment: const _EmptyEnvironment()})
      : this.options = options,
        this.cacheStrategy = new CacheStrategy(options.hasIncrementalSupport),
        this.userOutputProvider = outputProvider == null
            ? const NullCompilerOutput() : outputProvider {
    world = new World(this);
    // TODO(johnniwinther): Initialize core types in [initializeCoreClasses] and
    // make its field final.
    _reporter = new _CompilerDiagnosticReporter(this, options);
    _parsing = new _CompilerParsing(this);
    _resolution = new _CompilerResolution(this);
    _coreTypes = new _CompilerCoreTypes(_resolution);
    types = new Types(_resolution);
    tracer = new Tracer(this, this.outputProvider);

    if (options.verbose) {
      progress = new Stopwatch()..start();
    }

    // TODO(johnniwinther): Separate the dependency tracking from the enqueuing
    // for global dependencies.
    globalDependencies = new GlobalDependencyRegistry(this);

    if (options.emitJavaScript) {
      js_backend.JavaScriptBackend jsBackend =
          new js_backend.JavaScriptBackend(
              this, generateSourceMap: options.generateSourceMap,
              useStartupEmitter: options.useStartupEmitter,
              useNewSourceInfo: options.useNewSourceInfo);
      backend = jsBackend;
    } else {
      backend = new dart_backend.DartBackend(this, options.strips,
          multiFile: options.dart2dartMultiFile);
      if (options.dumpInfo) {
        throw new ArgumentError('--dump-info is not supported for dart2dart.');
      }
    }

    tasks = [
      dietParser = new DietParserTask(this, parsing.parserOptions),
      scanner = createScannerTask(),
      serialization = new SerializationTask(this),
      libraryLoader = new LibraryLoaderTask(this,
          new _ResolvedUriTranslator(this),
          new _ScriptLoader(this),
          new _ElementScanner(scanner),
          this.serialization,
          this,
          environment),
      parser = new ParserTask(this, parsing.parserOptions),
      patchParser = new PatchParserTask(this, parsing.parserOptions),
      resolver = createResolverTask(),
      closureToClassMapper = new closureMapping.ClosureTask(this),
      checker = new TypeCheckerTask(this),
      typesTask = new ti.TypesTask(this),
      constants = backend.constantCompilerTask,
      deferredLoadTask = new DeferredLoadTask(this),
      mirrorUsageAnalyzerTask = new MirrorUsageAnalyzerTask(this),
      enqueuer = new EnqueueTask(this),
      dumpInfoTask = new DumpInfoTask(this),
      reuseLibraryTask = new GenericTask('Reuse library', this),
    ];

    tasks.addAll(backend.tasks);
  }

  /// Creates the scanner task.
  ///
  /// Override this to mock the scanner for testing.
  ScannerTask createScannerTask() => new ScannerTask(this);

  /// Creates the resolver task.
  ///
  /// Override this to mock the resolver for testing.
  ResolverTask createResolverTask() {
    return new ResolverTask(this, backend.constantCompilerTask);
  }

  Universe get resolverWorld => enqueuer.resolution.universe;
  Universe get codegenWorld => enqueuer.codegen.universe;

  bool get analyzeAll => options.analyzeAll || compileAll;

  bool get compileAll => false;

  bool get disableTypeInference =>
      options.disableTypeInference || compilationFailed;

  int getNextFreeClassId() => nextFreeClassId++;

  void unimplemented(Spannable spannable, String methodName) {
    reporter.internalError(spannable, "$methodName not implemented.");
  }

  // Compiles the dart script at [uri].
  //
  // The resulting future will complete with true if the compilation
  // succeded.
  Future<bool> run(Uri uri) {
    totalCompileTime.start();

    return new Future.sync(() => runInternal(uri))
        .catchError((error) => _reporter.onError(uri, error))
        .whenComplete(() {
      tracer.close();
      totalCompileTime.stop();
    }).then((_) {
      return !compilationFailed;
    });
  }

  /// This method is called immediately after the [LibraryElement] [library] has
  /// been created.
  ///
  /// Use this callback method to store references to specific libraries.
  /// Note that [library] has not been scanned yet, nor has its imports/exports
  /// been resolved.
  void onLibraryCreated(LibraryElement library) {
    Uri uri = library.canonicalUri;
    if (uri == Uris.dart_core) {
      coreLibrary = library;
    } else if (uri == Uris.dart__native_typed_data) {
      typedDataLibrary = library;
    } else if (uri == Uris.dart_mirrors) {
      mirrorsLibrary = library;
    }
    backend.onLibraryCreated(library);
  }

  /// This method is called immediately after the [library] and its parts have
  /// been scanned.
  ///
  /// Use this callback method to store references to specific member declared
  /// in certain libraries. Note that [library] has not been patched yet, nor
  /// has its imports/exports been resolved.
  ///
  /// Use [loader] to register the creation and scanning of a patch library
  /// for [library].
  Future onLibraryScanned(LibraryElement library, LibraryLoader loader) {
    Uri uri = library.canonicalUri;
    if (uri == Uris.dart_core) {
      initializeCoreClasses();
      identicalFunction = coreLibrary.find('identical');
    } else if (uri == Uris.dart__internal) {
      symbolImplementationClass = findRequiredElement(library, 'Symbol');
    } else if (uri == Uris.dart_mirrors) {
      mirrorSystemClass = findRequiredElement(library, 'MirrorSystem');
      mirrorsUsedClass = findRequiredElement(library, 'MirrorsUsed');
    } else if (uri == Uris.dart_async) {
      asyncLibrary = library;
      deferredLibraryClass = findRequiredElement(library, 'DeferredLibrary');
      _coreTypes.futureClass = findRequiredElement(library, 'Future');
      _coreTypes.streamClass = findRequiredElement(library, 'Stream');
    } else if (uri == Uris.dart__native_typed_data) {
      typedDataClass = findRequiredElement(library, 'NativeTypedData');
    } else if (uri == js_backend.BackendHelpers.DART_JS_HELPER) {
      patchAnnotationClass = findRequiredElement(library, '_Patch');
      nativeAnnotationClass = findRequiredElement(library, 'Native');
    }
    return backend.onLibraryScanned(library, loader);
  }

  /// Compute the set of distinct import chains to the library at [uri] within
  /// [loadedLibraries].
  ///
  /// The chains are strings of the form
  ///
  ///       <main-uri> => <intermediate-uri1> => <intermediate-uri2> => <uri>
  ///
  Set<String> computeImportChainsFor(LoadedLibraries loadedLibraries, Uri uri) {
    // TODO(johnniwinther): Move computation of dependencies to the library
    // loader.
    Uri rootUri = loadedLibraries.rootUri;
    Set<String> importChains = new Set<String>();
    // The maximum number of full imports chains to process.
    final int chainLimit = 10000;
    // The maximum number of imports chains to show.
    final int compactChainLimit = options.verbose ? 20 : 10;
    int chainCount = 0;
    loadedLibraries.forEachImportChain(uri,
        callback: (Link<Uri> importChainReversed) {
      Link<CodeLocation> compactImportChain = const Link<CodeLocation>();
      CodeLocation currentCodeLocation =
          new UriLocation(importChainReversed.head);
      compactImportChain = compactImportChain.prepend(currentCodeLocation);
      for (Link<Uri> link = importChainReversed.tail;
           !link.isEmpty;
           link = link.tail) {
        Uri uri = link.head;
        if (!currentCodeLocation.inSameLocation(uri)) {
          currentCodeLocation =
              options.verbose ? new UriLocation(uri) : new CodeLocation(uri);
          compactImportChain =
              compactImportChain.prepend(currentCodeLocation);
        }
      }
      String importChain =
          compactImportChain.map((CodeLocation codeLocation) {
            return codeLocation.relativize(rootUri);
          }).join(' => ');

      if (!importChains.contains(importChain)) {
        if (importChains.length > compactChainLimit) {
          importChains.add('...');
          return false;
        } else {
          importChains.add(importChain);
        }
      }

      chainCount++;
      if (chainCount > chainLimit) {
        // Assume there are more import chains.
        importChains.add('...');
        return false;
      }
      return true;
    });
    return importChains;
  }

  /// Register that [uri] was recognized but disallowed as a dependency.
  ///
  /// For instance import of 'dart:io' without '--categories=Server'.
  void registerDisallowedLibraryUse(Uri uri) {
    disallowedLibraryUris.add(uri);
  }

  /// This method is called when all new libraries loaded through
  /// [LibraryLoader.loadLibrary] has been loaded and their imports/exports
  /// have been computed.
  ///
  /// [loadedLibraries] contains the newly loaded libraries.
  ///
  /// The method returns a [Future] allowing for the loading of additional
  /// libraries.
  Future onLibrariesLoaded(LoadedLibraries loadedLibraries) {
    return new Future.sync(() {
      for (Uri uri in disallowedLibraryUris) {
        if (loadedLibraries.containsLibrary(uri)) {
          Set<String> importChains =
              computeImportChainsFor(loadedLibraries, uri);
          reporter.reportInfo(NO_LOCATION_SPANNABLE,
             MessageKind.DISALLOWED_LIBRARY_IMPORT,
              {'uri': uri,
               'importChain': importChains.join(
                   MessageTemplate.DISALLOWED_LIBRARY_IMPORT_PADDING)});
        }
      }

      if (!loadedLibraries.containsLibrary(Uris.dart_core)) {
        return null;
      }

      bool importsMirrorsLibrary =
          loadedLibraries.containsLibrary(Uris.dart_mirrors);
      if (importsMirrorsLibrary && !backend.supportsReflection) {
        Set<String> importChains =
            computeImportChainsFor(loadedLibraries, Uris.dart_mirrors);
        reporter.reportErrorMessage(
            NO_LOCATION_SPANNABLE,
            MessageKind.MIRRORS_LIBRARY_NOT_SUPPORT_BY_BACKEND,
            {'importChain': importChains.join(
                MessageTemplate.MIRRORS_NOT_SUPPORTED_BY_BACKEND_PADDING)});
      } else if (importsMirrorsLibrary && !options.enableExperimentalMirrors) {
        Set<String> importChains =
            computeImportChainsFor(loadedLibraries, Uris.dart_mirrors);
        reporter.reportWarningMessage(
            NO_LOCATION_SPANNABLE,
            MessageKind.IMPORT_EXPERIMENTAL_MIRRORS,
            {'importChain': importChains.join(
                 MessageTemplate.IMPORT_EXPERIMENTAL_MIRRORS_PADDING)});
      }

      coreClasses.functionClass.ensureResolved(resolution);
      functionApplyMethod =
          coreClasses.functionClass.lookupLocalMember('apply');

      if (options.preserveComments) {
        return libraryLoader.loadLibrary(Uris.dart_mirrors)
            .then((LibraryElement libraryElement) {
          documentClass = libraryElement.find('Comment');
        });
      }
    }).then((_) => backend.onLibrariesLoaded(loadedLibraries));
  }

  bool isProxyConstant(ConstantValue value) {
    FieldElement field = coreLibrary.find('proxy');
    if (field == null) return false;
    if (!resolution.hasBeenResolved(field)) return false;
    if (proxyConstant == null) {
      proxyConstant =
          constants.getConstantValue(
              resolver.constantCompiler.compileConstant(field));
    }
    return proxyConstant == value;
  }

  Element findRequiredElement(LibraryElement library, String name) {
    var element = library.find(name);
    if (element == null) {
      reporter.internalError(library,
          "The library '${library.canonicalUri}' does not contain required "
          "element: '$name'.");
    }
    return element;
  }

  // TODO(johnniwinther): Move this to [PatchParser] when it is moved to the
  // [JavaScriptBackend]. Currently needed for testing.
  String get patchVersion => backend.patchVersion;

  void onClassResolved(ClassElement cls) {
    if (mirrorSystemClass == cls) {
      mirrorSystemGetNameFunction = cls.lookupLocalMember('getName');
    } else if (coreClasses.symbolClass == cls) {
      symbolConstructor = cls.constructors.head;
    } else if (symbolImplementationClass == cls) {
      symbolValidatedConstructor = cls.lookupConstructor(
          symbolValidatedConstructorSelector.name);
    } else if (mirrorsUsedClass == cls) {
      mirrorsUsedConstructor = cls.constructors.head;
    } else if (coreClasses.intClass == cls) {
      intEnvironment = cls.lookupConstructor(Identifiers.fromEnvironment);
    } else if (coreClasses.stringClass == cls) {
      stringEnvironment = cls.lookupConstructor(Identifiers.fromEnvironment);
    } else if (coreClasses.boolClass == cls) {
      boolEnvironment = cls.lookupConstructor(Identifiers.fromEnvironment);
    }
  }

  void initializeCoreClasses() {
    final List missingCoreClasses = [];
    ClassElement lookupCoreClass(String name) {
      ClassElement result = coreLibrary.find(name);
      if (result == null) {
        missingCoreClasses.add(name);
      }
      return result;
    }
    _coreTypes.objectClass = lookupCoreClass('Object');
    _coreTypes.boolClass = lookupCoreClass('bool');
    _coreTypes.numClass = lookupCoreClass('num');
    _coreTypes.intClass = lookupCoreClass('int');
    _coreTypes.doubleClass = lookupCoreClass('double');
    _coreTypes.resourceClass = lookupCoreClass('Resource');
    _coreTypes.stringClass = lookupCoreClass('String');
    _coreTypes.functionClass = lookupCoreClass('Function');
    _coreTypes.listClass = lookupCoreClass('List');
    _coreTypes.typeClass = lookupCoreClass('Type');
    _coreTypes.mapClass = lookupCoreClass('Map');
    _coreTypes.nullClass = lookupCoreClass('Null');
    _coreTypes.stackTraceClass = lookupCoreClass('StackTrace');
    _coreTypes.iterableClass = lookupCoreClass('Iterable');
    _coreTypes.symbolClass = lookupCoreClass('Symbol');
    if (!missingCoreClasses.isEmpty) {
      reporter.internalError(
          coreLibrary,
          'dart:core library does not contain required classes: '
          '$missingCoreClasses');
    }
  }

  Element _unnamedListConstructor;
  Element get unnamedListConstructor {
    if (_unnamedListConstructor != null) return _unnamedListConstructor;
    return _unnamedListConstructor =
        coreClasses.listClass.lookupDefaultConstructor();
  }

  Element _filledListConstructor;
  Element get filledListConstructor {
    if (_filledListConstructor != null) return _filledListConstructor;
    return _filledListConstructor =
        coreClasses.listClass.lookupConstructor("filled");
  }

  /**
   * Get an [Uri] pointing to a patch for the dart: library with
   * the given path. Returns null if there is no patch.
   */
  Uri resolvePatchUri(String dartLibraryPath);

  Future runInternal(Uri uri) {
    // TODO(ahe): This prevents memory leaks when invoking the compiler
    // multiple times. Implement a better mechanism where we can store
    // such caches in the compiler and get access to them through a
    // suitably maintained static reference to the current compiler.
    StringToken.canonicalizedSubstrings.clear();
    Selector.canonicalizedValues.clear();

    // The selector objects held in static fields must remain canonical.
    for (Selector selector in Selectors.ALL) {
      Selector.canonicalizedValues
        .putIfAbsent(selector.hashCode, () => <Selector>[])
        .add(selector);
    }

    assert(uri != null || options.analyzeOnly || options.hasIncrementalSupport);
    return new Future.sync(() {
      if (librariesToAnalyzeWhenRun != null) {
        return Future.forEach(librariesToAnalyzeWhenRun, (libraryUri) {
          reporter.log('Analyzing $libraryUri (${options.buildId})');
          return libraryLoader.loadLibrary(libraryUri);
        });
      }
    }).then((_) {
      if (uri != null) {
        if (options.analyzeOnly) {
          reporter.log('Analyzing $uri (${options.buildId})');
        } else {
          reporter.log('Compiling $uri (${options.buildId})');
        }
        return libraryLoader.loadLibrary(uri).then((LibraryElement library) {
          mainApp = library;
        });
      }
    }).then((_) {
      compileLoadedLibraries();
    });
  }

  void computeMain() {
    if (mainApp == null) return;

    Element main = mainApp.findExported(Identifiers.main);
    ErroneousElement errorElement = null;
    if (main == null) {
      if (options.analyzeOnly) {
        if (!analyzeAll) {
          errorElement = new ErroneousElementX(
              MessageKind.CONSIDER_ANALYZE_ALL, {'main': Identifiers.main},
              Identifiers.main, mainApp);
        }
      } else {
        // Compilation requires a main method.
        errorElement = new ErroneousElementX(
            MessageKind.MISSING_MAIN, {'main': Identifiers.main},
            Identifiers.main, mainApp);
      }
      mainFunction = backend.helperForMissingMain();
    } else if (main.isError && main.isSynthesized) {
      if (main is ErroneousElement) {
        errorElement = main;
      } else {
        reporter.internalError(main, 'Problem with ${Identifiers.main}.');
      }
      mainFunction = backend.helperForBadMain();
    } else if (!main.isFunction) {
      errorElement = new ErroneousElementX(
          MessageKind.MAIN_NOT_A_FUNCTION, {'main': Identifiers.main},
          Identifiers.main, main);
      mainFunction = backend.helperForBadMain();
    } else {
      mainFunction = main;
      mainFunction.computeType(resolution);
      FunctionSignature parameters = mainFunction.functionSignature;
      if (parameters.requiredParameterCount > 2) {
        int index = 0;
        parameters.orderedForEachParameter((Element parameter) {
          if (index++ < 2) return;
          errorElement = new ErroneousElementX(
              MessageKind.MAIN_WITH_EXTRA_PARAMETER, {'main': Identifiers.main},
              Identifiers.main,
              parameter);
          mainFunction = backend.helperForMainArity();
          // Don't warn about main not being used:
          enqueuer.resolution.registerStaticUse(new StaticUse.foreignUse(main));
        });
      }
    }
    if (mainFunction == null) {
      if (errorElement == null && !options.analyzeOnly && !analyzeAll) {
        reporter.internalError(mainApp, "Problem with '${Identifiers.main}'.");
      } else {
        mainFunction = errorElement;
      }
    }
    if (errorElement != null &&
        errorElement.isSynthesized &&
        !mainApp.isSynthesized) {
      reporter.reportWarningMessage(
          errorElement, errorElement.messageKind,
          errorElement.messageArguments);
    }
  }

  /// Analyze all members of the library in [libraryUri].
  ///
  /// If [skipLibraryWithPartOfTag] is `true`, member analysis is skipped if the
  /// library has a `part of` tag, assuming it is a part and not a library.
  ///
  /// This operation assumes an unclosed resolution queue and is only supported
  /// when the '--analyze-main' option is used.
  Future<LibraryElement> analyzeUri(
      Uri libraryUri,
      {bool skipLibraryWithPartOfTag: true}) {
    assert(options.analyzeMain);
    reporter.log('Analyzing $libraryUri (${options.buildId})');
    return libraryLoader.loadLibrary(
        libraryUri, skipFileWithPartOfTag: true).then(
            (LibraryElement library) {
      if (library == null) return null;
      fullyEnqueueLibrary(library, enqueuer.resolution);
      emptyQueue(enqueuer.resolution);
      enqueuer.resolution.logSummary(reporter.log);
      return library;
    });
  }

  /// Performs the compilation when all libraries have been loaded.
  void compileLoadedLibraries() {
    computeMain();

    mirrorUsageAnalyzerTask.analyzeUsage(mainApp);

    // In order to see if a library is deferred, we must compute the
    // compile-time constants that are metadata.  This means adding
    // something to the resolution queue.  So we cannot wait with
    // this until after the resolution queue is processed.
    deferredLoadTask.beforeResolution(this);
    impactStrategy = backend.createImpactStrategy(
        supportDeferredLoad: deferredLoadTask.isProgramSplit,
        supportDumpInfo: options.dumpInfo,
        supportSerialization: serialization.supportSerialization);

    phase = PHASE_RESOLVING;
    if (analyzeAll) {
      libraryLoader.libraries.forEach((LibraryElement library) {
      reporter.log('Enqueuing ${library.canonicalUri}');
        fullyEnqueueLibrary(library, enqueuer.resolution);
      });
    } else if (options.analyzeMain) {
      if (mainApp != null) {
        fullyEnqueueLibrary(mainApp, enqueuer.resolution);
      }
      if (librariesToAnalyzeWhenRun != null) {
        for (Uri libraryUri in librariesToAnalyzeWhenRun) {
          fullyEnqueueLibrary(libraryLoader.lookupLibrary(libraryUri),
              enqueuer.resolution);
        }
      }
    }
    // Elements required by enqueueHelpers are global dependencies
    // that are not pulled in by a particular element.
    backend.enqueueHelpers(enqueuer.resolution, globalDependencies);
    resolveLibraryMetadata();
    reporter.log('Resolving...');
    processQueue(enqueuer.resolution, mainFunction);
    enqueuer.resolution.logSummary(reporter.log);

    _reporter.reportSuppressedMessagesSummary();

    if (compilationFailed){
      if (!options.generateCodeWithCompileTimeErrors) return;
      if (!backend.enableCodegenWithErrorsIfSupported(NO_LOCATION_SPANNABLE)) {
        return;
      }
    }

    if (options.analyzeOnly) {
      if (!analyzeAll && !compilationFailed) {
        // No point in reporting unused code when [analyzeAll] is true: all
        // code is artificially used.
        // If compilation failed, it is possible that the error prevents the
        // compiler from analyzing all the code.
        // TODO(johnniwinther): Reenable this when the reporting is more
        // precise.
        //reportUnusedCode();
      }
      return;
    }
    assert(mainFunction != null);
    phase = PHASE_DONE_RESOLVING;

    world.populate();
    // Compute whole-program-knowledge that the backend needs. (This might
    // require the information computed in [world.populate].)
    backend.onResolutionComplete();

    deferredLoadTask.onResolutionComplete(mainFunction);

    reporter.log('Inferring types...');
    typesTask.onResolutionComplete(mainFunction);

    if (stopAfterTypeInference) return;

    backend.onTypeInferenceComplete();

    reporter.log('Compiling...');
    phase = PHASE_COMPILING;
    backend.onCodegenStart();
    // TODO(johnniwinther): Move these to [CodegenEnqueuer].
    if (hasIsolateSupport) {
      backend.enableIsolateSupport(enqueuer.codegen);
    }
    if (compileAll) {
      libraryLoader.libraries.forEach((LibraryElement library) {
        fullyEnqueueLibrary(library, enqueuer.codegen);
      });
    }
    processQueue(enqueuer.codegen, mainFunction);
    enqueuer.codegen.logSummary(reporter.log);

    int programSize = backend.assembleProgram();

    if (options.dumpInfo) {
      dumpInfoTask.reportSize(programSize);
      dumpInfoTask.dumpInfo();
    }

    backend.sourceInformationStrategy.onComplete();

    checkQueues();
  }

  void fullyEnqueueLibrary(LibraryElement library, Enqueuer world) {
    void enqueueAll(Element element) {
      fullyEnqueueTopLevelElement(element, world);
    }
    library.implementation.forEachLocalMember(enqueueAll);
  }

  void fullyEnqueueTopLevelElement(Element element, Enqueuer world) {
    if (element.isClass) {
      ClassElement cls = element;
      cls.ensureResolved(resolution);
      cls.forEachLocalMember(enqueuer.resolution.addToWorkList);
      backend.registerInstantiatedType(
          cls.rawType, world, globalDependencies);
    } else {
      world.addToWorkList(element);
    }
  }

  // Resolves metadata on library elements.  This is necessary in order to
  // resolve metadata classes referenced only from metadata on library tags.
  // TODO(ahe): Figure out how to do this lazily.
  void resolveLibraryMetadata() {
    for (LibraryElement library in libraryLoader.libraries) {
      if (library.metadata != null) {
        for (MetadataAnnotation metadata in library.metadata) {
          metadata.ensureResolved(resolution);
        }
      }
    }
  }

  /**
   * Empty the [world] queue.
   */
  void emptyQueue(Enqueuer world) {
    world.forEach((WorkItem work) {
    reporter.withCurrentElement(work.element, () {
        world.applyImpact(work.element, work.run(this, world));
      });
    });
  }

  void processQueue(Enqueuer world, Element main) {
    world.nativeEnqueuer.processNativeClasses(libraryLoader.libraries);
    if (main != null && !main.isMalformed) {
      FunctionElement mainMethod = main;
      mainMethod.computeType(resolution);
      if (mainMethod.functionSignature.parameterCount != 0) {
        // The first argument could be a list of strings.
        backend.listImplementation.ensureResolved(resolution);
        backend.registerInstantiatedType(
            backend.listImplementation.rawType, world, globalDependencies);
        backend.stringImplementation.ensureResolved(resolution);
        backend.registerInstantiatedType(
            backend.stringImplementation.rawType, world, globalDependencies);

        backend.registerMainHasArguments(world);
      }
      world.addToWorkList(main);
    }
    if (options.verbose) {
      progress.reset();
    }
    emptyQueue(world);
    world.queueIsClosed = true;
    // Notify the impact strategy impacts are no longer needed for this
    // enqueuer.
    impactStrategy.onImpactUsed(world.impactUse);
    backend.onQueueClosed();
    assert(compilationFailed || world.checkNoEnqueuedInvokedInstanceMethods());
  }

  /**
   * Perform various checks of the queues. This includes checking that
   * the queues are empty (nothing was added after we stopped
   * processing the queues). Also compute the number of methods that
   * were resolved, but not compiled (aka excess resolution).
   */
  checkQueues() {
    for (Enqueuer world in [enqueuer.resolution, enqueuer.codegen]) {
      world.forEach((WorkItem work) {
        reporter.internalError(work.element, "Work list is not empty.");
      });
    }
    if (!REPORT_EXCESS_RESOLUTION) return;
    var resolved = new Set.from(enqueuer.resolution.processedElements);
    for (Element e in enqueuer.codegen.generatedCode.keys) {
      resolved.remove(e);
    }
    for (Element e in new Set.from(resolved)) {
      if (e.isClass ||
          e.isField ||
          e.isTypeVariable ||
          e.isTypedef ||
          identical(e.kind, ElementKind.ABSTRACT_FIELD)) {
        resolved.remove(e);
      }
      if (identical(e.kind, ElementKind.GENERATIVE_CONSTRUCTOR)) {
        resolved.remove(e);
      }
      if (backend.isBackendLibrary(e.library)) {
        resolved.remove(e);
      }
    }
    reporter.log('Excess resolution work: ${resolved.length}.');
    for (Element e in resolved) {
      reporter.reportWarningMessage(e,
          MessageKind.GENERIC,
          {'text': 'Warning: $e resolved but not compiled.'});
    }
  }

  WorldImpact analyzeElement(Element element) {
    assert(invariant(element,
           element.impliesType ||
           element.isField ||
           element.isFunction ||
           element.isConstructor ||
           element.isGetter ||
           element.isSetter,
           message: 'Unexpected element kind: ${element.kind}'));
    assert(invariant(element, element is AnalyzableElement,
        message: 'Element $element is not analyzable.'));
    assert(invariant(element, element.isDeclaration));
    return resolution.computeWorldImpact(element);
  }

  WorldImpact analyze(ResolutionWorkItem work,
                      ResolutionEnqueuer world) {
    assert(invariant(work.element, identical(world, enqueuer.resolution)));
    assert(invariant(work.element, !work.isAnalyzed,
        message: 'Element ${work.element} has already been analyzed'));
    if (shouldPrintProgress) {
      // TODO(ahe): Add structured diagnostics to the compiler API and
      // use it to separate this from the --verbose option.
      if (phase == PHASE_RESOLVING) {
        reporter.log(
            'Resolved ${enqueuer.resolution.processedElements.length} '
            'elements.');
        progress.reset();
      }
    }
    AstElement element = work.element;
    if (world.hasBeenProcessed(element)) {
      return const WorldImpact();
    }
    WorldImpact worldImpact = analyzeElement(element);
    backend.onElementResolved(element, element.resolvedAst.elements);
    world.registerProcessedElement(element);
    return worldImpact;
  }

  WorldImpact codegen(CodegenWorkItem work, CodegenEnqueuer world) {
    assert(invariant(work.element, identical(world, enqueuer.codegen)));
    if (shouldPrintProgress) {
      // TODO(ahe): Add structured diagnostics to the compiler API and
      // use it to separate this from the --verbose option.
      reporter.log(
          'Compiled ${enqueuer.codegen.generatedCode.length} methods.');
      progress.reset();
    }
    return backend.codegen(work);
  }

  void reportDiagnostic(DiagnosticMessage message,
                        List<DiagnosticMessage> infos,
                        api.Diagnostic kind);

  void reportCrashInUserCode(String message, exception, stackTrace) {
    _reporter.onCrashInUserCode(message, exception, stackTrace);
  }

  /// Messages for which compile-time errors are reported but compilation
  /// continues regardless.
  static const List<MessageKind> BENIGN_ERRORS = const <MessageKind>[
      MessageKind.INVALID_METADATA,
      MessageKind.INVALID_METADATA_GENERIC,
  ];

  bool markCompilationAsFailed(DiagnosticMessage message, api.Diagnostic kind) {
    if (options.testMode) {
      // When in test mode, i.e. on the build-bot, we always stop compilation.
      return true;
    }
    if (reporter.options.fatalWarnings) {
      return true;
    }
    return !BENIGN_ERRORS.contains(message.message.kind);
  }

  void fatalDiagnosticReported(DiagnosticMessage message,
                               List<DiagnosticMessage> infos,
                               api.Diagnostic kind) {
    if (markCompilationAsFailed(message, kind)) {
      compilationFailed = true;
    }
  }

  // TODO(sigmund): move this dart doc somewhere else too.
  /**
   * Translates the [resolvedUri] into a readable URI.
   *
   * The [importingLibrary] holds the library importing [resolvedUri] or
   * [:null:] if [resolvedUri] is loaded as the main library. The
   * [importingLibrary] is used to grant access to internal libraries from
   * platform libraries and patch libraries.
   *
   * If the [resolvedUri] is not accessible from [importingLibrary], this method
   * is responsible for reporting errors.
   *
   * See [LibraryLoader] for terminology on URIs.
   */
  Uri translateResolvedUri(LibraryElement importingLibrary,
                           Uri resolvedUri, Spannable spannable) {
    unimplemented(importingLibrary, 'Compiler.translateResolvedUri');
    return null;
  }

  /**
   * Reads the script specified by the [readableUri].
   *
   * See [LibraryLoader] for terminology on URIs.
   */
  Future<Script> readScript(Uri readableUri, [Spannable node]) {
    unimplemented(node, 'Compiler.readScript');
    return null;
  }

  Element lookupElementIn(ScopeContainerElement container, String name) {
    Element element = container.localLookup(name);
    if (element == null) {
      throw 'Could not find $name in $container';
    }
    return element;
  }

  bool get isMockCompilation => false;

  Token processAndStripComments(Token currentToken) {
    Token firstToken = currentToken;
    Token prevToken;
    while (currentToken.kind != Tokens.EOF_TOKEN) {
      if (identical(currentToken.kind, Tokens.COMMENT_TOKEN)) {
        Token firstCommentToken = currentToken;
        while (identical(currentToken.kind, Tokens.COMMENT_TOKEN)) {
          currentToken = currentToken.next;
        }
        commentMap[currentToken] = firstCommentToken;
        if (prevToken == null) {
          firstToken = currentToken;
        } else {
          prevToken.next = currentToken;
        }
      }
      prevToken = currentToken;
      currentToken = currentToken.next;
    }
    return firstToken;
  }

  void reportUnusedCode() {
    void checkLive(member) {
      if (member.isMalformed) return;
      if (member.isFunction) {
        if (!enqueuer.resolution.hasBeenProcessed(member)) {
          reporter.reportHintMessage(
              member, MessageKind.UNUSED_METHOD, {'name': member.name});
        }
      } else if (member.isClass) {
        if (!member.isResolved) {
          reporter.reportHintMessage(
              member, MessageKind.UNUSED_CLASS, {'name': member.name});
        } else {
          member.forEachLocalMember(checkLive);
        }
      } else if (member.isTypedef) {
        if (!member.isResolved) {
          reporter.reportHintMessage(
              member, MessageKind.UNUSED_TYPEDEF, {'name': member.name});
        }
      }
    }
    libraryLoader.libraries.forEach((LibraryElement library) {
      // TODO(ahe): Implement better heuristics to discover entry points of
      // packages and use that to discover unused implementation details in
      // packages.
      if (library.isPlatformLibrary || library.isPackageLibrary) return;
      library.compilationUnits.forEach((unit) {
        unit.forEachLocalMember(checkLive);
      });
    });
  }

  /// Helper for determining whether the current element is declared within
  /// 'user code'.
  ///
  /// See [inUserCode] for what defines 'user code'.
  bool currentlyInUserCode() {
    return inUserCode(currentElement);
  }

  /// Helper for determining whether [element] is declared within 'user code'.
  ///
  /// What constitutes 'user code' is defined by the URI(s) provided by the
  /// entry point(s) of compilation or analysis:
  ///
  /// If an entrypoint URI uses the 'package' scheme then every library from
  /// that same package is considered to be in user code. For instance, if
  /// an entry point URI is 'package:foo/bar.dart' then every library whose
  /// canonical URI starts with 'package:foo/' is in user code.
  ///
  /// If an entrypoint URI uses another scheme than 'package' then every library
  /// with that scheme is in user code. For instance, an entry point URI is
  /// 'file:///foo.dart' then every library whose canonical URI scheme is
  /// 'file' is in user code.
  ///
  /// If [assumeInUserCode] is `true`, [element] is assumed to be in user code
  /// if no entrypoints have been set.
  bool inUserCode(Element element, {bool assumeInUserCode: false}) {
    if (element == null) return false;
    Iterable<CodeLocation> userCodeLocations =
        computeUserCodeLocations(assumeInUserCode: assumeInUserCode);
    Uri libraryUri = element.library.canonicalUri;
    return userCodeLocations.any(
        (CodeLocation codeLocation) => codeLocation.inSameLocation(libraryUri));
  }

  Iterable<CodeLocation> computeUserCodeLocations(
      {bool assumeInUserCode: false}) {
    List<CodeLocation> userCodeLocations = <CodeLocation>[];
    if (mainApp != null) {
      userCodeLocations.add(new CodeLocation(mainApp.canonicalUri));
    }
    if (librariesToAnalyzeWhenRun != null) {
      userCodeLocations.addAll(librariesToAnalyzeWhenRun.map(
          (Uri uri) => new CodeLocation(uri)));
    }
    if (userCodeLocations.isEmpty && assumeInUserCode) {
      // Assume in user code since [mainApp] has not been set yet.
      userCodeLocations.add(const AnyLocation());
    }
    return userCodeLocations;
  }

  /// Return a canonical URI for the source of [element].
  ///
  /// For a package library with canonical URI 'package:foo/bar/baz.dart' the
  /// return URI is 'package:foo'. For non-package libraries the returned URI is
  /// the canonical URI of the library itself.
  Uri getCanonicalUri(Element element) {
    if (element == null) return null;
    Uri libraryUri = element.library.canonicalUri;
    if (libraryUri.scheme == 'package') {
      int slashPos = libraryUri.path.indexOf('/');
      if (slashPos != -1) {
        String packageName = libraryUri.path.substring(0, slashPos);
        return new Uri(scheme: 'package', path: packageName);
      }
    }
    return libraryUri;
  }

  void forgetElement(Element element) {
    enqueuer.forgetElement(element);
    if (element is MemberElement) {
      for (Element closure in element.nestedClosures) {
        // TODO(ahe): It would be nice to reuse names of nested closures.
        closureToClassMapper.forgetElement(closure);
      }
    }
    backend.forgetElement(element);
  }

  bool elementHasCompileTimeError(Element element) {
    return elementsWithCompileTimeErrors.contains(element);
  }

  EventSink<String> outputProvider(String name, String extension) {
    if (compilationFailed) {
      if (!options.generateCodeWithCompileTimeErrors || options.testMode) {
        // Disable output in test mode: The build bot currently uses the time
        // stamp of the generated file to determine whether the output is
        // up-to-date.
        return new NullSink('$name.$extension');
      }
    }
    return userOutputProvider.createEventSink(name, extension);
  }
}

/// Information about suppressed warnings and hints for a given library.
class SuppressionInfo {
  int warnings = 0;
  int hints = 0;
}

class _CompilerCoreTypes implements CoreTypes, CoreClasses {
  final Resolution resolution;

  ClassElement objectClass;
  ClassElement boolClass;
  ClassElement numClass;
  ClassElement intClass;
  ClassElement doubleClass;
  ClassElement stringClass;
  ClassElement functionClass;
  ClassElement nullClass;
  ClassElement listClass;
  ClassElement typeClass;
  ClassElement mapClass;
  ClassElement symbolClass;
  ClassElement stackTraceClass;
  ClassElement futureClass;
  ClassElement iterableClass;
  ClassElement streamClass;
  ClassElement resourceClass;

  _CompilerCoreTypes(this.resolution);

  @override
  InterfaceType get objectType {
    objectClass.ensureResolved(resolution);
    return objectClass.rawType;
  }

  @override
  InterfaceType get boolType {
    boolClass.ensureResolved(resolution);
    return boolClass.rawType;
  }

  @override
  InterfaceType get doubleType {
    doubleClass.ensureResolved(resolution);
    return doubleClass.rawType;
  }

  @override
  InterfaceType get functionType {
    functionClass.ensureResolved(resolution);
    return functionClass.rawType;
  }

  @override
  InterfaceType get intType {
    intClass.ensureResolved(resolution);
    return intClass.rawType;
  }

  @override
  InterfaceType get resourceType {
    resourceClass.ensureResolved(resolution);
    return resourceClass.rawType;
  }

  @override
  InterfaceType listType([DartType elementType]) {
    listClass.ensureResolved(resolution);
    InterfaceType type = listClass.rawType;
    if (elementType == null) {
      return type;
    }
    return type.createInstantiation([elementType]);
  }

  @override
  InterfaceType mapType([DartType keyType,
                         DartType valueType]) {
    mapClass.ensureResolved(resolution);
    InterfaceType type = mapClass.rawType;
    if (keyType == null && valueType == null) {
      return type;
    } else if (keyType == null) {
      keyType = const DynamicType();
    } else if (valueType == null) {
      valueType = const DynamicType();
    }
    return type.createInstantiation([keyType, valueType]);
  }

  @override
  InterfaceType get nullType {
    nullClass.ensureResolved(resolution);
    return nullClass.rawType;
  }

  @override
  InterfaceType get numType {
    numClass.ensureResolved(resolution);
    return numClass.rawType;
  }

  @override
  InterfaceType get stringType {
    stringClass.ensureResolved(resolution);
    return stringClass.rawType;
  }

  @override
  InterfaceType get symbolType {
    symbolClass.ensureResolved(resolution);
    return symbolClass.rawType;
  }

  @override
  InterfaceType get typeType {
    typeClass.ensureResolved(resolution);
    return typeClass.rawType;
  }

  @override
  InterfaceType get stackTraceType {
    stackTraceClass.ensureResolved(resolution);
    return stackTraceClass.rawType;
  }

  @override
  InterfaceType iterableType([DartType elementType]) {
    iterableClass.ensureResolved(resolution);
    InterfaceType type = iterableClass.rawType;
    if (elementType == null) {
      return type;
    }
    return type.createInstantiation([elementType]);
  }

  @override
  InterfaceType futureType([DartType elementType]) {
    futureClass.ensureResolved(resolution);
    InterfaceType type = futureClass.rawType;
    if (elementType == null) {
      return type;
    }
    return type.createInstantiation([elementType]);
  }

  @override
  InterfaceType streamType([DartType elementType]) {
    streamClass.ensureResolved(resolution);
    InterfaceType type = streamClass.rawType;
    if (elementType == null) {
      return type;
    }
    return type.createInstantiation([elementType]);
  }
}

class _CompilerDiagnosticReporter extends DiagnosticReporter {
  final Compiler compiler;
  final DiagnosticOptions options;

  Element _currentElement;
  bool hasCrashed = false;

  /// `true` if the last diagnostic was filtered, in which case the
  /// accompanying info message should be filtered as well.
  bool lastDiagnosticWasFiltered = false;

  /// Map containing information about the warnings and hints that have been
  /// suppressed for each library.
  Map<Uri, SuppressionInfo> suppressedWarnings = <Uri, SuppressionInfo>{};

  _CompilerDiagnosticReporter(this.compiler, this.options);

  Element get currentElement => _currentElement;

  DiagnosticMessage createMessage(
      Spannable spannable,
      MessageKind messageKind,
      [Map arguments = const {}]) {
    SourceSpan span = spanFromSpannable(spannable);
    MessageTemplate template = MessageTemplate.TEMPLATES[messageKind];
    Message message = template.message(arguments, options.terseDiagnostics);
    return new DiagnosticMessage(span, spannable, message);
  }

  void reportError(
      DiagnosticMessage message,
      [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
    reportDiagnosticInternal(message, infos, api.Diagnostic.ERROR);
  }

  void reportWarning(
      DiagnosticMessage message,
      [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
    reportDiagnosticInternal(message, infos, api.Diagnostic.WARNING);
  }

  void reportHint(
      DiagnosticMessage message,
      [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
    reportDiagnosticInternal(message, infos, api.Diagnostic.HINT);
  }

  @deprecated
  void reportInfo(Spannable node, MessageKind messageKind,
                  [Map arguments = const {}]) {
    reportDiagnosticInternal(
        createMessage(node, messageKind, arguments),
        const <DiagnosticMessage>[],
        api.Diagnostic.INFO);
  }

  void reportDiagnosticInternal(DiagnosticMessage message,
                                List<DiagnosticMessage> infos,
                                api.Diagnostic kind) {
    if (!options.showAllPackageWarnings &&
        message.spannable != NO_LOCATION_SPANNABLE) {
      switch (kind) {
      case api.Diagnostic.WARNING:
      case api.Diagnostic.HINT:
        Element element = elementFromSpannable(message.spannable);
        if (!compiler.inUserCode(element, assumeInUserCode: true)) {
          Uri uri = compiler.getCanonicalUri(element);
          if (options.showPackageWarningsFor(uri)) {
            reportDiagnostic(message, infos, kind);
            return;
          }
          SuppressionInfo info =
              suppressedWarnings.putIfAbsent(uri, () => new SuppressionInfo());
          if (kind == api.Diagnostic.WARNING) {
            info.warnings++;
          } else {
            info.hints++;
          }
          lastDiagnosticWasFiltered = true;
          return;
        }
        break;
      case api.Diagnostic.INFO:
        if (lastDiagnosticWasFiltered) {
          return;
        }
        break;
      }
    }
    lastDiagnosticWasFiltered = false;
    reportDiagnostic(message, infos, kind);
  }

  void reportDiagnostic(DiagnosticMessage message,
                        List<DiagnosticMessage> infos,
                        api.Diagnostic kind) {
    compiler.reportDiagnostic(message, infos, kind);
    if (kind == api.Diagnostic.ERROR ||
        kind == api.Diagnostic.CRASH ||
        (options.fatalWarnings &&
         kind == api.Diagnostic.WARNING)) {
      compiler.fatalDiagnosticReported(message, infos, kind);
    }
  }

  /**
   * Perform an operation, [f], returning the return value from [f].  If an
   * error occurs then report it as having occurred during compilation of
   * [element].  Can be nested.
   */
  withCurrentElement(Element element, f()) {
    Element old = currentElement;
    _currentElement = element;
    try {
      return f();
    } on SpannableAssertionFailure catch (ex) {
      if (!hasCrashed) {
        reportAssertionFailure(ex);
        pleaseReportCrash();
      }
      hasCrashed = true;
      rethrow;
    } on StackOverflowError {
      // We cannot report anything useful in this case, because we
      // do not have enough stack space.
      rethrow;
    } catch (ex) {
      if (hasCrashed) rethrow;
      try {
        unhandledExceptionOnElement(element);
      } catch (doubleFault) {
        // Ignoring exceptions in exception handling.
      }
      rethrow;
    } finally {
      _currentElement = old;
    }
  }

  void reportAssertionFailure(SpannableAssertionFailure ex) {
    String message = (ex.message != null) ? tryToString(ex.message)
                                          : tryToString(ex);
    reportDiagnosticInternal(
        createMessage(ex.node, MessageKind.GENERIC, {'text': message}),
        const <DiagnosticMessage>[],
        api.Diagnostic.CRASH);
  }

  SourceSpan spanFromTokens(Token begin, Token end, [Uri uri]) {
    if (begin == null || end == null) {
      // TODO(ahe): We can almost always do better. Often it is only
      // end that is null. Otherwise, we probably know the current
      // URI.
      throw 'Cannot find tokens to produce error message.';
    }
    if (uri == null && currentElement != null) {
      uri = currentElement.compilationUnit.script.resourceUri;
      assert(invariant(currentElement, () {

        bool sameToken(Token token, Token sought) {
          if (token == sought) return true;
          if (token.stringValue == '>>') {
            // `>>` is converted to `>` in the parser when needed.
            return sought.stringValue == '>' &&
                token.charOffset <= sought.charOffset &&
                sought.charOffset < token.charEnd;
          }
          return false;
        }

        /// Check that [begin] and [end] can be found between [from] and [to].
        validateToken(Token from, Token to) {
          if (from == null || to == null) return true;
          bool foundBegin = false;
          bool foundEnd = false;
          Token token = from;
          while (true) {
            if (sameToken(token, begin)) {
              foundBegin = true;
            }
            if (sameToken(token, end)) {
              foundEnd = true;
            }
            if (foundBegin && foundEnd) {
              return true;
            }
            if (token == to || token == token.next || token.next == null) {
              break;
            }
            token = token.next;
          }

          // Create a good message for when the tokens were not found.
          StringBuffer sb = new StringBuffer();
          sb.write('Invalid current element: $currentElement. ');
          sb.write('Looking for ');
          sb.write('[${begin} (${begin.hashCode}),');
          sb.write('${end} (${end.hashCode})] in');

          token = from;
          while (true) {
            sb.write('\n ${token} (${token.hashCode})');
            if (token == to || token == token.next || token.next == null) {
              break;
            }
            token = token.next;
          }
          return sb.toString();
        }

        if (currentElement.enclosingClass != null &&
            currentElement.enclosingClass.isEnumClass) {
          // Enums ASTs are synthesized (and give messed up messages).
          return true;
        }

        if (currentElement is AstElement) {
          AstElement astElement = currentElement;
          if (astElement.hasNode) {
            Token from = astElement.node.getBeginToken();
            Token to = astElement.node.getEndToken();
            if (astElement.metadata.isNotEmpty) {
              from = astElement.metadata.first.beginToken;
            }
            return validateToken(from, to);
          }
        }
        return true;
      }, message: "Invalid current element: $currentElement [$begin,$end]."));
    }
    return new SourceSpan.fromTokens(uri, begin, end);
  }

  SourceSpan spanFromNode(Node node) {
    return spanFromTokens(node.getBeginToken(), node.getPrefixEndToken());
  }

  SourceSpan spanFromElement(Element element) {
    if (element != null && element.sourcePosition != null) {
      return element.sourcePosition;
    }
    while (element != null && element.isSynthesized) {
      element = element.enclosingElement;
    }
    if (element != null &&
        element.sourcePosition == null &&
        !element.isLibrary &&
        !element.isCompilationUnit) {
      // Sometimes, the backend fakes up elements that have no
      // position. So we use the enclosing element instead. It is
      // not a good error location, but cancel really is "internal
      // error" or "not implemented yet", so the vicinity is good
      // enough for now.
      element = element.enclosingElement;
      // TODO(ahe): I plan to overhaul this infrastructure anyways.
    }
    if (element == null) {
      element = currentElement;
    }
    if (element == null) {
      return null;
    }

    if (element.sourcePosition != null) {
      return element.sourcePosition;
    }
    Token position = element.position;
    Uri uri = element.compilationUnit.script.resourceUri;
    return (position == null)
        ? new SourceSpan(uri, 0, 0)
        : spanFromTokens(position, position, uri);
  }

  SourceSpan spanFromHInstruction(HInstruction instruction) {
    Element element = _elementFromHInstruction(instruction);
    if (element == null) element = currentElement;
    SourceInformation position = instruction.sourceInformation;
    if (position == null) return spanFromElement(element);
    return position.sourceSpan;
  }

  SourceSpan spanFromSpannable(Spannable node) {
    // TODO(johnniwinther): Disallow `node == null` ?
    if (node == null) return null;
    if (node == CURRENT_ELEMENT_SPANNABLE) {
      node = currentElement;
    } else if (node == NO_LOCATION_SPANNABLE) {
      if (currentElement == null) return null;
      node = currentElement;
    }
    if (node is SourceSpan) {
      return node;
    } else if (node is Node) {
      return spanFromNode(node);
    } else if (node is TokenPair) {
      return spanFromTokens(node.begin, node.end);
    } else if (node is Token) {
      return spanFromTokens(node, node);
    } else if (node is HInstruction) {
      return spanFromHInstruction(node);
    } else if (node is Element) {
      return spanFromElement(node);
    } else if (node is MetadataAnnotation) {
      Uri uri = node.annotatedElement.compilationUnit.script.resourceUri;
      return spanFromTokens(node.beginToken, node.endToken, uri);
    } else if (node is Local) {
      Local local = node;
      return spanFromElement(local.executableContext);
    } else {
      throw 'No error location.';
    }
  }

  Element _elementFromHInstruction(HInstruction instruction) {
    return instruction.sourceElement is Element
        ? instruction.sourceElement : null;
  }

  internalError(Spannable node, reason) {
    String message = tryToString(reason);
    reportDiagnosticInternal(
        createMessage(node, MessageKind.GENERIC, {'text': message}),
        const <DiagnosticMessage>[],
        api.Diagnostic.CRASH);
    throw 'Internal Error: $message';
  }

  void unhandledExceptionOnElement(Element element) {
    if (hasCrashed) return;
    hasCrashed = true;
    reportDiagnostic(
        createMessage(element, MessageKind.COMPILER_CRASHED),
        const <DiagnosticMessage>[],
        api.Diagnostic.CRASH);
    pleaseReportCrash();
  }

  void pleaseReportCrash() {
    print(
        MessageTemplate.TEMPLATES[MessageKind.PLEASE_REPORT_THE_CRASH]
            .message({'buildId': compiler.options.buildId}));
  }

  /// Finds the approximate [Element] for [node]. [currentElement] is used as
  /// the default value.
  Element elementFromSpannable(Spannable node) {
    Element element;
    if (node is Element) {
      element = node;
    } else if (node is HInstruction) {
      element = _elementFromHInstruction(node);
    } else if (node is MetadataAnnotation) {
      element = node.annotatedElement;
    }
    return element != null ? element : currentElement;
  }

  void log(message) {
    Message msg = MessageTemplate.TEMPLATES[MessageKind.GENERIC]
        .message({'text': '$message'});
    reportDiagnostic(
        new DiagnosticMessage(null, null, msg),
        const <DiagnosticMessage>[],
        api.Diagnostic.VERBOSE_INFO);
  }

  String tryToString(object) {
    try {
      return object.toString();
    } catch (_) {
      return '<exception in toString()>';
    }
  }

  onError(Uri uri, error) {
    try {
      if (!hasCrashed) {
        hasCrashed = true;
        if (error is SpannableAssertionFailure) {
          reportAssertionFailure(error);
        } else {
          reportDiagnostic(
              createMessage(
                  new SourceSpan(uri, 0, 0),
                  MessageKind.COMPILER_CRASHED),
              const <DiagnosticMessage>[],
              api.Diagnostic.CRASH);
        }
        pleaseReportCrash();
      }
    } catch (doubleFault) {
      // Ignoring exceptions in exception handling.
    }
    throw error;
  }

  void onCrashInUserCode(String message, exception, stackTrace) {
    hasCrashed = true;
    print('$message: ${tryToString(exception)}');
    print(tryToString(stackTrace));
  }

  void reportSuppressedMessagesSummary() {
    if (!options.showAllPackageWarnings && !options.suppressWarnings) {
      suppressedWarnings.forEach((Uri uri, SuppressionInfo info) {
        MessageKind kind = MessageKind.HIDDEN_WARNINGS_HINTS;
        if (info.warnings == 0) {
          kind = MessageKind.HIDDEN_HINTS;
        } else if (info.hints == 0) {
          kind = MessageKind.HIDDEN_WARNINGS;
        }
        MessageTemplate template = MessageTemplate.TEMPLATES[kind];
        Message message = template.message(
            {'warnings': info.warnings,
             'hints': info.hints,
             'uri': uri},
             options.terseDiagnostics);
        reportDiagnostic(
            new DiagnosticMessage(null, null, message),
            const <DiagnosticMessage>[],
            api.Diagnostic.HINT);
      });
    }
  }
}

// TODO(johnniwinther): Move [ResolverTask] here.
class _CompilerResolution implements Resolution {
  final Compiler compiler;
  final Map<Element, ResolutionImpact> _resolutionImpactCache =
      <Element, ResolutionImpact>{};
  final Map<Element, WorldImpact> _worldImpactCache = <Element, WorldImpact>{};
  bool retainCachesForTesting = false;

  _CompilerResolution(this.compiler);

  @override
  DiagnosticReporter get reporter => compiler.reporter;

  @override
  Parsing get parsing => compiler.parsing;

  @override
  CoreTypes get coreTypes => compiler.coreTypes;

  @override
  void registerClass(ClassElement cls) {
    compiler.world.registerClass(cls);
  }

  @override
  void resolveClass(ClassElement cls) {
    compiler.resolver.resolveClass(cls);
  }

  @override
  void resolveTypedef(TypedefElement typdef) {
    compiler.resolver.resolve(typdef);
  }

  @override
  void resolveMetadataAnnotation(MetadataAnnotation metadataAnnotation) {
    compiler.resolver.resolveMetadataAnnotation(metadataAnnotation);
  }

  @override
  FunctionSignature resolveSignature(FunctionElement function) {
    return compiler.resolver.resolveSignature(function);
  }

  @override
  DartType resolveTypeAnnotation(Element element, TypeAnnotation node) {
    return compiler.resolver.resolveTypeAnnotation(element, node);
  }

  @override
  bool hasResolutionImpact(Element element) {
    return _resolutionImpactCache.containsKey(element);
  }

  @override
  ResolutionImpact getResolutionImpact(Element element) {
    ResolutionImpact resolutionImpact = _resolutionImpactCache[element];
    assert(invariant(element, resolutionImpact != null,
        message: "ResolutionImpact not available for $element."));
    return resolutionImpact;
  }

  @override
  WorldImpact getWorldImpact(Element element) {
    WorldImpact worldImpact = _worldImpactCache[element];
    assert(invariant(element, worldImpact != null,
        message: "WorldImpact not computed for $element."));
    return worldImpact;
  }

  @override
  WorldImpact computeWorldImpact(Element element) {
    return _worldImpactCache.putIfAbsent(element, () {
      assert(compiler.parser != null);
      Node tree = compiler.parser.parse(element);
      assert(invariant(element, !element.isSynthesized || tree == null));
      ResolutionImpact resolutionImpact =
          compiler.resolver.resolve(element);
      if (compiler.serialization.supportSerialization || retainCachesForTesting) {
        // [ResolutionImpact] is currently only used by serialization. The
        // enqueuer uses the [WorldImpact] which is always cached.
        // TODO(johnniwinther): Align these use cases better; maybe only
        // cache [ResolutionImpact] and let the enqueuer transform it into
        // a [WorldImpact].
        _resolutionImpactCache[element] = resolutionImpact;
      }
      if (tree != null && !compiler.options.analyzeSignaturesOnly) {
        // TODO(het): don't do this if suppressWarnings is on, currently we have
        // to do it because the typechecker also sets types
        // Only analyze nodes with a corresponding [TreeElements].
        compiler.checker.check(element);
      }
      WorldImpact worldImpact =
          compiler.backend.impactTransformer.transformResolutionImpact(
              resolutionImpact);
      return worldImpact;
    });
  }

  @override
  void uncacheWorldImpact(Element element) {
    if (retainCachesForTesting) return;
    if (compiler.serialization.isDeserialized(element)) return;
    assert(invariant(element, _worldImpactCache[element] != null,
        message: "WorldImpact not computed for $element."));
    _worldImpactCache[element] = const WorldImpact();
    _resolutionImpactCache.remove(element);
  }

  @override
  void emptyCache() {
    if (retainCachesForTesting) return;
    for (Element element in _worldImpactCache.keys) {
      _worldImpactCache[element] = const WorldImpact();
    }
    _resolutionImpactCache.clear();
  }

  @override
  bool hasBeenResolved(Element element) {
    return _worldImpactCache.containsKey(element);
  }

  @override
  ResolutionWorkItem createWorkItem(
      Element element, ItemCompilationContext compilationContext) {
    if (compiler.serialization.isDeserialized(element)) {
      return compiler.serialization.createResolutionWorkItem(
          element, compilationContext);
    } else {
      return new ResolutionWorkItem(element, compilationContext);
    }
  }
}

// TODO(johnniwinther): Move [ParserTask], [PatchParserTask], [DietParserTask]
// and [ScannerTask] here.
class _CompilerParsing implements Parsing {
  final Compiler compiler;

  _CompilerParsing(this.compiler);

  @override
  DiagnosticReporter get reporter => compiler.reporter;

  @override
  measure(f()) => compiler.parser.measure(f);

  @override
  void parsePatchClass(ClassElement cls) {
    compiler.patchParser.measure(() {
      if (cls.isPatch) {
        compiler.patchParser.parsePatchClassNode(cls);
      }
    });
  }

  ScannerOptions getScannerOptionsFor(Element element) =>
      new ScannerOptions.from(compiler, element.library);

  ParserOptions get parserOptions => compiler.options;
}

class GlobalDependencyRegistry extends EagerRegistry {
  final Compiler compiler;
  Setlet<Element> _otherDependencies;

  GlobalDependencyRegistry(this.compiler) : super('GlobalDependencies', null);

  // TODO(johnniwinther): Rename world/universe/enqueuer through out the
  // compiler.
  @override
  Enqueuer get world => compiler.enqueuer.codegen;

  void registerDependency(Element element) {
    if (element == null) return;
    if (_otherDependencies == null) {
      _otherDependencies = new Setlet<Element>();
    }
    _otherDependencies.add(element.implementation);
  }

  Iterable<Element> get otherDependencies {
    return _otherDependencies != null ? _otherDependencies : const <Element>[];
  }
}

// TODO(sigmund): in the future, each of these classes should be self contained
// and not use references to `compiler`.
class _ResolvedUriTranslator implements ResolvedUriTranslator {
  Compiler compiler;
  _ResolvedUriTranslator(this.compiler);

  Uri translate(LibraryElement importingLibrary, Uri resolvedUri,
      [Spannable spannable]) =>
    compiler.translateResolvedUri(importingLibrary, resolvedUri, spannable);
}

class _ScriptLoader implements ScriptLoader {
  Compiler compiler;
  _ScriptLoader(this.compiler);

  Future<Script> readScript(Uri uri, [Spannable spannable]) =>
      compiler.readScript(uri, spannable);
}

class _ElementScanner implements ElementScanner {
  ScannerTask scanner;
  _ElementScanner(this.scanner);
  void scanLibrary(LibraryElement library) => scanner.scanLibrary(library);
  void scanUnit(CompilationUnitElement unit) => scanner.scan(unit);
}

class _EmptyEnvironment implements Environment {
  const _EmptyEnvironment();

  String valueOf(String key) => null;
}
