Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 | 1 |
| 2 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 2 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 3 // for details. All rights reserved. Use of this source code is governed by a | 3 // for details. All rights reserved. Use of this source code is governed by a |
| 4 // BSD-style license that can be found in the LICENSE file. | 4 // BSD-style license that can be found in the LICENSE file. |
| 5 | 5 |
| 6 library dart2js.common.resolution; | 6 library dart2js.common.resolution; |
| 7 | 7 |
| 8 import '../compiler.dart' show | 8 import '../compiler.dart' show |
| 9 Compiler; | 9 Compiler; |
| 10 import '../core_types.dart' show | 10 import '../core_types.dart' show |
| 11 CoreTypes; | 11 CoreTypes; |
| 12 import '../dart_types.dart' show | 12 import '../dart_types.dart' show |
| 13 DartType; | 13 DartType, |
| 14 InterfaceType; | |
| 14 import '../diagnostics/diagnostic_listener.dart' show | 15 import '../diagnostics/diagnostic_listener.dart' show |
| 15 DiagnosticListener; | 16 DiagnosticListener; |
| 16 import '../elements/elements.dart' show | 17 import '../elements/elements.dart' show |
| 17 AstElement, | 18 AstElement, |
| 18 ClassElement, | 19 ClassElement, |
| 19 Element, | 20 Element, |
| 20 ErroneousElement, | 21 ErroneousElement, |
| 21 FunctionElement, | 22 FunctionElement, |
| 22 FunctionSignature, | 23 FunctionSignature, |
| 24 LocalFunctionElement, | |
| 23 MetadataAnnotation, | 25 MetadataAnnotation, |
| 26 MethodElement, | |
| 24 TypedefElement, | 27 TypedefElement, |
| 25 TypeVariableElement; | 28 TypeVariableElement; |
| 26 import '../enqueue.dart' show | 29 import '../enqueue.dart' show |
| 27 ResolutionEnqueuer, | 30 ResolutionEnqueuer, |
| 28 WorldImpact; | 31 WorldImpact; |
| 29 import '../tree/tree.dart' show | 32 import '../tree/tree.dart' show |
| 30 AsyncForIn, | 33 AsyncForIn, |
| 31 Send, | 34 Send, |
| 32 TypeAnnotation; | 35 TypeAnnotation; |
| 36 import '../universe/universe.dart' show | |
| 37 UniverseSelector; | |
| 38 import '../util/util.dart' show | |
| 39 Setlet; | |
| 33 import 'registry.dart' show | 40 import 'registry.dart' show |
| 34 Registry; | 41 Registry; |
| 35 import 'work.dart' show | 42 import 'work.dart' show |
| 36 ItemCompilationContext, | 43 ItemCompilationContext, |
| 37 WorkItem; | 44 WorkItem; |
| 38 | 45 |
| 39 /// [WorkItem] used exclusively by the [ResolutionEnqueuer]. | 46 /// [WorkItem] used exclusively by the [ResolutionEnqueuer]. |
| 40 class ResolutionWorkItem extends WorkItem { | 47 class ResolutionWorkItem extends WorkItem { |
| 41 bool _isAnalyzed = false; | 48 bool _isAnalyzed = false; |
| 42 | 49 |
| 43 ResolutionWorkItem(AstElement element, | 50 ResolutionWorkItem(AstElement element, |
| 44 ItemCompilationContext compilationContext) | 51 ItemCompilationContext compilationContext) |
| 45 : super(element, compilationContext); | 52 : super(element, compilationContext); |
| 46 | 53 |
| 47 WorldImpact run(Compiler compiler, ResolutionEnqueuer world) { | 54 WorldImpact run(Compiler compiler, ResolutionEnqueuer world) { |
| 48 WorldImpact impact = compiler.analyze(this, world); | 55 WorldImpact impact = compiler.analyze(this, world); |
| 56 impact = compiler.backend.resolutionCallbacks.transformImpact(impact); | |
| 49 _isAnalyzed = true; | 57 _isAnalyzed = true; |
| 50 return impact; | 58 return impact; |
| 51 } | 59 } |
| 52 | 60 |
| 53 bool get isAnalyzed => _isAnalyzed; | 61 bool get isAnalyzed => _isAnalyzed; |
| 54 } | 62 } |
| 55 | 63 |
| 64 // TODO(johnniwinther): Rename this to something like `BackendResolutionApi` | |
| 65 // and clean up the interface. | |
| 56 /// Backend callbacks function specific to the resolution phase. | 66 /// Backend callbacks function specific to the resolution phase. |
| 57 class ResolutionCallbacks { | 67 class ResolutionCallbacks { |
| 68 /// | |
| 69 WorldImpact transformImpact(ResolutionWorldImpact worldImpact) => worldImpact; | |
| 70 | |
| 58 /// Register that an assert has been seen. | 71 /// Register that an assert has been seen. |
| 59 void onAssert(bool hasMessage, Registry registry) {} | 72 void onAssert(bool hasMessage, Registry registry) {} |
| 60 | 73 |
| 61 /// Register that an 'await for' has been seen. | 74 /// Register that an 'await for' has been seen. |
| 62 void onAsyncForIn(AsyncForIn node, Registry registry) {} | 75 void onAsyncForIn(AsyncForIn node, Registry registry) {} |
| 63 | 76 |
| 64 /// Called during resolution to notify to the backend that the | 77 /// Called during resolution to notify to the backend that the |
| 65 /// program uses string interpolation. | 78 /// program uses string interpolation. |
| 66 void onStringInterpolation(Registry registry) {} | 79 void onStringInterpolation(Registry registry) {} |
| 67 | 80 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 126 /// Register that the application creates a constant map. | 139 /// Register that the application creates a constant map. |
| 127 void onMapLiteral(Registry registry, DartType type, bool isConstant) {} | 140 void onMapLiteral(Registry registry, DartType type, bool isConstant) {} |
| 128 | 141 |
| 129 /// Called when resolving the `Symbol` constructor. | 142 /// Called when resolving the `Symbol` constructor. |
| 130 void onSymbolConstructor(Registry registry) {} | 143 void onSymbolConstructor(Registry registry) {} |
| 131 | 144 |
| 132 /// Called when resolving a prefix or postfix expression. | 145 /// Called when resolving a prefix or postfix expression. |
| 133 void onIncDecOperation(Registry registry) {} | 146 void onIncDecOperation(Registry registry) {} |
| 134 } | 147 } |
| 135 | 148 |
| 149 class ResolutionWorldImpact extends WorldImpact { | |
| 150 const ResolutionWorldImpact(); | |
| 151 | |
| 152 // TODO(johnniwinther): Remove this. | |
| 153 void registerDependency(Element element) {} | |
| 154 | |
| 155 Iterable<Feature> get features => const <Feature>[]; | |
| 156 Iterable<DartType> get requiredTypes => const <DartType>[]; | |
| 157 Iterable<MapLiteralUse> get mapLiterals => const <MapLiteralUse>[]; | |
| 158 Iterable<ListLiteralUse> get listLiterals => const <ListLiteralUse>[]; | |
| 159 Iterable<DartType> get typeLiterals => const <DartType>[]; | |
| 160 Iterable<String> get constSymbolNames => const <String>[]; | |
| 161 } | |
| 162 | |
| 163 /// A language feature seen during resolution. | |
| 164 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.
| |
| 165 /// Invocation of a generative construction on an abstract class. | |
| 166 ABSTRACT_CLASS_INSTANTIATION, | |
| 167 /// An assert statement with no message. | |
| 168 ASSERT, | |
| 169 /// An assert statement with a message. | |
| 170 ASSERT_WITH_MESSAGE, | |
| 171 /// 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.
| |
| 172 ASYNC, | |
| 173 /// An asynchronous for in statement like `await for (var e in i) {}`. | |
| 174 ASYNC_FOR_IN, | |
| 175 /// 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.
| |
| 176 ASYNC_STAR, | |
| 177 /// A catch statement. | |
| 178 CATCH_STATEMENT, | |
| 179 /// A compile time error. | |
| 180 COMPILE_TIME_ERROR, | |
| 181 /// A fall through in a switch case. | |
| 182 FALL_THROUGH_ERROR, | |
| 183 /// A ++/-- operation. | |
| 184 INC_DEC_OPERATION, | |
| 185 /// A field whose initialization is not a constant. | |
| 186 LAZY_FIELD, | |
| 187 /// A call to `new Symbol`. | |
| 188 NEW_SYMBOL, | |
| 189 /// A catch clause with a variable for the stack trace. | |
| 190 STACK_TRACE_IN_CATCH, | |
| 191 /// String interpolation. | |
| 192 STRING_INTERPOLATION, | |
| 193 /// An implicit call to `super.noSuchMethod`, like calling an unresolved | |
| 194 /// super method. | |
| 195 SUPER_NO_SUCH_METHOD, | |
| 196 /// A redirection to the `Symbol` constructor. | |
| 197 SYMBOL_CONSTRUCTOR, | |
| 198 /// 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.
| |
| 199 SYNC_FOR_IN, | |
| 200 /// An method with a `sync*` body modifier. | |
| 201 SYNC_STAR, | |
| 202 /// A throw expression. | |
| 203 THROW_EXPRESSION, | |
| 204 /// An implicit throw of a `NoSuchMethodError`, like calling an unresolved | |
| 205 /// static method. | |
| 206 THROW_NO_SUCH_METHOD, | |
| 207 /// An implicit throw of a runtime error, like | |
| 208 THROW_RUNTIME_ERROR, | |
| 209 /// The need for a type variable bound check, like instantiation of a generic | |
| 210 /// type whose type variable have non-trivial bounds. | |
| 211 TYPE_VARIABLE_BOUNDS_CHECK, | |
| 212 } | |
| 213 | |
| 214 /// A use of a map literal seen during resolution. | |
| 215 class MapLiteralUse { | |
| 216 final InterfaceType type; | |
| 217 final bool isConstant; | |
| 218 final bool isEmpty; | |
| 219 | |
| 220 MapLiteralUse(this.type, {this.isConstant: false, this.isEmpty: false}); | |
| 221 | |
| 222 int get hashCode { | |
| 223 return | |
| 224 type.hashCode * 13 + | |
| 225 isConstant.hashCode * 17 + | |
| 226 isEmpty.hashCode * 19; | |
| 227 } | |
| 228 | |
| 229 bool operator ==(other) { | |
| 230 if (identical(this, other)) return true; | |
| 231 if (other is! MapLiteralUse) return false; | |
| 232 return | |
| 233 type == other.type && | |
| 234 isConstant == other.isConstant && | |
| 235 isEmpty == other.isEmpty; | |
| 236 } | |
| 237 } | |
| 238 | |
| 239 /// A use of a list literal seen during resolution. | |
| 240 class ListLiteralUse { | |
| 241 final InterfaceType type; | |
| 242 final bool isConstant; | |
| 243 final bool isEmpty; | |
| 244 | |
| 245 ListLiteralUse(this.type, {this.isConstant: false, this.isEmpty: false}); | |
| 246 | |
| 247 int get hashCode { | |
| 248 return | |
| 249 type.hashCode * 13 + | |
| 250 isConstant.hashCode * 17 + | |
| 251 isEmpty.hashCode * 19; | |
| 252 } | |
| 253 | |
| 254 bool operator ==(other) { | |
| 255 if (identical(this, other)) return true; | |
| 256 if (other is! ListLiteralUse) return false; | |
| 257 return | |
| 258 type == other.type && | |
| 259 isConstant == other.isConstant && | |
| 260 isEmpty == other.isEmpty; | |
| 261 } | |
| 262 } | |
| 263 | |
| 264 /// Mutable implementation of [WorldImpact] used to transform | |
| 265 /// [ResolutionWorldImpact] to [WorldImpact]. | |
| 266 // TODO(johnniwinther): Remove [Registry] when dependency is tracked directly | |
| 267 // on [WorldImpact]. | |
| 268 class TransformedWorldImpact implements WorldImpact, Registry { | |
| 269 final ResolutionWorldImpact worldImpact; | |
| 270 | |
| 271 Setlet<Element> _staticUses; | |
| 272 Setlet<InterfaceType> _instantiatedTypes; | |
| 273 Setlet<UniverseSelector> _dynamicGetters; | |
| 274 Setlet<UniverseSelector> _dynamicInvocations; | |
| 275 Setlet<UniverseSelector> _dynamicSetters; | |
| 276 | |
| 277 TransformedWorldImpact(this.worldImpact); | |
| 278 | |
| 279 @override | |
| 280 Iterable<DartType> get asCasts => worldImpact.asCasts; | |
| 281 | |
| 282 @override | |
| 283 Iterable<DartType> get checkedModeChecks => worldImpact.checkedModeChecks; | |
| 284 | |
| 285 @override | |
| 286 Iterable<MethodElement> get closurizedFunctions { | |
| 287 return worldImpact.closurizedFunctions; | |
| 288 } | |
| 289 | |
| 290 @override | |
| 291 Iterable<UniverseSelector> get dynamicGetters { | |
| 292 return _dynamicGetters != null | |
| 293 ? _dynamicGetters : worldImpact.dynamicGetters; | |
| 294 } | |
| 295 | |
| 296 @override | |
| 297 Iterable<UniverseSelector> get dynamicInvocations { | |
| 298 return _dynamicInvocations != null | |
| 299 ? _dynamicInvocations : worldImpact.dynamicInvocations; | |
| 300 } | |
| 301 | |
| 302 @override | |
| 303 Iterable<UniverseSelector> get dynamicSetters { | |
| 304 return _dynamicSetters != null | |
| 305 ? _dynamicSetters : worldImpact.dynamicSetters; | |
| 306 } | |
| 307 | |
| 308 @override | |
| 309 Iterable<DartType> get isChecks => worldImpact.isChecks; | |
| 310 | |
| 311 @override | |
| 312 Iterable<Element> get staticUses { | |
| 313 if (_staticUses == null) { | |
| 314 return worldImpact.staticUses; | |
| 315 } | |
| 316 return _staticUses; | |
| 317 } | |
| 318 | |
| 319 @override | |
| 320 bool get isForResolution => true; | |
| 321 | |
| 322 _unsupported(String message) => throw new UnsupportedError(message); | |
| 323 | |
| 324 @override | |
| 325 Iterable<Element> get otherDependencies => _unsupported('otherDependencies'); | |
| 326 | |
| 327 @override | |
| 328 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.
| |
| 329 | |
| 330 @override | |
| 331 void registerDependency(Element element) { | |
| 332 worldImpact.registerDependency(element); | |
| 333 } | |
| 334 | |
| 335 @override | |
| 336 void registerDynamicGetter(UniverseSelector selector) { | |
| 337 if (_dynamicGetters == null) { | |
| 338 _dynamicGetters = new Setlet<UniverseSelector>(); | |
| 339 _dynamicGetters.addAll(worldImpact.dynamicGetters); | |
| 340 } | |
| 341 _dynamicGetters.add(selector); | |
| 342 } | |
| 343 | |
| 344 @override | |
| 345 void registerDynamicInvocation(UniverseSelector selector) { | |
| 346 if (_dynamicInvocations == null) { | |
| 347 _dynamicInvocations = new Setlet<UniverseSelector>(); | |
| 348 _dynamicInvocations.addAll(worldImpact.dynamicInvocations); | |
| 349 } | |
| 350 _dynamicInvocations.add(selector); | |
| 351 } | |
| 352 | |
| 353 @override | |
| 354 void registerDynamicSetter(UniverseSelector selector) { | |
| 355 if (_dynamicSetters == null) { | |
| 356 _dynamicSetters = new Setlet<UniverseSelector>(); | |
| 357 _dynamicSetters.addAll(worldImpact.dynamicSetters); | |
| 358 } | |
| 359 _dynamicSetters.add(selector); | |
| 360 } | |
| 361 | |
| 362 @override | |
| 363 void registerGetOfStaticFunction(FunctionElement element) { | |
| 364 _unsupported('registerGetOfStaticFunction($element)'); | |
| 365 } | |
| 366 | |
| 367 @override | |
| 368 void registerInstantiation(InterfaceType type) { | |
| 369 // TODO(johnniwinther): Remove this when dependency tracking is done on | |
| 370 // the world impact itself. | |
| 371 registerDependency(type.element); | |
| 372 if (_instantiatedTypes == null) { | |
| 373 _instantiatedTypes = new Setlet<InterfaceType>(); | |
| 374 } | |
| 375 _instantiatedTypes.add(type); | |
| 376 } | |
| 377 | |
| 378 @override | |
| 379 Iterable<InterfaceType> get instantiatedTypes { | |
| 380 return _instantiatedTypes != null | |
| 381 ? _instantiatedTypes : const <InterfaceType>[]; | |
| 382 } | |
| 383 | |
| 384 @override | |
| 385 void registerStaticInvocation(Element element) { | |
| 386 if (_staticUses == null) { | |
| 387 _staticUses = new Setlet<Element>(); | |
| 388 _staticUses.addAll(worldImpact.staticUses); | |
| 389 } | |
| 390 _staticUses.add(element); | |
| 391 } | |
| 392 | |
| 393 @override | |
| 394 Iterable<LocalFunctionElement> get closures => worldImpact.closures; | |
| 395 } | |
| 396 | |
| 136 // TODO(johnniwinther): Rename to `Resolver` or `ResolverContext`. | 397 // TODO(johnniwinther): Rename to `Resolver` or `ResolverContext`. |
| 137 abstract class Resolution { | 398 abstract class Resolution { |
| 138 Parsing get parsing; | 399 Parsing get parsing; |
| 139 DiagnosticListener get listener; | 400 DiagnosticListener get listener; |
| 140 CoreTypes get coreTypes; | 401 CoreTypes get coreTypes; |
| 141 | 402 |
| 142 void resolveTypedef(TypedefElement typdef); | 403 void resolveTypedef(TypedefElement typdef); |
| 143 void resolveClass(ClassElement cls); | 404 void resolveClass(ClassElement cls); |
| 144 void registerClass(ClassElement cls); | 405 void registerClass(ClassElement cls); |
| 145 void resolveMetadataAnnotation(MetadataAnnotation metadataAnnotation); | 406 void resolveMetadataAnnotation(MetadataAnnotation metadataAnnotation); |
| 146 FunctionSignature resolveSignature(FunctionElement function); | 407 FunctionSignature resolveSignature(FunctionElement function); |
| 147 DartType resolveTypeAnnotation(Element element, TypeAnnotation node); | 408 DartType resolveTypeAnnotation(Element element, TypeAnnotation node); |
| 409 | |
| 410 bool hasBeenResolved(Element element); | |
| 411 ResolutionWorldImpact analyzeElement(Element element); | |
| 148 } | 412 } |
| 149 | 413 |
| 150 // TODO(johnniwinther): Rename to `Parser` or `ParsingContext`. | 414 // TODO(johnniwinther): Rename to `Parser` or `ParsingContext`. |
| 151 abstract class Parsing { | 415 abstract class Parsing { |
| 152 DiagnosticListener get listener; | 416 DiagnosticListener get listener; |
| 153 void parsePatchClass(ClassElement cls); | 417 void parsePatchClass(ClassElement cls); |
| 154 measure(f()); | 418 measure(f()); |
| 155 } | 419 } |
| OLD | NEW |