// 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.dart' show Compiler;
import '../../constants/values.dart' show ConstantValue, FunctionConstantValue;
import '../../core_types.dart' show CommonElements;
import '../../elements/elements.dart' show ClassElement, FunctionElement;
import '../../js/js.dart' as js;
import '../../js_backend/js_backend.dart'
    show JavaScriptBackend, Namer, ConstantEmitter;
import '../constant_ordering.dart' show deepCompareConstants;
import '../js_emitter.dart' show NativeEmitter;
import '../js_emitter.dart' show NativeGenerator, buildTearOffCode;
import '../model.dart';

class ModelEmitter {
  final Compiler compiler;
  final Namer namer;
  ConstantEmitter constantEmitter;
  final NativeEmitter nativeEmitter;

  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(Compiler compiler, Namer namer, this.nativeEmitter)
      : this.compiler = compiler,
        this.namer = namer {
    this.constantEmitter = new ConstantEmitter(
        compiler, namer, this.generateConstantReference, constantListGenerator);
  }

  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 deepCompareConstants(a, b);
  }

  js.Expression generateStaticClosureAccess(FunctionElement element) {
    return js.js('#.#()',
        [namer.globalObjectFor(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((DeferredFragment 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(johnnniwinther): Support source maps in this emitter.
    for (int i = 0; i < fragmentsCode.length; ++i) {
      String code = js.createCodeBuffer(fragmentsCode[i], compiler).getText();
      totalSize += code.length;
      compiler.outputProvider(
          fragments[i + 1].outputFileName, deferredExtension)
        ..add(code)
        ..close();
    }

    String mainCode = js.createCodeBuffer(mainAst, compiler).getText();
    compiler.outputProvider(mainFragment.outputFileName, '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, 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(backend),
      'parseFunctionDescriptor':
          js.js.statement(parseFunctionDescriptorBoilerplate, {
        'argumentCount': js.string(namer.requiredParameterField),
        'defaultArgumentValues': js.string(namer.defaultValuesField),
        'callName': js.string(namer.callNameField)
      }),
      'cyclicThrow': backend.emitter
          .staticFunctionAccess(backend.helpers.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(backend)) {
      nativeIsolateAffinityTagInitialization =
          NativeGenerator.generateIsolateAffinityTagInitialization(
              backend,
              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 = compiler.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((DeferredFragment 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((DeferredFragment 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.rtiFieldName);
      }
    }
    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> typeVariableReaderStubs = cls.typeVariableReaderStubs;
    Iterable<Method> noSuchMethodStubs = cls.noSuchMethodStubs;
    Iterable<Method> gettersSetters = _generateGettersSetters(cls);
    Iterable<Method> allMethods = [
      methods,
      isChecks,
      callStubs,
      typeVariableReaderStubs,
      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) {
          bool isIntercepted = backend.isInterceptedMethod(method.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 ([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 = [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)
}""";
}
