<commit_before>// 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.


/**
 * If true, print a warning for each method that was resolved, but not
 * compiled.
 */
final bool REPORT_EXCESS_RESOLUTION = false;

/**
 * If true, trace information on pass2 optimizations.
 */
final bool REPORT_PASS2_OPTIMIZATIONS = false;

/**
 * Contains backend-specific data that is used throughout the compilation of
 * one work item.
 */
class ItemCompilationContext {
}

class WorkItem {
  final ItemCompilationContext compilationContext;
  final Element element;
  TreeElements resolutionTree;
  bool allowSpeculativeOptimization = true;
  List<HTypeGuard> guards = const <HTypeGuard>[];

  WorkItem(this.element, this.resolutionTree, this.compilationContext);

  bool isAnalyzed() => resolutionTree !== null;

  void run(Compiler compiler, Enqueuer world) {
    CodeBuffer codeBuffer = world.universe.generatedCode[element];
    if (codeBuffer !== null) return;
    resolutionTree = compiler.analyze(this, world);
    compiler.codegen(this, world);
  }
}

class Backend {
  final Compiler compiler;

  Backend(this.compiler);

  void enqueueAllTopLevelFunctions(LibraryElement lib, Enqueuer world) {
    lib.forEachExport((Element e) {
      if (e.isFunction()) world.addToWorkList(e);
    });
  }

  abstract void enqueueHelpers(Enqueuer world);
  abstract void codegen(WorkItem work);
  abstract void processNativeClasses(Enqueuer world,
                                     Collection<LibraryElement> libraries);
  abstract void assembleProgram();
  abstract List<CompilerTask> get tasks();

  ItemCompilationContext createItemCompilationContext() {
    return new ItemCompilationContext();
  }
}

class Compiler implements DiagnosticListener {
  final Map<String, LibraryElement> libraries;
  int nextFreeClassId = 0;
  World world;
  String assembledCode;
  Namer namer;
  Types types;
  final bool enableTypeAssertions;
  final bool enableUserAssertions;

  final Tracer tracer;

  CompilerTask measuredTask;
  Element _currentElement;
  LibraryElement coreLibrary;
  LibraryElement coreImplLibrary;
  LibraryElement isolateLibrary;
  LibraryElement jsHelperLibrary;
  LibraryElement interceptorsLibrary;
  LibraryElement mainApp;

  ClassElement objectClass;
  ClassElement closureClass;
  ClassElement dynamicClass;
  ClassElement boolClass;
  ClassElement numClass;
  ClassElement intClass;
  ClassElement doubleClass;
  ClassElement stringClass;
  ClassElement functionClass;
  ClassElement nullClass;
  ClassElement listClass;
  Element assertMethod;

  /**
   * Interface used to determine if an object has the JavaScript
   * indexing behavior. The interface is only visible to specific
   * libraries.
   */
  ClassElement jsIndexingBehaviorInterface;

  Element get currentElement() => _currentElement;
  withCurrentElement(Element element, f()) {
    Element old = currentElement;
    _currentElement = element;
    try {
      return f();
    } catch (CompilerCancelledException ex) {
      throw;
    } catch (StackOverflowException ex) {
      // We cannot report anything useful in this case, because we
      // do not have enough stack space.
      throw;
    } catch (var ex) {
      try {
        unhandledExceptionOnElement(element);
      } catch (var doubleFault) {
        // Ignoring exceptions in exception handling.
      }
      throw;
    } finally {
      _currentElement = old;
    }
  }

  List<CompilerTask> tasks;
  ScannerTask scanner;
  DietParserTask dietParser;
  ParserTask parser;
  PatchParserTask patchParser;
  TreeValidatorTask validator;
  ResolverTask resolver;
  closureMapping.ClosureTask closureToClassMapper;
  TypeCheckerTask checker;
  ti.TypesTask typesTask;
  Backend backend;
  ConstantHandler constantHandler;
  EnqueueTask enqueuer;

