Chromium Code Reviews| 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 abstract class ConstantHandler { | |
|
floitsch
2014/04/02 16:50:02
The name "ConstantHandler" is now used with three
Johnni Winther
2014/04/07 11:42:27
Done.
| |
| 8 Constant getConstantForVariable(VariableElement element); | |
| 9 } | |
| 10 | |
| 11 abstract class ConstantCompiler extends ConstantHandler { | |
| 12 /** | |
| 13 * Returns a compile-time constant, or reports an error if the element is not | |
| 14 * a compile-time constant. | |
| 15 */ | |
| 16 Constant compileConstant(VariableElement element); | |
| 17 | |
| 18 Constant compileNode(Node node, TreeElements elements); | |
|
karlklose
2014/04/02 13:04:44
Please ad comments to these methods, too. And perh
Johnni Winther
2014/04/07 11:42:27
Done.
| |
| 19 | |
| 20 Constant compileMetadata(MetadataAnnotation metadata, | |
| 21 Node node, TreeElements elements); | |
| 22 } | |
| 23 | |
| 24 abstract class BackendConstantHandler extends ConstantHandler { | |
| 25 /** | |
| 26 * Returns the a compile-time constant if the variable could be compiled | |
| 27 * eagerly. Otherwise returns `null`. | |
| 28 */ | |
| 29 void compileVariable(VariableElement element); | |
| 30 | |
| 31 Constant getConstantForNode(Node node, TreeElements elements); | |
| 32 | |
| 33 Constant getConstantForMetadata(MetadataAnnotation metadata); | |
| 34 } | |
| 35 | |
| 36 class DartConstantHandler extends CompilerTask | |
| 37 implements ConstantCompiler, BackendConstantHandler { | |
| 38 final DartConstantCompiler constantCompiler; | |
| 39 | |
| 40 DartConstantHandler(Compiler compiler) | |
| 41 : this.constantCompiler = new DartConstantCompiler(compiler), | |
| 42 super(compiler); | |
| 43 | |
| 44 String get name => 'ConstantHandler'; | |
| 45 | |
| 46 Constant getConstantForVariable(VariableElement element) { | |
| 47 return constantCompiler.getConstantForVariable(element); | |
| 48 } | |
| 49 | |
| 50 Constant getConstantForNode(Node node, TreeElements elements) { | |
| 51 return constantCompiler.getConstantForNode(node, elements); | |
| 52 } | |
| 53 | |
| 54 Constant getConstantForMetadata(MetadataAnnotation metadata) { | |
| 55 return metadata.value; | |
| 56 } | |
| 57 | |
| 58 Constant compileConstant(VariableElement element) { | |
| 59 return measure(() { | |
| 60 return constantCompiler.compileConstant(element); | |
| 61 }); | |
| 62 } | |
| 63 | |
| 64 Constant compileVariable(VariableElement element) { | |
| 65 return measure(() { | |
| 66 return constantCompiler.compileVariable(element); | |
| 67 }); | |
| 68 } | |
| 69 | |
| 70 Constant compileNode(Node node, TreeElements elements) { | |
| 71 return measure(() { | |
| 72 return constantCompiler.compileNodeWithDefinitions(node, elements); | |
| 73 }); | |
| 74 } | |
| 75 | |
| 76 Constant compileMetadata(MetadataAnnotation metadata, | |
| 77 Node node, | |
| 78 TreeElements elements) { | |
| 79 return measure(() { | |
| 80 return constantCompiler.compileMetadata(metadata, node, elements); | |
| 81 }); | |
| 82 } | |
| 83 } | |
| 84 | |
| 7 /** | 85 /** |
| 8 * The [ConstantHandler] keeps track of compile-time constants, | 86 * The [ConstantCompilerBase] is used to keeps track of compile-time constants, |
| 9 * initializations of global and static fields, and default values of | 87 * initializations of global and static fields, and default values of |
| 10 * optional parameters. | 88 * optional parameters. |
| 11 */ | 89 */ |
| 12 class ConstantHandler extends CompilerTask { | 90 abstract class ConstantCompilerBase implements ConstantCompiler { |
| 91 final Compiler compiler; | |
| 13 final ConstantSystem constantSystem; | 92 final ConstantSystem constantSystem; |
| 14 final bool isMetadata; | |
| 15 | 93 |
| 16 /** | 94 /** |
| 17 * Contains the initial value of fields. Must contain all static and global | 95 * Contains the initial value of fields. Must contain all static and global |
| 18 * initializations of const fields. May contain eagerly compiled values for | 96 * initializations of const fields. May contain eagerly compiled values for |
| 19 * statics and instance fields. | 97 * statics and instance fields. |
| 20 * | 98 * |
| 21 * Invariant: The keys in this map are declarations. | 99 * Invariant: The keys in this map are declarations. |
| 22 */ | 100 */ |
| 23 final Map<VariableElement, Constant> initialVariableValues; | 101 final Map<VariableElement, Constant> initialVariableValues = |
| 24 | 102 new Map<VariableElement, Constant>(); |
| 25 /** Set of all registered compiled constants. */ | |
| 26 final Set<Constant> compiledConstants; | |
| 27 | 103 |
| 28 /** The set of variable elements that are in the process of being computed. */ | 104 /** The set of variable elements that are in the process of being computed. */ |
| 29 final Set<VariableElement> pendingVariables; | 105 final Set<VariableElement> pendingVariables = new Set<VariableElement>(); |
| 30 | 106 |
| 31 /** Caches the statics where the initial value cannot be eagerly compiled. */ | 107 ConstantCompilerBase(this.compiler, this.constantSystem); |
| 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 } | |
| 47 | 108 |
| 48 Constant getConstantForVariable(VariableElement element) { | 109 Constant getConstantForVariable(VariableElement element) { |
| 49 return initialVariableValues[element.declaration]; | 110 return initialVariableValues[element.declaration]; |
| 50 } | 111 } |
| 51 | 112 |
| 52 /** | |
| 53 * Returns a compile-time constant, or reports an error if the element is not | |
| 54 * a compile-time constant. | |
| 55 */ | |
| 56 Constant compileConstant(VariableElement element) { | 113 Constant compileConstant(VariableElement element) { |
| 57 return compileVariable(element, isConst: true); | 114 return compileVariable(element, isConst: true); |
| 58 } | 115 } |
| 59 | 116 |
| 60 /** | |
| 61 * Returns the a compile-time constant if the variable could be compiled | |
| 62 * eagerly. Otherwise returns `null`. | |
| 63 */ | |
| 64 Constant compileVariable(VariableElement element, {bool isConst: false}) { | 117 Constant compileVariable(VariableElement element, {bool isConst: false}) { |
| 65 return measure(() { | 118 |
| 66 if (initialVariableValues.containsKey(element.declaration)) { | 119 if (initialVariableValues.containsKey(element.declaration)) { |
| 67 Constant result = initialVariableValues[element.declaration]; | 120 Constant result = initialVariableValues[element.declaration]; |
| 68 return result; | 121 return result; |
| 69 } | 122 } |
| 70 Element currentElement = element; | 123 Element currentElement = element; |
| 71 if (element.isParameter() | 124 if (element.isParameter() || |
| 72 || element.isFieldParameter() | 125 element.isFieldParameter() || |
| 73 || element.isVariable()) { | 126 element.isVariable()) { |
| 74 currentElement = element.enclosingElement; | 127 currentElement = element.enclosingElement; |
| 75 } | 128 } |
| 76 return compiler.withCurrentElement(currentElement, () { | 129 return compiler.withCurrentElement(currentElement, () { |
| 77 TreeElements definitions = | 130 TreeElements definitions = |
| 78 compiler.analyzeElement(currentElement.declaration); | 131 compiler.analyzeElement(currentElement.declaration); |
| 79 Constant constant = compileVariableWithDefinitions( | 132 Constant constant = compileVariableWithDefinitions( |
| 80 element, definitions, isConst: isConst); | 133 element, definitions, isConst: isConst); |
| 81 return constant; | 134 return constant; |
| 82 }); | |
| 83 }); | 135 }); |
| 84 } | 136 } |
| 85 | 137 |
| 86 /** | 138 /** |
| 87 * Returns the a compile-time constant if the variable could be compiled | 139 * Returns the a compile-time constant if the variable could be compiled |
| 88 * eagerly. If the variable needs to be initialized lazily returns `null`. | 140 * eagerly. If the variable needs to be initialized lazily returns `null`. |
| 89 * If the variable is `const` but cannot be compiled eagerly reports an | 141 * If the variable is `const` but cannot be compiled eagerly reports an |
| 90 * error. | 142 * error. |
| 91 */ | 143 */ |
| 92 Constant compileVariableWithDefinitions(VariableElement element, | 144 Constant compileVariableWithDefinitions(VariableElement element, |
| 93 TreeElements definitions, | 145 TreeElements definitions, |
| 94 {bool isConst: false}) { | 146 {bool isConst: false}) { |
| 95 return measure(() { | 147 Node node = element.parseNode(compiler); |
| 96 if (!isConst && lazyStatics.contains(element)) return null; | 148 if (pendingVariables.contains(element)) { |
| 149 if (isConst) { | |
| 150 compiler.reportFatalError( | |
| 151 node, MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS); | |
| 152 } | |
| 153 return null; | |
| 154 } | |
| 155 pendingVariables.add(element); | |
| 97 | 156 |
| 98 Node node = element.parseNode(compiler); | 157 Expression initializer = element.initializer; |
| 99 if (pendingVariables.contains(element)) { | 158 Constant value; |
| 100 if (isConst) { | 159 if (initializer == null) { |
| 101 compiler.reportFatalError( | 160 // No initial value. |
| 102 node, MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS); | 161 value = new NullConstant(); |
| 162 } else { | |
| 163 value = compileNodeWithDefinitions( | |
| 164 initializer, definitions, isConst: isConst); | |
| 165 if (compiler.enableTypeAssertions && | |
| 166 value != null && | |
| 167 element.isField()) { | |
| 168 DartType elementType = element.type; | |
| 169 if (elementType.kind == TypeKind.MALFORMED_TYPE && !value.isNull) { | |
| 170 if (isConst) { | |
| 171 ErroneousElement element = elementType.element; | |
| 172 compiler.reportFatalError( | |
| 173 node, element.messageKind, element.messageArguments); | |
| 174 } else { | |
| 175 // We need to throw an exception at runtime. | |
| 176 value = null; | |
| 177 } | |
| 103 } else { | 178 } else { |
| 104 lazyStatics.add(element); | 179 DartType constantType = value.computeType(compiler); |
| 105 return null; | 180 if (!constantSystem.isSubtype(compiler, |
| 106 } | 181 constantType, elementType)) { |
| 107 } | |
| 108 pendingVariables.add(element); | |
| 109 | |
| 110 Expression initializer = element.initializer; | |
| 111 Constant value; | |
| 112 if (initializer == null) { | |
| 113 // No initial value. | |
| 114 value = new NullConstant(); | |
| 115 } else { | |
| 116 value = compileNodeWithDefinitions( | |
| 117 initializer, definitions, isConst: isConst); | |
| 118 if (compiler.enableTypeAssertions && | |
| 119 value != null && | |
| 120 element.isField()) { | |
| 121 DartType elementType = element.type; | |
| 122 if (elementType.kind == TypeKind.MALFORMED_TYPE && !value.isNull) { | |
| 123 if (isConst) { | 182 if (isConst) { |
| 124 ErroneousElement element = elementType.element; | |
| 125 compiler.reportFatalError( | 183 compiler.reportFatalError( |
| 126 node, element.messageKind, element.messageArguments); | 184 node, MessageKind.NOT_ASSIGNABLE, |
| 185 {'fromType': constantType, 'toType': elementType}); | |
| 127 } else { | 186 } else { |
| 128 // We need to throw an exception at runtime. | 187 // If the field cannot be lazily initialized, we will throw |
| 188 // the exception at runtime. | |
| 129 value = null; | 189 value = null; |
| 130 } | 190 } |
| 131 } else { | |
| 132 DartType constantType = value.computeType(compiler); | |
| 133 if (!constantSystem.isSubtype(compiler, | |
| 134 constantType, elementType)) { | |
| 135 if (isConst) { | |
| 136 compiler.reportFatalError( | |
| 137 node, MessageKind.NOT_ASSIGNABLE, | |
| 138 {'fromType': constantType, 'toType': elementType}); | |
| 139 } else { | |
| 140 // If the field cannot be lazily initialized, we will throw | |
| 141 // the exception at runtime. | |
| 142 value = null; | |
| 143 } | |
| 144 } | |
| 145 } | 191 } |
| 146 } | 192 } |
| 147 } | 193 } |
| 148 if (value != null) { | 194 } |
| 149 initialVariableValues[element.declaration] = value; | 195 if (value != null) { |
| 150 } else { | 196 initialVariableValues[element.declaration] = value; |
| 151 assert(!isConst); | 197 } else { |
| 152 lazyStatics.add(element); | 198 assert(!isConst); |
| 153 } | 199 } |
| 154 pendingVariables.remove(element); | 200 pendingVariables.remove(element); |
| 155 return value; | 201 return value; |
| 156 }); | |
| 157 } | 202 } |
| 158 | 203 |
| 159 Constant compileNodeWithDefinitions(Node node, | 204 Constant compileNodeWithDefinitions(Node node, |
| 160 TreeElements definitions, | 205 TreeElements definitions, |
| 161 {bool isConst: false}) { | 206 {bool isConst: true}) { |
| 162 return measure(() { | 207 assert(node != null); |
| 163 assert(node != null); | 208 CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator( |
| 164 Constant constant = definitions.getConstant(node); | 209 this, definitions, compiler, isConst: isConst); |
| 165 if (constant != null) { | 210 return evaluator.evaluate(node); |
| 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 }); | |
| 176 } | 211 } |
| 177 | 212 |
| 178 /** | 213 Constant compileNode(Node node, TreeElements elements) { |
| 179 * Returns an [Iterable] of static non final fields that need to be | 214 return compileNodeWithDefinitions(node, elements); |
| 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 }); | |
| 191 } | 215 } |
| 192 | 216 |
| 193 List<VariableElement> getLazilyInitializedFieldsForEmission() { | 217 Constant compileMetadata(MetadataAnnotation metadata, |
| 194 return new List<VariableElement>.from(lazyStatics); | 218 Node node, |
| 219 TreeElements elements) { | |
| 220 return compileNodeWithDefinitions(node, elements); | |
| 221 } | |
| 222 } | |
| 223 | |
| 224 class DartConstantCompiler extends ConstantCompilerBase { | |
| 225 DartConstantCompiler(Compiler compiler) | |
| 226 : super(compiler, const DartConstantSystem()); | |
| 227 | |
| 228 Constant getConstantForNode(Node node, TreeElements definitions) { | |
| 229 return definitions.getConstant(node); | |
| 195 } | 230 } |
| 196 | 231 |
| 197 /** | 232 Constant getConstantForMetadata(MetadataAnnotation metadata) { |
| 198 * Returns a list of constants topologically sorted so that dependencies | 233 return metadata.value; |
| 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; | |
| 224 } | 234 } |
| 225 | 235 |
| 226 Constant getInitialValueFor(VariableElement element) { | 236 Constant compileNodeWithDefinitions(Node node, |
| 227 Constant initialValue = initialVariableValues[element.declaration]; | 237 TreeElements definitions, |
| 228 if (initialValue == null) { | 238 {bool isConst: true}) { |
| 229 compiler.internalError(element, "No initial value for given element."); | 239 Constant constant = definitions.getConstant(node); |
| 240 if (constant != null) { | |
| 241 return constant; | |
| 230 } | 242 } |
| 231 return initialValue; | 243 constant = |
| 244 super.compileNodeWithDefinitions(node, definitions, isConst: isConst); | |
| 245 if (constant != null) { | |
| 246 definitions.setConstant(node, constant); | |
| 247 } | |
| 248 return constant; | |
| 232 } | 249 } |
| 233 } | 250 } |
| 234 | 251 |
| 235 class CompileTimeConstantEvaluator extends Visitor { | 252 class CompileTimeConstantEvaluator extends Visitor { |
| 236 bool isEvaluatingConstant; | 253 bool isEvaluatingConstant; |
| 237 final ConstantHandler handler; | 254 final ConstantCompilerBase handler; |
| 238 final TreeElements elements; | 255 final TreeElements elements; |
| 239 final Compiler compiler; | 256 final Compiler compiler; |
| 240 | 257 |
| 241 CompileTimeConstantEvaluator(this.handler, | 258 CompileTimeConstantEvaluator(this.handler, |
| 242 this.elements, | 259 this.elements, |
| 243 this.compiler, | 260 this.compiler, |
| 244 {bool isConst: false}) | 261 {bool isConst: false}) |
| 245 : this.isEvaluatingConstant = isConst; | 262 : this.isEvaluatingConstant = isConst; |
| 246 | 263 |
| 247 ConstantSystem get constantSystem => handler.constantSystem; | 264 ConstantSystem get constantSystem => handler.constantSystem; |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 433 if (prefixNode != null) { | 450 if (prefixNode != null) { |
| 434 Element maybePrefix = elements[prefixNode.asIdentifier()]; | 451 Element maybePrefix = elements[prefixNode.asIdentifier()]; |
| 435 if (maybePrefix != null && maybePrefix.isPrefix() && | 452 if (maybePrefix != null && maybePrefix.isPrefix() && |
| 436 (maybePrefix as PrefixElement).isDeferred) { | 453 (maybePrefix as PrefixElement).isDeferred) { |
| 437 return true; | 454 return true; |
| 438 } | 455 } |
| 439 } | 456 } |
| 440 return false; | 457 return false; |
| 441 } | 458 } |
| 442 | 459 |
| 460 Constant visitIdentifier(Identifier node) { | |
| 461 Element element = elements[node]; | |
| 462 if (Elements.isClass(element) || Elements.isTypedef(element)) { | |
| 463 return makeTypeConstant(element); | |
| 464 } | |
| 465 return signalNotCompileTimeConstant(node); | |
| 466 } | |
| 467 | |
| 443 // TODO(floitsch): provide better error-messages. | 468 // TODO(floitsch): provide better error-messages. |
| 444 Constant visitSend(Send send) { | 469 Constant visitSend(Send send) { |
| 445 Element element = elements[send]; | 470 Element element = elements[send]; |
| 446 if (send.isPropertyAccess) { | 471 if (send.isPropertyAccess) { |
| 447 if (isDeferredUse(send)) { | 472 if (isDeferredUse(send)) { |
| 448 return signalNotCompileTimeConstant(send, | 473 return signalNotCompileTimeConstant(send, |
| 449 message: MessageKind.DEFERRED_COMPILE_TIME_CONSTANT); | 474 message: MessageKind.DEFERRED_COMPILE_TIME_CONSTANT); |
| 450 } | 475 } |
| 451 if (Elements.isStaticOrTopLevelFunction(element)) { | 476 if (Elements.isStaticOrTopLevelFunction(element)) { |
| 452 return new FunctionConstant(element); | 477 return new FunctionConstant(element); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 470 if (result != null) return result; | 495 if (result != null) return result; |
| 471 } | 496 } |
| 472 return signalNotCompileTimeConstant(send); | 497 return signalNotCompileTimeConstant(send); |
| 473 } else if (send.isCall) { | 498 } else if (send.isCall) { |
| 474 if (identical(element, compiler.identicalFunction) | 499 if (identical(element, compiler.identicalFunction) |
| 475 && send.argumentCount() == 2) { | 500 && send.argumentCount() == 2) { |
| 476 Constant left = evaluate(send.argumentsNode.nodes.head); | 501 Constant left = evaluate(send.argumentsNode.nodes.head); |
| 477 Constant right = evaluate(send.argumentsNode.nodes.tail.head); | 502 Constant right = evaluate(send.argumentsNode.nodes.tail.head); |
| 478 Constant result = constantSystem.identity.fold(left, right); | 503 Constant result = constantSystem.identity.fold(left, right); |
| 479 if (result != null) return result; | 504 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); | |
| 485 } | 505 } |
| 486 return signalNotCompileTimeConstant(send); | 506 return signalNotCompileTimeConstant(send); |
| 487 } else if (send.isPrefix) { | 507 } else if (send.isPrefix) { |
| 488 assert(send.isOperator); | 508 assert(send.isOperator); |
| 489 Constant receiverConstant = evaluate(send.receiver); | 509 Constant receiverConstant = evaluate(send.receiver); |
| 490 if (receiverConstant == null) return null; | 510 if (receiverConstant == null) return null; |
| 491 Operator op = send.selector; | 511 Operator op = send.selector; |
| 492 Constant folded; | 512 Constant folded; |
| 493 switch (op.source) { | 513 switch (op.source) { |
| 494 case "!": | 514 case "!": |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 803 final FunctionElement constructor; | 823 final FunctionElement constructor; |
| 804 final Map<Element, Constant> definitions; | 824 final Map<Element, Constant> definitions; |
| 805 final Map<Element, Constant> fieldValues; | 825 final Map<Element, Constant> fieldValues; |
| 806 | 826 |
| 807 /** | 827 /** |
| 808 * Documentation wanted -- johnniwinther | 828 * Documentation wanted -- johnniwinther |
| 809 * | 829 * |
| 810 * Invariant: [constructor] must be an implementation element. | 830 * Invariant: [constructor] must be an implementation element. |
| 811 */ | 831 */ |
| 812 ConstructorEvaluator(FunctionElement constructor, | 832 ConstructorEvaluator(FunctionElement constructor, |
| 813 ConstantHandler handler, | 833 ConstantCompiler handler, |
| 814 Compiler compiler) | 834 Compiler compiler) |
| 815 : this.constructor = constructor, | 835 : this.constructor = constructor, |
| 816 this.definitions = new Map<Element, Constant>(), | 836 this.definitions = new Map<Element, Constant>(), |
| 817 this.fieldValues = new Map<Element, Constant>(), | 837 this.fieldValues = new Map<Element, Constant>(), |
| 818 super(handler, | 838 super(handler, |
| 819 compiler.resolver.resolveMethodElement(constructor.declaration), | 839 compiler.resolver.resolveMethodElement(constructor.declaration), |
| 820 compiler, | 840 compiler, |
| 821 isConst: true) { | 841 isConst: true) { |
| 822 assert(invariant(constructor, constructor.isImplementation)); | 842 assert(invariant(constructor, constructor.isImplementation)); |
| 823 } | 843 } |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 836 | 856 |
| 837 void potentiallyCheckType(Node node, | 857 void potentiallyCheckType(Node node, |
| 838 TypedElement element, | 858 TypedElement element, |
| 839 Constant constant) { | 859 Constant constant) { |
| 840 if (compiler.enableTypeAssertions) { | 860 if (compiler.enableTypeAssertions) { |
| 841 DartType elementType = element.type; | 861 DartType elementType = element.type; |
| 842 DartType constantType = constant.computeType(compiler); | 862 DartType constantType = constant.computeType(compiler); |
| 843 // TODO(ngeoffray): Handle type parameters. | 863 // TODO(ngeoffray): Handle type parameters. |
| 844 if (elementType.element.isTypeVariable()) return; | 864 if (elementType.element.isTypeVariable()) return; |
| 845 if (!constantSystem.isSubtype(compiler, constantType, elementType)) { | 865 if (!constantSystem.isSubtype(compiler, constantType, elementType)) { |
| 866 // TODO(johnniwinther): Provide better [node] values that point to the | |
| 867 // origin of the constant and not (just) the assignment. | |
| 846 compiler.reportFatalError( | 868 compiler.reportFatalError( |
| 847 node, MessageKind.NOT_ASSIGNABLE, | 869 node, MessageKind.NOT_ASSIGNABLE, |
| 848 {'fromType': elementType, 'toType': constantType}); | 870 {'fromType': elementType, 'toType': constantType}); |
| 849 } | 871 } |
| 850 } | 872 } |
| 851 } | 873 } |
| 852 | 874 |
| 853 void updateFieldValue(Node node, TypedElement element, Constant constant) { | 875 void updateFieldValue(Node node, TypedElement element, Constant constant) { |
| 854 potentiallyCheckType(node, element, constant); | 876 potentiallyCheckType(node, element, constant); |
| 855 fieldValues[element] = constant; | 877 fieldValues[element] = constant; |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 981 if (fieldValue == null) { | 1003 if (fieldValue == null) { |
| 982 // Use the default value. | 1004 // Use the default value. |
| 983 fieldValue = handler.compileConstant(field); | 1005 fieldValue = handler.compileConstant(field); |
| 984 } | 1006 } |
| 985 jsNewArguments.add(fieldValue); | 1007 jsNewArguments.add(fieldValue); |
| 986 }, | 1008 }, |
| 987 includeSuperAndInjectedMembers: true); | 1009 includeSuperAndInjectedMembers: true); |
| 988 return jsNewArguments; | 1010 return jsNewArguments; |
| 989 } | 1011 } |
| 990 } | 1012 } |
| OLD | NEW |