| 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]. |
| 11 ConstExp getConstantForVariable(VariableElement element); | 11 ConstantExpression getConstantForVariable(VariableElement element); |
| 12 } | 12 } |
| 13 | 13 |
| 14 /// A class that can compile and provide constants for variables, nodes and | 14 /// A class that can compile and provide constants for variables, nodes and |
| 15 /// metadata. | 15 /// metadata. |
| 16 abstract class ConstantCompiler extends ConstantEnvironment { | 16 abstract class ConstantCompiler extends ConstantEnvironment { |
| 17 /// Compiles the compile-time constant for the initializer of [element], or | 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. | 18 /// reports an error if the initializer is not a compile-time constant. |
| 19 /// | 19 /// |
| 20 /// Depending on implementation, the constant compiler might also compute | 20 /// Depending on implementation, the constant compiler might also compute |
| 21 /// the compile-time constant for the backend interpretation of constants. | 21 /// the compile-time constant for the backend interpretation of constants. |
| 22 /// | 22 /// |
| 23 /// The returned constant is always of the frontend interpretation. | 23 /// The returned constant is always of the frontend interpretation. |
| 24 ConstExp compileConstant(VariableElement element); | 24 ConstantExpression compileConstant(VariableElement element); |
| 25 | 25 |
| 26 /// Computes the compile-time constant for the variable initializer, | 26 /// Computes the compile-time constant for the variable initializer, |
| 27 /// if possible. | 27 /// if possible. |
| 28 void compileVariable(VariableElement element); | 28 void compileVariable(VariableElement element); |
| 29 | 29 |
| 30 /// Compiles the compile-time constant for [node], or reports an error if | 30 /// Compiles the compile-time constant for [node], or reports an error if |
| 31 /// [node] is not a compile-time constant. | 31 /// [node] is not a compile-time constant. |
| 32 /// | 32 /// |
| 33 /// Depending on implementation, the constant compiler might also compute | 33 /// Depending on implementation, the constant compiler might also compute |
| 34 /// the compile-time constant for the backend interpretation of constants. | 34 /// the compile-time constant for the backend interpretation of constants. |
| 35 /// | 35 /// |
| 36 /// The returned constant is always of the frontend interpretation. | 36 /// The returned constant is always of the frontend interpretation. |
| 37 ConstExp compileNode(Node node, TreeElements elements); | 37 ConstantExpression compileNode(Node node, TreeElements elements); |
| 38 | 38 |
| 39 /// Compiles the compile-time constant for the value [metadata], or reports an | 39 /// Compiles the compile-time constant for the value [metadata], or reports an |
| 40 /// error if the value is not a compile-time constant. | 40 /// error if the value is not a compile-time constant. |
| 41 /// | 41 /// |
| 42 /// Depending on implementation, the constant compiler might also compute | 42 /// Depending on implementation, the constant compiler might also compute |
| 43 /// the compile-time constant for the backend interpretation of constants. | 43 /// the compile-time constant for the backend interpretation of constants. |
| 44 /// | 44 /// |
| 45 /// The returned constant is always of the frontend interpretation. | 45 /// The returned constant is always of the frontend interpretation. |
| 46 ConstExp compileMetadata(MetadataAnnotation metadata, | 46 ConstantExpression compileMetadata(MetadataAnnotation metadata, |
| 47 Node node, TreeElements elements); | 47 Node node, |
| 48 TreeElements elements); |
| 48 } | 49 } |
| 49 | 50 |
| 50 /// A [BackendConstantEnvironment] provides access to constants needed for | 51 /// A [BackendConstantEnvironment] provides access to constants needed for |
| 51 /// backend implementation. | 52 /// backend implementation. |
| 52 abstract class BackendConstantEnvironment extends ConstantEnvironment { | 53 abstract class BackendConstantEnvironment extends ConstantEnvironment { |
| 53 /// Returns the compile-time constant associated with [node]. | 54 /// Returns the compile-time constant associated with [node]. |
| 54 /// | 55 /// |
| 55 /// Depending on implementation, the constant might be stored in [elements]. | 56 /// Depending on implementation, the constant might be stored in [elements]. |
| 56 ConstExp getConstantForNode(Node node, TreeElements elements); | 57 ConstantExpression getConstantForNode(Node node, TreeElements elements); |
| 57 | 58 |
| 58 /// Returns the compile-time constant value of [metadata]. | 59 /// Returns the compile-time constant value of [metadata]. |
| 59 ConstExp getConstantForMetadata(MetadataAnnotation metadata); | 60 ConstantExpression getConstantForMetadata(MetadataAnnotation metadata); |
| 60 } | 61 } |
| 61 | 62 |
| 62 /// Interface for the task that compiles the constant environments for the | 63 /// Interface for the task that compiles the constant environments for the |
| 63 /// frontend and backend interpretation of compile-time constants. | 64 /// frontend and backend interpretation of compile-time constants. |
| 64 abstract class ConstantCompilerTask extends CompilerTask | 65 abstract class ConstantCompilerTask extends CompilerTask |
| 65 implements ConstantCompiler { | 66 implements ConstantCompiler { |
| 66 ConstantCompilerTask(Compiler compiler) : super(compiler); | 67 ConstantCompilerTask(Compiler compiler) : super(compiler); |
| 67 } | 68 } |
| 68 | 69 |
| 69 /** | 70 /** |
| 70 * The [ConstantCompilerBase] is provides base implementation for compilation of | 71 * The [ConstantCompilerBase] is provides base implementation for compilation of |
| 71 * compile-time constants for both the Dart and JavaScript interpretation of | 72 * compile-time constants for both the Dart and JavaScript interpretation of |
| 72 * constants. It keeps track of compile-time constants for initializations of | 73 * constants. It keeps track of compile-time constants for initializations of |
| 73 * global and static fields, and default values of optional parameters. | 74 * global and static fields, and default values of optional parameters. |
| 74 */ | 75 */ |
| 75 abstract class ConstantCompilerBase implements ConstantCompiler { | 76 abstract class ConstantCompilerBase implements ConstantCompiler { |
| 76 final Compiler compiler; | 77 final Compiler compiler; |
| 77 final ConstantSystem constantSystem; | 78 final ConstantSystem constantSystem; |
| 78 | 79 |
| 79 /** | 80 /** |
| 80 * Contains the initial value of fields. Must contain all static and global | 81 * Contains the initial value of fields. Must contain all static and global |
| 81 * initializations of const fields. May contain eagerly compiled values for | 82 * initializations of const fields. May contain eagerly compiled values for |
| 82 * statics and instance fields. | 83 * statics and instance fields. |
| 83 * | 84 * |
| 84 * Invariant: The keys in this map are declarations. | 85 * Invariant: The keys in this map are declarations. |
| 85 */ | 86 */ |
| 86 final Map<VariableElement, ConstExp> initialVariableValues = | 87 final Map<VariableElement, ConstantExpression> initialVariableValues = |
| 87 new Map<VariableElement, ConstExp>(); | 88 new Map<VariableElement, ConstantExpression>(); |
| 88 | 89 |
| 89 /** The set of variable elements that are in the process of being computed. */ | 90 /** The set of variable elements that are in the process of being computed. */ |
| 90 final Set<VariableElement> pendingVariables = new Set<VariableElement>(); | 91 final Set<VariableElement> pendingVariables = new Set<VariableElement>(); |
| 91 | 92 |
| 92 ConstantCompilerBase(this.compiler, this.constantSystem); | 93 ConstantCompilerBase(this.compiler, this.constantSystem); |
| 93 | 94 |
| 94 ConstExp getConstantForVariable(VariableElement element) { | 95 ConstantExpression getConstantForVariable(VariableElement element) { |
| 95 return initialVariableValues[element.declaration]; | 96 return initialVariableValues[element.declaration]; |
| 96 } | 97 } |
| 97 | 98 |
| 98 ConstExp compileConstant(VariableElement element) { | 99 ConstantExpression compileConstant(VariableElement element) { |
| 99 return compileVariable(element, isConst: true); | 100 return compileVariable(element, isConst: true); |
| 100 } | 101 } |
| 101 | 102 |
| 102 ConstExp compileVariable(VariableElement element, {bool isConst: false}) { | 103 ConstantExpression compileVariable(VariableElement element, |
| 104 {bool isConst: false}) { |
| 103 | 105 |
| 104 if (initialVariableValues.containsKey(element.declaration)) { | 106 if (initialVariableValues.containsKey(element.declaration)) { |
| 105 ConstExp result = initialVariableValues[element.declaration]; | 107 ConstantExpression result = initialVariableValues[element.declaration]; |
| 106 return result; | 108 return result; |
| 107 } | 109 } |
| 108 AstElement currentElement = element.analyzableElement; | 110 AstElement currentElement = element.analyzableElement; |
| 109 return compiler.withCurrentElement(currentElement, () { | 111 return compiler.withCurrentElement(currentElement, () { |
| 110 compiler.analyzeElement(currentElement.declaration); | 112 compiler.analyzeElement(currentElement.declaration); |
| 111 ConstExp constant = compileVariableWithDefinitions( | 113 ConstantExpression constant = compileVariableWithDefinitions( |
| 112 element, currentElement.resolvedAst.elements, isConst: isConst); | 114 element, currentElement.resolvedAst.elements, isConst: isConst); |
| 113 return constant; | 115 return constant; |
| 114 }); | 116 }); |
| 115 } | 117 } |
| 116 | 118 |
| 117 /** | 119 /** |
| 118 * Returns the a compile-time constant if the variable could be compiled | 120 * Returns the a compile-time constant if the variable could be compiled |
| 119 * eagerly. If the variable needs to be initialized lazily returns `null`. | 121 * eagerly. If the variable needs to be initialized lazily returns `null`. |
| 120 * If the variable is `const` but cannot be compiled eagerly reports an | 122 * If the variable is `const` but cannot be compiled eagerly reports an |
| 121 * error. | 123 * error. |
| 122 */ | 124 */ |
| 123 ConstExp compileVariableWithDefinitions(VariableElement element, | 125 ConstantExpression compileVariableWithDefinitions(VariableElement element, |
| 124 TreeElements definitions, | 126 TreeElements definitions, |
| 125 {bool isConst: false}) { | 127 {bool isConst: false}) { |
| 126 Node node = element.node; | 128 Node node = element.node; |
| 127 if (pendingVariables.contains(element)) { | 129 if (pendingVariables.contains(element)) { |
| 128 if (isConst) { | 130 if (isConst) { |
| 129 compiler.reportFatalError( | 131 compiler.reportFatalError( |
| 130 node, MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS); | 132 node, MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS); |
| 131 } | 133 } |
| 132 return null; | 134 return null; |
| 133 } | 135 } |
| 134 pendingVariables.add(element); | 136 pendingVariables.add(element); |
| 135 | 137 |
| 136 Expression initializer = element.initializer; | 138 Expression initializer = element.initializer; |
| 137 ConstExp value; | 139 ConstantExpression value; |
| 138 if (initializer == null) { | 140 if (initializer == null) { |
| 139 // No initial value. | 141 // No initial value. |
| 140 value = new PrimitiveConstExp(new NullConstant()); | 142 value = new PrimitiveConstantExpression(new NullConstantValue()); |
| 141 } else { | 143 } else { |
| 142 value = compileNodeWithDefinitions( | 144 value = compileNodeWithDefinitions( |
| 143 initializer, definitions, isConst: isConst); | 145 initializer, definitions, isConst: isConst); |
| 144 if (compiler.enableTypeAssertions && | 146 if (compiler.enableTypeAssertions && |
| 145 value != null && | 147 value != null && |
| 146 element.isField) { | 148 element.isField) { |
| 147 DartType elementType = element.type; | 149 DartType elementType = element.type; |
| 148 if (elementType.isMalformed && !value.value.isNull) { | 150 if (elementType.isMalformed && !value.value.isNull) { |
| 149 if (isConst) { | 151 if (isConst) { |
| 150 ErroneousElement element = elementType.element; | 152 ErroneousElement element = elementType.element; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 174 if (value != null) { | 176 if (value != null) { |
| 175 initialVariableValues[element.declaration] = value; | 177 initialVariableValues[element.declaration] = value; |
| 176 } else { | 178 } else { |
| 177 assert(invariant(element, !isConst, | 179 assert(invariant(element, !isConst, |
| 178 message: "Variable $element does not compile to a constant.")); | 180 message: "Variable $element does not compile to a constant.")); |
| 179 } | 181 } |
| 180 pendingVariables.remove(element); | 182 pendingVariables.remove(element); |
| 181 return value; | 183 return value; |
| 182 } | 184 } |
| 183 | 185 |
| 184 ConstExp compileNodeWithDefinitions(Node node, | 186 ConstantExpression compileNodeWithDefinitions(Node node, |
| 185 TreeElements definitions, | 187 TreeElements definitions, |
| 186 {bool isConst: true}) { | 188 {bool isConst: true}) { |
| 187 assert(node != null); | 189 assert(node != null); |
| 188 CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator( | 190 CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator( |
| 189 this, definitions, compiler, isConst: isConst); | 191 this, definitions, compiler, isConst: isConst); |
| 190 AstConstant constant = evaluator.evaluate(node); | 192 AstConstant constant = evaluator.evaluate(node); |
| 191 return constant != null ? constant.expression : null; | 193 return constant != null ? constant.expression : null; |
| 192 } | 194 } |
| 193 | 195 |
| 194 ConstExp compileNode(Node node, TreeElements elements) { | 196 ConstantExpression compileNode(Node node, TreeElements elements) { |
| 195 return compileNodeWithDefinitions(node, elements); | 197 return compileNodeWithDefinitions(node, elements); |
| 196 } | 198 } |
| 197 | 199 |
| 198 ConstExp compileMetadata(MetadataAnnotation metadata, | 200 ConstantExpression compileMetadata(MetadataAnnotation metadata, |
| 199 Node node, | 201 Node node, |
| 200 TreeElements elements) { | 202 TreeElements elements) { |
| 201 return compileNodeWithDefinitions(node, elements); | 203 return compileNodeWithDefinitions(node, elements); |
| 202 } | 204 } |
| 203 } | 205 } |
| 204 | 206 |
| 205 /// [ConstantCompiler] that uses the Dart semantics for the compile-time | 207 /// [ConstantCompiler] that uses the Dart semantics for the compile-time |
| 206 /// constant evaluation. | 208 /// constant evaluation. |
| 207 class DartConstantCompiler extends ConstantCompilerBase { | 209 class DartConstantCompiler extends ConstantCompilerBase { |
| 208 DartConstantCompiler(Compiler compiler) | 210 DartConstantCompiler(Compiler compiler) |
| 209 : super(compiler, const DartConstantSystem()); | 211 : super(compiler, const DartConstantSystem()); |
| 210 | 212 |
| 211 ConstExp getConstantForNode(Node node, TreeElements definitions) { | 213 ConstantExpression getConstantForNode(Node node, TreeElements definitions) { |
| 212 return definitions.getConstant(node); | 214 return definitions.getConstant(node); |
| 213 } | 215 } |
| 214 | 216 |
| 215 ConstExp getConstantForMetadata(MetadataAnnotation metadata) { | 217 ConstantExpression getConstantForMetadata(MetadataAnnotation metadata) { |
| 216 return metadata.constant; | 218 return metadata.constant; |
| 217 } | 219 } |
| 218 | 220 |
| 219 ConstExp compileNodeWithDefinitions(Node node, | 221 ConstantExpression compileNodeWithDefinitions(Node node, |
| 220 TreeElements definitions, | 222 TreeElements definitions, |
| 221 {bool isConst: true}) { | 223 {bool isConst: true}) { |
| 222 ConstExp constant = definitions.getConstant(node); | 224 ConstantExpression constant = definitions.getConstant(node); |
| 223 if (constant != null) { | 225 if (constant != null) { |
| 224 return constant; | 226 return constant; |
| 225 } | 227 } |
| 226 constant = | 228 constant = |
| 227 super.compileNodeWithDefinitions(node, definitions, isConst: isConst); | 229 super.compileNodeWithDefinitions(node, definitions, isConst: isConst); |
| 228 if (constant != null) { | 230 if (constant != null) { |
| 229 definitions.setConstant(node, constant); | 231 definitions.setConstant(node, constant); |
| 230 } | 232 } |
| 231 return constant; | 233 return constant; |
| 232 } | 234 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 262 assert(result != null); | 264 assert(result != null); |
| 263 return result; | 265 return result; |
| 264 } | 266 } |
| 265 | 267 |
| 266 AstConstant visitNode(Node node) { | 268 AstConstant visitNode(Node node) { |
| 267 return signalNotCompileTimeConstant(node); | 269 return signalNotCompileTimeConstant(node); |
| 268 } | 270 } |
| 269 | 271 |
| 270 AstConstant visitLiteralBool(LiteralBool node) { | 272 AstConstant visitLiteralBool(LiteralBool node) { |
| 271 return new AstConstant( | 273 return new AstConstant( |
| 272 context, node, new PrimitiveConstExp( | 274 context, node, new PrimitiveConstantExpression( |
| 273 constantSystem.createBool(node.value))); | 275 constantSystem.createBool(node.value))); |
| 274 } | 276 } |
| 275 | 277 |
| 276 AstConstant visitLiteralDouble(LiteralDouble node) { | 278 AstConstant visitLiteralDouble(LiteralDouble node) { |
| 277 return new AstConstant( | 279 return new AstConstant( |
| 278 context, node, new PrimitiveConstExp( | 280 context, node, new PrimitiveConstantExpression( |
| 279 constantSystem.createDouble(node.value))); | 281 constantSystem.createDouble(node.value))); |
| 280 } | 282 } |
| 281 | 283 |
| 282 AstConstant visitLiteralInt(LiteralInt node) { | 284 AstConstant visitLiteralInt(LiteralInt node) { |
| 283 return new AstConstant( | 285 return new AstConstant( |
| 284 context, node, new PrimitiveConstExp( | 286 context, node, new PrimitiveConstantExpression( |
| 285 constantSystem.createInt(node.value))); | 287 constantSystem.createInt(node.value))); |
| 286 } | 288 } |
| 287 | 289 |
| 288 AstConstant visitLiteralList(LiteralList node) { | 290 AstConstant visitLiteralList(LiteralList node) { |
| 289 if (!node.isConst) { | 291 if (!node.isConst) { |
| 290 return signalNotCompileTimeConstant(node); | 292 return signalNotCompileTimeConstant(node); |
| 291 } | 293 } |
| 292 List<ConstExp> argumentExpressions = <ConstExp>[]; | 294 List<ConstantExpression> argumentExpressions = <ConstantExpression>[]; |
| 293 List<Constant> argumentValues = <Constant>[]; | 295 List<ConstantValue> argumentValues = <ConstantValue>[]; |
| 294 for (Link<Node> link = node.elements.nodes; | 296 for (Link<Node> link = node.elements.nodes; |
| 295 !link.isEmpty; | 297 !link.isEmpty; |
| 296 link = link.tail) { | 298 link = link.tail) { |
| 297 AstConstant argument = evaluateConstant(link.head); | 299 AstConstant argument = evaluateConstant(link.head); |
| 298 if (argument == null) { | 300 if (argument == null) { |
| 299 return null; | 301 return null; |
| 300 } | 302 } |
| 301 argumentExpressions.add(argument.expression); | 303 argumentExpressions.add(argument.expression); |
| 302 argumentValues.add(argument.value); | 304 argumentValues.add(argument.value); |
| 303 } | 305 } |
| 304 DartType type = elements.getType(node); | 306 DartType type = elements.getType(node); |
| 305 return new AstConstant( | 307 return new AstConstant( |
| 306 context, node, new ListConstExp( | 308 context, node, new ListConstantExpression( |
| 307 new ListConstant(type, argumentValues), | 309 new ListConstantValue(type, argumentValues), |
| 308 type, | 310 type, |
| 309 argumentExpressions)); | 311 argumentExpressions)); |
| 310 } | 312 } |
| 311 | 313 |
| 312 AstConstant visitLiteralMap(LiteralMap node) { | 314 AstConstant visitLiteralMap(LiteralMap node) { |
| 313 if (!node.isConst) { | 315 if (!node.isConst) { |
| 314 return signalNotCompileTimeConstant(node); | 316 return signalNotCompileTimeConstant(node); |
| 315 } | 317 } |
| 316 List<ConstExp> keyExpressions = <ConstExp>[]; | 318 List<ConstantExpression> keyExpressions = <ConstantExpression>[]; |
| 317 List<Constant> keyValues = <Constant>[]; | 319 List<ConstantValue> keyValues = <ConstantValue>[]; |
| 318 Map<Constant, ConstExp> map = new Map<Constant, ConstExp>(); | 320 Map<ConstantValue, ConstantExpression> map = |
| 321 new Map<ConstantValue, ConstantExpression>(); |
| 319 for (Link<Node> link = node.entries.nodes; | 322 for (Link<Node> link = node.entries.nodes; |
| 320 !link.isEmpty; | 323 !link.isEmpty; |
| 321 link = link.tail) { | 324 link = link.tail) { |
| 322 LiteralMapEntry entry = link.head; | 325 LiteralMapEntry entry = link.head; |
| 323 AstConstant key = evaluateConstant(entry.key); | 326 AstConstant key = evaluateConstant(entry.key); |
| 324 if (key == null) { | 327 if (key == null) { |
| 325 return null; | 328 return null; |
| 326 } | 329 } |
| 327 if (!map.containsKey(key.value)) { | 330 if (!map.containsKey(key.value)) { |
| 328 keyExpressions.add(key.expression); | 331 keyExpressions.add(key.expression); |
| 329 keyValues.add(key.value); | 332 keyValues.add(key.value); |
| 330 } else { | 333 } else { |
| 331 compiler.reportWarning(entry.key, MessageKind.EQUAL_MAP_ENTRY_KEY); | 334 compiler.reportWarning(entry.key, MessageKind.EQUAL_MAP_ENTRY_KEY); |
| 332 } | 335 } |
| 333 AstConstant value = evaluateConstant(entry.value); | 336 AstConstant value = evaluateConstant(entry.value); |
| 334 if (value == null) { | 337 if (value == null) { |
| 335 return null; | 338 return null; |
| 336 } | 339 } |
| 337 map[key.value] = value.expression; | 340 map[key.value] = value.expression; |
| 338 } | 341 } |
| 339 List<ConstExp> valueExpressions = map.values.toList(); | 342 List<ConstantExpression> valueExpressions = map.values.toList(); |
| 340 InterfaceType type = elements.getType(node); | 343 InterfaceType type = elements.getType(node); |
| 341 return new AstConstant( | 344 return new AstConstant( |
| 342 context, node, new MapConstExp( | 345 context, node, new MapConstantExpression( |
| 343 constantSystem.createMap(compiler, type, keyValues, | 346 constantSystem.createMap(compiler, type, keyValues, |
| 344 valueExpressions.map((e) => e.value).toList()), | 347 valueExpressions.map((e) => e.value).toList()), |
| 345 type, | 348 type, |
| 346 keyExpressions, | 349 keyExpressions, |
| 347 valueExpressions)); | 350 valueExpressions)); |
| 348 } | 351 } |
| 349 | 352 |
| 350 AstConstant visitLiteralNull(LiteralNull node) { | 353 AstConstant visitLiteralNull(LiteralNull node) { |
| 351 return new AstConstant( | 354 return new AstConstant( |
| 352 context, node, new PrimitiveConstExp( | 355 context, node, new PrimitiveConstantExpression( |
| 353 constantSystem.createNull())); | 356 constantSystem.createNull())); |
| 354 } | 357 } |
| 355 | 358 |
| 356 AstConstant visitLiteralString(LiteralString node) { | 359 AstConstant visitLiteralString(LiteralString node) { |
| 357 return new AstConstant( | 360 return new AstConstant( |
| 358 context, node, new PrimitiveConstExp( | 361 context, node, new PrimitiveConstantExpression( |
| 359 constantSystem.createString(node.dartString))); | 362 constantSystem.createString(node.dartString))); |
| 360 } | 363 } |
| 361 | 364 |
| 362 AstConstant visitStringJuxtaposition(StringJuxtaposition node) { | 365 AstConstant visitStringJuxtaposition(StringJuxtaposition node) { |
| 363 AstConstant left = evaluate(node.first); | 366 AstConstant left = evaluate(node.first); |
| 364 AstConstant right = evaluate(node.second); | 367 AstConstant right = evaluate(node.second); |
| 365 if (left == null || right == null) return null; | 368 if (left == null || right == null) return null; |
| 366 StringConstant leftValue = left.value; | 369 StringConstantValue leftValue = left.value; |
| 367 StringConstant rightValue = right.value; | 370 StringConstantValue rightValue = right.value; |
| 368 return new AstConstant( | 371 return new AstConstant( |
| 369 context, node, new ConcatenateConstExp( | 372 context, node, new ConcatenateConstantExpression( |
| 370 constantSystem.createString( | 373 constantSystem.createString( |
| 371 new DartString.concat(leftValue.value, rightValue.value)), | 374 new DartString.concat( |
| 375 leftValue.primitiveValue, rightValue.primitiveValue)), |
| 372 [left.expression, right.expression])); | 376 [left.expression, right.expression])); |
| 373 } | 377 } |
| 374 | 378 |
| 375 AstConstant visitStringInterpolation(StringInterpolation node) { | 379 AstConstant visitStringInterpolation(StringInterpolation node) { |
| 376 List<ConstExp> subexpressions = <ConstExp>[]; | 380 List<ConstantExpression> subexpressions = <ConstantExpression>[]; |
| 377 AstConstant initialString = evaluate(node.string); | 381 AstConstant initialString = evaluate(node.string); |
| 378 if (initialString == null) { | 382 if (initialString == null) { |
| 379 return null; | 383 return null; |
| 380 } | 384 } |
| 381 subexpressions.add(initialString.expression); | 385 subexpressions.add(initialString.expression); |
| 382 StringConstant initialStringValue = initialString.value; | 386 StringConstantValue initialStringValue = initialString.value; |
| 383 DartString accumulator = initialStringValue.value; | 387 DartString accumulator = initialStringValue.primitiveValue; |
| 384 for (StringInterpolationPart part in node.parts) { | 388 for (StringInterpolationPart part in node.parts) { |
| 385 AstConstant subexpression = evaluate(part.expression); | 389 AstConstant subexpression = evaluate(part.expression); |
| 386 if (subexpression == null) { | 390 if (subexpression == null) { |
| 387 return null; | 391 return null; |
| 388 } | 392 } |
| 389 subexpressions.add(subexpression.expression); | 393 subexpressions.add(subexpression.expression); |
| 390 Constant expression = subexpression.value; | 394 ConstantValue expression = subexpression.value; |
| 391 DartString expressionString; | 395 DartString expressionString; |
| 392 if (expression.isNum || expression.isBool) { | 396 if (expression.isNum || expression.isBool) { |
| 393 PrimitiveConstant primitive = expression; | 397 PrimitiveConstantValue primitive = expression; |
| 394 expressionString = new DartString.literal(primitive.value.toString()); | 398 expressionString = |
| 399 new DartString.literal(primitive.primitiveValue.toString()); |
| 395 } else if (expression.isString) { | 400 } else if (expression.isString) { |
| 396 PrimitiveConstant primitive = expression; | 401 PrimitiveConstantValue primitive = expression; |
| 397 expressionString = primitive.value; | 402 expressionString = primitive.primitiveValue; |
| 398 } else { | 403 } else { |
| 399 // TODO(johnniwinther): Specialize message to indicated that the problem | 404 // TODO(johnniwinther): Specialize message to indicated that the problem |
| 400 // is not constness but the types of the const expressions. | 405 // is not constness but the types of the const expressions. |
| 401 return signalNotCompileTimeConstant(part.expression); | 406 return signalNotCompileTimeConstant(part.expression); |
| 402 } | 407 } |
| 403 accumulator = new DartString.concat(accumulator, expressionString); | 408 accumulator = new DartString.concat(accumulator, expressionString); |
| 404 AstConstant partString = evaluate(part.string); | 409 AstConstant partString = evaluate(part.string); |
| 405 if (partString == null) return null; | 410 if (partString == null) return null; |
| 406 subexpressions.add(partString.expression); | 411 subexpressions.add(partString.expression); |
| 407 StringConstant partStringValue = partString.value; | 412 StringConstantValue partStringValue = partString.value; |
| 408 accumulator = new DartString.concat(accumulator, partStringValue.value); | 413 accumulator = |
| 414 new DartString.concat(accumulator, partStringValue.primitiveValue); |
| 409 }; | 415 }; |
| 410 return new AstConstant( | 416 return new AstConstant( |
| 411 context, node, new ConcatenateConstExp( | 417 context, node, new ConcatenateConstantExpression( |
| 412 constantSystem.createString(accumulator), | 418 constantSystem.createString(accumulator), |
| 413 subexpressions)); | 419 subexpressions)); |
| 414 } | 420 } |
| 415 | 421 |
| 416 AstConstant visitLiteralSymbol(LiteralSymbol node) { | 422 AstConstant visitLiteralSymbol(LiteralSymbol node) { |
| 417 InterfaceType type = compiler.symbolClass.rawType; | 423 InterfaceType type = compiler.symbolClass.rawType; |
| 418 String text = node.slowNameString; | 424 String text = node.slowNameString; |
| 419 List<AstConstant> arguments = | 425 List<AstConstant> arguments = |
| 420 <AstConstant>[new AstConstant(context, node, | 426 <AstConstant>[new AstConstant(context, node, |
| 421 new PrimitiveConstExp(constantSystem.createString( | 427 new PrimitiveConstantExpression(constantSystem.createString( |
| 422 new DartString.literal(text))))]; | 428 new DartString.literal(text))))]; |
| 423 AstConstant constant = makeConstructedConstant( | 429 AstConstant constant = makeConstructedConstant( |
| 424 compiler, handler, context, node, type, compiler.symbolConstructor, | 430 compiler, handler, context, node, type, compiler.symbolConstructor, |
| 425 new Selector.callConstructor('', null, 1), | 431 new Selector.callConstructor('', null, 1), |
| 426 arguments, arguments); | 432 arguments, arguments); |
| 427 return new AstConstant( | 433 return new AstConstant( |
| 428 context, node, new SymbolConstExp(constant.value, text)); | 434 context, node, new SymbolConstantExpression(constant.value, text)); |
| 429 } | 435 } |
| 430 | 436 |
| 431 AstConstant makeTypeConstant(Node node, DartType elementType) { | 437 AstConstant makeTypeConstant(Node node, DartType elementType) { |
| 432 DartType constantType = | 438 DartType constantType = |
| 433 compiler.backend.typeImplementation.computeType(compiler); | 439 compiler.backend.typeImplementation.computeType(compiler); |
| 434 return new AstConstant( | 440 return new AstConstant( |
| 435 context, node, new TypeConstExp( | 441 context, node, new TypeConstantExpression( |
| 436 new TypeConstant(elementType, constantType), | 442 new TypeConstantValue(elementType, constantType), |
| 437 elementType)); | 443 elementType)); |
| 438 } | 444 } |
| 439 | 445 |
| 440 /// Returns true if the prefix of the send resolves to a deferred import | 446 /// Returns true if the prefix of the send resolves to a deferred import |
| 441 /// prefix. | 447 /// prefix. |
| 442 bool isDeferredUse(Send send) { | 448 bool isDeferredUse(Send send) { |
| 443 if (send == null) return false; | 449 if (send == null) return false; |
| 444 return compiler.deferredLoadTask | 450 return compiler.deferredLoadTask |
| 445 .deferredPrefixElement(send, elements) != null; | 451 .deferredPrefixElement(send, elements) != null; |
| 446 } | 452 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 458 // TODO(floitsch): provide better error-messages. | 464 // TODO(floitsch): provide better error-messages. |
| 459 AstConstant visitSend(Send send) { | 465 AstConstant visitSend(Send send) { |
| 460 Element element = elements[send]; | 466 Element element = elements[send]; |
| 461 if (send.isPropertyAccess) { | 467 if (send.isPropertyAccess) { |
| 462 if (isDeferredUse(send)) { | 468 if (isDeferredUse(send)) { |
| 463 return signalNotCompileTimeConstant(send, | 469 return signalNotCompileTimeConstant(send, |
| 464 message: MessageKind.DEFERRED_COMPILE_TIME_CONSTANT); | 470 message: MessageKind.DEFERRED_COMPILE_TIME_CONSTANT); |
| 465 } | 471 } |
| 466 if (Elements.isStaticOrTopLevelFunction(element)) { | 472 if (Elements.isStaticOrTopLevelFunction(element)) { |
| 467 return new AstConstant( | 473 return new AstConstant( |
| 468 context, send, new FunctionConstExp( | 474 context, send, new FunctionConstantExpression( |
| 469 new FunctionConstant(element), | 475 new FunctionConstantValue(element), |
| 470 element)); | 476 element)); |
| 471 } else if (Elements.isStaticOrTopLevelField(element)) { | 477 } else if (Elements.isStaticOrTopLevelField(element)) { |
| 472 ConstExp result; | 478 ConstantExpression result; |
| 473 if (element.isConst) { | 479 if (element.isConst) { |
| 474 result = handler.compileConstant(element); | 480 result = handler.compileConstant(element); |
| 475 } else if (element.isFinal && !isEvaluatingConstant) { | 481 } else if (element.isFinal && !isEvaluatingConstant) { |
| 476 result = handler.compileVariable(element); | 482 result = handler.compileVariable(element); |
| 477 } | 483 } |
| 478 if (result != null) { | 484 if (result != null) { |
| 479 return new AstConstant( | 485 return new AstConstant( |
| 480 context, send, new VariableConstExp(result.value, element)); | 486 context, send, |
| 487 new VariableConstantExpression(result.value, element)); |
| 481 } | 488 } |
| 482 } else if (Elements.isClass(element) || Elements.isTypedef(element)) { | 489 } else if (Elements.isClass(element) || Elements.isTypedef(element)) { |
| 483 assert(elements.isTypeLiteral(send)); | 490 assert(elements.isTypeLiteral(send)); |
| 484 return makeTypeConstant(send, elements.getTypeLiteralType(send)); | 491 return makeTypeConstant(send, elements.getTypeLiteralType(send)); |
| 485 } else if (send.receiver != null) { | 492 } else if (send.receiver != null) { |
| 486 // Fall through to error handling. | 493 // Fall through to error handling. |
| 487 } else if (!Elements.isUnresolved(element) | 494 } else if (!Elements.isUnresolved(element) |
| 488 && element.isVariable | 495 && element.isVariable |
| 489 && element.isConst) { | 496 && element.isConst) { |
| 490 ConstExp result = handler.compileConstant(element); | 497 ConstantExpression result = handler.compileConstant(element); |
| 491 if (result != null) { | 498 if (result != null) { |
| 492 return new AstConstant( | 499 return new AstConstant( |
| 493 context, send, new VariableConstExp(result.value, element)); | 500 context, send, |
| 501 new VariableConstantExpression(result.value, element)); |
| 494 } | 502 } |
| 495 } | 503 } |
| 496 return signalNotCompileTimeConstant(send); | 504 return signalNotCompileTimeConstant(send); |
| 497 } else if (send.isCall) { | 505 } else if (send.isCall) { |
| 498 if (identical(element, compiler.identicalFunction) | 506 if (identical(element, compiler.identicalFunction) |
| 499 && send.argumentCount() == 2) { | 507 && send.argumentCount() == 2) { |
| 500 AstConstant left = evaluate(send.argumentsNode.nodes.head); | 508 AstConstant left = evaluate(send.argumentsNode.nodes.head); |
| 501 AstConstant right = evaluate(send.argumentsNode.nodes.tail.head); | 509 AstConstant right = evaluate(send.argumentsNode.nodes.tail.head); |
| 502 if (left == null || right == null) { | 510 if (left == null || right == null) { |
| 503 return null; | 511 return null; |
| 504 } | 512 } |
| 505 Constant result = constantSystem.identity.fold(left.value, right.value); | 513 ConstantValue result = |
| 514 constantSystem.identity.fold(left.value, right.value); |
| 506 if (result != null) { | 515 if (result != null) { |
| 507 return new AstConstant( | 516 return new AstConstant( |
| 508 context, send, new BinaryConstExp(result, | 517 context, send, new BinaryConstantExpression(result, |
| 509 left.expression, 'identical', right.expression)); | 518 left.expression, 'identical', right.expression)); |
| 510 } | 519 } |
| 511 } | 520 } |
| 512 return signalNotCompileTimeConstant(send); | 521 return signalNotCompileTimeConstant(send); |
| 513 } else if (send.isPrefix) { | 522 } else if (send.isPrefix) { |
| 514 assert(send.isOperator); | 523 assert(send.isOperator); |
| 515 AstConstant receiverConstant = evaluate(send.receiver); | 524 AstConstant receiverConstant = evaluate(send.receiver); |
| 516 if (receiverConstant == null) { | 525 if (receiverConstant == null) { |
| 517 return null; | 526 return null; |
| 518 } | 527 } |
| 519 Operator op = send.selector; | 528 Operator op = send.selector; |
| 520 UnaryOperation operation = constantSystem.lookupUnary(op.source); | 529 UnaryOperation operation = constantSystem.lookupUnary(op.source); |
| 521 if (operation == null) { | 530 if (operation == null) { |
| 522 compiler.internalError(op, "Unexpected operator."); | 531 compiler.internalError(op, "Unexpected operator."); |
| 523 } | 532 } |
| 524 Constant folded = operation.fold(receiverConstant.value); | 533 ConstantValue folded = operation.fold(receiverConstant.value); |
| 525 if (folded == null) { | 534 if (folded == null) { |
| 526 return signalNotCompileTimeConstant(send); | 535 return signalNotCompileTimeConstant(send); |
| 527 } | 536 } |
| 528 return new AstConstant( | 537 return new AstConstant( |
| 529 context, send, new UnaryConstExp(folded, | 538 context, send, new UnaryConstantExpression(folded, |
| 530 op.source, receiverConstant.expression)); | 539 op.source, receiverConstant.expression)); |
| 531 } else if (send.isOperator && !send.isPostfix) { | 540 } else if (send.isOperator && !send.isPostfix) { |
| 532 assert(send.argumentCount() == 1); | 541 assert(send.argumentCount() == 1); |
| 533 AstConstant left = evaluate(send.receiver); | 542 AstConstant left = evaluate(send.receiver); |
| 534 AstConstant right = evaluate(send.argumentsNode.nodes.head); | 543 AstConstant right = evaluate(send.argumentsNode.nodes.head); |
| 535 if (left == null || right == null) { | 544 if (left == null || right == null) { |
| 536 return null; | 545 return null; |
| 537 } | 546 } |
| 538 Constant leftValue = left.value; | 547 ConstantValue leftValue = left.value; |
| 539 Constant rightValue = right.value; | 548 ConstantValue rightValue = right.value; |
| 540 Operator op = send.selector.asOperator(); | 549 Operator op = send.selector.asOperator(); |
| 541 Constant folded = null; | 550 ConstantValue folded = null; |
| 542 switch (op.source) { | 551 switch (op.source) { |
| 543 case "==": | 552 case "==": |
| 544 if (leftValue.isPrimitive && rightValue.isPrimitive) { | 553 if (leftValue.isPrimitive && rightValue.isPrimitive) { |
| 545 folded = constantSystem.equal.fold(leftValue, rightValue); | 554 folded = constantSystem.equal.fold(leftValue, rightValue); |
| 546 } | 555 } |
| 547 break; | 556 break; |
| 548 case "!=": | 557 case "!=": |
| 549 if (leftValue.isPrimitive && rightValue.isPrimitive) { | 558 if (leftValue.isPrimitive && rightValue.isPrimitive) { |
| 550 BoolConstant areEquals = | 559 BoolConstantValue areEquals = |
| 551 constantSystem.equal.fold(leftValue, rightValue); | 560 constantSystem.equal.fold(leftValue, rightValue); |
| 552 if (areEquals == null) { | 561 if (areEquals == null) { |
| 553 folded = null; | 562 folded = null; |
| 554 } else { | 563 } else { |
| 555 folded = areEquals.negate(); | 564 folded = areEquals.negate(); |
| 556 } | 565 } |
| 557 } | 566 } |
| 558 break; | 567 break; |
| 559 default: | 568 default: |
| 560 BinaryOperation operation = constantSystem.lookupBinary(op.source); | 569 BinaryOperation operation = constantSystem.lookupBinary(op.source); |
| 561 if (operation != null) { | 570 if (operation != null) { |
| 562 folded = operation.fold(leftValue, rightValue); | 571 folded = operation.fold(leftValue, rightValue); |
| 563 } | 572 } |
| 564 } | 573 } |
| 565 if (folded == null) { | 574 if (folded == null) { |
| 566 return signalNotCompileTimeConstant(send); | 575 return signalNotCompileTimeConstant(send); |
| 567 } | 576 } |
| 568 return new AstConstant( | 577 return new AstConstant( |
| 569 context, send, new BinaryConstExp(folded, | 578 context, send, new BinaryConstantExpression(folded, |
| 570 left.expression, op.source, right.expression)); | 579 left.expression, op.source, right.expression)); |
| 571 } | 580 } |
| 572 return signalNotCompileTimeConstant(send); | 581 return signalNotCompileTimeConstant(send); |
| 573 } | 582 } |
| 574 | 583 |
| 575 AstConstant visitConditional(Conditional node) { | 584 AstConstant visitConditional(Conditional node) { |
| 576 AstConstant condition = evaluate(node.condition); | 585 AstConstant condition = evaluate(node.condition); |
| 577 if (condition == null) { | 586 if (condition == null) { |
| 578 return null; | 587 return null; |
| 579 } else if (!condition.value.isBool) { | 588 } else if (!condition.value.isBool) { |
| 580 DartType conditionType = condition.value.computeType(compiler); | 589 DartType conditionType = condition.value.computeType(compiler); |
| 581 if (isEvaluatingConstant) { | 590 if (isEvaluatingConstant) { |
| 582 compiler.reportFatalError( | 591 compiler.reportFatalError( |
| 583 node.condition, MessageKind.NOT_ASSIGNABLE, | 592 node.condition, MessageKind.NOT_ASSIGNABLE, |
| 584 {'fromType': conditionType, 'toType': compiler.boolClass.rawType}); | 593 {'fromType': conditionType, 'toType': compiler.boolClass.rawType}); |
| 585 } | 594 } |
| 586 return null; | 595 return null; |
| 587 } | 596 } |
| 588 AstConstant thenExpression = evaluate(node.thenExpression); | 597 AstConstant thenExpression = evaluate(node.thenExpression); |
| 589 AstConstant elseExpression = evaluate(node.elseExpression); | 598 AstConstant elseExpression = evaluate(node.elseExpression); |
| 590 if (thenExpression == null || elseExpression == null) { | 599 if (thenExpression == null || elseExpression == null) { |
| 591 return null; | 600 return null; |
| 592 } | 601 } |
| 593 BoolConstant boolCondition = condition.value; | 602 BoolConstantValue boolCondition = condition.value; |
| 594 return new AstConstant( | 603 return new AstConstant( |
| 595 context, node, new ConditionalConstExp( | 604 context, node, new ConditionalConstantExpression( |
| 596 boolCondition.value ? thenExpression.value : elseExpression.value, | 605 boolCondition.primitiveValue |
| 606 ? thenExpression.value |
| 607 : elseExpression.value, |
| 597 condition.expression, | 608 condition.expression, |
| 598 thenExpression.expression, | 609 thenExpression.expression, |
| 599 elseExpression.expression)); | 610 elseExpression.expression)); |
| 600 } | 611 } |
| 601 | 612 |
| 602 AstConstant visitSendSet(SendSet node) { | 613 AstConstant visitSendSet(SendSet node) { |
| 603 return signalNotCompileTimeConstant(node); | 614 return signalNotCompileTimeConstant(node); |
| 604 } | 615 } |
| 605 | 616 |
| 606 /** | 617 /** |
| 607 * Returns the normalized list of constant arguments that are passed to the | 618 * Returns the normalized list of constant arguments that are passed to the |
| 608 * constructor including both the concrete arguments and default values for | 619 * constructor including both the concrete arguments and default values for |
| 609 * omitted optional arguments. | 620 * omitted optional arguments. |
| 610 * | 621 * |
| 611 * Invariant: [target] must be an implementation element. | 622 * Invariant: [target] must be an implementation element. |
| 612 */ | 623 */ |
| 613 List<AstConstant> evaluateArgumentsToConstructor( | 624 List<AstConstant> evaluateArgumentsToConstructor( |
| 614 Node node, | 625 Node node, |
| 615 Selector selector, | 626 Selector selector, |
| 616 Link<Node> arguments, | 627 Link<Node> arguments, |
| 617 FunctionElement target, | 628 FunctionElement target, |
| 618 {AstConstant compileArgument(Node node)}) { | 629 {AstConstant compileArgument(Node node)}) { |
| 619 assert(invariant(node, target.isImplementation)); | 630 assert(invariant(node, target.isImplementation)); |
| 620 List<AstConstant> compiledArguments = <AstConstant>[]; | 631 List<AstConstant> compiledArguments = <AstConstant>[]; |
| 621 | 632 |
| 622 AstConstant compileDefaultValue(VariableElement element) { | 633 AstConstant compileDefaultValue(VariableElement element) { |
| 623 ConstExp constant = handler.compileConstant(element); | 634 ConstantExpression constant = handler.compileConstant(element); |
| 624 return new AstConstant.fromDefaultValue(element, constant); | 635 return new AstConstant.fromDefaultValue(element, constant); |
| 625 } | 636 } |
| 626 target.computeSignature(compiler); | 637 target.computeSignature(compiler); |
| 627 bool succeeded = selector.addArgumentsToList(arguments, | 638 bool succeeded = selector.addArgumentsToList(arguments, |
| 628 compiledArguments, | 639 compiledArguments, |
| 629 target, | 640 target, |
| 630 compileArgument, | 641 compileArgument, |
| 631 compileDefaultValue, | 642 compileDefaultValue, |
| 632 compiler.world); | 643 compiler.world); |
| 633 if (!succeeded) { | 644 if (!succeeded) { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 682 evaluateArgumentsToConstructor( | 693 evaluateArgumentsToConstructor( |
| 683 node, selector, send.arguments, constructor.implementation, | 694 node, selector, send.arguments, constructor.implementation, |
| 684 compileArgument: (node) => concreteArgumentMap[node]); | 695 compileArgument: (node) => concreteArgumentMap[node]); |
| 685 List<AstConstant> concreteArguments = | 696 List<AstConstant> concreteArguments = |
| 686 concreteArgumentMap.values.toList(); | 697 concreteArgumentMap.values.toList(); |
| 687 | 698 |
| 688 if (constructor == compiler.intEnvironment || | 699 if (constructor == compiler.intEnvironment || |
| 689 constructor == compiler.boolEnvironment || | 700 constructor == compiler.boolEnvironment || |
| 690 constructor == compiler.stringEnvironment) { | 701 constructor == compiler.stringEnvironment) { |
| 691 | 702 |
| 692 AstConstant createEvaluatedConstant(Constant value) { | 703 AstConstant createEvaluatedConstant(ConstantValue value) { |
| 693 return new AstConstant( | 704 return new AstConstant( |
| 694 context, node, new ConstructorConstExp( | 705 context, node, new ConstructedConstantExpresssion( |
| 695 value, | 706 value, |
| 696 type, | 707 type, |
| 697 constructor, | 708 constructor, |
| 698 elements.getSelector(send), | 709 elements.getSelector(send), |
| 699 concreteArguments.map((e) => e.expression).toList())); | 710 concreteArguments.map((e) => e.expression).toList())); |
| 700 } | 711 } |
| 701 | 712 |
| 702 var firstArgument = normalizedArguments[0].value; | 713 var firstArgument = normalizedArguments[0].value; |
| 703 Constant defaultValue = normalizedArguments[1].value; | 714 ConstantValue defaultValue = normalizedArguments[1].value; |
| 704 | 715 |
| 705 if (firstArgument is NullConstant) { | 716 if (firstArgument.isNull) { |
| 706 compiler.reportFatalError( | 717 compiler.reportFatalError( |
| 707 send.arguments.head, MessageKind.NULL_NOT_ALLOWED); | 718 send.arguments.head, MessageKind.NULL_NOT_ALLOWED); |
| 708 return null; | 719 return null; |
| 709 } | 720 } |
| 710 | 721 |
| 711 if (firstArgument is! StringConstant) { | 722 if (!firstArgument.isString) { |
| 712 DartType type = defaultValue.computeType(compiler); | 723 DartType type = defaultValue.computeType(compiler); |
| 713 compiler.reportFatalError( | 724 compiler.reportFatalError( |
| 714 send.arguments.head, MessageKind.NOT_ASSIGNABLE, | 725 send.arguments.head, MessageKind.NOT_ASSIGNABLE, |
| 715 {'fromType': type, 'toType': compiler.stringClass.rawType}); | 726 {'fromType': type, 'toType': compiler.stringClass.rawType}); |
| 716 return null; | 727 return null; |
| 717 } | 728 } |
| 718 | 729 |
| 719 if (constructor == compiler.intEnvironment | 730 if (constructor == compiler.intEnvironment && |
| 720 && !(defaultValue is NullConstant || defaultValue is IntConstant)) { | 731 !(defaultValue.isNull || defaultValue.isInt)) { |
| 721 DartType type = defaultValue.computeType(compiler); | 732 DartType type = defaultValue.computeType(compiler); |
| 722 compiler.reportFatalError( | 733 compiler.reportFatalError( |
| 723 send.arguments.tail.head, MessageKind.NOT_ASSIGNABLE, | 734 send.arguments.tail.head, MessageKind.NOT_ASSIGNABLE, |
| 724 {'fromType': type, 'toType': compiler.intClass.rawType}); | 735 {'fromType': type, 'toType': compiler.intClass.rawType}); |
| 725 return null; | 736 return null; |
| 726 } | 737 } |
| 727 | 738 |
| 728 if (constructor == compiler.boolEnvironment | 739 if (constructor == compiler.boolEnvironment && |
| 729 && !(defaultValue is NullConstant || defaultValue is BoolConstant)) { | 740 !(defaultValue.isNull || defaultValue.isBool)) { |
| 730 DartType type = defaultValue.computeType(compiler); | 741 DartType type = defaultValue.computeType(compiler); |
| 731 compiler.reportFatalError( | 742 compiler.reportFatalError( |
| 732 send.arguments.tail.head, MessageKind.NOT_ASSIGNABLE, | 743 send.arguments.tail.head, MessageKind.NOT_ASSIGNABLE, |
| 733 {'fromType': type, 'toType': compiler.boolClass.rawType}); | 744 {'fromType': type, 'toType': compiler.boolClass.rawType}); |
| 734 return null; | 745 return null; |
| 735 } | 746 } |
| 736 | 747 |
| 737 if (constructor == compiler.stringEnvironment | 748 if (constructor == compiler.stringEnvironment && |
| 738 && !(defaultValue is NullConstant | 749 !(defaultValue.isNull || defaultValue.isString)) { |
| 739 || defaultValue is StringConstant)) { | |
| 740 DartType type = defaultValue.computeType(compiler); | 750 DartType type = defaultValue.computeType(compiler); |
| 741 compiler.reportFatalError( | 751 compiler.reportFatalError( |
| 742 send.arguments.tail.head, MessageKind.NOT_ASSIGNABLE, | 752 send.arguments.tail.head, MessageKind.NOT_ASSIGNABLE, |
| 743 {'fromType': type, 'toType': compiler.stringClass.rawType}); | 753 {'fromType': type, 'toType': compiler.stringClass.rawType}); |
| 744 return null; | 754 return null; |
| 745 } | 755 } |
| 746 | 756 |
| 747 String value = | 757 String value = |
| 748 compiler.fromEnvironment(firstArgument.value.slowToString()); | 758 compiler.fromEnvironment(firstArgument.primitiveValue.slowToString()); |
| 749 | 759 |
| 750 if (value == null) { | 760 if (value == null) { |
| 751 return createEvaluatedConstant(defaultValue); | 761 return createEvaluatedConstant(defaultValue); |
| 752 } else if (constructor == compiler.intEnvironment) { | 762 } else if (constructor == compiler.intEnvironment) { |
| 753 int number = int.parse(value, onError: (_) => null); | 763 int number = int.parse(value, onError: (_) => null); |
| 754 return createEvaluatedConstant( | 764 return createEvaluatedConstant( |
| 755 (number == null) | 765 (number == null) |
| 756 ? defaultValue | 766 ? defaultValue |
| 757 : constantSystem.createInt(number)); | 767 : constantSystem.createInt(number)); |
| 758 } else if (constructor == compiler.boolEnvironment) { | 768 } else if (constructor == compiler.boolEnvironment) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 802 target = target.implementation; | 812 target = target.implementation; |
| 803 assert(invariant(node, target.isImplementation)); | 813 assert(invariant(node, target.isImplementation)); |
| 804 | 814 |
| 805 ConstructorEvaluator evaluator = new ConstructorEvaluator( | 815 ConstructorEvaluator evaluator = new ConstructorEvaluator( |
| 806 constructedType, target, handler, compiler); | 816 constructedType, target, handler, compiler); |
| 807 evaluator.evaluateConstructorFieldValues(normalizedArguments); | 817 evaluator.evaluateConstructorFieldValues(normalizedArguments); |
| 808 List<AstConstant> fieldConstants = | 818 List<AstConstant> fieldConstants = |
| 809 evaluator.buildFieldConstants(classElement); | 819 evaluator.buildFieldConstants(classElement); |
| 810 | 820 |
| 811 return new AstConstant( | 821 return new AstConstant( |
| 812 context, node, new ConstructorConstExp( | 822 context, node, new ConstructedConstantExpresssion( |
| 813 new ConstructedConstant( | 823 new ConstructedConstantValue( |
| 814 constructedType, | 824 constructedType, |
| 815 fieldConstants.map((e) => e.value).toList()), | 825 fieldConstants.map((e) => e.value).toList()), |
| 816 type, | 826 type, |
| 817 constructor, | 827 constructor, |
| 818 selector, | 828 selector, |
| 819 concreteArguments.map((e) => e.expression).toList())); | 829 concreteArguments.map((e) => e.expression).toList())); |
| 820 } | 830 } |
| 821 | 831 |
| 822 AstConstant visitParenthesizedExpression(ParenthesizedExpression node) { | 832 AstConstant visitParenthesizedExpression(ParenthesizedExpression node) { |
| 823 return node.expression.accept(this); | 833 return node.expression.accept(this); |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1044 return fieldConstants; | 1054 return fieldConstants; |
| 1045 } | 1055 } |
| 1046 } | 1056 } |
| 1047 | 1057 |
| 1048 /// A constant created from the front-end AST. | 1058 /// A constant created from the front-end AST. |
| 1049 /// | 1059 /// |
| 1050 /// [element] and [node] point to the source location of the constant. | 1060 /// [element] and [node] point to the source location of the constant. |
| 1051 /// [expression] holds the symbolic constant expression and [value] its constant | 1061 /// [expression] holds the symbolic constant expression and [value] its constant |
| 1052 /// value. | 1062 /// value. |
| 1053 /// | 1063 /// |
| 1054 /// This class differs from [ConstExp] in that it is coupled to the front-end | 1064 /// This class differs from [ConstantExpression] in that it is coupled to the |
| 1055 /// AST whereas [ConstExp] is only coupled to the element model. | 1065 /// front-end AST whereas [ConstantExpression] is only coupled to the element |
| 1066 /// model. |
| 1056 class AstConstant { | 1067 class AstConstant { |
| 1057 final Element element; | 1068 final Element element; |
| 1058 final Node node; | 1069 final Node node; |
| 1059 final ConstExp expression; | 1070 final ConstantExpression expression; |
| 1060 | 1071 |
| 1061 AstConstant(this.element, this.node, this.expression); | 1072 AstConstant(this.element, this.node, this.expression); |
| 1062 | 1073 |
| 1063 factory AstConstant.fromDefaultValue( | 1074 factory AstConstant.fromDefaultValue( |
| 1064 VariableElement element, | 1075 VariableElement element, |
| 1065 ConstExp constant) { | 1076 ConstantExpression constant) { |
| 1066 return new AstConstant( | 1077 return new AstConstant( |
| 1067 element, | 1078 element, |
| 1068 element.initializer != null ? element.initializer : element.node, | 1079 element.initializer != null ? element.initializer : element.node, |
| 1069 constant); | 1080 constant); |
| 1070 } | 1081 } |
| 1071 | 1082 |
| 1072 Constant get value => expression.value; | 1083 ConstantValue get value => expression.value; |
| 1073 | 1084 |
| 1074 String toString() => expression.toString(); | 1085 String toString() => expression.toString(); |
| 1075 } | 1086 } |
| OLD | NEW |