  static final SourceString MAIN = const SourceString('main');
  static final SourceString CALL_OPERATOR_NAME = const SourceString('call');
  static final SourceString NO_SUCH_METHOD = const SourceString('noSuchMethod');
  static final SourceString NO_SUCH_METHOD_EXCEPTION =
      const SourceString('NoSuchMethodException');
  static final SourceString START_ROOT_ISOLATE =
      const SourceString('startRootIsolate');
  bool enabledNoSuchMethod = false;

  Stopwatch progress;

  static final int PHASE_SCANNING = 0;
  static final int PHASE_RESOLVING = 1;
  static final int PHASE_COMPILING = 2;
  static final int PHASE_RECOMPILING = 3;
  int phase;

  bool compilationFailed = false;

  bool hasCrashed = false;

  Compiler([this.tracer = const Tracer(),
            this.enableTypeAssertions = false,
            this.enableUserAssertions = false,
            bool emitJavascript = true,
            validateUnparse = false,
            generateSourceMap = true])
      : libraries = new Map<String, LibraryElement>(),
        world = new World(),
        progress = new Stopwatch.start() {
    namer = new Namer(this);
    constantHandler = new ConstantHandler(this);
    scanner = new ScannerTask(this);
    dietParser = new DietParserTask(this);
    parser = new ParserTask(this);
    patchParser = new PatchParserTask(this);
    validator = new TreeValidatorTask(this);
    resolver = new ResolverTask(this);
    closureToClassMapper = new closureMapping.ClosureTask(this);
    checker = new TypeCheckerTask(this);
    typesTask = new ti.TypesTask(this);
    backend = emitJavascript ?
        new js_backend.JavaScriptBackend(this, generateSourceMap) :
        new dart_backend.DartBackend(this, validateUnparse);
    enqueuer = new EnqueueTask(this);
    tasks = [scanner, dietParser, parser, resolver, closureToClassMapper,
             checker, typesTask, constantHandler, enqueuer];
    tasks.addAll(backend.tasks);
  }

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

  int getNextFreeClassId() => nextFreeClassId++;

  void ensure(bool condition) {
    if (!condition) cancel('failed assertion in leg');
  }

  void unimplemented(String methodName,
                     [Node node, Token token, HInstruction instruction,
                      Element element]) {
    internalError("$methodName not implemented",
                  node, token, instruction, element);
  }

  void internalError(String message,
                     [Node node, Token token, HInstruction instruction,
                      Element element]) {
    cancel('Internal error: $message', node, token, instruction, element);
  }

  void internalErrorOnElement(Element element, String message) {
    internalError(message, element: element);
  }

  void unhandledExceptionOnElement(Element element) {
    if (hasCrashed) return;
    hasCrashed = true;
    reportDiagnostic(spanFromElement(element),
                     MessageKind.COMPILER_CRASHED.error().toString(),
                     api.Diagnostic.CRASH);
    // TODO(ahe): Obtain the build ID.
    var buildId = 'build number could not be determined';
    print(MessageKind.PLEASE_REPORT_THE_CRASH.message([buildId]));
  }

  void cancel([String reason, Node node, Token token,
               HInstruction instruction, Element element]) {
    assembledCode = null; // Compilation failed. Make sure that we
                          // don't return a bogus result.
    SourceSpan span = null;
    if (node !== null) {
      span = spanFromNode(node);
    } else if (token !== null) {
      span = spanFromTokens(token, token);
    } else if (instruction !== null) {
      span = spanFromElement(currentElement);
    } else if (element !== null) {
      span = spanFromElement(element);
    } else {
      throw 'No error location for error: $reason';
    }
    reportDiagnostic(span, reason, api.Diagnostic.ERROR);
    throw new CompilerCancelledException(reason);
  }

  void reportFatalError(String reason, Element element,
                        [Node node, Token token, HInstruction instruction]) {
    withCurrentElement(element, () {
      cancel(reason, node, token, instruction, element);
    });
  }

