blob: f70be0505674b9be7ced3bb3c9eb780b2df5e88a [file] [log] [blame]
// 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.new_js_emitter.model;
import '../js/js.dart' as js show Expression;
import '../constants/values.dart' show ConstantValue;
class Program {
final List<Output> outputs;
final bool outputContainsConstantList;
/// A map from load id to the list of outputs that need to be loaded.
final Map<String, List<Output>> loadMap;
Program(this.outputs, this.outputContainsConstantList, this.loadMap);
}
/**
* This class represents a JavaScript object that contains static state, like
* classes or functions.
*/
class Holder {
final String name;
final int index;
Holder(this.name, this.index);
}
/**
* This class represents one output file.
*
* If no library is deferred, there is only one [Output] of type [MainOutput].
*/
abstract class Output {
bool get isMainOutput => mainOutput == this;
MainOutput get mainOutput;
final List<Library> libraries;
final List<Constant> constants;
// TODO(floitsch): should we move static fields into libraries or classes?
final List<StaticField> staticNonFinalFields;
// TODO(floitsch): lazy fields should be in their library or even class.
final List<StaticField> staticLazilyInitializedFields;
/// Output file name without extension.
final String outputFileName;
Output(this.outputFileName,
this.libraries,
this.staticNonFinalFields,
this.staticLazilyInitializedFields,
this.constants);
}
/**
* The main output file.
*
* This code emitted from this [Output] must be loaded first. It can then load
* other [DeferredOutput]s.
*/
class MainOutput extends Output {
final js.Expression main;
final List<Holder> holders;
MainOutput(String outputFileName,
this.main,
List<Library> libraries,
List<StaticField> staticNonFinalFields,
List<StaticField> staticLazilyInitializedFields,
List<Constant> constants,
this.holders)
: super(outputFileName,
libraries,
staticNonFinalFields,
staticLazilyInitializedFields,
constants);
MainOutput get mainOutput => this;
}
/**
* An output (file) for deferred code.
*/
class DeferredOutput extends Output {
final MainOutput mainOutput;
final String name;
List<Holder> get holders => mainOutput.holders;
DeferredOutput(String outputFileName,
this.name,
this.mainOutput,
List<Library> libraries,
List<StaticField> staticNonFinalFields,
List<StaticField> staticLazilyInitializedFields,
List<Constant> constants)
: super(outputFileName,
libraries,
staticNonFinalFields,
staticLazilyInitializedFields,
constants);
}
class Constant {
final String name;
final Holder holder;
final ConstantValue value;
Constant(this.name, this.holder, this.value);
}
class Library {
final String uri;
final List<StaticMethod> statics;
final List<Class> classes;
Library(this.uri, this.statics, this.classes);
}
class StaticField {
final String name;
// TODO(floitsch): the holder for static fields is the isolate object. We
// could remove this field and use the isolate object directly.
final Holder holder;
final js.Expression code;
final bool isFinal;
final bool isLazy;
StaticField(this.name, this.holder, this.code,
this.isFinal, this.isLazy);
}
class Class {
final String name;
final Holder holder;
Class superclass;
final List<Method> methods;
final List<InstanceField> fields;
/// Whether the class must be evaluated eagerly.
bool isEager = false;
Class(this.name, this.holder, this.methods, this.fields,
{ this.isEager: false });
void setSuperclass(Class superclass) {
this.superclass = superclass;
}
String get superclassName
=> (superclass == null) ? "" : superclass.name;
int get superclassHolderIndex
=> (superclass == null) ? 0 : superclass.holder.index;
}
class InstanceField {
final String name;
/// 00: Does not need any getter.
/// 01: function() { return this.field; }
/// 10: function(receiver) { return receiver.field; }
/// 11: function(receiver) { return this.field; }
final int getterFlags;
/// 00: Does not need any setter.
/// 01: function(value) { this.field = value; }
/// 10: function(receiver, value) { receiver.field = value; }
/// 11: function(receiver, value) { this.field = value; }
final int setterFlags;
// TODO(floitsch): support renamed fields.
InstanceField(this.name, this.getterFlags, this.setterFlags);
bool get needsGetter => getterFlags != 0;
bool get needsSetter => setterFlags != 0;
}
class Method {
final String name;
final js.Expression code;
Method(this.name, this.code);
}
class StaticMethod extends Method {
final Holder holder;
StaticMethod(String name, this.holder, js.Expression code)
: super(name, code);
}