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 library dart2js.compile_time_constant_evaluator; | 5 library dart2js.compile_time_constant_evaluator; |
| 6 | 6 |
| 7 import 'constant_system_dart.dart'; | 7 import 'constant_system_dart.dart'; |
| 8 import 'constants/constant_system.dart'; | 8 import 'constants/constant_system.dart'; |
| 9 import 'constants/expressions.dart'; | 9 import 'constants/expressions.dart'; |
| 10 import 'constants/values.dart'; | 10 import 'constants/values.dart'; |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 146 @override | 146 @override |
| 147 ConstantValue getConstantValueForVariable(VariableElement element) { | 147 ConstantValue getConstantValueForVariable(VariableElement element) { |
| 148 return getConstantValue(initialVariableValues[element.declaration]); | 148 return getConstantValue(initialVariableValues[element.declaration]); |
| 149 } | 149 } |
| 150 | 150 |
| 151 @override | 151 @override |
| 152 ConstantExpression getConstantForVariable(VariableElement element) { | 152 ConstantExpression getConstantForVariable(VariableElement element) { |
| 153 return initialVariableValues[element.declaration]; | 153 return initialVariableValues[element.declaration]; |
| 154 } | 154 } |
| 155 | 155 |
| 156 ConstantExpression compileConstant(VariableElement element) { | 156 ConstantExpression compileConstant(VariableElement element, |
| 157 return compileVariable(element, isConst: true); | 157 {bool checkType: true}) { |
|
Johnni Winther
2015/06/17 06:56:29
This method overrides ConstantCompiler.compileCons
Harry Terkelsen
2015/08/10 23:49:34
Done.
| |
| 158 return compileVariable(element, isConst: true, checkType: checkType); | |
| 158 } | 159 } |
| 159 | 160 |
| 160 ConstantExpression compileVariable(VariableElement element, | 161 ConstantExpression compileVariable(VariableElement element, |
| 161 {bool isConst: false}) { | 162 {bool isConst: false, |
| 163 bool checkType: true}) { | |
|
Johnni Winther
2015/06/17 06:56:29
Ditto.
Harry Terkelsen
2015/08/10 23:49:34
Done.
| |
| 162 | 164 |
| 163 if (initialVariableValues.containsKey(element.declaration)) { | 165 if (initialVariableValues.containsKey(element.declaration)) { |
| 164 ConstantExpression result = initialVariableValues[element.declaration]; | 166 ConstantExpression result = initialVariableValues[element.declaration]; |
| 165 return result; | 167 return result; |
| 166 } | 168 } |
| 167 AstElement currentElement = element.analyzableElement; | 169 AstElement currentElement = element.analyzableElement; |
| 168 return compiler.withCurrentElement(currentElement, () { | 170 return compiler.withCurrentElement(currentElement, () { |
| 169 // TODO(johnniwinther): Avoid this eager analysis. | 171 // TODO(johnniwinther): Avoid this eager analysis. |
| 170 _analyzeElementEagerly(compiler, currentElement); | 172 _analyzeElementEagerly(compiler, currentElement); |
| 171 | 173 |
| 172 ConstantExpression constant = compileVariableWithDefinitions( | 174 ConstantExpression constant = compileVariableWithDefinitions( |
| 173 element, currentElement.resolvedAst.elements, isConst: isConst); | 175 element, currentElement.resolvedAst.elements, isConst: isConst, |
| 176 checkType: checkType); | |
| 174 return constant; | 177 return constant; |
| 175 }); | 178 }); |
| 176 } | 179 } |
| 177 | 180 |
| 178 /** | 181 /** |
| 179 * Returns the a compile-time constant if the variable could be compiled | 182 * Returns the a compile-time constant if the variable could be compiled |
| 180 * eagerly. If the variable needs to be initialized lazily returns `null`. | 183 * eagerly. If the variable needs to be initialized lazily returns `null`. |
| 181 * If the variable is `const` but cannot be compiled eagerly reports an | 184 * If the variable is `const` but cannot be compiled eagerly reports an |
| 182 * error. | 185 * error. |
| 183 */ | 186 */ |
| 184 ConstantExpression compileVariableWithDefinitions(VariableElement element, | 187 ConstantExpression compileVariableWithDefinitions(VariableElement element, |
| 185 TreeElements definitions, | 188 TreeElements definitions, |
| 186 {bool isConst: false}) { | 189 {bool isConst: false, |
| 190 bool checkType: true}) { | |
| 187 Node node = element.node; | 191 Node node = element.node; |
| 188 if (pendingVariables.contains(element)) { | 192 if (pendingVariables.contains(element)) { |
| 189 if (isConst) { | 193 if (isConst) { |
| 190 compiler.reportError( | 194 compiler.reportError( |
| 191 node, MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS); | 195 node, MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS); |
| 192 ConstantExpression expression = new ErroneousConstantExpression(); | 196 ConstantExpression expression = new ErroneousConstantExpression(); |
| 193 constantValueMap[expression] = constantSystem.createNull(); | 197 constantValueMap[expression] = constantSystem.createNull(); |
| 194 return expression; | 198 return expression; |
| 195 } | 199 } |
| 196 return null; | 200 return null; |
| 197 } | 201 } |
| 198 pendingVariables.add(element); | 202 pendingVariables.add(element); |
| 199 | 203 |
| 200 Expression initializer = element.initializer; | 204 Expression initializer = element.initializer; |
| 201 ConstantExpression expression; | 205 ConstantExpression expression; |
| 202 if (initializer == null) { | 206 if (initializer == null) { |
| 203 // No initial value. | 207 // No initial value. |
| 204 expression = new NullConstantExpression(); | 208 expression = new NullConstantExpression(); |
| 205 constantValueMap[expression] = constantSystem.createNull(); | 209 constantValueMap[expression] = constantSystem.createNull(); |
| 206 } else { | 210 } else { |
| 207 expression = compileNodeWithDefinitions( | 211 expression = compileNodeWithDefinitions( |
| 208 initializer, definitions, isConst: isConst); | 212 initializer, definitions, isConst: isConst); |
| 209 if (compiler.enableTypeAssertions && | 213 if (compiler.enableTypeAssertions && |
| 214 checkType && | |
| 210 expression != null && | 215 expression != null && |
| 211 element.isField) { | 216 element.isField) { |
| 212 DartType elementType = element.type; | 217 DartType elementType = element.type; |
| 213 ConstantValue value = getConstantValue(expression); | 218 ConstantValue value = getConstantValue(expression); |
| 214 if (elementType.isMalformed && !value.isNull) { | 219 if (elementType.isMalformed && !value.isNull) { |
| 215 if (isConst) { | 220 if (isConst) { |
| 216 ErroneousElement element = elementType.element; | 221 ErroneousElement element = elementType.element; |
| 217 compiler.reportError( | 222 compiler.reportError( |
| 218 node, element.messageKind, element.messageArguments); | 223 node, element.messageKind, element.messageArguments); |
| 219 } else { | 224 } else { |
| (...skipping 894 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1114 if (Elements.isLocal(element)) { | 1119 if (Elements.isLocal(element)) { |
| 1115 AstConstant constant = definitions[element]; | 1120 AstConstant constant = definitions[element]; |
| 1116 if (constant == null) { | 1121 if (constant == null) { |
| 1117 compiler.internalError(send, "Local variable without value."); | 1122 compiler.internalError(send, "Local variable without value."); |
| 1118 } | 1123 } |
| 1119 return constant; | 1124 return constant; |
| 1120 } | 1125 } |
| 1121 return super.visitSend(send); | 1126 return super.visitSend(send); |
| 1122 } | 1127 } |
| 1123 | 1128 |
| 1124 void potentiallyCheckType(Node node, | 1129 void potentiallyCheckType(TypedElement element, |
| 1125 TypedElement element, | |
| 1126 AstConstant constant) { | 1130 AstConstant constant) { |
| 1127 if (compiler.enableTypeAssertions) { | 1131 if (compiler.enableTypeAssertions) { |
| 1128 DartType elementType = element.type.substByContext(constructedType); | 1132 DartType elementType = element.type.substByContext(constructedType); |
| 1129 DartType constantType = constant.value.getType(compiler.coreTypes); | 1133 DartType constantType = constant.value.getType(compiler.coreTypes); |
| 1130 if (!constantSystem.isSubtype(compiler.types, | 1134 if (!constantSystem.isSubtype(compiler.types, |
| 1131 constantType, elementType)) { | 1135 constantType, elementType)) { |
| 1132 compiler.withCurrentElement(constant.element, () { | 1136 compiler.withCurrentElement(constant.element, () { |
| 1133 compiler.reportError( | 1137 compiler.reportError( |
| 1134 constant.node, MessageKind.NOT_ASSIGNABLE, | 1138 constant.node, MessageKind.NOT_ASSIGNABLE, |
| 1135 {'fromType': constantType, 'toType': elementType}); | 1139 {'fromType': constantType, 'toType': elementType}); |
| 1136 }); | 1140 }); |
| 1137 } | 1141 } |
| 1138 } | 1142 } |
| 1139 } | 1143 } |
| 1140 | 1144 |
| 1141 void updateFieldValue(Node node, | 1145 void updateFieldValue(Node node, |
| 1142 TypedElement element, | 1146 TypedElement element, |
| 1143 AstConstant constant) { | 1147 AstConstant constant) { |
| 1144 potentiallyCheckType(node, element, constant); | 1148 potentiallyCheckType(element, constant); |
| 1145 fieldValues[element] = constant; | 1149 fieldValues[element] = constant; |
| 1146 } | 1150 } |
| 1147 | 1151 |
| 1148 /** | 1152 /** |
| 1149 * Given the arguments (a list of constants) assigns them to the parameters, | 1153 * Given the arguments (a list of constants) assigns them to the parameters, |
| 1150 * updating the definitions map. If the constructor has field-initializer | 1154 * updating the definitions map. If the constructor has field-initializer |
| 1151 * parameters (like [:this.x:]), also updates the [fieldValues] map. | 1155 * parameters (like [:this.x:]), also updates the [fieldValues] map. |
| 1152 */ | 1156 */ |
| 1153 void assignArgumentsToParameters(List<AstConstant> arguments) { | 1157 void assignArgumentsToParameters(List<AstConstant> arguments) { |
| 1154 if (constructor.isErroneous) return; | 1158 if (constructor.isErroneous) return; |
| 1155 // Assign arguments to parameters. | 1159 // Assign arguments to parameters. |
| 1156 FunctionSignature signature = constructor.functionSignature; | 1160 FunctionSignature signature = constructor.functionSignature; |
| 1157 int index = 0; | 1161 int index = 0; |
| 1158 signature.orderedForEachParameter((ParameterElement parameter) { | 1162 signature.orderedForEachParameter((ParameterElement parameter) { |
| 1159 AstConstant argument = arguments[index++]; | 1163 AstConstant argument = arguments[index++]; |
| 1160 Node node = parameter.node; | 1164 Node node = parameter.node; |
| 1161 if (parameter.isInitializingFormal) { | 1165 if (parameter.isInitializingFormal) { |
| 1162 InitializingFormalElement initializingFormal = parameter; | 1166 InitializingFormalElement initializingFormal = parameter; |
| 1163 updateFieldValue(node, initializingFormal.fieldElement, argument); | 1167 updateFieldValue(node, initializingFormal.fieldElement, argument); |
| 1164 } else { | 1168 } else { |
| 1165 potentiallyCheckType(node, parameter, argument); | 1169 potentiallyCheckType(parameter, argument); |
| 1166 definitions[parameter] = argument; | 1170 definitions[parameter] = argument; |
| 1167 } | 1171 } |
| 1168 }); | 1172 }); |
| 1169 } | 1173 } |
| 1170 | 1174 |
| 1171 void evaluateSuperOrRedirectSend(List<AstConstant> compiledArguments, | 1175 void evaluateSuperOrRedirectSend(List<AstConstant> compiledArguments, |
| 1172 FunctionElement targetConstructor) { | 1176 FunctionElement targetConstructor) { |
| 1173 ConstructorEvaluator evaluator = new ConstructorEvaluator( | 1177 ConstructorEvaluator evaluator = new ConstructorEvaluator( |
| 1174 constructedType.asInstanceOf(targetConstructor.enclosingClass), | 1178 constructedType.asInstanceOf(targetConstructor.enclosingClass), |
| 1175 targetConstructor, handler, compiler); | 1179 targetConstructor, handler, compiler); |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1272 /// inheritance chain of [classElement]. | 1276 /// inheritance chain of [classElement]. |
| 1273 Map<FieldElement, AstConstant> buildFieldConstants( | 1277 Map<FieldElement, AstConstant> buildFieldConstants( |
| 1274 ClassElement classElement) { | 1278 ClassElement classElement) { |
| 1275 Map<FieldElement, AstConstant> fieldConstants = | 1279 Map<FieldElement, AstConstant> fieldConstants = |
| 1276 <FieldElement, AstConstant>{}; | 1280 <FieldElement, AstConstant>{}; |
| 1277 classElement.implementation.forEachInstanceField( | 1281 classElement.implementation.forEachInstanceField( |
| 1278 (ClassElement enclosing, FieldElement field) { | 1282 (ClassElement enclosing, FieldElement field) { |
| 1279 AstConstant fieldValue = fieldValues[field]; | 1283 AstConstant fieldValue = fieldValues[field]; |
| 1280 if (fieldValue == null) { | 1284 if (fieldValue == null) { |
| 1281 // Use the default value. | 1285 // Use the default value. |
| 1282 ConstantExpression fieldExpression = handler.compileConstant(field); | 1286 ConstantExpression fieldExpression = |
| 1287 handler.compileConstant(field, checkType: false); | |
| 1283 fieldValue = new AstConstant.fromDefaultValue( | 1288 fieldValue = new AstConstant.fromDefaultValue( |
| 1284 field, | 1289 field, |
| 1285 fieldExpression, | 1290 fieldExpression, |
| 1286 handler.getConstantValue(fieldExpression)); | 1291 handler.getConstantValue(fieldExpression)); |
| 1292 potentiallyCheckType(field, fieldValue); | |
| 1287 } | 1293 } |
| 1288 fieldConstants[field] = fieldValue; | 1294 fieldConstants[field] = fieldValue; |
| 1289 }, | 1295 }, |
| 1290 includeSuperAndInjectedMembers: true); | 1296 includeSuperAndInjectedMembers: true); |
| 1291 return fieldConstants; | 1297 return fieldConstants; |
| 1292 } | 1298 } |
| 1293 } | 1299 } |
| 1294 | 1300 |
| 1295 /// A constant created from the front-end AST. | 1301 /// A constant created from the front-end AST. |
| 1296 /// | 1302 /// |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1330 // TODO(johnniwinther): Return a [NonConstantValue] instead. | 1336 // TODO(johnniwinther): Return a [NonConstantValue] instead. |
| 1331 new ErroneousConstantExpression(), new NullConstantValue()); | 1337 new ErroneousConstantExpression(), new NullConstantValue()); |
| 1332 } | 1338 } |
| 1333 | 1339 |
| 1334 // TODO(johnniwinther): Avoid the need for this hack. | 1340 // TODO(johnniwinther): Avoid the need for this hack. |
| 1335 TreeElements _analyzeElementEagerly(Compiler compiler, AstElement element) { | 1341 TreeElements _analyzeElementEagerly(Compiler compiler, AstElement element) { |
| 1336 WorldImpact worldImpact = compiler.analyzeElement(element.declaration); | 1342 WorldImpact worldImpact = compiler.analyzeElement(element.declaration); |
| 1337 compiler.enqueuer.resolution.applyImpact(element.declaration, worldImpact); | 1343 compiler.enqueuer.resolution.applyImpact(element.declaration, worldImpact); |
| 1338 return element.resolvedAst.elements; | 1344 return element.resolvedAst.elements; |
| 1339 } | 1345 } |
| OLD | NEW |