  void log(message) {
    reportDiagnostic(null, message, api.Diagnostic.VERBOSE_INFO);
  }

  bool run(Uri uri) {
    try {
      runCompiler(uri);
    } catch (CompilerCancelledException exception) {
      log(exception.toString());
      log('compilation failed');
      return false;
    }
    tracer.close();
    log('compilation succeeded');
    return true;
  }

  void enableNoSuchMethod(Element element) {
    // TODO(ahe): Move this method to Enqueuer.
    if (enabledNoSuchMethod) return;
    if (element.getEnclosingClass() === objectClass) {
      enqueuer.resolution.registerDynamicInvocationOf(element);
      return;
    }
    enabledNoSuchMethod = true;
    Selector selector = new Selector.noSuchMethod();
    enqueuer.resolution.registerInvocation(NO_SUCH_METHOD, selector);
    enqueuer.codegen.registerInvocation(NO_SUCH_METHOD, selector);
  }

  void enableIsolateSupport(LibraryElement element) {
    // TODO(ahe): Move this method to Enqueuer.
    isolateLibrary = element;
    enqueuer.resolution.addToWorkList(element.find(START_ROOT_ISOLATE));
    enqueuer.resolution.addToWorkList(
        element.find(const SourceString('_currentIsolate')));
    enqueuer.resolution.addToWorkList(
        element.find(const SourceString('_callInIsolate')));
    enqueuer.codegen.addToWorkList(element.find(START_ROOT_ISOLATE));
  }

  bool hasIsolateSupport() => isolateLibrary !== null;

  void onLibraryLoaded(LibraryElement library, Uri uri) {
    if (uri.toString() == 'dart:isolate') {
      enableIsolateSupport(library);
    }
    if (dynamicClass !== null) {
      // When loading the built-in libraries, dynamicClass is null. We
      // take advantage of this as core and coreimpl import js_helper
      // and see Dynamic this way.
      withCurrentElement(dynamicClass, () {
        library.addToScope(dynamicClass, this);
      });
    }
  }

  abstract LibraryElement scanBuiltinLibrary(String filename);

  void initializeSpecialClasses() {
    bool coreLibValid = true;
    ClassElement lookupSpecialClass(SourceString name) {
      ClassElement result = coreLibrary.find(name);
      if (result === null) {
        log('core library class $name missing');
        coreLibValid = false;
      }
      return result;
    }
    objectClass = lookupSpecialClass(const SourceString('Object'));
    boolClass = lookupSpecialClass(const SourceString('bool'));
    numClass = lookupSpecialClass(const SourceString('num'));
    intClass = lookupSpecialClass(const SourceString('int'));
    doubleClass = lookupSpecialClass(const SourceString('double'));
    stringClass = lookupSpecialClass(const SourceString('String'));
    functionClass = lookupSpecialClass(const SourceString('Function'));
    listClass = lookupSpecialClass(const SourceString('List'));
    closureClass = lookupSpecialClass(const SourceString('Closure'));
    dynamicClass = lookupSpecialClass(const SourceString('Dynamic'));
    nullClass = lookupSpecialClass(const SourceString('Null'));
    types = new Types(this, dynamicClass);
    if (!coreLibValid) {
      cancel('core library does not contain required classes');
    }

    jsIndexingBehaviorInterface =
        findHelper(const SourceString('JavaScriptIndexingBehavior'));
  }

  void scanBuiltinLibraries() {
    coreImplLibrary = scanBuiltinLibrary('coreimpl');
    jsHelperLibrary = scanBuiltinLibrary('_js_helper');
    interceptorsLibrary = scanBuiltinLibrary('_interceptors');

    addForeignFunctions(jsHelperLibrary);
    addForeignFunctions(interceptorsLibrary);

    libraries['dart:core'] = coreLibrary;
    libraries['dart:coreimpl'] = coreImplLibrary;

    assertMethod = coreLibrary.find(const SourceString('assert'));

    initializeSpecialClasses();

    //patchDartLibrary(coreLibrary, 'core');
    //patchDartLibrary(coreImplLibrary, 'coreimpl');
  }

