| 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 part of dart2js; | 5 part of dart2js; |
| 6 | 6 |
| 7 /// A [ConstantEnvironment] provides access for constants compiled for variable | 7 /// A [ConstantEnvironment] provides access for constants compiled for variable |
| 8 /// initializers. | 8 /// initializers. |
| 9 abstract class ConstantEnvironment { | 9 abstract class ConstantEnvironment { |
| 10 /// Returns the constant for the initializer of [element]. | 10 /// Returns the constant for the initializer of [element]. |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 return compileVariable(element, isConst: true); | 99 return compileVariable(element, isConst: true); |
| 100 } | 100 } |
| 101 | 101 |
| 102 Constant compileVariable(VariableElement element, {bool isConst: false}) { | 102 Constant compileVariable(VariableElement element, {bool isConst: false}) { |
| 103 | 103 |
| 104 if (initialVariableValues.containsKey(element.declaration)) { | 104 if (initialVariableValues.containsKey(element.declaration)) { |
| 105 Constant result = initialVariableValues[element.declaration]; | 105 Constant result = initialVariableValues[element.declaration]; |
| 106 return result; | 106 return result; |
| 107 } | 107 } |
| 108 Element currentElement = element; | 108 Element currentElement = element; |
| 109 if (element.isParameter() || | 109 if (element.isParameter || |
| 110 element.isFieldParameter() || | 110 element.isFieldParameter || |
| 111 element.isVariable()) { | 111 element.isVariable) { |
| 112 currentElement = element.enclosingElement; | 112 currentElement = element.enclosingElement; |
| 113 } | 113 } |
| 114 return compiler.withCurrentElement(currentElement, () { | 114 return compiler.withCurrentElement(currentElement, () { |
| 115 TreeElements definitions = | 115 TreeElements definitions = |
| 116 compiler.analyzeElement(currentElement.declaration); | 116 compiler.analyzeElement(currentElement.declaration); |
| 117 Constant constant = compileVariableWithDefinitions( | 117 Constant constant = compileVariableWithDefinitions( |
| 118 element, definitions, isConst: isConst); | 118 element, definitions, isConst: isConst); |
| 119 return constant; | 119 return constant; |
| 120 }); | 120 }); |
| 121 } | 121 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 142 Expression initializer = element.initializer; | 142 Expression initializer = element.initializer; |
| 143 Constant value; | 143 Constant value; |
| 144 if (initializer == null) { | 144 if (initializer == null) { |
| 145 // No initial value. | 145 // No initial value. |
| 146 value = new NullConstant(); | 146 value = new NullConstant(); |
| 147 } else { | 147 } else { |
| 148 value = compileNodeWithDefinitions( | 148 value = compileNodeWithDefinitions( |
| 149 initializer, definitions, isConst: isConst); | 149 initializer, definitions, isConst: isConst); |
| 150 if (compiler.enableTypeAssertions && | 150 if (compiler.enableTypeAssertions && |
| 151 value != null && | 151 value != null && |
| 152 element.isField()) { | 152 element.isField) { |
| 153 DartType elementType = element.type; | 153 DartType elementType = element.type; |
| 154 if (elementType.kind == TypeKind.MALFORMED_TYPE && !value.isNull) { | 154 if (elementType.kind == TypeKind.MALFORMED_TYPE && !value.isNull) { |
| 155 if (isConst) { | 155 if (isConst) { |
| 156 ErroneousElement element = elementType.element; | 156 ErroneousElement element = elementType.element; |
| 157 compiler.reportFatalError( | 157 compiler.reportFatalError( |
| 158 node, element.messageKind, element.messageArguments); | 158 node, element.messageKind, element.messageArguments); |
| 159 } else { | 159 } else { |
| 160 // We need to throw an exception at runtime. | 160 // We need to throw an exception at runtime. |
| 161 value = null; | 161 value = null; |
| 162 } | 162 } |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 273 | 273 |
| 274 Constant visitLiteralDouble(LiteralDouble node) { | 274 Constant visitLiteralDouble(LiteralDouble node) { |
| 275 return constantSystem.createDouble(node.value); | 275 return constantSystem.createDouble(node.value); |
| 276 } | 276 } |
| 277 | 277 |
| 278 Constant visitLiteralInt(LiteralInt node) { | 278 Constant visitLiteralInt(LiteralInt node) { |
| 279 return constantSystem.createInt(node.value); | 279 return constantSystem.createInt(node.value); |
| 280 } | 280 } |
| 281 | 281 |
| 282 Constant visitLiteralList(LiteralList node) { | 282 Constant visitLiteralList(LiteralList node) { |
| 283 if (!node.isConst()) { | 283 if (!node.isConst) { |
| 284 return signalNotCompileTimeConstant(node); | 284 return signalNotCompileTimeConstant(node); |
| 285 } | 285 } |
| 286 List<Constant> arguments = <Constant>[]; | 286 List<Constant> arguments = <Constant>[]; |
| 287 for (Link<Node> link = node.elements.nodes; | 287 for (Link<Node> link = node.elements.nodes; |
| 288 !link.isEmpty; | 288 !link.isEmpty; |
| 289 link = link.tail) { | 289 link = link.tail) { |
| 290 arguments.add(evaluateConstant(link.head)); | 290 arguments.add(evaluateConstant(link.head)); |
| 291 } | 291 } |
| 292 DartType type = elements.getType(node); | 292 DartType type = elements.getType(node); |
| 293 return new ListConstant(type, arguments); | 293 return new ListConstant(type, arguments); |
| 294 } | 294 } |
| 295 | 295 |
| 296 Constant visitLiteralMap(LiteralMap node) { | 296 Constant visitLiteralMap(LiteralMap node) { |
| 297 if (!node.isConst()) { | 297 if (!node.isConst) { |
| 298 return signalNotCompileTimeConstant(node); | 298 return signalNotCompileTimeConstant(node); |
| 299 } | 299 } |
| 300 List<Constant> keys = <Constant>[]; | 300 List<Constant> keys = <Constant>[]; |
| 301 Map<Constant, Constant> map = new Map<Constant, Constant>(); | 301 Map<Constant, Constant> map = new Map<Constant, Constant>(); |
| 302 for (Link<Node> link = node.entries.nodes; | 302 for (Link<Node> link = node.entries.nodes; |
| 303 !link.isEmpty; | 303 !link.isEmpty; |
| 304 link = link.tail) { | 304 link = link.tail) { |
| 305 LiteralMapEntry entry = link.head; | 305 LiteralMapEntry entry = link.head; |
| 306 Constant key = evaluateConstant(entry.key); | 306 Constant key = evaluateConstant(entry.key); |
| 307 if (!map.containsKey(key)) { | 307 if (!map.containsKey(key)) { |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 435 Element element = elements[send]; | 435 Element element = elements[send]; |
| 436 if (send.isPropertyAccess) { | 436 if (send.isPropertyAccess) { |
| 437 if (isDeferredUse(send)) { | 437 if (isDeferredUse(send)) { |
| 438 return signalNotCompileTimeConstant(send, | 438 return signalNotCompileTimeConstant(send, |
| 439 message: MessageKind.DEFERRED_COMPILE_TIME_CONSTANT); | 439 message: MessageKind.DEFERRED_COMPILE_TIME_CONSTANT); |
| 440 } | 440 } |
| 441 if (Elements.isStaticOrTopLevelFunction(element)) { | 441 if (Elements.isStaticOrTopLevelFunction(element)) { |
| 442 return new FunctionConstant(element); | 442 return new FunctionConstant(element); |
| 443 } else if (Elements.isStaticOrTopLevelField(element)) { | 443 } else if (Elements.isStaticOrTopLevelField(element)) { |
| 444 Constant result; | 444 Constant result; |
| 445 if (element.modifiers.isConst()) { | 445 if (element.modifiers.isConst) { |
| 446 result = handler.compileConstant(element); | 446 result = handler.compileConstant(element); |
| 447 } else if (element.modifiers.isFinal() && !isEvaluatingConstant) { | 447 } else if (element.modifiers.isFinal && !isEvaluatingConstant) { |
| 448 result = handler.compileVariable(element); | 448 result = handler.compileVariable(element); |
| 449 } | 449 } |
| 450 if (result != null) return result; | 450 if (result != null) return result; |
| 451 } else if (Elements.isClass(element) || Elements.isTypedef(element)) { | 451 } else if (Elements.isClass(element) || Elements.isTypedef(element)) { |
| 452 assert(elements.isTypeLiteral(send)); | 452 assert(elements.isTypeLiteral(send)); |
| 453 return makeTypeConstant(element); | 453 return makeTypeConstant(element); |
| 454 } else if (send.receiver != null) { | 454 } else if (send.receiver != null) { |
| 455 // Fall through to error handling. | 455 // Fall through to error handling. |
| 456 } else if (!Elements.isUnresolved(element) | 456 } else if (!Elements.isUnresolved(element) |
| 457 && element.isVariable() | 457 && element.isVariable |
| 458 && element.modifiers.isConst()) { | 458 && element.modifiers.isConst) { |
| 459 Constant result = handler.compileConstant(element); | 459 Constant result = handler.compileConstant(element); |
| 460 if (result != null) return result; | 460 if (result != null) return result; |
| 461 } | 461 } |
| 462 return signalNotCompileTimeConstant(send); | 462 return signalNotCompileTimeConstant(send); |
| 463 } else if (send.isCall) { | 463 } else if (send.isCall) { |
| 464 if (identical(element, compiler.identicalFunction) | 464 if (identical(element, compiler.identicalFunction) |
| 465 && send.argumentCount() == 2) { | 465 && send.argumentCount() == 2) { |
| 466 Constant left = evaluate(send.argumentsNode.nodes.head); | 466 Constant left = evaluate(send.argumentsNode.nodes.head); |
| 467 Constant right = evaluate(send.argumentsNode.nodes.tail.head); | 467 Constant right = evaluate(send.argumentsNode.nodes.tail.head); |
| 468 Constant result = constantSystem.identity.fold(left, right); | 468 Constant result = constantSystem.identity.fold(left, right); |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 629 compiler); | 629 compiler); |
| 630 if (!succeeded) { | 630 if (!succeeded) { |
| 631 compiler.reportFatalError( | 631 compiler.reportFatalError( |
| 632 node, | 632 node, |
| 633 MessageKind.INVALID_ARGUMENTS, {'methodName': target.name}); | 633 MessageKind.INVALID_ARGUMENTS, {'methodName': target.name}); |
| 634 } | 634 } |
| 635 return compiledArguments; | 635 return compiledArguments; |
| 636 } | 636 } |
| 637 | 637 |
| 638 Constant visitNewExpression(NewExpression node) { | 638 Constant visitNewExpression(NewExpression node) { |
| 639 if (!node.isConst()) { | 639 if (!node.isConst) { |
| 640 return signalNotCompileTimeConstant(node); | 640 return signalNotCompileTimeConstant(node); |
| 641 } | 641 } |
| 642 | 642 |
| 643 Send send = node.send; | 643 Send send = node.send; |
| 644 FunctionElement constructor = elements[send]; | 644 FunctionElement constructor = elements[send]; |
| 645 if (Elements.isUnresolved(constructor)) { | 645 if (Elements.isUnresolved(constructor)) { |
| 646 return signalNotCompileTimeConstant(node); | 646 return signalNotCompileTimeConstant(node); |
| 647 } | 647 } |
| 648 | 648 |
| 649 // Deferred types can not be used in const instance creation expressions. | 649 // Deferred types can not be used in const instance creation expressions. |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 738 } | 738 } |
| 739 | 739 |
| 740 Constant makeConstructedConstant( | 740 Constant makeConstructedConstant( |
| 741 Spannable node, InterfaceType type, FunctionElement constructor, | 741 Spannable node, InterfaceType type, FunctionElement constructor, |
| 742 List<Constant> getArguments(FunctionElement constructor)) { | 742 List<Constant> getArguments(FunctionElement constructor)) { |
| 743 // The redirection chain of this element may not have been resolved through | 743 // The redirection chain of this element may not have been resolved through |
| 744 // a post-process action, so we have to make sure it is done here. | 744 // a post-process action, so we have to make sure it is done here. |
| 745 compiler.resolver.resolveRedirectionChain(constructor, node); | 745 compiler.resolver.resolveRedirectionChain(constructor, node); |
| 746 InterfaceType constructedType = constructor.computeTargetType(type); | 746 InterfaceType constructedType = constructor.computeTargetType(type); |
| 747 constructor = constructor.redirectionTarget; | 747 constructor = constructor.redirectionTarget; |
| 748 ClassElement classElement = constructor.getEnclosingClass(); | 748 ClassElement classElement = constructor.enclosingClass; |
| 749 // The constructor must be an implementation to ensure that field | 749 // The constructor must be an implementation to ensure that field |
| 750 // initializers are handled correctly. | 750 // initializers are handled correctly. |
| 751 constructor = constructor.implementation; | 751 constructor = constructor.implementation; |
| 752 assert(invariant(node, constructor.isImplementation)); | 752 assert(invariant(node, constructor.isImplementation)); |
| 753 | 753 |
| 754 List<Constant> arguments = getArguments(constructor); | 754 List<Constant> arguments = getArguments(constructor); |
| 755 ConstructorEvaluator evaluator = new ConstructorEvaluator( | 755 ConstructorEvaluator evaluator = new ConstructorEvaluator( |
| 756 constructedType, constructor, handler, compiler); | 756 constructedType, constructor, handler, compiler); |
| 757 evaluator.evaluateConstructorFieldValues(arguments); | 757 evaluator.evaluateConstructorFieldValues(arguments); |
| 758 List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement); | 758 List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 857 if (parameter.kind == ElementKind.FIELD_PARAMETER) { | 857 if (parameter.kind == ElementKind.FIELD_PARAMETER) { |
| 858 FieldParameterElement fieldParameterElement = parameter; | 858 FieldParameterElement fieldParameterElement = parameter; |
| 859 updateFieldValue(node, fieldParameterElement.fieldElement, argument); | 859 updateFieldValue(node, fieldParameterElement.fieldElement, argument); |
| 860 } | 860 } |
| 861 }); | 861 }); |
| 862 } | 862 } |
| 863 | 863 |
| 864 void evaluateSuperOrRedirectSend(List<Constant> compiledArguments, | 864 void evaluateSuperOrRedirectSend(List<Constant> compiledArguments, |
| 865 FunctionElement targetConstructor) { | 865 FunctionElement targetConstructor) { |
| 866 ConstructorEvaluator evaluator = new ConstructorEvaluator( | 866 ConstructorEvaluator evaluator = new ConstructorEvaluator( |
| 867 constructedType.asInstanceOf(targetConstructor.getEnclosingClass()), | 867 constructedType.asInstanceOf(targetConstructor.enclosingClass), |
| 868 targetConstructor, handler, compiler); | 868 targetConstructor, handler, compiler); |
| 869 evaluator.evaluateConstructorFieldValues(compiledArguments); | 869 evaluator.evaluateConstructorFieldValues(compiledArguments); |
| 870 // Copy over the fieldValues from the super/redirect-constructor. | 870 // Copy over the fieldValues from the super/redirect-constructor. |
| 871 // No need to go through [updateFieldValue] because the | 871 // No need to go through [updateFieldValue] because the |
| 872 // assignments have already been checked in checked mode. | 872 // assignments have already been checked in checked mode. |
| 873 evaluator.fieldValues.forEach((key, value) => fieldValues[key] = value); | 873 evaluator.fieldValues.forEach((key, value) => fieldValues[key] = value); |
| 874 } | 874 } |
| 875 | 875 |
| 876 /** | 876 /** |
| 877 * Runs through the initializers of the given [constructor] and updates | 877 * Runs through the initializers of the given [constructor] and updates |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 918 assert(!initArguments.isEmpty && initArguments.tail.isEmpty); | 918 assert(!initArguments.isEmpty && initArguments.tail.isEmpty); |
| 919 Constant fieldValue = evaluate(initArguments.head); | 919 Constant fieldValue = evaluate(initArguments.head); |
| 920 updateFieldValue(init, elements[init], fieldValue); | 920 updateFieldValue(init, elements[init], fieldValue); |
| 921 } | 921 } |
| 922 } | 922 } |
| 923 } | 923 } |
| 924 | 924 |
| 925 if (!foundSuperOrRedirect) { | 925 if (!foundSuperOrRedirect) { |
| 926 // No super initializer found. Try to find the default constructor if | 926 // No super initializer found. Try to find the default constructor if |
| 927 // the class is not Object. | 927 // the class is not Object. |
| 928 ClassElement enclosingClass = constructor.getEnclosingClass(); | 928 ClassElement enclosingClass = constructor.enclosingClass; |
| 929 ClassElement superClass = enclosingClass.superclass; | 929 ClassElement superClass = enclosingClass.superclass; |
| 930 if (enclosingClass != compiler.objectClass) { | 930 if (enclosingClass != compiler.objectClass) { |
| 931 assert(superClass != null); | 931 assert(superClass != null); |
| 932 assert(superClass.resolutionState == STATE_DONE); | 932 assert(superClass.resolutionState == STATE_DONE); |
| 933 | 933 |
| 934 Selector selector = | 934 Selector selector = |
| 935 new Selector.callDefaultConstructor(enclosingClass.getLibrary()); | 935 new Selector.callDefaultConstructor(enclosingClass.library); |
| 936 | 936 |
| 937 FunctionElement targetConstructor = | 937 FunctionElement targetConstructor = |
| 938 superClass.lookupConstructor(selector); | 938 superClass.lookupConstructor(selector); |
| 939 if (targetConstructor == null) { | 939 if (targetConstructor == null) { |
| 940 compiler.internalError(functionNode, | 940 compiler.internalError(functionNode, |
| 941 "No default constructor available."); | 941 "No default constructor available."); |
| 942 } | 942 } |
| 943 List<Constant> compiledArguments = evaluateArgumentsToConstructor( | 943 List<Constant> compiledArguments = evaluateArgumentsToConstructor( |
| 944 functionNode, selector, const Link<Node>(), targetConstructor); | 944 functionNode, selector, const Link<Node>(), targetConstructor); |
| 945 evaluateSuperOrRedirectSend(compiledArguments, targetConstructor); | 945 evaluateSuperOrRedirectSend(compiledArguments, targetConstructor); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 967 if (fieldValue == null) { | 967 if (fieldValue == null) { |
| 968 // Use the default value. | 968 // Use the default value. |
| 969 fieldValue = handler.compileConstant(field); | 969 fieldValue = handler.compileConstant(field); |
| 970 } | 970 } |
| 971 jsNewArguments.add(fieldValue); | 971 jsNewArguments.add(fieldValue); |
| 972 }, | 972 }, |
| 973 includeSuperAndInjectedMembers: true); | 973 includeSuperAndInjectedMembers: true); |
| 974 return jsNewArguments; | 974 return jsNewArguments; |
| 975 } | 975 } |
| 976 } | 976 } |
| OLD | NEW |