| 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 | |
| 8 /// initializers. | |
| 9 abstract class ConstantEnvironment { | |
| 10 /// Returns the constant for the initializer of [element]. | |
| 11 Constant getConstantForVariable(VariableElement element); | |
| 12 } | |
| 13 | |
| 14 /// A class that can compile and provide constants for variables, nodes and | |
| 15 /// metadata. | |
| 16 abstract class ConstantCompiler extends ConstantEnvironment { | |
| 17 /// Compiles the compile-time constant for the initializer of [element], or | |
| 18 /// reports an error if the initializer is not a compile-time constant. | |
| 19 /// | |
| 20 /// Depending on implementation, the constant compiler might also compute | |
| 21 /// the compile-time constant for the backend interpretation of constants. | |
| 22 /// | |
| 23 /// The returned constant is always of the frontend interpretation. | |
| 24 Constant compileConstant(VariableElement element); | |
| 25 | |
| 26 /// Computes the compile-time constant for the variable initializer, | |
| 27 /// if possible. | |
| 28 void compileVariable(VariableElement element); | |
| 29 | |
| 30 /// Compiles the compile-time constant for [node], or reports an error if | |
| 31 /// [node] is not a compile-time constant. | |
| 32 /// | |
| 33 /// Depending on implementation, the constant compiler might also compute | |
| 34 /// the compile-time constant for the backend interpretation of constants. | |
| 35 /// | |
| 36 /// The returned constant is always of the frontend interpretation. | |
| 37 Constant compileNode(Node node, TreeElements elements); | |
| 38 | |
| 39 /// Compiles the compile-time constant for the value [metadata], or reports an | |
| 40 /// error if the value is not a compile-time constant. | |
| 41 /// | |
| 42 /// Depending on implementation, the constant compiler might also compute | |
| 43 /// the compile-time constant for the backend interpretation of constants. | |
| 44 /// | |
| 45 /// The returned constant is always of the frontend interpretation. | |
| 46 Constant compileMetadata(MetadataAnnotation metadata, | |
| 47 Node node, TreeElements elements); | |
| 48 } | |
| 49 | |
| 50 /// A [BackendConstantEnvironment] provides access to constants needed for | |
| 51 /// backend implementation. | |
| 52 abstract class BackendConstantEnvironment extends ConstantEnvironment { | |
| 53 /// Returns the compile-time constant associated with [node]. | |
| 54 /// | |
| 55 /// Depending on implementation, the constant might be stored in [elements]. | |
| 56 Constant getConstantForNode(Node node, TreeElements elements); | |
| 57 | |
| 58 /// Returns the compile-time constant value of [metadata]. | |
| 59 Constant getConstantForMetadata(MetadataAnnotation metadata); | |
| 60 } | |
| 61 | |
| 62 /// Interface for the task that compiles the constant environments for the | |
| 63 /// frontend and backend interpretation of compile-time constants. | |
| 64 abstract class ConstantCompilerTask extends CompilerTask | |
| 65 implements ConstantCompiler { | |
| 66 ConstantCompilerTask(Compiler compiler) : super(compiler); | |
| 67 } | |
| 68 | |
| 69 /** | 7 /** |
| 70 * The [ConstantCompilerBase] is provides base implementation for compilation of | 8 * The [ConstantHandler] keeps track of compile-time constants, |
| 71 * compile-time constants for both the Dart and JavaScript interpretation of | 9 * initializations of global and static fields, and default values of |
| 72 * constants. It keeps track of compile-time constants for initializations of | 10 * optional parameters. |
| 73 * global and static fields, and default values of optional parameters. | |
| 74 */ | 11 */ |
| 75 abstract class ConstantCompilerBase implements ConstantCompiler { | 12 class ConstantHandler extends CompilerTask { |
| 76 final Compiler compiler; | |
| 77 final ConstantSystem constantSystem; | 13 final ConstantSystem constantSystem; |
| 14 final bool isMetadata; |
| 78 | 15 |
| 79 /** | 16 /** |
| 80 * Contains the initial value of fields. Must contain all static and global | 17 * Contains the initial value of fields. Must contain all static and global |
| 81 * initializations of const fields. May contain eagerly compiled values for | 18 * initializations of const fields. May contain eagerly compiled values for |
| 82 * statics and instance fields. | 19 * statics and instance fields. |
| 83 * | 20 * |
| 84 * Invariant: The keys in this map are declarations. | 21 * Invariant: The keys in this map are declarations. |
| 85 */ | 22 */ |
| 86 final Map<VariableElement, Constant> initialVariableValues = | 23 final Map<VariableElement, Constant> initialVariableValues; |
| 87 new Map<VariableElement, Constant>(); | 24 |
| 25 /** Set of all registered compiled constants. */ |
| 26 final Set<Constant> compiledConstants; |
| 88 | 27 |
| 89 /** The set of variable elements that are in the process of being computed. */ | 28 /** The set of variable elements that are in the process of being computed. */ |
| 90 final Set<VariableElement> pendingVariables = new Set<VariableElement>(); | 29 final Set<VariableElement> pendingVariables; |
| 91 | 30 |
| 92 ConstantCompilerBase(this.compiler, this.constantSystem); | 31 /** Caches the statics where the initial value cannot be eagerly compiled. */ |
| 32 final Set<VariableElement> lazyStatics; |
| 33 |
| 34 ConstantHandler(Compiler compiler, this.constantSystem, |
| 35 { bool this.isMetadata: false }) |
| 36 : initialVariableValues = new Map<VariableElement, dynamic>(), |
| 37 compiledConstants = new Set<Constant>(), |
| 38 pendingVariables = new Set<VariableElement>(), |
| 39 lazyStatics = new Set<VariableElement>(), |
| 40 super(compiler); |
| 41 |
| 42 String get name => 'ConstantHandler'; |
| 43 |
| 44 void addCompileTimeConstantForEmission(Constant constant) { |
| 45 compiledConstants.add(constant); |
| 46 } |
| 93 | 47 |
| 94 Constant getConstantForVariable(VariableElement element) { | 48 Constant getConstantForVariable(VariableElement element) { |
| 95 return initialVariableValues[element.declaration]; | 49 return initialVariableValues[element.declaration]; |
| 96 } | 50 } |
| 97 | 51 |
| 52 /** |
| 53 * Returns a compile-time constant, or reports an error if the element is not |
| 54 * a compile-time constant. |
| 55 */ |
| 98 Constant compileConstant(VariableElement element) { | 56 Constant compileConstant(VariableElement element) { |
| 99 return compileVariable(element, isConst: true); | 57 return compileVariable(element, isConst: true); |
| 100 } | 58 } |
| 101 | 59 |
| 60 /** |
| 61 * Returns the a compile-time constant if the variable could be compiled |
| 62 * eagerly. Otherwise returns `null`. |
| 63 */ |
| 102 Constant compileVariable(VariableElement element, {bool isConst: false}) { | 64 Constant compileVariable(VariableElement element, {bool isConst: false}) { |
| 103 | 65 return measure(() { |
| 104 if (initialVariableValues.containsKey(element.declaration)) { | 66 if (initialVariableValues.containsKey(element.declaration)) { |
| 105 Constant result = initialVariableValues[element.declaration]; | 67 Constant result = initialVariableValues[element.declaration]; |
| 106 return result; | 68 return result; |
| 107 } | 69 } |
| 108 Element currentElement = element; | 70 Element currentElement = element; |
| 109 if (element.isParameter() || | 71 if (element.isParameter() |
| 110 element.isFieldParameter() || | 72 || element.isFieldParameter() |
| 111 element.isVariable()) { | 73 || element.isVariable()) { |
| 112 currentElement = element.enclosingElement; | 74 currentElement = element.enclosingElement; |
| 113 } | 75 } |
| 114 return compiler.withCurrentElement(currentElement, () { | 76 return compiler.withCurrentElement(currentElement, () { |
| 115 TreeElements definitions = | 77 TreeElements definitions = |
| 116 compiler.analyzeElement(currentElement.declaration); | 78 compiler.analyzeElement(currentElement.declaration); |
| 117 Constant constant = compileVariableWithDefinitions( | 79 Constant constant = compileVariableWithDefinitions( |
| 118 element, definitions, isConst: isConst); | 80 element, definitions, isConst: isConst); |
| 119 return constant; | 81 return constant; |
| 82 }); |
| 120 }); | 83 }); |
| 121 } | 84 } |
| 122 | 85 |
| 123 /** | 86 /** |
| 124 * Returns the a compile-time constant if the variable could be compiled | 87 * Returns the a compile-time constant if the variable could be compiled |
| 125 * eagerly. If the variable needs to be initialized lazily returns `null`. | 88 * eagerly. If the variable needs to be initialized lazily returns `null`. |
| 126 * If the variable is `const` but cannot be compiled eagerly reports an | 89 * If the variable is `const` but cannot be compiled eagerly reports an |
| 127 * error. | 90 * error. |
| 128 */ | 91 */ |
| 129 Constant compileVariableWithDefinitions(VariableElement element, | 92 Constant compileVariableWithDefinitions(VariableElement element, |
| 130 TreeElements definitions, | 93 TreeElements definitions, |
| 131 {bool isConst: false}) { | 94 {bool isConst: false}) { |
| 132 Node node = element.parseNode(compiler); | 95 return measure(() { |
| 133 if (pendingVariables.contains(element)) { | 96 if (!isConst && lazyStatics.contains(element)) return null; |
| 134 if (isConst) { | 97 |
| 135 compiler.reportFatalError( | 98 Node node = element.parseNode(compiler); |
| 136 node, MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS); | 99 if (pendingVariables.contains(element)) { |
| 100 if (isConst) { |
| 101 compiler.reportFatalError( |
| 102 node, MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS); |
| 103 } else { |
| 104 lazyStatics.add(element); |
| 105 return null; |
| 106 } |
| 137 } | 107 } |
| 138 return null; | 108 pendingVariables.add(element); |
| 139 } | |
| 140 pendingVariables.add(element); | |
| 141 | 109 |
| 142 Expression initializer = element.initializer; | 110 Expression initializer = element.initializer; |
| 143 Constant value; | 111 Constant value; |
| 144 if (initializer == null) { | 112 if (initializer == null) { |
| 145 // No initial value. | 113 // No initial value. |
| 146 value = new NullConstant(); | 114 value = new NullConstant(); |
| 147 } else { | 115 } else { |
| 148 value = compileNodeWithDefinitions( | 116 value = compileNodeWithDefinitions( |
| 149 initializer, definitions, isConst: isConst); | 117 initializer, definitions, isConst: isConst); |
| 150 if (compiler.enableTypeAssertions && | 118 if (compiler.enableTypeAssertions && |
| 151 value != null && | 119 value != null && |
| 152 element.isField()) { | 120 element.isField()) { |
| 153 DartType elementType = element.type; | 121 DartType elementType = element.type; |
| 154 if (elementType.kind == TypeKind.MALFORMED_TYPE && !value.isNull) { | 122 if (elementType.kind == TypeKind.MALFORMED_TYPE && !value.isNull) { |
| 155 if (isConst) { | 123 if (isConst) { |
| 156 ErroneousElement element = elementType.element; | 124 ErroneousElement element = elementType.element; |
| 157 compiler.reportFatalError( | 125 compiler.reportFatalError( |
| 158 node, element.messageKind, element.messageArguments); | 126 node, element.messageKind, element.messageArguments); |
| 127 } else { |
| 128 // We need to throw an exception at runtime. |
| 129 value = null; |
| 130 } |
| 159 } else { | 131 } else { |
| 160 // We need to throw an exception at runtime. | 132 DartType constantType = value.computeType(compiler); |
| 161 value = null; | 133 if (!constantSystem.isSubtype(compiler, |
| 162 } | 134 constantType, elementType)) { |
| 163 } else { | 135 if (isConst) { |
| 164 DartType constantType = value.computeType(compiler); | 136 compiler.reportFatalError( |
| 165 if (!constantSystem.isSubtype(compiler, | 137 node, MessageKind.NOT_ASSIGNABLE, |
| 166 constantType, elementType)) { | 138 {'fromType': constantType, 'toType': elementType}); |
| 167 if (isConst) { | 139 } else { |
| 168 compiler.reportFatalError( | 140 // If the field cannot be lazily initialized, we will throw |
| 169 node, MessageKind.NOT_ASSIGNABLE, | 141 // the exception at runtime. |
| 170 {'fromType': constantType, 'toType': elementType}); | 142 value = null; |
| 171 } else { | 143 } |
| 172 // If the field cannot be lazily initialized, we will throw | |
| 173 // the exception at runtime. | |
| 174 value = null; | |
| 175 } | 144 } |
| 176 } | 145 } |
| 177 } | 146 } |
| 178 } | 147 } |
| 179 } | 148 if (value != null) { |
| 180 if (value != null) { | 149 initialVariableValues[element.declaration] = value; |
| 181 initialVariableValues[element.declaration] = value; | 150 } else { |
| 182 } else { | 151 assert(!isConst); |
| 183 assert(!isConst); | 152 lazyStatics.add(element); |
| 184 } | 153 } |
| 185 pendingVariables.remove(element); | 154 pendingVariables.remove(element); |
| 186 return value; | 155 return value; |
| 156 }); |
| 187 } | 157 } |
| 188 | 158 |
| 189 Constant compileNodeWithDefinitions(Node node, | 159 Constant compileNodeWithDefinitions(Node node, |
| 190 TreeElements definitions, | 160 TreeElements definitions, |
| 191 {bool isConst: true}) { | 161 {bool isConst: false}) { |
| 192 assert(node != null); | 162 return measure(() { |
| 193 CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator( | 163 assert(node != null); |
| 194 this, definitions, compiler, isConst: isConst); | 164 Constant constant = definitions.getConstant(node); |
| 195 return evaluator.evaluate(node); | 165 if (constant != null) { |
| 166 return constant; |
| 167 } |
| 168 CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator( |
| 169 this, definitions, compiler, isConst: isConst); |
| 170 constant = evaluator.evaluate(node); |
| 171 if (constant != null) { |
| 172 definitions.setConstant(node, constant); |
| 173 } |
| 174 return constant; |
| 175 }); |
| 196 } | 176 } |
| 197 | 177 |
| 198 Constant compileNode(Node node, TreeElements elements) { | 178 /** |
| 199 return compileNodeWithDefinitions(node, elements); | 179 * Returns an [Iterable] of static non final fields that need to be |
| 180 * initialized. The fields list must be evaluated in order since they might |
| 181 * depend on each other. |
| 182 */ |
| 183 Iterable<VariableElement> getStaticNonFinalFieldsForEmission() { |
| 184 return initialVariableValues.keys.where((element) { |
| 185 return element.kind == ElementKind.FIELD |
| 186 && !element.isInstanceMember() |
| 187 && !element.modifiers.isFinal() |
| 188 // The const fields are all either emitted elsewhere or inlined. |
| 189 && !element.modifiers.isConst(); |
| 190 }); |
| 200 } | 191 } |
| 201 | 192 |
| 202 Constant compileMetadata(MetadataAnnotation metadata, | 193 List<VariableElement> getLazilyInitializedFieldsForEmission() { |
| 203 Node node, | 194 return new List<VariableElement>.from(lazyStatics); |
| 204 TreeElements elements) { | |
| 205 return compileNodeWithDefinitions(node, elements); | |
| 206 } | |
| 207 } | |
| 208 | |
| 209 /// [ConstantCompiler] that uses the Dart semantics for the compile-time | |
| 210 /// constant evaluation. | |
| 211 class DartConstantCompiler extends ConstantCompilerBase { | |
| 212 DartConstantCompiler(Compiler compiler) | |
| 213 : super(compiler, const DartConstantSystem()); | |
| 214 | |
| 215 Constant getConstantForNode(Node node, TreeElements definitions) { | |
| 216 return definitions.getConstant(node); | |
| 217 } | 195 } |
| 218 | 196 |
| 219 Constant getConstantForMetadata(MetadataAnnotation metadata) { | 197 /** |
| 220 return metadata.value; | 198 * Returns a list of constants topologically sorted so that dependencies |
| 199 * appear before the dependent constant. [preSortCompare] is a comparator |
| 200 * function that gives the constants a consistent order prior to the |
| 201 * topological sort which gives the constants an ordering that is less |
| 202 * sensitive to perturbations in the source code. |
| 203 */ |
| 204 List<Constant> getConstantsForEmission([preSortCompare]) { |
| 205 // We must emit dependencies before their uses. |
| 206 Set<Constant> seenConstants = new Set<Constant>(); |
| 207 List<Constant> result = new List<Constant>(); |
| 208 |
| 209 void addConstant(Constant constant) { |
| 210 if (!seenConstants.contains(constant)) { |
| 211 constant.getDependencies().forEach(addConstant); |
| 212 assert(!seenConstants.contains(constant)); |
| 213 result.add(constant); |
| 214 seenConstants.add(constant); |
| 215 } |
| 216 } |
| 217 |
| 218 List<Constant> sorted = compiledConstants.toList(); |
| 219 if (preSortCompare != null) { |
| 220 sorted.sort(preSortCompare); |
| 221 } |
| 222 sorted.forEach(addConstant); |
| 223 return result; |
| 221 } | 224 } |
| 222 | 225 |
| 223 Constant compileNodeWithDefinitions(Node node, | 226 Constant getInitialValueFor(VariableElement element) { |
| 224 TreeElements definitions, | 227 Constant initialValue = initialVariableValues[element.declaration]; |
| 225 {bool isConst: true}) { | 228 if (initialValue == null) { |
| 226 Constant constant = definitions.getConstant(node); | 229 compiler.internalError(element, "No initial value for given element."); |
| 227 if (constant != null) { | |
| 228 return constant; | |
| 229 } | 230 } |
| 230 constant = | 231 return initialValue; |
| 231 super.compileNodeWithDefinitions(node, definitions, isConst: isConst); | |
| 232 if (constant != null) { | |
| 233 definitions.setConstant(node, constant); | |
| 234 } | |
| 235 return constant; | |
| 236 } | 232 } |
| 237 } | 233 } |
| 238 | 234 |
| 239 class CompileTimeConstantEvaluator extends Visitor { | 235 class CompileTimeConstantEvaluator extends Visitor { |
| 240 bool isEvaluatingConstant; | 236 bool isEvaluatingConstant; |
| 241 final ConstantCompilerBase handler; | 237 final ConstantHandler handler; |
| 242 final TreeElements elements; | 238 final TreeElements elements; |
| 243 final Compiler compiler; | 239 final Compiler compiler; |
| 244 | 240 |
| 245 CompileTimeConstantEvaluator(this.handler, | 241 CompileTimeConstantEvaluator(this.handler, |
| 246 this.elements, | 242 this.elements, |
| 247 this.compiler, | 243 this.compiler, |
| 248 {bool isConst: false}) | 244 {bool isConst: false}) |
| 249 : this.isEvaluatingConstant = isConst; | 245 : this.isEvaluatingConstant = isConst; |
| 250 | 246 |
| 251 ConstantSystem get constantSystem => handler.constantSystem; | 247 ConstantSystem get constantSystem => handler.constantSystem; |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 437 if (prefixNode != null) { | 433 if (prefixNode != null) { |
| 438 Element maybePrefix = elements[prefixNode.asIdentifier()]; | 434 Element maybePrefix = elements[prefixNode.asIdentifier()]; |
| 439 if (maybePrefix != null && maybePrefix.isPrefix() && | 435 if (maybePrefix != null && maybePrefix.isPrefix() && |
| 440 (maybePrefix as PrefixElement).isDeferred) { | 436 (maybePrefix as PrefixElement).isDeferred) { |
| 441 return true; | 437 return true; |
| 442 } | 438 } |
| 443 } | 439 } |
| 444 return false; | 440 return false; |
| 445 } | 441 } |
| 446 | 442 |
| 447 Constant visitIdentifier(Identifier node) { | |
| 448 Element element = elements[node]; | |
| 449 if (Elements.isClass(element) || Elements.isTypedef(element)) { | |
| 450 return makeTypeConstant(element); | |
| 451 } | |
| 452 return signalNotCompileTimeConstant(node); | |
| 453 } | |
| 454 | |
| 455 // TODO(floitsch): provide better error-messages. | 443 // TODO(floitsch): provide better error-messages. |
| 456 Constant visitSend(Send send) { | 444 Constant visitSend(Send send) { |
| 457 Element element = elements[send]; | 445 Element element = elements[send]; |
| 458 if (send.isPropertyAccess) { | 446 if (send.isPropertyAccess) { |
| 459 if (isDeferredUse(send)) { | 447 if (isDeferredUse(send)) { |
| 460 return signalNotCompileTimeConstant(send, | 448 return signalNotCompileTimeConstant(send, |
| 461 message: MessageKind.DEFERRED_COMPILE_TIME_CONSTANT); | 449 message: MessageKind.DEFERRED_COMPILE_TIME_CONSTANT); |
| 462 } | 450 } |
| 463 if (Elements.isStaticOrTopLevelFunction(element)) { | 451 if (Elements.isStaticOrTopLevelFunction(element)) { |
| 464 return new FunctionConstant(element); | 452 return new FunctionConstant(element); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 482 if (result != null) return result; | 470 if (result != null) return result; |
| 483 } | 471 } |
| 484 return signalNotCompileTimeConstant(send); | 472 return signalNotCompileTimeConstant(send); |
| 485 } else if (send.isCall) { | 473 } else if (send.isCall) { |
| 486 if (identical(element, compiler.identicalFunction) | 474 if (identical(element, compiler.identicalFunction) |
| 487 && send.argumentCount() == 2) { | 475 && send.argumentCount() == 2) { |
| 488 Constant left = evaluate(send.argumentsNode.nodes.head); | 476 Constant left = evaluate(send.argumentsNode.nodes.head); |
| 489 Constant right = evaluate(send.argumentsNode.nodes.tail.head); | 477 Constant right = evaluate(send.argumentsNode.nodes.tail.head); |
| 490 Constant result = constantSystem.identity.fold(left, right); | 478 Constant result = constantSystem.identity.fold(left, right); |
| 491 if (result != null) return result; | 479 if (result != null) return result; |
| 480 } else if (Elements.isClass(element) || Elements.isTypedef(element)) { |
| 481 // The node itself is not a constant but we register the selector (the |
| 482 // identifier that refers to the class/typedef) as a constant. |
| 483 Constant typeConstant = makeTypeConstant(element); |
| 484 elements.setConstant(send.selector, typeConstant); |
| 492 } | 485 } |
| 493 return signalNotCompileTimeConstant(send); | 486 return signalNotCompileTimeConstant(send); |
| 494 } else if (send.isPrefix) { | 487 } else if (send.isPrefix) { |
| 495 assert(send.isOperator); | 488 assert(send.isOperator); |
| 496 Constant receiverConstant = evaluate(send.receiver); | 489 Constant receiverConstant = evaluate(send.receiver); |
| 497 if (receiverConstant == null) return null; | 490 if (receiverConstant == null) return null; |
| 498 Operator op = send.selector; | 491 Operator op = send.selector; |
| 499 Constant folded; | 492 Constant folded; |
| 500 switch (op.source) { | 493 switch (op.source) { |
| 501 case "!": | 494 case "!": |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 810 final FunctionElement constructor; | 803 final FunctionElement constructor; |
| 811 final Map<Element, Constant> definitions; | 804 final Map<Element, Constant> definitions; |
| 812 final Map<Element, Constant> fieldValues; | 805 final Map<Element, Constant> fieldValues; |
| 813 | 806 |
| 814 /** | 807 /** |
| 815 * Documentation wanted -- johnniwinther | 808 * Documentation wanted -- johnniwinther |
| 816 * | 809 * |
| 817 * Invariant: [constructor] must be an implementation element. | 810 * Invariant: [constructor] must be an implementation element. |
| 818 */ | 811 */ |
| 819 ConstructorEvaluator(FunctionElement constructor, | 812 ConstructorEvaluator(FunctionElement constructor, |
| 820 ConstantCompiler handler, | 813 ConstantHandler handler, |
| 821 Compiler compiler) | 814 Compiler compiler) |
| 822 : this.constructor = constructor, | 815 : this.constructor = constructor, |
| 823 this.definitions = new Map<Element, Constant>(), | 816 this.definitions = new Map<Element, Constant>(), |
| 824 this.fieldValues = new Map<Element, Constant>(), | 817 this.fieldValues = new Map<Element, Constant>(), |
| 825 super(handler, | 818 super(handler, |
| 826 compiler.resolver.resolveMethodElement(constructor.declaration), | 819 compiler.resolver.resolveMethodElement(constructor.declaration), |
| 827 compiler, | 820 compiler, |
| 828 isConst: true) { | 821 isConst: true) { |
| 829 assert(invariant(constructor, constructor.isImplementation)); | 822 assert(invariant(constructor, constructor.isImplementation)); |
| 830 } | 823 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 843 | 836 |
| 844 void potentiallyCheckType(Node node, | 837 void potentiallyCheckType(Node node, |
| 845 TypedElement element, | 838 TypedElement element, |
| 846 Constant constant) { | 839 Constant constant) { |
| 847 if (compiler.enableTypeAssertions) { | 840 if (compiler.enableTypeAssertions) { |
| 848 DartType elementType = element.type; | 841 DartType elementType = element.type; |
| 849 DartType constantType = constant.computeType(compiler); | 842 DartType constantType = constant.computeType(compiler); |
| 850 // TODO(ngeoffray): Handle type parameters. | 843 // TODO(ngeoffray): Handle type parameters. |
| 851 if (elementType.element.isTypeVariable()) return; | 844 if (elementType.element.isTypeVariable()) return; |
| 852 if (!constantSystem.isSubtype(compiler, constantType, elementType)) { | 845 if (!constantSystem.isSubtype(compiler, constantType, elementType)) { |
| 853 // TODO(johnniwinther): Provide better [node] values that point to the | |
| 854 // origin of the constant and not (just) the assignment. | |
| 855 compiler.reportFatalError( | 846 compiler.reportFatalError( |
| 856 node, MessageKind.NOT_ASSIGNABLE, | 847 node, MessageKind.NOT_ASSIGNABLE, |
| 857 {'fromType': elementType, 'toType': constantType}); | 848 {'fromType': elementType, 'toType': constantType}); |
| 858 } | 849 } |
| 859 } | 850 } |
| 860 } | 851 } |
| 861 | 852 |
| 862 void updateFieldValue(Node node, TypedElement element, Constant constant) { | 853 void updateFieldValue(Node node, TypedElement element, Constant constant) { |
| 863 potentiallyCheckType(node, element, constant); | 854 potentiallyCheckType(node, element, constant); |
| 864 fieldValues[element] = constant; | 855 fieldValues[element] = constant; |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 990 if (fieldValue == null) { | 981 if (fieldValue == null) { |
| 991 // Use the default value. | 982 // Use the default value. |
| 992 fieldValue = handler.compileConstant(field); | 983 fieldValue = handler.compileConstant(field); |
| 993 } | 984 } |
| 994 jsNewArguments.add(fieldValue); | 985 jsNewArguments.add(fieldValue); |
| 995 }, | 986 }, |
| 996 includeSuperAndInjectedMembers: true); | 987 includeSuperAndInjectedMembers: true); |
| 997 return jsNewArguments; | 988 return jsNewArguments; |
| 998 } | 989 } |
| 999 } | 990 } |
| OLD | NEW |