OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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.constructors; | 5 library dart2js.resolution.constructors; |
6 | 6 |
7 import '../common.dart'; | 7 import '../common.dart'; |
8 import '../common/resolution.dart' show Feature; | 8 import '../common/resolution.dart' show Feature; |
9 import '../compiler.dart' show Compiler; | 9 import '../compiler.dart' show Compiler; |
10 import '../constants/constructors.dart' | 10 import '../constants/constructors.dart' |
(...skipping 14 matching lines...) Expand all Loading... |
25 ParameterElementX; | 25 ParameterElementX; |
26 import '../tree/tree.dart'; | 26 import '../tree/tree.dart'; |
27 import '../util/util.dart' show Link; | 27 import '../util/util.dart' show Link; |
28 import '../universe/call_structure.dart' show CallStructure; | 28 import '../universe/call_structure.dart' show CallStructure; |
29 import '../universe/use.dart' show StaticUse; | 29 import '../universe/use.dart' show StaticUse; |
30 | 30 |
31 import 'members.dart' show lookupInScope, ResolverVisitor; | 31 import 'members.dart' show lookupInScope, ResolverVisitor; |
32 import 'registry.dart' show ResolutionRegistry; | 32 import 'registry.dart' show ResolutionRegistry; |
33 import 'resolution_common.dart' show CommonResolverVisitor; | 33 import 'resolution_common.dart' show CommonResolverVisitor; |
34 import 'resolution_result.dart'; | 34 import 'resolution_result.dart'; |
| 35 import 'scope.dart' show Scope, ExtensionScope; |
35 | 36 |
36 class InitializerResolver { | 37 class InitializerResolver { |
37 final ResolverVisitor visitor; | 38 final ResolverVisitor visitor; |
38 final ConstructorElementX constructor; | 39 final ConstructorElementX constructor; |
39 final FunctionExpression functionNode; | 40 final FunctionExpression functionNode; |
40 final Map<FieldElement, Node> initialized = <FieldElement, Node>{}; | 41 final Map<FieldElement, Node> initialized = <FieldElement, Node>{}; |
41 final Map<FieldElement, ConstantExpression> fieldInitializers = | 42 final Map<FieldElement, ConstantExpression> fieldInitializers = |
42 <FieldElement, ConstantExpression>{}; | 43 <FieldElement, ConstantExpression>{}; |
43 Link<Node> initializers; | 44 Link<Node> initializers; |
44 bool hasSuper = false; | 45 bool hasSuper = false; |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 node, constructorName, kind, {}); | 288 node, constructorName, kind, {}); |
288 } | 289 } |
289 } | 290 } |
290 return result; | 291 return result; |
291 } | 292 } |
292 | 293 |
293 /** | 294 /** |
294 * Resolve all initializers of this constructor. In the case of a redirecting | 295 * Resolve all initializers of this constructor. In the case of a redirecting |
295 * constructor, the resolved constructor's function element is returned. | 296 * constructor, the resolved constructor's function element is returned. |
296 */ | 297 */ |
297 ConstructorElement resolveInitializers() { | 298 ConstructorElement resolveInitializers( |
| 299 {bool enableInitializingFormalAccess: false}) { |
298 Map<dynamic /*String|int*/, ConstantExpression> defaultValues = | 300 Map<dynamic /*String|int*/, ConstantExpression> defaultValues = |
299 <dynamic /*String|int*/, ConstantExpression>{}; | 301 <dynamic /*String|int*/, ConstantExpression>{}; |
300 ConstructedConstantExpression constructorInvocation; | 302 ConstructedConstantExpression constructorInvocation; |
301 // Keep track of all "this.param" parameters specified for constructor so | 303 // Keep track of all "this.param" parameters specified for constructor so |
302 // that we can ensure that fields are initialized only once. | 304 // that we can ensure that fields are initialized only once. |
303 FunctionSignature functionParameters = constructor.functionSignature; | 305 FunctionSignature functionParameters = constructor.functionSignature; |
| 306 Scope oldScope = visitor.scope; |
| 307 if (enableInitializingFormalAccess) { |
| 308 // In order to get the correct detection of name clashes between all |
| 309 // parameters (regular ones and initializing formals) we must extend |
| 310 // the parameter scope rather than adding a new nested scope. |
| 311 visitor.scope = new ExtensionScope(visitor.scope); |
| 312 } |
| 313 Link<Node> parameterNodes = (functionNode.parameters == null) |
| 314 ? const Link<Node>() |
| 315 : functionNode.parameters.nodes; |
304 functionParameters.forEachParameter((ParameterElementX element) { | 316 functionParameters.forEachParameter((ParameterElementX element) { |
| 317 List<Element> optionals = functionParameters.optionalParameters; |
| 318 if (!optionals.isEmpty && element == optionals.first) { |
| 319 NodeList nodes = parameterNodes.head; |
| 320 parameterNodes = nodes.nodes; |
| 321 } |
305 if (isConst) { | 322 if (isConst) { |
306 if (element.isOptional) { | 323 if (element.isOptional) { |
307 if (element.constantCache == null) { | 324 if (element.constantCache == null) { |
308 // TODO(johnniwinther): Remove this when all constant expressions | 325 // TODO(johnniwinther): Remove this when all constant expressions |
309 // can be computed during resolution. | 326 // can be computed during resolution. |
310 isValidAsConstant = false; | 327 isValidAsConstant = false; |
311 } else { | 328 } else { |
312 ConstantExpression defaultValue = element.constant; | 329 ConstantExpression defaultValue = element.constant; |
313 if (defaultValue != null) { | 330 if (defaultValue != null) { |
314 if (element.isNamed) { | 331 if (element.isNamed) { |
315 defaultValues[element.name] = defaultValue; | 332 defaultValues[element.name] = defaultValue; |
316 } else { | 333 } else { |
317 int index = | 334 int index = |
318 element.functionDeclaration.parameters.indexOf(element); | 335 element.functionDeclaration.parameters.indexOf(element); |
319 defaultValues[index] = defaultValue; | 336 defaultValues[index] = defaultValue; |
320 } | 337 } |
321 } else { | 338 } else { |
322 isValidAsConstant = false; | 339 isValidAsConstant = false; |
323 } | 340 } |
324 } | 341 } |
325 } | 342 } |
326 } | 343 } |
327 if (element.isInitializingFormal) { | 344 if (element.isInitializingFormal) { |
| 345 VariableDefinitions variableDefinitions = parameterNodes.head; |
| 346 Node parameterNode = variableDefinitions.definitions.nodes.head; |
328 InitializingFormalElementX initializingFormal = element; | 347 InitializingFormalElementX initializingFormal = element; |
329 FieldElement field = initializingFormal.fieldElement; | 348 FieldElement field = initializingFormal.fieldElement; |
330 checkForDuplicateInitializers(field, element.initializer); | 349 checkForDuplicateInitializers(field, element.initializer); |
| 350 if (enableInitializingFormalAccess) { |
| 351 visitor.defineLocalVariable(parameterNode, initializingFormal); |
| 352 visitor.addToScope(initializingFormal); |
| 353 } |
331 if (isConst) { | 354 if (isConst) { |
332 if (element.isNamed) { | 355 if (element.isNamed) { |
333 fieldInitializers[field] = new NamedArgumentReference(element.name); | 356 fieldInitializers[field] = new NamedArgumentReference(element.name); |
334 } else { | 357 } else { |
335 int index = element.functionDeclaration.parameters.indexOf(element); | 358 int index = element.functionDeclaration.parameters.indexOf(element); |
336 fieldInitializers[field] = new PositionalArgumentReference(index); | 359 fieldInitializers[field] = new PositionalArgumentReference(index); |
337 } | 360 } |
338 } else { | 361 } else { |
339 isValidAsConstant = false; | 362 isValidAsConstant = false; |
340 } | 363 } |
341 } | 364 } |
| 365 parameterNodes = parameterNodes.tail; |
342 }); | 366 }); |
343 | 367 |
344 if (functionNode.initializers == null) { | 368 if (functionNode.initializers == null) { |
345 initializers = const Link<Node>(); | 369 initializers = const Link<Node>(); |
346 } else { | 370 } else { |
347 initializers = functionNode.initializers.nodes; | 371 initializers = functionNode.initializers.nodes; |
348 } | 372 } |
349 bool resolvedSuper = false; | 373 bool resolvedSuper = false; |
350 for (Link<Node> link = initializers; !link.isEmpty; link = link.tail) { | 374 for (Link<Node> link = initializers; !link.isEmpty; link = link.tail) { |
351 if (link.head.asSendSet() != null) { | 375 if (link.head.asSendSet() != null) { |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
423 if (!resolvedSuper) { | 447 if (!resolvedSuper) { |
424 constructorInvocation = resolveImplicitSuperConstructorSend(); | 448 constructorInvocation = resolveImplicitSuperConstructorSend(); |
425 } | 449 } |
426 if (isConst && isValidAsConstant) { | 450 if (isConst && isValidAsConstant) { |
427 constructor.constantConstructor = new GenerativeConstantConstructor( | 451 constructor.constantConstructor = new GenerativeConstantConstructor( |
428 constructor.enclosingClass.thisType, | 452 constructor.enclosingClass.thisType, |
429 defaultValues, | 453 defaultValues, |
430 fieldInitializers, | 454 fieldInitializers, |
431 constructorInvocation); | 455 constructorInvocation); |
432 } | 456 } |
| 457 visitor.scope = oldScope; |
433 return null; // If there was no redirection always return null. | 458 return null; // If there was no redirection always return null. |
434 } | 459 } |
435 } | 460 } |
436 | 461 |
437 class ConstructorResolver extends CommonResolverVisitor<ConstructorResult> { | 462 class ConstructorResolver extends CommonResolverVisitor<ConstructorResult> { |
438 final ResolverVisitor resolver; | 463 final ResolverVisitor resolver; |
439 final bool inConstContext; | 464 final bool inConstContext; |
440 | 465 |
441 ConstructorResolver(Compiler compiler, this.resolver, | 466 ConstructorResolver(Compiler compiler, this.resolver, |
442 {bool this.inConstContext: false}) | 467 {bool this.inConstContext: false}) |
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
850 // constructors. | 875 // constructors. |
851 return null; | 876 return null; |
852 } | 877 } |
853 // TODO(johnniwinther): Use [Name] for lookup. | 878 // TODO(johnniwinther): Use [Name] for lookup. |
854 ConstructorElement constructor = cls.lookupConstructor(constructorName); | 879 ConstructorElement constructor = cls.lookupConstructor(constructorName); |
855 if (constructor != null) { | 880 if (constructor != null) { |
856 constructor = constructor.declaration; | 881 constructor = constructor.declaration; |
857 } | 882 } |
858 return constructor; | 883 return constructor; |
859 } | 884 } |
OLD | NEW |