Chromium Code Reviews| 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 1a998f3f04faff5b36b083c2e4d131722ee93cd0..a46ecedb4603801e104a38a7ab2e1a5ae141b8b8 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 |
| DiagnosticListener; |
| 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,254 @@ 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. |
| +enum Feature { |
|
sigurdm
2015/10/06 09:17:13
Should mirror usage be part of this?
Johnni Winther
2015/10/06 10:48:43
Added TODO.
|
| + /// 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, |
| + /// An method with an `async` body modifier. |
|
sigurdm
2015/10/06 09:17:13
An -> a
Johnni Winther
2015/10/06 10:48:43
Done.
|
| + ASYNC, |
| + /// An asynchronous for in statement like `await for (var e in i) {}`. |
| + ASYNC_FOR_IN, |
| + /// An method with an `async*` body modifier. |
|
sigurdm
2015/10/06 09:17:13
An -> a
Johnni Winther
2015/10/06 10:48:43
Done.
|
| + 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) {}`. |
|
sigurdm
2015/10/06 09:17:14
An -> a
Johnni Winther
2015/10/06 10:48:43
Done.
|
| + SYNC_FOR_IN, |
| + /// An 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'); |
| + |
| + @override |
| + void registerAssert(bool hasMessage) => _unsupported('registerAssert'); |
|
sigurdm
2015/10/06 09:17:14
Not sure why this is unsupported?
Johnni Winther
2015/10/06 10:48:43
Not currently needed. Added to TODO to remove it.
|
| + |
| + @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) { |
| + if (_staticUses == null) { |
| + _staticUses = new Setlet<Element>(); |
| + _staticUses.addAll(worldImpact.staticUses); |
| + } |
| + _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 +406,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`. |