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 DiagnosticReporter; | 16 DiagnosticReporter; |
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 // TODO(johnniwinther): Should mirror usage be part of this? |
| 165 enum Feature { |
| 166 /// Invocation of a generative construction on an abstract class. |
| 167 ABSTRACT_CLASS_INSTANTIATION, |
| 168 /// An assert statement with no message. |
| 169 ASSERT, |
| 170 /// An assert statement with a message. |
| 171 ASSERT_WITH_MESSAGE, |
| 172 /// A method with an `async` body modifier. |
| 173 ASYNC, |
| 174 /// An asynchronous for in statement like `await for (var e in i) {}`. |
| 175 ASYNC_FOR_IN, |
| 176 /// A method with an `async*` body modifier. |
| 177 ASYNC_STAR, |
| 178 /// A catch statement. |
| 179 CATCH_STATEMENT, |
| 180 /// A compile time error. |
| 181 COMPILE_TIME_ERROR, |
| 182 /// A fall through in a switch case. |
| 183 FALL_THROUGH_ERROR, |
| 184 /// A ++/-- operation. |
| 185 INC_DEC_OPERATION, |
| 186 /// A field whose initialization is not a constant. |
| 187 LAZY_FIELD, |
| 188 /// A call to `new Symbol`. |
| 189 NEW_SYMBOL, |
| 190 /// A catch clause with a variable for the stack trace. |
| 191 STACK_TRACE_IN_CATCH, |
| 192 /// String interpolation. |
| 193 STRING_INTERPOLATION, |
| 194 /// An implicit call to `super.noSuchMethod`, like calling an unresolved |
| 195 /// super method. |
| 196 SUPER_NO_SUCH_METHOD, |
| 197 /// A redirection to the `Symbol` constructor. |
| 198 SYMBOL_CONSTRUCTOR, |
| 199 /// An synchronous for in statement, like `for (var e in i) {}`. |
| 200 SYNC_FOR_IN, |
| 201 /// A method with a `sync*` body modifier. |
| 202 SYNC_STAR, |
| 203 /// A throw expression. |
| 204 THROW_EXPRESSION, |
| 205 /// An implicit throw of a `NoSuchMethodError`, like calling an unresolved |
| 206 /// static method. |
| 207 THROW_NO_SUCH_METHOD, |
| 208 /// An implicit throw of a runtime error, like |
| 209 THROW_RUNTIME_ERROR, |
| 210 /// The need for a type variable bound check, like instantiation of a generic |
| 211 /// type whose type variable have non-trivial bounds. |
| 212 TYPE_VARIABLE_BOUNDS_CHECK, |
| 213 } |
| 214 |
| 215 /// A use of a map literal seen during resolution. |
| 216 class MapLiteralUse { |
| 217 final InterfaceType type; |
| 218 final bool isConstant; |
| 219 final bool isEmpty; |
| 220 |
| 221 MapLiteralUse(this.type, {this.isConstant: false, this.isEmpty: false}); |
| 222 |
| 223 int get hashCode { |
| 224 return |
| 225 type.hashCode * 13 + |
| 226 isConstant.hashCode * 17 + |
| 227 isEmpty.hashCode * 19; |
| 228 } |
| 229 |
| 230 bool operator ==(other) { |
| 231 if (identical(this, other)) return true; |
| 232 if (other is! MapLiteralUse) return false; |
| 233 return |
| 234 type == other.type && |
| 235 isConstant == other.isConstant && |
| 236 isEmpty == other.isEmpty; |
| 237 } |
| 238 } |
| 239 |
| 240 /// A use of a list literal seen during resolution. |
| 241 class ListLiteralUse { |
| 242 final InterfaceType type; |
| 243 final bool isConstant; |
| 244 final bool isEmpty; |
| 245 |
| 246 ListLiteralUse(this.type, {this.isConstant: false, this.isEmpty: false}); |
| 247 |
| 248 int get hashCode { |
| 249 return |
| 250 type.hashCode * 13 + |
| 251 isConstant.hashCode * 17 + |
| 252 isEmpty.hashCode * 19; |
| 253 } |
| 254 |
| 255 bool operator ==(other) { |
| 256 if (identical(this, other)) return true; |
| 257 if (other is! ListLiteralUse) return false; |
| 258 return |
| 259 type == other.type && |
| 260 isConstant == other.isConstant && |
| 261 isEmpty == other.isEmpty; |
| 262 } |
| 263 } |
| 264 |
| 265 /// Mutable implementation of [WorldImpact] used to transform |
| 266 /// [ResolutionWorldImpact] to [WorldImpact]. |
| 267 // TODO(johnniwinther): Remove [Registry] when dependency is tracked directly |
| 268 // on [WorldImpact]. |
| 269 class TransformedWorldImpact implements WorldImpact, Registry { |
| 270 final ResolutionWorldImpact worldImpact; |
| 271 |
| 272 Setlet<Element> _staticUses; |
| 273 Setlet<InterfaceType> _instantiatedTypes; |
| 274 Setlet<UniverseSelector> _dynamicGetters; |
| 275 Setlet<UniverseSelector> _dynamicInvocations; |
| 276 Setlet<UniverseSelector> _dynamicSetters; |
| 277 |
| 278 TransformedWorldImpact(this.worldImpact); |
| 279 |
| 280 @override |
| 281 Iterable<DartType> get asCasts => worldImpact.asCasts; |
| 282 |
| 283 @override |
| 284 Iterable<DartType> get checkedModeChecks => worldImpact.checkedModeChecks; |
| 285 |
| 286 @override |
| 287 Iterable<MethodElement> get closurizedFunctions { |
| 288 return worldImpact.closurizedFunctions; |
| 289 } |
| 290 |
| 291 @override |
| 292 Iterable<UniverseSelector> get dynamicGetters { |
| 293 return _dynamicGetters != null |
| 294 ? _dynamicGetters : worldImpact.dynamicGetters; |
| 295 } |
| 296 |
| 297 @override |
| 298 Iterable<UniverseSelector> get dynamicInvocations { |
| 299 return _dynamicInvocations != null |
| 300 ? _dynamicInvocations : worldImpact.dynamicInvocations; |
| 301 } |
| 302 |
| 303 @override |
| 304 Iterable<UniverseSelector> get dynamicSetters { |
| 305 return _dynamicSetters != null |
| 306 ? _dynamicSetters : worldImpact.dynamicSetters; |
| 307 } |
| 308 |
| 309 @override |
| 310 Iterable<DartType> get isChecks => worldImpact.isChecks; |
| 311 |
| 312 @override |
| 313 Iterable<Element> get staticUses { |
| 314 if (_staticUses == null) { |
| 315 return worldImpact.staticUses; |
| 316 } |
| 317 return _staticUses; |
| 318 } |
| 319 |
| 320 @override |
| 321 bool get isForResolution => true; |
| 322 |
| 323 _unsupported(String message) => throw new UnsupportedError(message); |
| 324 |
| 325 @override |
| 326 Iterable<Element> get otherDependencies => _unsupported('otherDependencies'); |
| 327 |
| 328 // TODO(johnniwinther): Remove this. |
| 329 @override |
| 330 void registerAssert(bool hasMessage) => _unsupported('registerAssert'); |
| 331 |
| 332 @override |
| 333 void registerDependency(Element element) { |
| 334 worldImpact.registerDependency(element); |
| 335 } |
| 336 |
| 337 @override |
| 338 void registerDynamicGetter(UniverseSelector selector) { |
| 339 if (_dynamicGetters == null) { |
| 340 _dynamicGetters = new Setlet<UniverseSelector>(); |
| 341 _dynamicGetters.addAll(worldImpact.dynamicGetters); |
| 342 } |
| 343 _dynamicGetters.add(selector); |
| 344 } |
| 345 |
| 346 @override |
| 347 void registerDynamicInvocation(UniverseSelector selector) { |
| 348 if (_dynamicInvocations == null) { |
| 349 _dynamicInvocations = new Setlet<UniverseSelector>(); |
| 350 _dynamicInvocations.addAll(worldImpact.dynamicInvocations); |
| 351 } |
| 352 _dynamicInvocations.add(selector); |
| 353 } |
| 354 |
| 355 @override |
| 356 void registerDynamicSetter(UniverseSelector selector) { |
| 357 if (_dynamicSetters == null) { |
| 358 _dynamicSetters = new Setlet<UniverseSelector>(); |
| 359 _dynamicSetters.addAll(worldImpact.dynamicSetters); |
| 360 } |
| 361 _dynamicSetters.add(selector); |
| 362 } |
| 363 |
| 364 @override |
| 365 void registerGetOfStaticFunction(FunctionElement element) { |
| 366 _unsupported('registerGetOfStaticFunction($element)'); |
| 367 } |
| 368 |
| 369 @override |
| 370 void registerInstantiation(InterfaceType type) { |
| 371 // TODO(johnniwinther): Remove this when dependency tracking is done on |
| 372 // the world impact itself. |
| 373 registerDependency(type.element); |
| 374 if (_instantiatedTypes == null) { |
| 375 _instantiatedTypes = new Setlet<InterfaceType>(); |
| 376 } |
| 377 _instantiatedTypes.add(type); |
| 378 } |
| 379 |
| 380 @override |
| 381 Iterable<InterfaceType> get instantiatedTypes { |
| 382 return _instantiatedTypes != null |
| 383 ? _instantiatedTypes : const <InterfaceType>[]; |
| 384 } |
| 385 |
| 386 @override |
| 387 void registerStaticInvocation(Element element) { |
| 388 // TODO(johnniwinther): Remove this when dependency tracking is done on |
| 389 // the world impact itself. |
| 390 registerDependency(element); |
| 391 if (_staticUses == null) { |
| 392 _staticUses = new Setlet<Element>(); |
| 393 } |
| 394 _staticUses.add(element); |
| 395 } |
| 396 |
| 397 @override |
| 398 Iterable<LocalFunctionElement> get closures => worldImpact.closures; |
| 399 } |
| 400 |
136 // TODO(johnniwinther): Rename to `Resolver` or `ResolverContext`. | 401 // TODO(johnniwinther): Rename to `Resolver` or `ResolverContext`. |
137 abstract class Resolution { | 402 abstract class Resolution { |
138 Parsing get parsing; | 403 Parsing get parsing; |
139 DiagnosticReporter get reporter; | 404 DiagnosticReporter get reporter; |
140 CoreTypes get coreTypes; | 405 CoreTypes get coreTypes; |
141 | 406 |
142 void resolveTypedef(TypedefElement typdef); | 407 void resolveTypedef(TypedefElement typdef); |
143 void resolveClass(ClassElement cls); | 408 void resolveClass(ClassElement cls); |
144 void registerClass(ClassElement cls); | 409 void registerClass(ClassElement cls); |
145 void resolveMetadataAnnotation(MetadataAnnotation metadataAnnotation); | 410 void resolveMetadataAnnotation(MetadataAnnotation metadataAnnotation); |
146 FunctionSignature resolveSignature(FunctionElement function); | 411 FunctionSignature resolveSignature(FunctionElement function); |
147 DartType resolveTypeAnnotation(Element element, TypeAnnotation node); | 412 DartType resolveTypeAnnotation(Element element, TypeAnnotation node); |
| 413 |
| 414 bool hasBeenResolved(Element element); |
| 415 ResolutionWorldImpact analyzeElement(Element element); |
148 } | 416 } |
149 | 417 |
150 // TODO(johnniwinther): Rename to `Parser` or `ParsingContext`. | 418 // TODO(johnniwinther): Rename to `Parser` or `ParsingContext`. |
151 abstract class Parsing { | 419 abstract class Parsing { |
152 DiagnosticReporter get reporter; | 420 DiagnosticReporter get reporter; |
153 void parsePatchClass(ClassElement cls); | 421 void parsePatchClass(ClassElement cls); |
154 measure(f()); | 422 measure(f()); |
155 } | 423 } |
OLD | NEW |