Index: pkg/compiler/lib/src/common/resolution.dart |
diff --git a/pkg/compiler/lib/src/common/resolution.dart b/pkg/compiler/lib/src/common/resolution.dart |
index 38b8d5c295be363c1bd1ae3757f297f922b4f6f5..474b10e743803d7a257c514d8f6a8e50eb0249f3 100644 |
--- a/pkg/compiler/lib/src/common/resolution.dart |
+++ b/pkg/compiler/lib/src/common/resolution.dart |
@@ -10,7 +10,8 @@ import '../compiler.dart' show |
import '../core_types.dart' show |
CoreTypes; |
import '../dart_types.dart' show |
- DartType; |
+ DartType, |
+ InterfaceType; |
import '../diagnostics/diagnostic_listener.dart' show |
DiagnosticReporter; |
import '../elements/elements.dart' show |
@@ -20,7 +21,9 @@ import '../elements/elements.dart' show |
ErroneousElement, |
FunctionElement, |
FunctionSignature, |
+ LocalFunctionElement, |
MetadataAnnotation, |
+ MethodElement, |
TypedefElement, |
TypeVariableElement; |
import '../enqueue.dart' show |
@@ -30,6 +33,10 @@ import '../tree/tree.dart' show |
AsyncForIn, |
Send, |
TypeAnnotation; |
+import '../universe/universe.dart' show |
+ UniverseSelector; |
+import '../util/util.dart' show |
+ Setlet; |
import 'registry.dart' show |
Registry; |
import 'work.dart' show |
@@ -46,6 +53,7 @@ class ResolutionWorkItem extends WorkItem { |
WorldImpact run(Compiler compiler, ResolutionEnqueuer world) { |
WorldImpact impact = compiler.analyze(this, world); |
+ impact = compiler.backend.resolutionCallbacks.transformImpact(impact); |
_isAnalyzed = true; |
return impact; |
} |
@@ -53,8 +61,13 @@ class ResolutionWorkItem extends WorkItem { |
bool get isAnalyzed => _isAnalyzed; |
} |
+// TODO(johnniwinther): Rename this to something like `BackendResolutionApi` |
+// and clean up the interface. |
/// Backend callbacks function specific to the resolution phase. |
class ResolutionCallbacks { |
+ /// |
+ WorldImpact transformImpact(ResolutionWorldImpact worldImpact) => worldImpact; |
+ |
/// Register that an assert has been seen. |
void onAssert(bool hasMessage, Registry registry) {} |
@@ -133,6 +146,258 @@ class ResolutionCallbacks { |
void onIncDecOperation(Registry registry) {} |
} |
+class ResolutionWorldImpact extends WorldImpact { |
+ const ResolutionWorldImpact(); |
+ |
+ // TODO(johnniwinther): Remove this. |
+ void registerDependency(Element element) {} |
+ |
+ Iterable<Feature> get features => const <Feature>[]; |
+ Iterable<DartType> get requiredTypes => const <DartType>[]; |
+ Iterable<MapLiteralUse> get mapLiterals => const <MapLiteralUse>[]; |
+ Iterable<ListLiteralUse> get listLiterals => const <ListLiteralUse>[]; |
+ Iterable<DartType> get typeLiterals => const <DartType>[]; |
+ Iterable<String> get constSymbolNames => const <String>[]; |
+} |
+ |
+/// A language feature seen during resolution. |
+// TODO(johnniwinther): Should mirror usage be part of this? |
+enum Feature { |
+ /// Invocation of a generative construction on an abstract class. |
+ ABSTRACT_CLASS_INSTANTIATION, |
+ /// An assert statement with no message. |
+ ASSERT, |
+ /// An assert statement with a message. |
+ ASSERT_WITH_MESSAGE, |
+ /// A method with an `async` body modifier. |
+ ASYNC, |
+ /// An asynchronous for in statement like `await for (var e in i) {}`. |
+ ASYNC_FOR_IN, |
+ /// A method with an `async*` body modifier. |
+ ASYNC_STAR, |
+ /// A catch statement. |
+ CATCH_STATEMENT, |
+ /// A compile time error. |
+ COMPILE_TIME_ERROR, |
+ /// A fall through in a switch case. |
+ FALL_THROUGH_ERROR, |
+ /// A ++/-- operation. |
+ INC_DEC_OPERATION, |
+ /// A field whose initialization is not a constant. |
+ LAZY_FIELD, |
+ /// A call to `new Symbol`. |
+ NEW_SYMBOL, |
+ /// A catch clause with a variable for the stack trace. |
+ STACK_TRACE_IN_CATCH, |
+ /// String interpolation. |
+ STRING_INTERPOLATION, |
+ /// An implicit call to `super.noSuchMethod`, like calling an unresolved |
+ /// super method. |
+ SUPER_NO_SUCH_METHOD, |
+ /// A redirection to the `Symbol` constructor. |
+ SYMBOL_CONSTRUCTOR, |
+ /// An synchronous for in statement, like `for (var e in i) {}`. |
+ SYNC_FOR_IN, |
+ /// A method with a `sync*` body modifier. |
+ SYNC_STAR, |
+ /// A throw expression. |
+ THROW_EXPRESSION, |
+ /// An implicit throw of a `NoSuchMethodError`, like calling an unresolved |
+ /// static method. |
+ THROW_NO_SUCH_METHOD, |
+ /// An implicit throw of a runtime error, like |
+ THROW_RUNTIME_ERROR, |
+ /// The need for a type variable bound check, like instantiation of a generic |
+ /// type whose type variable have non-trivial bounds. |
+ TYPE_VARIABLE_BOUNDS_CHECK, |
+} |
+ |
+/// A use of a map literal seen during resolution. |
+class MapLiteralUse { |
+ final InterfaceType type; |
+ final bool isConstant; |
+ final bool isEmpty; |
+ |
+ MapLiteralUse(this.type, {this.isConstant: false, this.isEmpty: false}); |
+ |
+ int get hashCode { |
+ return |
+ type.hashCode * 13 + |
+ isConstant.hashCode * 17 + |
+ isEmpty.hashCode * 19; |
+ } |
+ |
+ bool operator ==(other) { |
+ if (identical(this, other)) return true; |
+ if (other is! MapLiteralUse) return false; |
+ return |
+ type == other.type && |
+ isConstant == other.isConstant && |
+ isEmpty == other.isEmpty; |
+ } |
+} |
+ |
+/// A use of a list literal seen during resolution. |
+class ListLiteralUse { |
+ final InterfaceType type; |
+ final bool isConstant; |
+ final bool isEmpty; |
+ |
+ ListLiteralUse(this.type, {this.isConstant: false, this.isEmpty: false}); |
+ |
+ int get hashCode { |
+ return |
+ type.hashCode * 13 + |
+ isConstant.hashCode * 17 + |
+ isEmpty.hashCode * 19; |
+ } |
+ |
+ bool operator ==(other) { |
+ if (identical(this, other)) return true; |
+ if (other is! ListLiteralUse) return false; |
+ return |
+ type == other.type && |
+ isConstant == other.isConstant && |
+ isEmpty == other.isEmpty; |
+ } |
+} |
+ |
+/// Mutable implementation of [WorldImpact] used to transform |
+/// [ResolutionWorldImpact] to [WorldImpact]. |
+// TODO(johnniwinther): Remove [Registry] when dependency is tracked directly |
+// on [WorldImpact]. |
+class TransformedWorldImpact implements WorldImpact, Registry { |
+ final ResolutionWorldImpact worldImpact; |
+ |
+ Setlet<Element> _staticUses; |
+ Setlet<InterfaceType> _instantiatedTypes; |
+ Setlet<UniverseSelector> _dynamicGetters; |
+ Setlet<UniverseSelector> _dynamicInvocations; |
+ Setlet<UniverseSelector> _dynamicSetters; |
+ |
+ TransformedWorldImpact(this.worldImpact); |
+ |
+ @override |
+ Iterable<DartType> get asCasts => worldImpact.asCasts; |
+ |
+ @override |
+ Iterable<DartType> get checkedModeChecks => worldImpact.checkedModeChecks; |
+ |
+ @override |
+ Iterable<MethodElement> get closurizedFunctions { |
+ return worldImpact.closurizedFunctions; |
+ } |
+ |
+ @override |
+ Iterable<UniverseSelector> get dynamicGetters { |
+ return _dynamicGetters != null |
+ ? _dynamicGetters : worldImpact.dynamicGetters; |
+ } |
+ |
+ @override |
+ Iterable<UniverseSelector> get dynamicInvocations { |
+ return _dynamicInvocations != null |
+ ? _dynamicInvocations : worldImpact.dynamicInvocations; |
+ } |
+ |
+ @override |
+ Iterable<UniverseSelector> get dynamicSetters { |
+ return _dynamicSetters != null |
+ ? _dynamicSetters : worldImpact.dynamicSetters; |
+ } |
+ |
+ @override |
+ Iterable<DartType> get isChecks => worldImpact.isChecks; |
+ |
+ @override |
+ Iterable<Element> get staticUses { |
+ if (_staticUses == null) { |
+ return worldImpact.staticUses; |
+ } |
+ return _staticUses; |
+ } |
+ |
+ @override |
+ bool get isForResolution => true; |
+ |
+ _unsupported(String message) => throw new UnsupportedError(message); |
+ |
+ @override |
+ Iterable<Element> get otherDependencies => _unsupported('otherDependencies'); |
+ |
+ // TODO(johnniwinther): Remove this. |
+ @override |
+ void registerAssert(bool hasMessage) => _unsupported('registerAssert'); |
+ |
+ @override |
+ void registerDependency(Element element) { |
+ worldImpact.registerDependency(element); |
+ } |
+ |
+ @override |
+ void registerDynamicGetter(UniverseSelector selector) { |
+ if (_dynamicGetters == null) { |
+ _dynamicGetters = new Setlet<UniverseSelector>(); |
+ _dynamicGetters.addAll(worldImpact.dynamicGetters); |
+ } |
+ _dynamicGetters.add(selector); |
+ } |
+ |
+ @override |
+ void registerDynamicInvocation(UniverseSelector selector) { |
+ if (_dynamicInvocations == null) { |
+ _dynamicInvocations = new Setlet<UniverseSelector>(); |
+ _dynamicInvocations.addAll(worldImpact.dynamicInvocations); |
+ } |
+ _dynamicInvocations.add(selector); |
+ } |
+ |
+ @override |
+ void registerDynamicSetter(UniverseSelector selector) { |
+ if (_dynamicSetters == null) { |
+ _dynamicSetters = new Setlet<UniverseSelector>(); |
+ _dynamicSetters.addAll(worldImpact.dynamicSetters); |
+ } |
+ _dynamicSetters.add(selector); |
+ } |
+ |
+ @override |
+ void registerGetOfStaticFunction(FunctionElement element) { |
+ _unsupported('registerGetOfStaticFunction($element)'); |
+ } |
+ |
+ @override |
+ void registerInstantiation(InterfaceType type) { |
+ // TODO(johnniwinther): Remove this when dependency tracking is done on |
+ // the world impact itself. |
+ registerDependency(type.element); |
+ if (_instantiatedTypes == null) { |
+ _instantiatedTypes = new Setlet<InterfaceType>(); |
+ } |
+ _instantiatedTypes.add(type); |
+ } |
+ |
+ @override |
+ Iterable<InterfaceType> get instantiatedTypes { |
+ return _instantiatedTypes != null |
+ ? _instantiatedTypes : const <InterfaceType>[]; |
+ } |
+ |
+ @override |
+ void registerStaticInvocation(Element element) { |
+ // TODO(johnniwinther): Remove this when dependency tracking is done on |
+ // the world impact itself. |
+ registerDependency(element); |
+ if (_staticUses == null) { |
+ _staticUses = new Setlet<Element>(); |
+ } |
+ _staticUses.add(element); |
+ } |
+ |
+ @override |
+ Iterable<LocalFunctionElement> get closures => worldImpact.closures; |
+} |
+ |
// TODO(johnniwinther): Rename to `Resolver` or `ResolverContext`. |
abstract class Resolution { |
Parsing get parsing; |
@@ -145,6 +410,9 @@ abstract class Resolution { |
void resolveMetadataAnnotation(MetadataAnnotation metadataAnnotation); |
FunctionSignature resolveSignature(FunctionElement function); |
DartType resolveTypeAnnotation(Element element, TypeAnnotation node); |
+ |
+ bool hasBeenResolved(Element element); |
+ ResolutionWorldImpact analyzeElement(Element element); |
} |
// TODO(johnniwinther): Rename to `Parser` or `ParsingContext`. |