  void importCoreLibrary(LibraryElement library) {
    Uri coreUri = new Uri.fromComponents(scheme: 'dart', path: 'core');
    if (coreLibrary === null) {
      coreLibrary = scanner.loadLibrary(coreUri, null, coreUri);
    }
    scanner.importLibrary(library,
                          coreLibrary,
                          null,
                          library.entryCompilationUnit);
  }

  void patchDartLibrary(LibraryElement library, String dartLibraryPath) {
    if (library.isPatched) return;
    Uri patchUri = resolvePatchUri(dartLibraryPath);
    if (patchUri !== null) {
       patchParser.patchLibrary(patchUri, library);
      // We allow foreign functions in patched libraries.
      addForeignFunctions(library);  // Is safe even if already added.
    }
  }

  void applyContainerPatch(ScopeContainerElement original,
                           Link<Element> patches) {
    while (!patches.isEmpty()) {
      Element patchElement = patches.head;
      Element originalElement = original.localLookup(patchElement.name);
      if (patchElement.isAccessor()) {
        // TODO(lrn): When we change to always add accessors to members, and
        // not add abstract fields, the logic here should be reversed.
        // For now, access getters through the abstract field and skip
        // any accessors.
      } else if (patchElement.kind === ElementKind.ABSTRACT_FIELD) {
        // Getters and setters are kept inside a synthetic field.
        if (originalElement !== null &&
            originalElement.kind !== ElementKind.ABSTRACT_FIELD) {
          internalError("Cannot patch non-getter/setter with getter/setter",
                        element: originalElement);
        }
        AbstractFieldElement patchField = patchElement;<commit_msg>Only add JS once, and not to very single patched library.<commit_after>// 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.


/**
 * If true, print a warning for each method that was resolved, but not
 * compiled.
 */
final bool REPORT_EXCESS_RESOLUTION = false;

/**
 * If true, trace information on pass2 optimizations.
 */
final bool REPORT_PASS2_OPTIMIZATIONS = false;

/**
 * Contains backend-specific data that is used throughout the compilation of
 * one work item.
 */
class ItemCompilationContext {
}

class WorkItem {
  final ItemCompilationContext compilationContext;
  final Element element;
  TreeElements resolutionTree;
  bool allowSpeculativeOptimization = true;
  List<HTypeGuard> guards = const <HTypeGuard>[];

  WorkItem(this.element, this.resolutionTree, this.compilationContext);

  bool isAnalyzed() => resolutionTree !== null;

  void run(Compiler compiler, Enqueuer world) {
    CodeBuffer codeBuffer = world.universe.generatedCode[element];
    if (codeBuffer !== null) return;
    resolutionTree = compiler.analyze(this, world);
    compiler.codegen(this, world);
  }
}

class Backend {
  final Compiler compiler;

  Backend(this.compiler);

  void enqueueAllTopLevelFunctions(LibraryElement lib, Enqueuer world) {
    lib.forEachExport((Element e) {
      if (e.isFunction()) world.addToWorkList(e);
    });
  }

  abstract void enqueueHelpers(Enqueuer world);
  abstract void codegen(WorkItem work);
  abstract void processNativeClasses(Enqueuer world,
                                     Collection<LibraryElement> libraries);
  abstract void assembleProgram();
  abstract List<CompilerTask> get tasks();

  ItemCompilationContext createItemCompilationContext() {
    return new ItemCompilationContext();
  }
}

class Compiler implements DiagnosticListener {
  final Map<String, LibraryElement> libraries;
  int nextFreeClassId = 0;
  World world;
  String assembledCode;
  Namer namer;
  Types types;
  final bool enableTypeAssertions;
  final bool enableUserAssertions;

  final Tracer tracer;

  CompilerTask measuredTask;
  Element _currentElement;
  LibraryElement coreLibrary;
  LibraryElement coreImplLibrary;
  LibraryElement isolateLibrary;
  LibraryElement jsHelperLibrary;
  LibraryElement interceptorsLibrary;
  LibraryElement mainApp;

  ClassElement objectClass;
  ClassElement closureClass;
  ClassElement dynamicClass;
  ClassElement boolClass;
  ClassElement numClass;
  ClassElement intClass;
  ClassElement doubleClass;
  ClassElement stringClass;
  ClassElement functionClass;
  ClassElement nullClass;
  ClassElement listClass;
  Element assertMethod;

  /**
   * Interface used to determine if an object has the JavaScript
   * indexing behavior. The interface is only visible to specific
   * libraries.
   */
  ClassElement jsIndexingBehaviorInterface;

  Element get currentElement() => _currentElement;
  withCurrentElement(Element element, f()) {
    Element old = currentElement;
    _currentElement = element;
    try {
      return f();
    } catch (CompilerCancelledException ex) {
      throw;
    } catch (StackOverflowException ex) {
      // We cannot report anything useful in this case, because we
      // do not have enough stack space.
      throw;
    } catch (var ex) {
      try {
        unhandledExceptionOnElement(element);
      } catch (var doubleFault) {
        // Ignoring exceptions in exception handling.
      }
      throw;
    } finally {
      _currentElement = old;
    }
  }

  List<CompilerTask> tasks;
  ScannerTask scanner;
  DietParserTask dietParser;
  ParserTask parser;
  PatchParserTask patchParser;
  TreeValidatorTask validator;
  ResolverTask resolver;
  closureMapping.ClosureTask closureToClassMapper;
  TypeCheckerTask checker;
  ti.TypesTask typesTask;
  Backend backend;
  ConstantHandler constantHandler;
  EnqueueTask enqueuer;

  static final SourceString MAIN = const SourceString('main');
  static final SourceString CALL_OPERATOR_NAME = const SourceString('call');
  static final SourceString NO_SUCH_METHOD = const SourceString('noSuchMethod');
  static final SourceString NO_SUCH_METHOD_EXCEPTION =
      const SourceString('NoSuchMethodException');
  static final SourceString START_ROOT_ISOLATE =
      const SourceString('startRootIsolate');
  bool enabledNoSuchMethod = false;

  Stopwatch progress;

  static final int PHASE_SCANNING = 0;
  static final int PHASE_RESOLVING = 1;
  static final int PHASE_COMPILING = 2;
  static final int PHASE_RECOMPILING = 3;
  int phase;

  bool compilationFailed = false;

  bool hasCrashed = false;

  Compiler([this.tracer = const Tracer(),
            this.enableTypeAssertions = false,
            this.enableUserAssertions = false,
            bool emitJavascript = true,
            validateUnparse = false,
            generateSourceMap = true])
      : libraries = new Map<String, LibraryElement>(),
        world = new World(),
        progress = new Stopwatch.start() {
    namer = new Namer(this);
    constantHandler = new ConstantHandler(this);
    scanner = new ScannerTask(this);
    dietParser = new DietParserTask(this);
    parser = new ParserTask(this);
    patchParser = new PatchParserTask(this);
    validator = new TreeValidatorTask(this);
    resolver = new ResolverTask(this);
    closureToClassMapper = new closureMapping.ClosureTask(this);
    checker = new TypeCheckerTask(this);
    typesTask = new ti.TypesTask(this);
    backend = emitJavascript ?
        new js_backend.JavaScriptBackend(this, generateSourceMap) :
        new dart_backend.DartBackend(this, validateUnparse);
    enqueuer = new EnqueueTask(this);
    tasks = [scanner, dietParser, parser, resolver, closureToClassMapper,
             checker, typesTask, constantHandler, enqueuer];
    tasks.addAll(backend.tasks);
  }

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

  int getNextFreeClassId() => nextFreeClassId++;

  void ensure(bool condition) {
    if (!condition) cancel('failed assertion in leg');
  }

  void unimplemented(String methodName,
                     [Node node, Token token, HInstruction instruction,
                      Element element]) {
    internalError("$methodName not implemented",
                  node, token, instruction, element);
  }

  void internalError(String message,
                     [Node node, Token token, HInstruction instruction,
                      Element element]) {
    cancel('Internal error: $message', node, token, instruction, element);
  }

  void internalErrorOnElement(Element element, String message) {
    internalError(message, element: element);
  }

  void unhandledExceptionOnElement(Element element) {
    if (hasCrashed) return;
    hasCrashed = true;
    reportDiagnostic(spanFromElement(element),
                     MessageKind.COMPILER_CRASHED.error().toString(),
                     api.Diagnostic.CRASH);
    // TODO(ahe): Obtain the build ID.
    var buildId = 'build number could not be determined';
    print(MessageKind.PLEASE_REPORT_THE_CRASH.message([buildId]));
  }

  void cancel([String reason, Node node, Token token,
               HInstruction instruction, Element element]) {
    assembledCode = null; // Compilation failed. Make sure that we
                          // don't return a bogus result.
    SourceSpan span = null;
    if (node !== null) {
      span = spanFromNode(node);
    } else if (token !== null) {
      span = spanFromTokens(token, token);
    } else if (instruction !== null) {
      span = spanFromElement(currentElement);
    } else if (element !== null) {
      span = spanFromElement(element);
    } else {
      throw 'No error location for error: $reason';
    }
    reportDiagnostic(span, reason, api.Diagnostic.ERROR);
    throw new CompilerCancelledException(reason);
  }

  void reportFatalError(String reason, Element element,
                        [Node node, Token token, HInstruction instruction]) {
    withCurrentElement(element, () {
      cancel(reason, node, token, instruction, element);
    });
  }

  void log(message) {
    reportDiagnostic(null, message, api.Diagnostic.VERBOSE_INFO);
  }

  bool run(Uri uri) {
    try {
      runCompiler(uri);
    } catch (CompilerCancelledException exception) {
      log(exception.toString());
      log('compilation failed');
      return false;
    }
    tracer.close();
    log('compilation succeeded');
    return true;
  }

  void enableNoSuchMethod(Element element) {
    // TODO(ahe): Move this method to Enqueuer.
    if (enabledNoSuchMethod) return;
    if (element.getEnclosingClass() === objectClass) {
      enqueuer.resolution.registerDynamicInvocationOf(element);
      return;
    }
    enabledNoSuchMethod = true;
    Selector selector = new Selector.noSuchMethod();
    enqueuer.resolution.registerInvocation(NO_SUCH_METHOD, selector);
    enqueuer.codegen.registerInvocation(NO_SUCH_METHOD, selector);
  }

  void enableIsolateSupport(LibraryElement element) {
    // TODO(ahe): Move this method to Enqueuer.
    isolateLibrary = element;
    enqueuer.resolution.addToWorkList(element.find(START_ROOT_ISOLATE));
    enqueuer.resolution.addToWorkList(
        element.find(const SourceString('_currentIsolate')));
    enqueuer.resolution.addToWorkList(
        element.find(const SourceString('_callInIsolate')));
    enqueuer.codegen.addToWorkList(element.find(START_ROOT_ISOLATE));
  }

  bool hasIsolateSupport() => isolateLibrary !== null;

  void onLibraryLoaded(LibraryElement library, Uri uri) {
    if (uri.toString() == 'dart:isolate') {
      enableIsolateSupport(library);
    }
    if (dynamicClass !== null) {
      // When loading the built-in libraries, dynamicClass is null. We
      // take advantage of this as core and coreimpl import js_helper
      // and see Dynamic this way.
      withCurrentElement(dynamicClass, () {
        library.addToScope(dynamicClass, this);
      });
    }
  }

  abstract LibraryElement scanBuiltinLibrary(String filename);

  void initializeSpecialClasses() {
    bool coreLibValid = true;
    ClassElement lookupSpecialClass(SourceString name) {
      ClassElement result = coreLibrary.find(name);
      if (result === null) {
        log('core library class $name missing');
        coreLibValid = false;
      }
      return result;
    }
    objectClass = lookupSpecialClass(const SourceString('Object'));
    boolClass = lookupSpecialClass(const SourceString('bool'));
    numClass = lookupSpecialClass(const SourceString('num'));
    intClass = lookupSpecialClass(const SourceString('int'));
    doubleClass = lookupSpecialClass(const SourceString('double'));
    stringClass = lookupSpecialClass(const SourceString('String'));
    functionClass = lookupSpecialClass(const SourceString('Function'));
    listClass = lookupSpecialClass(const SourceString('List'));
    closureClass = lookupSpecialClass(const SourceString('Closure'));
    dynamicClass = lookupSpecialClass(const SourceString('Dynamic'));
    nullClass = lookupSpecialClass(const SourceString('Null'));
    types = new Types(this, dynamicClass);
    if (!coreLibValid) {
      cancel('core library does not contain required classes');
    }

    jsIndexingBehaviorInterface =
        findHelper(const SourceString('JavaScriptIndexingBehavior'));
  }

  void scanBuiltinLibraries() {
    coreImplLibrary = scanBuiltinLibrary('coreimpl');
    jsHelperLibrary = scanBuiltinLibrary('_js_helper');
    interceptorsLibrary = scanBuiltinLibrary('_interceptors');

    addForeignFunctions(jsHelperLibrary);
    addForeignFunctions(interceptorsLibrary);

    libraries['dart:core'] = coreLibrary;
    libraries['dart:coreimpl'] = coreImplLibrary;

    assertMethod = coreLibrary.find(const SourceString('assert'));

    initializeSpecialClasses();

    //patchDartLibrary(coreLibrary, 'core');
    //patchDartLibrary(coreImplLibrary, 'coreimpl');
  }

  void importCoreLibrary(LibraryElement library) {
    Uri coreUri = new Uri.fromComponents(scheme: 'dart', path: 'core');
    if (coreLibrary === null) {
      coreLibrary = scanner.loadLibrary(coreUri, null, coreUri);
    }
    scanner.importLibrary(library,
                          coreLibrary,
                          null,
                          library.entryCompilationUnit);
  }

  void patchDartLibrary(LibraryElement library, String dartLibraryPath) {
    if (library.isPatched) return;
    Uri patchUri = resolvePatchUri(dartLibraryPath);
    if (patchUri !== null) {
      patchParser.patchLibrary(patchUri, library);
    }
  }

  void applyContainerPatch(ScopeContainerElement original,
                           Link<Element> patches) {
    while (!patches.isEmpty()) {
      Element patchElement = patches.head;
      Element originalElement = original.localLookup(patchElement.name);
      if (patchElement.isAccessor()) {
        // TODO(lrn): When we change to always add accessors to members, and
        // not add abstract fields, the logic here should be reversed.
        // For now, access getters through the abstract field and skip
        // any accessors.
      } else if (patchElement.kind === ElementKind.ABSTRACT_FIELD) {
        // Getters and setters are kept inside a synthetic field.
        if (originalElement !== null &&
            originalElement.kind !== ElementKind.ABSTRACT_FIELD) {
          internalError("Cannot patch non-getter/setter with getter/setter",
                        element: originalElement);
        }
        AbstractFieldElement patchField = patchElement;
{'fraction_non_alphanumeric': 0.09130973193473194, 'fraction_numerical': 0.0008012820512820513, 'mean_word_length': 3.473281199087651, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5204684', 'n_tokens_mistral': 7500, 'n_tokens_neox': 7302, 'n_words': 1969}