OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library dart2js.resolution; | 5 library dart2js.resolution; |
6 | 6 |
7 import 'dart:collection' show Queue; | 7 import 'dart:collection' show Queue; |
8 | 8 |
9 import '../common.dart'; | 9 import '../common.dart'; |
10 import '../common/names.dart' show | 10 import '../common/names.dart' show |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 import '../util/util.dart' show | 48 import '../util/util.dart' show |
49 Link, | 49 Link, |
50 LinkBuilder, | 50 LinkBuilder, |
51 Setlet; | 51 Setlet; |
52 | 52 |
53 import 'class_hierarchy.dart'; | 53 import 'class_hierarchy.dart'; |
54 import 'class_members.dart' show MembersCreator; | 54 import 'class_members.dart' show MembersCreator; |
55 import 'constructors.dart'; | 55 import 'constructors.dart'; |
56 import 'members.dart'; | 56 import 'members.dart'; |
57 import 'registry.dart'; | 57 import 'registry.dart'; |
| 58 import 'resolution_result.dart'; |
58 import 'signatures.dart'; | 59 import 'signatures.dart'; |
59 import 'tree_elements.dart'; | 60 import 'tree_elements.dart'; |
60 import 'typedefs.dart'; | 61 import 'typedefs.dart'; |
61 | 62 |
62 class ResolverTask extends CompilerTask { | 63 class ResolverTask extends CompilerTask { |
63 final ConstantCompiler constantCompiler; | 64 final ConstantCompiler constantCompiler; |
64 | 65 |
65 ResolverTask(Compiler compiler, this.constantCompiler) : super(compiler); | 66 ResolverTask(Compiler compiler, this.constantCompiler) : super(compiler); |
66 | 67 |
67 String get name => 'Resolver'; | 68 String get name => 'Resolver'; |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 } | 221 } |
221 } | 222 } |
222 | 223 |
223 ResolverVisitor visitor = visitorFor(element); | 224 ResolverVisitor visitor = visitorFor(element); |
224 ResolutionRegistry registry = visitor.registry; | 225 ResolutionRegistry registry = visitor.registry; |
225 registry.defineFunction(tree, element); | 226 registry.defineFunction(tree, element); |
226 visitor.setupFunction(tree, element); | 227 visitor.setupFunction(tree, element); |
227 processAsyncMarker(compiler, element, registry); | 228 processAsyncMarker(compiler, element, registry); |
228 | 229 |
229 if (element.isGenerativeConstructor) { | 230 if (element.isGenerativeConstructor) { |
| 231 ConstructorElementX constructor = element; |
230 // Even if there is no initializer list we still have to do the | 232 // Even if there is no initializer list we still have to do the |
231 // resolution in case there is an implicit super constructor call. | 233 // resolution in case there is an implicit super constructor call. |
232 InitializerResolver resolver = | 234 InitializerResolver resolver = |
233 new InitializerResolver(visitor, element, tree); | 235 new InitializerResolver(visitor, constructor, tree); |
234 FunctionElement redirection = resolver.resolveInitializers(); | 236 FunctionElement redirection = resolver.resolveInitializers(); |
| 237 constructor.constantConstructor; |
| 238 /*if (constructor.isConst && !constructor.isFromEnvironmentConstructor)
{ |
| 239 assert(invariant(constructor, |
| 240 constructor.constantConstructorCache != null, |
| 241 message: "Constant constructor has")) |
| 242 }*/ |
235 if (redirection != null) { | 243 if (redirection != null) { |
236 resolveRedirectingConstructor(resolver, tree, element, redirection); | 244 resolveRedirectingConstructor( |
| 245 resolver, tree, constructor, redirection); |
237 } | 246 } |
238 } else if (tree.initializers != null) { | 247 } else if (tree.initializers != null) { |
239 reporter.reportErrorMessage( | 248 reporter.reportErrorMessage( |
240 tree, MessageKind.FUNCTION_WITH_INITIALIZER); | 249 tree, MessageKind.FUNCTION_WITH_INITIALIZER); |
241 } | 250 } |
242 | 251 |
243 if (!compiler.analyzeSignaturesOnly || tree.isRedirectingFactory) { | 252 if (!compiler.analyzeSignaturesOnly || tree.isRedirectingFactory) { |
244 // We need to analyze the redirecting factory bodies to ensure that | 253 // We need to analyze the redirecting factory bodies to ensure that |
245 // we can analyze compile-time constants. | 254 // we can analyze compile-time constants. |
246 visitor.visit(tree.body); | 255 visitor.visit(tree.body); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
332 useEnclosingScope: useEnclosingScope); | 341 useEnclosingScope: useEnclosingScope); |
333 } | 342 } |
334 | 343 |
335 WorldImpact resolveField(FieldElementX element) { | 344 WorldImpact resolveField(FieldElementX element) { |
336 VariableDefinitions tree = element.parseNode(parsing); | 345 VariableDefinitions tree = element.parseNode(parsing); |
337 if(element.modifiers.isStatic && element.isTopLevel) { | 346 if(element.modifiers.isStatic && element.isTopLevel) { |
338 reporter.reportErrorMessage( | 347 reporter.reportErrorMessage( |
339 element.modifiers.getStatic(), | 348 element.modifiers.getStatic(), |
340 MessageKind.TOP_LEVEL_VARIABLE_DECLARED_STATIC); | 349 MessageKind.TOP_LEVEL_VARIABLE_DECLARED_STATIC); |
341 } | 350 } |
| 351 bool requireConstant = element.isConst; |
| 352 if (!requireConstant && element.isInstanceMember) { |
| 353 for (ConstructorElement constructor in |
| 354 element.enclosingClass.constructors) { |
| 355 if (constructor.isConst) { |
| 356 requireConstant = true; |
| 357 break; |
| 358 } |
| 359 } |
| 360 } |
342 ResolverVisitor visitor = visitorFor(element); | 361 ResolverVisitor visitor = visitorFor(element); |
343 ResolutionRegistry registry = visitor.registry; | 362 ResolutionRegistry registry = visitor.registry; |
344 // TODO(johnniwinther): Maybe remove this when placeholderCollector migrates | 363 // TODO(johnniwinther): Maybe remove this when placeholderCollector migrates |
345 // to the backend ast. | 364 // to the backend ast. |
346 registry.defineElement(tree.definitions.nodes.head, element); | 365 registry.defineElement(tree.definitions.nodes.head, element); |
347 // TODO(johnniwinther): Share the resolved type between all variables | 366 // TODO(johnniwinther): Share the resolved type between all variables |
348 // declared in the same declaration. | 367 // declared in the same declaration. |
349 if (tree.type != null) { | 368 if (tree.type != null) { |
350 element.variables.type = visitor.resolveTypeAnnotation(tree.type); | 369 element.variables.type = visitor.resolveTypeAnnotation(tree.type); |
351 } else { | 370 } else { |
352 element.variables.type = const DynamicType(); | 371 element.variables.type = const DynamicType(); |
353 } | 372 } |
354 | 373 |
355 Expression initializer = element.initializer; | 374 Expression initializer = element.initializer; |
356 Modifiers modifiers = element.modifiers; | 375 Modifiers modifiers = element.modifiers; |
| 376 ResolutionResult result = const NoneResult(); |
357 if (initializer != null) { | 377 if (initializer != null) { |
358 // TODO(johnniwinther): Avoid analyzing initializers if | 378 // TODO(johnniwinther): Avoid analyzing initializers if |
359 // [Compiler.analyzeSignaturesOnly] is set. | 379 // [Compiler.analyzeSignaturesOnly] is set. |
360 visitor.visit(initializer); | 380 //reportHere(reporter, element, 'resolveField:$element (${visitor.constant
State}) (${initializer.runtimeType})'); |
| 381 if (requireConstant) { |
| 382 result = visitor.visitInConstantContext(initializer); |
| 383 visitor.checkConstantInvariant(initializer, result); |
| 384 } else { |
| 385 result = visitor.visit(initializer); |
| 386 } |
| 387 registry.setConstant(initializer, result.constant); |
361 } else if (modifiers.isConst) { | 388 } else if (modifiers.isConst) { |
362 reporter.reportErrorMessage( | 389 reporter.reportErrorMessage( |
363 element, MessageKind.CONST_WITHOUT_INITIALIZER); | 390 element, MessageKind.CONST_WITHOUT_INITIALIZER); |
364 } else if (modifiers.isFinal && !element.isInstanceMember) { | 391 } else if (modifiers.isFinal && !element.isInstanceMember) { |
365 reporter.reportErrorMessage( | 392 reporter.reportErrorMessage( |
366 element, MessageKind.FINAL_WITHOUT_INITIALIZER); | 393 element, MessageKind.FINAL_WITHOUT_INITIALIZER); |
367 } else { | 394 } else { |
368 registry.registerInstantiatedClass(compiler.nullClass); | 395 registry.registerInstantiatedClass(compiler.nullClass); |
369 } | 396 } |
| 397 element.constant = result.constant; |
370 | 398 |
371 if (Elements.isStaticOrTopLevelField(element)) { | 399 if (Elements.isStaticOrTopLevelField(element)) { |
372 visitor.addDeferredAction(element, () { | 400 visitor.addDeferredAction(element, () { |
373 if (element.modifiers.isConst) { | 401 if (element.modifiers.isConst) { |
374 element.constant = constantCompiler.compileConstant(element); | 402 // Ensure constant expression will be evaluated. |
| 403 constantCompiler.compileConstant(element); |
375 } else { | 404 } else { |
376 constantCompiler.compileVariable(element); | 405 constantCompiler.compileVariable(element); |
377 } | 406 } |
378 }); | 407 }); |
379 if (initializer != null) { | 408 if (initializer != null) { |
380 if (!element.modifiers.isConst) { | 409 if (!element.modifiers.isConst) { |
381 // TODO(johnniwinther): Determine the const-ness eagerly to avoid | 410 // TODO(johnniwinther): Determine the const-ness eagerly to avoid |
382 // unnecessary registrations. | 411 // unnecessary registrations. |
383 registry.registerLazyField(); | 412 registry.registerLazyField(); |
384 } | 413 } |
(...skipping 638 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1023 assert(invariant(node, context != null, | 1052 assert(invariant(node, context != null, |
1024 message: "No context found for metadata annotation " | 1053 message: "No context found for metadata annotation " |
1025 "on $annotatedElement.")); | 1054 "on $annotatedElement.")); |
1026 ResolverVisitor visitor = visitorFor(context, useEnclosingScope: true); | 1055 ResolverVisitor visitor = visitorFor(context, useEnclosingScope: true); |
1027 ResolutionRegistry registry = visitor.registry; | 1056 ResolutionRegistry registry = visitor.registry; |
1028 node.accept(visitor); | 1057 node.accept(visitor); |
1029 // TODO(johnniwinther): Avoid passing the [TreeElements] to | 1058 // TODO(johnniwinther): Avoid passing the [TreeElements] to |
1030 // [compileMetadata]. | 1059 // [compileMetadata]. |
1031 annotation.constant = | 1060 annotation.constant = |
1032 constantCompiler.compileMetadata(annotation, node, registry.mapping); | 1061 constantCompiler.compileMetadata(annotation, node, registry.mapping); |
1033 constantCompiler.evaluate(annotation.constant); | 1062 constantCompiler.evaluate(node, annotation.constant); |
1034 // TODO(johnniwinther): Register the relation between the annotation | 1063 // TODO(johnniwinther): Register the relation between the annotation |
1035 // and the annotated element instead. This will allow the backend to | 1064 // and the annotated element instead. This will allow the backend to |
1036 // retrieve the backend constant and only register metadata on the | 1065 // retrieve the backend constant and only register metadata on the |
1037 // elements for which it is needed. (Issue 17732). | 1066 // elements for which it is needed. (Issue 17732). |
1038 registry.registerMetadataConstant(annotation); | 1067 registry.registerMetadataConstant(annotation); |
1039 annotation.resolutionState = STATE_DONE; | 1068 annotation.resolutionState = STATE_DONE; |
1040 })); | 1069 })); |
1041 } | 1070 } |
1042 | 1071 |
1043 List<MetadataAnnotation> resolveMetadata(Element element, | 1072 List<MetadataAnnotation> resolveMetadata(Element element, |
(...skipping 24 matching lines...) Expand all Loading... |
1068 TreeElements get treeElements { | 1097 TreeElements get treeElements { |
1069 assert(invariant(this, _treeElements !=null, | 1098 assert(invariant(this, _treeElements !=null, |
1070 message: "TreeElements have not been computed for $this.")); | 1099 message: "TreeElements have not been computed for $this.")); |
1071 return _treeElements; | 1100 return _treeElements; |
1072 } | 1101 } |
1073 | 1102 |
1074 void reuseElement() { | 1103 void reuseElement() { |
1075 _treeElements = null; | 1104 _treeElements = null; |
1076 } | 1105 } |
1077 } | 1106 } |
OLD | NEW |