// Copyright (c) 2014, 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.js_emitter.lazy_emitter.model_emitter;

import 'package:js_runtime/shared/embedded_names.dart'
    show
        CREATE_NEW_ISOLATE,
        DEFERRED_LIBRARY_URIS,
        DEFERRED_LIBRARY_HASHES,
        GET_TYPE_FROM_NAME,
        INITIALIZE_LOADED_HUNK,
        INTERCEPTORS_BY_TAG,
        IS_HUNK_INITIALIZED,
        IS_HUNK_LOADED,
        LEAF_TAGS,
        MANGLED_GLOBAL_NAMES,
        METADATA,
        TYPE_TO_INTERCEPTOR_MAP,
        TYPES;

import '../../../compiler_new.dart';
import '../../compiler.dart' show Compiler;
import '../../constants/values.dart' show ConstantValue, FunctionConstantValue;
import '../../common_elements.dart' show CommonElements;
import '../../elements/elements.dart' show ClassElement, MethodElement;
import '../../js/js.dart' as js;
import '../../js_backend/js_backend.dart'
    show JavaScriptBackend, Namer, ConstantEmitter;
import '../../js_backend/interceptor_data.dart';
import '../../world.dart';
import '../constant_ordering.dart' show ConstantOrdering;
import '../code_emitter_task.dart';
import '../js_emitter.dart' show NativeEmitter;
import '../js_emitter.dart' show NativeGenerator, buildTearOffCode;
import '../model.dart';
import '../sorter.dart' show Sorter;

class ModelEmitter {
  final Compiler compiler;
  final Namer namer;
  ConstantEmitter constantEmitter;
  final NativeEmitter nativeEmitter;
  final ClosedWorld _closedWorld;
  final ConstantOrdering _constantOrdering;

  JavaScriptBackend get backend => compiler.backend;

  /// For deferred loading we communicate the initializers via this global var.
  static const String deferredInitializersGlobal =
      r"$__dart_deferred_initializers__";

  static const String deferredExtension = "part.js";

  static const String typeNameProperty = r"builtin$cls";

  ModelEmitter(this.compiler, this.namer, this.nativeEmitter, this._closedWorld,
      Sorter sorter, CodeEmitterTask task)
      : _constantOrdering = new ConstantOrdering(sorter) {
    this.constantEmitter = new ConstantEmitter(
        compiler.options,
        _closedWorld.commonElements,
        compiler.codegenWorldBuilder,
        _closedWorld.rtiNeed,
        compiler.backend.rtiEncoder,
        namer,
        task,
        this.generateConstantReference,
        constantListGenerator);
  }

  InterceptorData get _interceptorData => _closedWorld.interceptorData;

  js.Expression constantListGenerator(js.Expression array) {
    // TODO(floitsch): remove hard-coded name.
    return js.js('makeConstList(#)', [array]);
  }

  js.Expression generateEmbeddedGlobalAccess(String global) {
    return js.js(generateEmbeddedGlobalAccessString(global));
  }

  String generateEmbeddedGlobalAccessString(String global) {
    // TODO(floitsch): don't use 'init' as global embedder storage.
    return 'init.$global';
  }

  bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) {
    if (constant.isFunction) return true; // Already emitted.
    if (constant.isPrimitive) return true; // Inlined.
    if (constant.isDummy) return true; // Inlined.
    // The name is null when the constant is already a JS constant.
    // TODO(floitsch): every constant should be registered, so that we can
    // share the ones that take up too much space (like some strings).
    if (namer.constantName(constant) == null) return true;
    return false;
  }

  // TODO(floitsch): copied from full emitter. Adjust or share.
  int compareConstants(ConstantValue a, ConstantValue b) {
    // Inlined constants don't affect the order and sometimes don't even have
    // names.
    int cmp1 = isConstantInlinedOrAlreadyEmitted(a) ? 0 : 1;
    int cmp2 = isConstantInlinedOrAlreadyEmitted(b) ? 0 : 1;
    if (cmp1 + cmp2 < 2) return cmp1 - cmp2;

    // Emit constant interceptors first. Constant interceptors for primitives
    // might be used by code that builds other constants.  See Issue 18173.
    if (a.isInterceptor != b.isInterceptor) {
      return a.isInterceptor ? -1 : 1;
    }

    // Sorting by the long name clusters constants with the same constructor
    // which compresses a tiny bit better.
    int r = namer.constantLongName(a).compareTo(namer.constantLongName(b));
    if (r != 0) return r;

    // Resolve collisions in the long name by using a structural order.
    return _constantOrdering.compare(a, b);
  }

  js.Expression generateStaticClosureAccess(MethodElement element) {
    return js.js('#.#()', [
      namer.globalObjectForMember(element),
      namer.staticClosureName(element)
    ]);
  }

  js.Expression generateConstantReference(ConstantValue value) {
    if (value.isFunction) {
      FunctionConstantValue functionConstant = value;
      return generateStaticClosureAccess(functionConstant.element);
    }

    // We are only interested in the "isInlined" part, but it does not hurt to
    // test for the other predicates.
    if (isConstantInlinedOrAlreadyEmitted(value)) {
      return constantEmitter.generate(value);
    }
    return js.js('#.#()',
        [namer.globalObjectForConstant(value), namer.constantName(value)]);
  }

  int emitProgram(Program program) {
    List<Fragment> fragments = program.fragments;
    MainFragment mainFragment = fragments.first;
    Iterable<Fragment> deferredFragments = program.deferredFragments;

    int totalSize = 0;

    // We have to emit the deferred fragments first, since we need their
    // deferred hash (which depends on the output) when emitting the main
    // fragment.
    List<js.Expression> fragmentsCode = deferredFragments.map((deferredUnit) {
      js.Expression types =
          program.metadataTypesForOutputUnit(deferredUnit.outputUnit);
      return emitDeferredFragment(types, deferredUnit, program.holders);
    }).toList();

    js.Statement mainAst = emitMainFragment(program);

    js.TokenCounter counter = new js.TokenCounter();
    fragmentsCode.forEach(counter.countTokens);
    counter.countTokens(mainAst);

    program.finalizers.forEach((js.TokenFinalizer f) => f.finalizeTokens());

    // TODO(johnniwinther): Support source maps in this emitter.
    for (int i = 0; i < fragmentsCode.length; ++i) {
      String code = js
          .createCodeBuffer(fragmentsCode[i], compiler.options,
              backend.sourceInformationStrategy)
          .getText();
      totalSize += code.length;
      compiler.outputProvider.createOutputSink(
          fragments[i + 1].outputFileName, deferredExtension, OutputType.jsPart)
        ..add(code)
        ..close();
    }

    String mainCode = js
        .createCodeBuffer(
            mainAst, compiler.options, backend.sourceInformationStrategy)
        .getText();
    compiler.outputProvider
        .createOutputSink(mainFragment.outputFileName, 'js', OutputType.js)
          ..add(buildGeneratedBy(compiler))
          ..add(mainCode)
          ..close();
    totalSize += mainCode.length;

    return totalSize;
  }

  /// Returns a [js.Literal] that represents the string result of unparsing
  /// [value].
  ///
  /// The returned node will, when its string value is requested, pretty-print
  /// the given [value] and, if [protectForEval] is true, wrap the resulting
  /// string in parenthesis. The result is also escaped.
  ///
  /// See [_UnparsedNode] for details.
  js.Literal unparse(Compiler compiler, js.Node value,
      {bool protectForEval: true}) {
    return new js.UnparsedNode(value, compiler.options, protectForEval);
  }

  String buildGeneratedBy(compiler) {
    var suffix = '';
    if (compiler.options.hasBuildId) {
      suffix = ' version: ${compiler.options.buildId}';
    }
    return '// Generated by dart2js, the Dart to JavaScript compiler$suffix.\n';
  }

  js.Statement emitMainFragment(Program program) {
    MainFragment fragment = program.fragments.first;
    List<js.Expression> elements = fragment.libraries.map(emitLibrary).toList();
    elements.add(
        emitLazilyInitializedStatics(fragment.staticLazilyInitializedFields));
    elements.add(emitConstants(fragment.constants));

    js.Expression code = new js.ArrayInitializer(elements);

    Map<String, dynamic> holes = {
      'deferredInitializer': emitDeferredInitializerGlobal(program.loadMap),
      'holders': emitHolders(program.holders),
      'tearOff': buildTearOffCode(compiler.options, backend.emitter.emitter,
          backend.namer, _closedWorld.commonElements),
      'parseFunctionDescriptor':
          js.js.statement(parseFunctionDescriptorBoilerplate, {
        'argumentCount': js.string(namer.requiredParameterField),
        'defaultArgumentValues': js.string(namer.defaultValuesField),
        'callName': js.string(namer.callNameField)
      }),
      'cyclicThrow': backend.emitter
          .staticFunctionAccess(_closedWorld.commonElements.cyclicThrowHelper),
      'outputContainsConstantList': program.outputContainsConstantList,
      'embeddedGlobals': emitEmbeddedGlobals(program),
      'readMetadataTypeFunction': readMetadataTypeFunction,
      'staticNonFinals':
          emitStaticNonFinalFields(fragment.staticNonFinalFields),
      'operatorIsPrefix': js.string(namer.operatorIsPrefix),
      'callName': js.string(namer.callNameField),
      'argumentCount': js.string(namer.requiredParameterField),
      'defaultArgumentValues': js.string(namer.defaultValuesField),
      'eagerClasses': emitEagerClassInitializations(fragment.libraries),
      'invokeMain': fragment.invokeMain,
      'code': code
    };

    holes.addAll(nativeHoles(program));

    return js.js.statement(boilerplate, holes);
  }

  Map<String, dynamic> nativeHoles(Program program) {
    Map<String, dynamic> nativeHoles = <String, dynamic>{};

    js.Statement nativeIsolateAffinityTagInitialization;
    if (NativeGenerator
        .needsIsolateAffinityTagInitialization(_closedWorld.backendUsage)) {
      nativeIsolateAffinityTagInitialization =
          NativeGenerator.generateIsolateAffinityTagInitialization(
              _closedWorld.backendUsage,
              generateEmbeddedGlobalAccess,
              // TODO(floitsch): internStringFunction.
              js.js("(function(x) { return x; })", []));
    } else {
      nativeIsolateAffinityTagInitialization = js.js.statement(";");
    }
    nativeHoles['nativeIsolateAffinityTagInitialization'] =
        nativeIsolateAffinityTagInitialization;

    js.Expression nativeInfoAccess = js.js('nativeInfo', []);
    js.Expression constructorAccess = js.js('constructor', []);
    Function subclassReadGenerator = (js.Expression subclass) {
      return js.js('holdersMap[#][#].ensureResolved()', [subclass, subclass]);
    };
    js.Expression interceptorsByTagAccess =
        generateEmbeddedGlobalAccess(INTERCEPTORS_BY_TAG);
    js.Expression leafTagsAccess = generateEmbeddedGlobalAccess(LEAF_TAGS);
    js.Statement nativeInfoHandler = NativeGenerator.buildNativeInfoHandler(
        nativeInfoAccess,
        constructorAccess,
        subclassReadGenerator,
        interceptorsByTagAccess,
        leafTagsAccess);

    nativeHoles['needsNativeSupport'] = program.needsNativeSupport;
    nativeHoles['needsNoNativeSupport'] = !program.needsNativeSupport;
    nativeHoles['nativeInfoHandler'] = nativeInfoHandler;

    return nativeHoles;
  }

  js.Block emitHolders(List<Holder> holders) {
    // The top-level variables for holders must *not* be renamed by the
    // JavaScript pretty printer because a lot of code already uses the
    // non-renamed names. The generated code looks like this:
    //
    //    var H = {}, ..., G = {};
    //    var holders = [ H, ..., G ];
    //
    // and it is inserted at the top of the top-level function expression
    // that covers the entire program.

    List<js.Statement> statements = [
      new js.ExpressionStatement(new js.VariableDeclarationList(holders
          .map((e) => new js.VariableInitialization(
              new js.VariableDeclaration(e.name, allowRename: false),
              new js.ObjectInitializer(const [])))
          .toList())),
      js.js.statement(
          'var holders = #',
          new js.ArrayInitializer(holders
              .map((e) => new js.VariableUse(e.name))
              .toList(growable: false))),
      js.js.statement('var holdersMap = Object.create(null)')
    ];
    return new js.Block(statements);
  }

  js.Block emitEmbeddedGlobals(Program program) {
    List<js.Property> globals = <js.Property>[];

    if (program.loadMap.isNotEmpty) {
      globals.addAll(emitEmbeddedGlobalsForDeferredLoading(program.loadMap));
    }

    if (program.typeToInterceptorMap != null) {
      globals.add(new js.Property(
          js.string(TYPE_TO_INTERCEPTOR_MAP), program.typeToInterceptorMap));
    }

    if (program.hasIsolateSupport) {
      String isolateName = namer.staticStateHolder;
      globals.add(new js.Property(js.string(CREATE_NEW_ISOLATE),
          js.js('function () { return $isolateName; }')));
      // TODO(floitsch): add remaining isolate functions.
    }

    globals.add(emitMangledGlobalNames());

    globals.add(emitGetTypeFromName());

    globals.addAll(emitMetadata(program));

    if (program.needsNativeSupport) {
      globals.add(new js.Property(
          js.string(INTERCEPTORS_BY_TAG), js.js('Object.create(null)', [])));
      globals.add(new js.Property(
          js.string(LEAF_TAGS), js.js('Object.create(null)', [])));
    }

    js.ObjectInitializer globalsObject = new js.ObjectInitializer(globals);

    List<js.Statement> statements = [
      new js.ExpressionStatement(new js.VariableDeclarationList([
        new js.VariableInitialization(
            new js.VariableDeclaration("init", allowRename: false),
            globalsObject)
      ]))
    ];
    return new js.Block(statements);
  }

  js.Property emitMangledGlobalNames() {
    List<js.Property> names = <js.Property>[];

    CommonElements commonElements = _closedWorld.commonElements;
    // We want to keep the original names for the most common core classes when
    // calling toString on them.
    List<ClassElement> nativeClassesNeedingUnmangledName = [
      commonElements.intClass,
      commonElements.doubleClass,
      commonElements.numClass,
      commonElements.stringClass,
      commonElements.boolClass,
      commonElements.nullClass,
      commonElements.listClass
    ];
    nativeClassesNeedingUnmangledName.forEach((element) {
      names.add(new js.Property(
          js.quoteName(namer.className(element)), js.string(element.name)));
    });

    return new js.Property(
        js.string(MANGLED_GLOBAL_NAMES), new js.ObjectInitializer(names));
  }

  js.Statement emitDeferredInitializerGlobal(Map loadMap) {
    if (loadMap.isEmpty) return new js.Block.empty();

    return js.js.statement("""
  if (typeof($deferredInitializersGlobal) === 'undefined')
    var $deferredInitializersGlobal = Object.create(null);""");
  }

  Iterable<js.Property> emitEmbeddedGlobalsForDeferredLoading(
      Map<String, List<Fragment>> loadMap) {
    List<js.Property> globals = <js.Property>[];

    js.ArrayInitializer fragmentUris(List<Fragment> fragments) {
      return js.stringArray(fragments
          .map((fragment) => "${fragment.outputFileName}.$deferredExtension"));
    }

    js.ArrayInitializer fragmentHashes(List<Fragment> fragments) {
      // TODO(floitsch): the hash must depend on the generated code.
      return js.numArray(fragments.map((fragment) => fragment.hashCode));
    }

    List<js.Property> uris = new List<js.Property>(loadMap.length);
    List<js.Property> hashes = new List<js.Property>(loadMap.length);
    int count = 0;
    loadMap.forEach((String loadId, List<Fragment> fragmentList) {
      uris[count] =
          new js.Property(js.string(loadId), fragmentUris(fragmentList));
      hashes[count] =
          new js.Property(js.string(loadId), fragmentHashes(fragmentList));
      count++;
    });

    globals.add(new js.Property(
        js.string(DEFERRED_LIBRARY_URIS), new js.ObjectInitializer(uris)));
    globals.add(new js.Property(
        js.string(DEFERRED_LIBRARY_HASHES), new js.ObjectInitializer(hashes)));

    js.Expression isHunkLoadedFunction =
        js.js("function(hash) { return !!$deferredInitializersGlobal[hash]; }");
    globals
        .add(new js.Property(js.string(IS_HUNK_LOADED), isHunkLoadedFunction));

    js.Expression isHunkInitializedFunction =
        js.js("function(hash) { return false; }");
    globals.add(new js.Property(
        js.string(IS_HUNK_INITIALIZED), isHunkInitializedFunction));

    js.Expression typesAccess = generateEmbeddedGlobalAccess(TYPES);

    /// See [emitEmbeddedGlobalsForDeferredLoading] for the format of the
    /// deferred hunk.
    js.Expression initializeLoadedHunkFunction = js.js("""
          function(hash) {
            var hunk = $deferredInitializersGlobal[hash];
            $setupProgramName(hunk[0], #typesAccess.length);
            eval(hunk[1]);
            var deferredTypes = eval(hunk[2]);
            #typesAccess.push.apply(#typesAccess, deferredTypes);
          }""", {'typesAccess': typesAccess});

    globals.add(new js.Property(
        js.string(INITIALIZE_LOADED_HUNK), initializeLoadedHunkFunction));

    return globals;
  }

  js.Property emitGetTypeFromName() {
    js.Expression function = js.js("""function(name) {
                    return holdersMap[name][name].ensureResolved();
                  }""");
    return new js.Property(js.string(GET_TYPE_FROM_NAME), function);
  }

  static final String readMetadataTypeName = "readMetadataType";

  js.Statement get readMetadataTypeFunction {
    // Types are non-evaluated and must be compiled at first use.
    // Compiled strings are guaranteed not to be strings, and it's thus safe
    // to use a type-test to determine if a type has already been compiled.
    return js.js.statement('''function $readMetadataTypeName(index) {
      var type = #typesAccess[index];
      if (typeof type == 'string') {
        type = expressionCompile(type);
        #typesAccess[index] = type;
      }
      return type;
    }''', {"typesAccess": generateEmbeddedGlobalAccess(TYPES)});
  }

  js.Template get templateForReadType {
    // TODO(floitsch): make sure that no local variable shadows the access to
    // the readMetadataType function.
    return js.js.expressionTemplateFor('$readMetadataTypeName(#)');
  }

  static final String readMetadataName = "readLazyMetadata";
  static final String lazyMetadataName = "lazy_$METADATA";

  js.Statement get readMetadataFunction {
    // Types are non-evaluated and must be compiled at first use.
    // Compiled strings are guaranteed not to be strings, and it's thus safe
    // to use a type-test to determine if a type has already been compiled.
    return js.js.statement('''function $readMetadataName(index) {
      var lazyMetadata = #lazyMetadataAccess[index];
      if (typeof lazyMetadata == 'string') {
        #metadataAccess[index] = expressionCompile(lazyMetadata);
        #lazyMetadataAccess[index] = null;
      }
      return #metadataAccess[index];
    }''', {
      "lazyMetadataAccess": generateEmbeddedGlobalAccess(lazyMetadataName),
      "metadataAccess": generateEmbeddedGlobalAccess(METADATA)
    });
  }

  js.Template get templateForReadMetadata {
    // TODO(floitsch): make sure that no local variable shadows the access to
    // the readMetadata function.
    return js.js.expressionTemplateFor('$readMetadataName(#)');
  }

  List<js.Property> emitMetadata(Program program) {
    List<js.Property> metadataGlobals = <js.Property>[];

    js.Property createGlobal(js.Expression metadata, String global) {
      return new js.Property(js.string(global), metadata);
    }

    metadataGlobals.add(createGlobal(program.metadata, METADATA));
    js.Expression types =
        program.metadataTypesForOutputUnit(program.mainFragment.outputUnit);
    metadataGlobals.add(createGlobal(types, TYPES));

    return metadataGlobals;
  }

  js.Expression emitDeferredFragment(js.Expression deferredTypes,
      DeferredFragment fragment, List<Holder> holders) {
    // TODO(floitsch): initialize eager classes.
    // TODO(floitsch): the hash must depend on the output.
    int hash = fragment.hashCode;

    List<js.Expression> deferredCode =
        fragment.libraries.map(emitLibrary).toList();

    deferredCode.add(
        emitLazilyInitializedStatics(fragment.staticLazilyInitializedFields));
    deferredCode.add(emitConstants(fragment.constants));

    js.ArrayInitializer deferredArray = new js.ArrayInitializer(deferredCode);

    // This is the code that must be evaluated after all deferred classes have
    // been setup.
    js.Statement immediateCode = new js.Block([
      emitStaticNonFinalFields(fragment.staticNonFinalFields),
      emitEagerClassInitializations(fragment.libraries)
    ]);

    js.Literal immediateString = unparse(compiler, immediateCode);

    js.ArrayInitializer hunk = new js.ArrayInitializer(
        [deferredArray, immediateString, deferredTypes]);

    return js.js("$deferredInitializersGlobal[$hash] = #", hunk);
  }

  // This string should be referenced wherever JavaScript code makes assumptions
  // on the constants format.
  static final String constantsDescription =
      "The constants are encoded as a follows:"
      "   [constantsHolderIndex, name, code, name2, code2, ...]."
      "The array is completely empty if there is no constant at all.";

  js.ArrayInitializer emitConstants(List<Constant> constants) {
    List<js.Expression> data = <js.Expression>[];
    if (constants.isNotEmpty) {
      int holderIndex = constants.first.holder.index;
      data.add(js.number(holderIndex));
      data.addAll(constants.expand((Constant constant) {
        assert(constant.holder.index == holderIndex);
        js.Expression code = constantEmitter.generate(constant.value);
        return [js.quoteName(constant.name), unparse(compiler, code)];
      }));
    }
    return new js.ArrayInitializer(data);
  }

  js.Block emitStaticNonFinalFields(List<StaticField> fields) {
    Iterable<js.Statement> statements = fields.map((StaticField field) {
      return js.js
          .statement("#.# = #;", [field.holder.name, field.name, field.code]);
    });
    return new js.Block(statements.toList());
  }

  js.Expression emitLazilyInitializedStatics(List<StaticField> fields) {
    Iterable fieldDescriptors = fields.expand((field) => [
          js.quoteName(field.name),
          js.quoteName(namer.deriveLazyInitializerName(field.name)),
          js.number(field.holder.index),
          emitLazyInitializer(field)
        ]);
    return new js.ArrayInitializer(fieldDescriptors.toList(growable: false));
  }

  js.Block emitEagerClassInitializations(List<Library> libraries) {
    js.Statement createInstantiation(Class cls) {
      return js.js.statement('new #.#()', [cls.holder.name, cls.name]);
    }

    List<js.Statement> instantiations = libraries
        .expand((Library library) => library.classes)
        .where((Class cls) => cls.isEager)
        .map(createInstantiation)
        .toList(growable: false);
    return new js.Block(instantiations);
  }

  // This string should be referenced wherever JavaScript code makes assumptions
  // on the mixin format.
  static final String nativeInfoDescription = "A class is encoded as follows:"
      "   [name, class-code, holder-index], or "
      "   [name, class-code, native-info, holder-index].";

  js.Expression emitLibrary(Library library) {
    Iterable staticDescriptors = library.statics.expand(emitStaticMethod);

    Iterable classDescriptors = library.classes.expand((Class cls) {
      js.Literal name = js.quoteName(cls.name);
      js.LiteralNumber holderIndex = js.number(cls.holder.index);
      js.Expression emittedClass = emitClass(cls);
      js.Expression nativeInfo = NativeGenerator.encodeNativeInfo(cls);
      if (nativeInfo == null) {
        return [name, emittedClass, holderIndex];
      } else {
        return [name, emittedClass, nativeInfo, holderIndex];
      }
    });

    js.Expression staticArray =
        new js.ArrayInitializer(staticDescriptors.toList(growable: false));
    js.Expression classArray =
        new js.ArrayInitializer(classDescriptors.toList(growable: false));

    return new js.ArrayInitializer([staticArray, classArray]);
  }

  js.Expression _generateConstructor(Class cls) {
    List<js.Name> fieldNames = const <js.Name>[];

    // If the class is not directly instantiated we only need it for inheritance
    // or RTI. In either case we don't need its fields.
    if (cls.isDirectlyInstantiated && !cls.isNative) {
      fieldNames = cls.fields.map((Field field) => field.name).toList();
      if (cls.hasRtiField) {
        fieldNames.add(namer.rtiFieldJsName);
      }
    }
    js.Name name = cls.name;

    Iterable<js.Name> assignments = fieldNames.map((js.Name field) {
      return js.js("this.#field = #field", {"field": field});
    });

    return js.js('function #(#) { # }', [name, fieldNames, assignments]);
  }

  Method _generateGetter(Field field) {
    String getterTemplateFor(int flags) {
      switch (flags) {
        case 1:
          return "function() { return this[#]; }";
        case 2:
          return "function(receiver) { return receiver[#]; }";
        case 3:
          return "function(receiver) { return this[#]; }";
      }
      return null;
    }

    js.Expression fieldName = js.quoteName(field.name);
    js.Expression code = js.js(getterTemplateFor(field.getterFlags), fieldName);
    js.Name getterName = namer.deriveGetterName(field.accessorName);
    return new StubMethod(getterName, code);
  }

  Method _generateSetter(Field field) {
    String setterTemplateFor(int flags) {
      switch (flags) {
        case 1:
          return "function(val) { return this[#] = val; }";
        case 2:
          return "function(receiver, val) { return receiver[#] = val; }";
        case 3:
          return "function(receiver, val) { return this[#] = val; }";
      }
      return null;
    }

    js.Expression fieldName = js.quoteName(field.name);
    js.Expression code = js.js(setterTemplateFor(field.setterFlags), fieldName);
    js.Name setterName = namer.deriveSetterName(field.accessorName);
    return new StubMethod(setterName, code);
  }

  Iterable<Method> _generateGettersSetters(Class cls) {
    Iterable<Method> getters = cls.fields
        .where((Field field) => field.needsGetter)
        .map(_generateGetter);

    Iterable<Method> setters = cls.fields
        .where((Field field) => field.needsUncheckedSetter)
        .map(_generateSetter);

    return [getters, setters].expand((x) => x);
  }

  // This string should be referenced wherever JavaScript code makes assumptions
  // on the mixin format.
  static final String mixinFormatDescription =
      "Mixins have a reference to their mixin class at the place of the usual"
      "constructor. If they are instantiated the constructor follows the"
      "reference.";

  js.Expression emitClass(Class cls) {
    List elements = [
      js.quoteName(cls.superclassName, allowNull: true),
      js.number(cls.superclassHolderIndex)
    ];

    if (cls.isMixinApplication) {
      MixinApplication mixin = cls;
      elements.add(js.quoteName(mixin.mixinClass.name));
      elements.add(js.number(mixin.mixinClass.holder.index));
      if (cls.isDirectlyInstantiated) {
        elements.add(_generateConstructor(cls));
      }
    } else {
      elements.add(_generateConstructor(cls));
    }
    Iterable<Method> methods = cls.methods;
    Iterable<Method> isChecks = cls.isChecks;
    Iterable<Method> callStubs = cls.callStubs;
    Iterable<Method> noSuchMethodStubs = cls.noSuchMethodStubs;
    Iterable<Method> gettersSetters = _generateGettersSetters(cls);
    Iterable<Method> allMethods = [
      methods,
      isChecks,
      callStubs,
      noSuchMethodStubs,
      gettersSetters
    ].expand((x) => x);
    elements.addAll(allMethods.expand(emitInstanceMethod));

    return unparse(compiler, new js.ArrayInitializer(elements));
  }

  js.Expression emitLazyInitializer(StaticField field) {
    assert(field.isLazy);
    return unparse(compiler, field.code);
  }

  /// JavaScript code template that implements parsing of a function descriptor.
  /// Descriptors are used in place of the actual JavaScript function
  /// definition in the output if additional information needs to be passed to
  /// facilitate the generation of tearOffs at runtime. The format is an array
  /// with the following fields:
  ///
  /// * [InstanceMethod.aliasName] (optional).
  /// * [Method.code]
  /// * [DartMethod.callName]
  /// * isInterceptedMethod (optional, present if [DartMethod.needsTearOff]).
  /// * [DartMethod.tearOffName] (optional, present if
  ///   [DartMethod.needsTearOff]).
  /// * functionType (optional, present if [DartMethod.needsTearOff]).
  ///
  /// followed by
  ///
  /// * [ParameterStubMethod.name]
  /// * [ParameterStubMethod.callName]
  /// * [ParameterStubMethod.code]
  ///
  /// for each stub in [DartMethod.parameterStubs].
  ///
  /// If the closure could be used in `Function.apply` (i.e.
  /// [DartMethod.canBeApplied] is true) then the following fields are appended:
  ///
  /// * [DartMethod.requiredParameterCount]
  /// * [DartMethod.optionalParameterDefaultValues]

  static final String parseFunctionDescriptorBoilerplate = r"""
function parseFunctionDescriptor(proto, name, descriptor, typesOffset) {
  if (descriptor instanceof Array) {
    // 'pos' points to the last read entry.
    var f, pos = -1;
    var aliasOrFunction = descriptor[++pos];
    if (typeof aliasOrFunction == "string") {
      // Install the alias for super calls on the prototype chain.
      proto[aliasOrFunction] = f = descriptor[++pos];
    } else {
      f = aliasOrFunction;
    }

    proto[name] = f;
    var funs = [f];
    f[#callName] = descriptor[++pos];

    var isInterceptedOrParameterStubName = descriptor[pos + 1];
    var isIntercepted, tearOffName, reflectionInfo;
    if (typeof isInterceptedOrParameterStubName == "boolean") {
      isIntercepted = descriptor[++pos];
      tearOffName = descriptor[++pos];
      reflectionInfo = descriptor[++pos];
      if (typeof reflectionInfo == "number") {
        reflectionInfo = reflectionInfo + typesOffset;
      }
    }

    // We iterate in blocks of 3 but have to stop before we reach the (optional)
    // two trailing items. To accomplish this, we only iterate until we reach
    // length - 2.
    for (++pos; pos < descriptor.length - 2; pos += 3) {
      var stub = descriptor[pos + 2];
      stub[#callName] = descriptor[pos + 1];
      proto[descriptor[pos]] = stub;
      funs.push(stub);
    }

    if (tearOffName) {
      proto[tearOffName] =
          tearOff(funs, reflectionInfo, false, name, isIntercepted);
    }
    if (pos < descriptor.length) {
      f[#argumentCount] = descriptor[pos];
      f[#defaultArgumentValues] = descriptor[pos + 1];
    }
  } else {
    proto[name] = descriptor;
  }
}
""";

  js.Expression _encodeOptionalParameterDefaultValues(DartMethod method) {
    // TODO(herhut): Replace [js.LiteralNull] with [js.ArrayHole].
    if (method.optionalParameterDefaultValues is List) {
      List<ConstantValue> defaultValues = method.optionalParameterDefaultValues;
      Iterable<js.Expression> elements =
          defaultValues.map(generateConstantReference);
      return new js.ArrayInitializer(elements.toList());
    } else {
      Map<String, ConstantValue> defaultValues =
          method.optionalParameterDefaultValues;
      List<js.Property> properties = <js.Property>[];
      defaultValues.forEach((String name, ConstantValue value) {
        properties.add(
            new js.Property(js.string(name), generateConstantReference(value)));
      });
      return new js.ObjectInitializer(properties);
    }
  }

  Iterable<js.Expression> emitInstanceMethod(Method method) {
    List<js.Expression> makeNameCodePair(Method method) {
      return [js.quoteName(method.name), method.code];
    }

    List<js.Expression> makeNameCallNameCodeTriplet(ParameterStubMethod stub) {
      js.Expression callName = stub.callName == null
          ? new js.LiteralNull()
          : js.quoteName(stub.callName);
      return [js.quoteName(stub.name), callName, stub.code];
    }

    if (method is InstanceMethod) {
      if (method.needsTearOff || method.aliasName != null) {
        /// See [parseFunctionDescriptorBoilerplate] for a full description of
        /// the format.
        // [name, [aliasName, function, callName, isIntercepted, tearOffName,
        // functionType, stub1_name, stub1_callName, stub1_code, ...]
        var data = [];
        if (method.aliasName != null) {
          data.add(js.quoteName(method.aliasName));
        }
        data.add(method.code);
        data.add(js.quoteName(method.callName, allowNull: true));

        if (method.needsTearOff) {
          MethodElement element = method.element;
          bool isIntercepted = _interceptorData.isInterceptedMethod(element);
          data.add(new js.LiteralBool(isIntercepted));
          data.add(js.quoteName(method.tearOffName));
          data.add((method.functionType));
        }

        data.addAll(method.parameterStubs.expand(makeNameCallNameCodeTriplet));
        if (method.canBeApplied) {
          data.add(js.number(method.requiredParameterCount));
          data.add(_encodeOptionalParameterDefaultValues(method));
        }
        return [js.quoteName(method.name), new js.ArrayInitializer(data)];
      } else {
        // TODO(floitsch): not the most efficient way...
        return (<dynamic>[method]..addAll(method.parameterStubs))
            .expand(makeNameCodePair);
      }
    } else {
      return makeNameCodePair(method);
    }
  }

  Iterable<js.Expression> emitStaticMethod(StaticMethod method) {
    js.Expression holderIndex = js.number(method.holder.index);
    List<js.Expression> output = <js.Expression>[];

    void _addMethod(Method method) {
      js.Expression unparsed = unparse(compiler, method.code);
      output.add(js.quoteName(method.name));
      output.add(holderIndex);
      output.add(unparsed);
    }

    List<js.Expression> makeNameCallNameCodeTriplet(ParameterStubMethod stub) {
      js.Expression callName = stub.callName == null
          ? new js.LiteralNull()
          : js.quoteName(stub.callName);
      return [js.quoteName(stub.name), callName, unparse(compiler, stub.code)];
    }

    _addMethod(method);
    // TODO(floitsch): can there be anything else than a StaticDartMethod?
    if (method is StaticDartMethod) {
      if (method.needsTearOff) {
        /// The format emitted is the same as for the parser specified at
        /// [parseFunctionDescriptorBoilerplate] except for the missing
        /// field whether the method is intercepted.
        // [name, [function, callName, tearOffName, functionType,
        //     stub1_name, stub1_callName, stub1_code, ...]
        var data = <js.Expression>[unparse(compiler, method.code)];
        data.add(js.quoteName(method.callName));
        data.add(js.quoteName(method.tearOffName));
        data.add(method.functionType);
        data.addAll(method.parameterStubs.expand(makeNameCallNameCodeTriplet));
        if (method.canBeApplied) {
          data.add(js.number(method.requiredParameterCount));
          data.add(_encodeOptionalParameterDefaultValues(method));
        }
        return [
          js.quoteName(method.name),
          holderIndex,
          new js.ArrayInitializer(data)
        ];
      } else {
        method.parameterStubs.forEach(_addMethod);
      }
    }
    return output;
  }

  static final String setupProgramName = "setupProgram";

  static final String boilerplate = """
{
// Declare deferred-initializer global.
#deferredInitializer;

(function(start, program) {
  // Initialize holder objects.
  #holders;
  var nativeInfos = Object.create(null);

  // Counter to generate unique names for tear offs.
  var functionCounter = 0;

  function $setupProgramName(program, typesOffset) {
    for (var i = 0; i < program.length - 2; i++) {
      setupLibrary(program[i], typesOffset);
    }
    setupLazyStatics(program[i]);
    setupConstants(program[i + 1]);
  }

  function setupLibrary(library, typesOffset) {
    var statics = library[0];
    for (var i = 0; i < statics.length; i += 3) {
      var holderIndex = statics[i + 1];
      setupStatic(statics[i], holders[holderIndex], statics[i + 2],
                  typesOffset);
    }

    var classes = library[1];
    for (var i = 0; i < classes.length; i += 3) {
      var name = classes[i];
      var cls = classes[i + 1];

      if (#needsNativeSupport) {
        // $nativeInfoDescription.
        var indexOrNativeInfo = classes[i + 2];
        if (typeof indexOrNativeInfo == "number") {
          var holderIndex = classes[i + 2];
        } else {
          nativeInfos[name] = indexOrNativeInfo;
          holderIndex = classes[i + 3];
          i++;
        }
      }

      if (#needsNoNativeSupport) {
        var holderIndex = classes[i + 2];
      }

      holdersMap[name] = holders[holderIndex];
      setupClass(name, holders[holderIndex], cls, typesOffset);
    }
  }

  function setupLazyStatics(statics) {
    for (var i = 0; i < statics.length; i += 4) {
      var name = statics[i];
      var getterName = statics[i + 1];
      var holderIndex = statics[i + 2];
      var initializer = statics[i + 3];
      setupLazyStatic(name, getterName, holders[holderIndex], initializer);
    }
  }

  function setupConstants(constants) {
    // $constantsDescription.
    if (constants.length == 0) return;
    // We assume that all constants are in the same holder.
    var holder = holders[constants[0]];
    for (var i = 1; i < constants.length; i += 2) {
      var name = constants[i];
      var initializer = constants[i + 1];
      setupConstant(name, holder, initializer);
    }
  }

  function setupStatic(name, holder, descriptor, typesOffset) {
    if (typeof descriptor == 'string') {
      holder[name] = function() {
        if (descriptor == null) {
          // Already compiled. This happens when we have calls to the static as
          // arguments to the static: `foo(foo(499))`;
          return holder[name].apply(this, arguments);
        }
        var method = compile(name, descriptor);
        holder[name] = method;
        descriptor = null;  // GC the descriptor.
        return method.apply(this, arguments);
      };
    } else {
      // Parse the tear off information and generate compile handlers.
      // TODO(herhut): Share parser with instance methods.
      function compileAllStubs(typesOffset) {
        var funs;
        var fun = compile(name, descriptor[0]);
        fun[#callName] = descriptor[1];
        holder[name] = fun;
        funs = [fun];
        // We iterate in blocks of 3 but have to stop before we reach the
        // (optional) two trailing items. To accomplish this, we only iterate
        // until we reach length - 2.
        for (var pos = 4; pos < descriptor.length - 2; pos += 3) {
          var stubName = descriptor[pos];
          fun = compile(stubName, descriptor[pos + 2]);
          fun[#callName] = descriptor[pos + 1];
          holder[stubName] = fun;
          funs.push(fun);
        }
        if (descriptor[2] != null) {  // tear-off name.
          // functions, reflectionInfo, isStatic, name, isIntercepted.
          var reflectionInfo = descriptor[3];
          if (typeof reflectionInfo == "number") {
            reflectionInfo = reflectionInfo + typesOffset;
          }
          holder[descriptor[2]] =
              tearOff(funs, reflectionInfo, true, name, false);
        }
        if (pos < descriptor.length) {
          fun[#argumentCount] = descriptor[pos];
          fun[#defaultArgumentValues] = descriptor[pos + 1];
        }
      }

      function setupCompileAllAndDelegateStub(name, typesOffset) {
        holder[name] = function() {
          // The descriptor is null if we already compiled this function. This
          // happens when we have calls to the static as arguments to the
          // static: `foo(foo(499))`;
          if (descriptor != null) {
            compileAllStubs(typesOffset);
            descriptor = null;  // GC the descriptor.
          }
          return holder[name].apply(this, arguments);
        };
      }

      setupCompileAllAndDelegateStub(name, typesOffset);
      for (var pos = 4; pos < descriptor.length; pos += 3) {
        setupCompileAllAndDelegateStub(descriptor[pos], typesOffset);
      }
      if (descriptor[2] != null) {  // tear-off name.
        setupCompileAllAndDelegateStub(descriptor[2], typesOffset)
      }
    }
  }

  function setupLazyStatic(name, getterName, holder, descriptor) {
    holder[name] = null;
    holder[getterName] = function() {
      var initializer = compile(name, descriptor);
      holder[getterName] = function() { #cyclicThrow(name) };
      var result;
      var sentinelInProgress = descriptor;
      try {
        result = holder[name] = sentinelInProgress;
        result = holder[name] = initializer();
      } finally {
        // Use try-finally, not try-catch/throw as it destroys the stack trace.
        if (result === sentinelInProgress) {
          // The lazy static (holder[name]) might have been set to a different
          // value. According to spec we still have to reset it to null, if the
          // initialization failed.
          holder[name] = null;
        }
        // TODO(floitsch): the function should probably be unique for each
        // static.
        holder[getterName] = function() { return this[name]; };
      }
      return result;
    };
  }

  function setupConstant(name, holder, descriptor) {
    var c;
    holder[name] = function() {
      if (descriptor !== null) {
        c = compile(name, descriptor);
        name = null;
        descriptor = null;
      }
      return c;
    };
  }

  function setupClass(name, holder, descriptor, typesOffset) {
    var patch = function() {
      if (patch.ensureResolved == patch) {
        // We have not yet been compiled.
        var constructor = compileConstructor(name, descriptor, typesOffset);
        holder[name] = constructor;
        name = holder = descriptor = null;  // GC the captured arguments.
        // Make sure we can invoke 'ensureResolved' multiple times on the patch
        // function.
        patch.ensureResolved = function() { return constructor; };
        constructor.ensureResolved = function() { return this; };
      } else {
        // This can happen when arguments to the constructor are of the same
        // class, like in `new A(new A(null))`.
        constructor = patch.ensureResolved();
      }
      // If the patch has been called as "ensureResolved" return.
      if (this === patch) return constructor;
      var object = new constructor();
      constructor.apply(object, arguments);
      return object;
    };

    // We store the patch function on itself to make it
    // possible to resolve superclass references without constructing instances.
    patch.ensureResolved = patch;
    holder[name] = patch;
  }

  #tearOff;

  #parseFunctionDescriptor;

  function compileConstructor(name, descriptor, typesOffset) {
    descriptor = compile(name, descriptor);
    var prototype = determinePrototype(descriptor);
    var constructor;
    var functionsIndex;
    // $mixinFormatDescription.
    if (typeof descriptor[2] !== 'function') {
      fillPrototypeWithMixedIn(descriptor[2], descriptor[3], prototype);
      // descriptor[4] contains the constructor if the mixin application is
      // directly instantiated.
      if (typeof descriptor[4] === 'function') {
        constructor = descriptor[4];
        functionsIndex = 5;
      } else {
        constructor = function() {};
        functionsIndex = 4;
      }
    } else {
      constructor = descriptor[2];
      functionsIndex = 3;
    }

    for (var i = functionsIndex; i < descriptor.length; i += 2) {
      parseFunctionDescriptor(prototype, descriptor[i], descriptor[i + 1],
                              typesOffset);
    }

    constructor.$typeNameProperty = name;  // Needed for RTI.
    constructor.prototype = prototype;
    prototype[#operatorIsPrefix + name] = constructor;
    prototype.constructor = constructor;
    return constructor;
  }

  function fillPrototypeWithMixedIn(mixinName, mixinHolderIndex, prototype) {
    var mixin = holders[mixinHolderIndex][mixinName].ensureResolved();
    var mixinPrototype = mixin.prototype;

    // Fill the prototype with the mixin's properties.
    var mixinProperties = Object.keys(mixinPrototype);
    for (var i = 0; i < mixinProperties.length; i++) {
      var p = mixinProperties[i];
      prototype[p] = mixinPrototype[p];
    }
  }

  function determinePrototype(descriptor) {
    var superclassName = descriptor[0];
    if (!superclassName) return { };

    // Look up the superclass constructor function in the right holder.
    var holderIndex = descriptor[1];
    var superclass = holders[holderIndex][superclassName].ensureResolved();

    // Create a new prototype object chained to the superclass prototype.
    var intermediate = function() { };
    intermediate.prototype = superclass.prototype;
    return new intermediate();
  }

  function compile(__name__, __s__) {
    'use strict';
    // TODO(floitsch): evaluate the performance impact of the string
    // concatenations.
    return eval(__s__ + "\\n//# sourceURL=" + __name__ + ".js");
  }

  if (#outputContainsConstantList) {
    function makeConstList(list) {
      // By assigning a function to the properties they become part of the
      // hidden class. The actual values of the fields don't matter, since we
      // only check if they exist.
      list.immutable\$list = Array;
      list.fixed\$length = Array;
      return list;
    }
  }

  if (#needsNativeSupport) {
    function handleNativeClassInfos() {
      for (var nativeClass in nativeInfos) {
        var constructor = holdersMap[nativeClass][nativeClass].ensureResolved();
        var nativeInfo = nativeInfos[nativeClass];
        #nativeInfoHandler;
      }
    }
  }

  $setupProgramName(program, 0);

  // Initialize globals.
  #embeddedGlobals;

  function expressionCompile(__s__) {
    'use strict';
    return eval('(' + __s__ + ')');
  }

  #readMetadataTypeFunction;

  // TODO(floitsch): this order means that native classes may not be
  // referenced from constants. I'm mostly afraid of things like using them as
  // generic arguments (which should be fine, but maybe there are other
  // similar things).
  // Initialize natives.
  if (#needsNativeSupport) handleNativeClassInfos();

  // Initialize static non-final fields.
  #staticNonFinals;

  // Add native boilerplate code.
  #nativeIsolateAffinityTagInitialization;

  // Initialize eager classes.
  #eagerClasses;

  var end = Date.now();
  // print('Setup: ' + (end - start) + ' ms.');

  #invokeMain;  // Start main.

})(Date.now(), #code)
}""";
}
