| 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 'common.dart'; | 7 import 'common.dart'; |
| 8 import 'common/resolution.dart' show | 8 import 'common/resolution.dart' show Resolution; |
| 9 Resolution; | 9 import 'common/tasks.dart' show CompilerTask; |
| 10 import 'common/tasks.dart' show | 10 import 'compiler.dart' show Compiler; |
| 11 CompilerTask; | |
| 12 import 'compiler.dart' show | |
| 13 Compiler; | |
| 14 import 'constant_system_dart.dart'; | 11 import 'constant_system_dart.dart'; |
| 15 import 'constants/constant_system.dart'; | 12 import 'constants/constant_system.dart'; |
| 16 import 'constants/evaluation.dart'; | 13 import 'constants/evaluation.dart'; |
| 17 import 'constants/expressions.dart'; | 14 import 'constants/expressions.dart'; |
| 18 import 'constants/values.dart'; | 15 import 'constants/values.dart'; |
| 19 import 'core_types.dart' show | 16 import 'core_types.dart' show CoreTypes; |
| 20 CoreTypes; | |
| 21 import 'dart_types.dart'; | 17 import 'dart_types.dart'; |
| 22 import 'elements/elements.dart'; | 18 import 'elements/elements.dart'; |
| 23 import 'elements/modelx.dart' show | 19 import 'elements/modelx.dart' show FunctionElementX; |
| 24 FunctionElementX; | 20 import 'resolution/tree_elements.dart' show TreeElements; |
| 25 import 'resolution/tree_elements.dart' show | |
| 26 TreeElements; | |
| 27 import 'resolution/operators.dart'; | 21 import 'resolution/operators.dart'; |
| 28 import 'tree/tree.dart'; | 22 import 'tree/tree.dart'; |
| 29 import 'util/util.dart' show | 23 import 'util/util.dart' show Link; |
| 30 Link; | 24 import 'universe/call_structure.dart' show CallStructure; |
| 31 import 'universe/call_structure.dart' show | |
| 32 CallStructure; | |
| 33 | 25 |
| 34 /// A [ConstantEnvironment] provides access for constants compiled for variable | 26 /// A [ConstantEnvironment] provides access for constants compiled for variable |
| 35 /// initializers. | 27 /// initializers. |
| 36 abstract class ConstantEnvironment { | 28 abstract class ConstantEnvironment { |
| 37 /// The [ConstantSystem] used by this environment. | 29 /// The [ConstantSystem] used by this environment. |
| 38 ConstantSystem get constantSystem; | 30 ConstantSystem get constantSystem; |
| 39 | 31 |
| 40 /// Returns the constant value computed for [expression]. | 32 /// Returns the constant value computed for [expression]. |
| 41 // TODO(johnniwinther): Support directly evaluation of [expression]. | 33 // TODO(johnniwinther): Support directly evaluation of [expression]. |
| 42 ConstantValue getConstantValue(ConstantExpression expression); | 34 ConstantValue getConstantValue(ConstantExpression expression); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 ConstantExpression compileNode(Node node, TreeElements elements, | 72 ConstantExpression compileNode(Node node, TreeElements elements, |
| 81 {bool enforceConst: true}); | 73 {bool enforceConst: true}); |
| 82 | 74 |
| 83 /// Compiles the compile-time constant for the value [metadata], or reports an | 75 /// Compiles the compile-time constant for the value [metadata], or reports an |
| 84 /// error if the value is not a compile-time constant. | 76 /// error if the value is not a compile-time constant. |
| 85 /// | 77 /// |
| 86 /// Depending on implementation, the constant compiler might also compute | 78 /// Depending on implementation, the constant compiler might also compute |
| 87 /// the compile-time constant for the backend interpretation of constants. | 79 /// the compile-time constant for the backend interpretation of constants. |
| 88 /// | 80 /// |
| 89 /// The returned constant is always of the frontend interpretation. | 81 /// The returned constant is always of the frontend interpretation. |
| 90 ConstantExpression compileMetadata(MetadataAnnotation metadata, | 82 ConstantExpression compileMetadata( |
| 91 Node node, | 83 MetadataAnnotation metadata, Node node, TreeElements elements); |
| 92 TreeElements elements); | |
| 93 | 84 |
| 94 /// Evaluates [constant] and caches the result. | 85 /// Evaluates [constant] and caches the result. |
| 95 // TODO(johnniwinther): Remove when all constants are evaluated. | 86 // TODO(johnniwinther): Remove when all constants are evaluated. |
| 96 void evaluate(ConstantExpression constant); | 87 void evaluate(ConstantExpression constant); |
| 97 } | 88 } |
| 98 | 89 |
| 99 /// A [BackendConstantEnvironment] provides access to constants needed for | 90 /// A [BackendConstantEnvironment] provides access to constants needed for |
| 100 /// backend implementation. | 91 /// backend implementation. |
| 101 abstract class BackendConstantEnvironment extends ConstantEnvironment { | 92 abstract class BackendConstantEnvironment extends ConstantEnvironment { |
| 102 /// Returns the compile-time constant value associated with [node]. | 93 /// Returns the compile-time constant value associated with [node]. |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 } | 166 } |
| 176 | 167 |
| 177 ConstantExpression compileConstant(VariableElement element) { | 168 ConstantExpression compileConstant(VariableElement element) { |
| 178 return internalCompileVariable(element, true, true); | 169 return internalCompileVariable(element, true, true); |
| 179 } | 170 } |
| 180 | 171 |
| 181 @override | 172 @override |
| 182 void evaluate(ConstantExpression constant) { | 173 void evaluate(ConstantExpression constant) { |
| 183 constantValueMap.putIfAbsent(constant, () { | 174 constantValueMap.putIfAbsent(constant, () { |
| 184 return constant.evaluate( | 175 return constant.evaluate( |
| 185 new _CompilerEnvironment(compiler), | 176 new _CompilerEnvironment(compiler), constantSystem); |
| 186 constantSystem); | |
| 187 }); | 177 }); |
| 188 } | 178 } |
| 189 | 179 |
| 190 ConstantExpression compileVariable(VariableElement element) { | 180 ConstantExpression compileVariable(VariableElement element) { |
| 191 return internalCompileVariable(element, false, true); | 181 return internalCompileVariable(element, false, true); |
| 192 } | 182 } |
| 193 | 183 |
| 194 /// Compile [element] into a constant expression. If [isConst] is true, | 184 /// Compile [element] into a constant expression. If [isConst] is true, |
| 195 /// then [element] is a constant variable. If [checkType] is true, then | 185 /// then [element] is a constant variable. If [checkType] is true, then |
| 196 /// report an error if [element] does not typecheck. | 186 /// report an error if [element] does not typecheck. |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 node, element.messageKind, element.messageArguments); | 246 node, element.messageKind, element.messageArguments); |
| 257 } else { | 247 } else { |
| 258 // We need to throw an exception at runtime. | 248 // We need to throw an exception at runtime. |
| 259 expression = null; | 249 expression = null; |
| 260 } | 250 } |
| 261 } else { | 251 } else { |
| 262 DartType constantType = value.getType(coreTypes); | 252 DartType constantType = value.getType(coreTypes); |
| 263 if (!constantSystem.isSubtype( | 253 if (!constantSystem.isSubtype( |
| 264 compiler.types, constantType, elementType)) { | 254 compiler.types, constantType, elementType)) { |
| 265 if (isConst) { | 255 if (isConst) { |
| 266 reporter.reportErrorMessage( | 256 reporter.reportErrorMessage(node, MessageKind.NOT_ASSIGNABLE, |
| 267 node, | 257 {'fromType': constantType, 'toType': elementType}); |
| 268 MessageKind.NOT_ASSIGNABLE, | |
| 269 {'fromType': constantType, | |
| 270 'toType': elementType}); | |
| 271 } else { | 258 } else { |
| 272 // If the field cannot be lazily initialized, we will throw | 259 // If the field cannot be lazily initialized, we will throw |
| 273 // the exception at runtime. | 260 // the exception at runtime. |
| 274 expression = null; | 261 expression = null; |
| 275 } | 262 } |
| 276 } | 263 } |
| 277 } | 264 } |
| 278 } | 265 } |
| 279 } | 266 } |
| 280 if (expression != null) { | 267 if (expression != null) { |
| 281 initialVariableValues[element.declaration] = expression; | 268 initialVariableValues[element.declaration] = expression; |
| 282 } else { | 269 } else { |
| 283 assert(invariant(element, !isConst, | 270 assert(invariant(element, !isConst, |
| 284 message: "Variable $element does not compile to a constant.")); | 271 message: "Variable $element does not compile to a constant.")); |
| 285 } | 272 } |
| 286 pendingVariables.remove(element); | 273 pendingVariables.remove(element); |
| 287 return expression; | 274 return expression; |
| 288 } | 275 } |
| 289 | 276 |
| 290 void cacheConstantValue(ConstantExpression expression, ConstantValue value) { | 277 void cacheConstantValue(ConstantExpression expression, ConstantValue value) { |
| 291 constantValueMap[expression] = value; | 278 constantValueMap[expression] = value; |
| 292 } | 279 } |
| 293 | 280 |
| 294 ConstantExpression compileNodeWithDefinitions( | 281 ConstantExpression compileNodeWithDefinitions( |
| 295 Node node, TreeElements definitions, {bool isConst: true}) { | 282 Node node, TreeElements definitions, |
| 283 {bool isConst: true}) { |
| 296 assert(node != null); | 284 assert(node != null); |
| 297 CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator( | 285 CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator( |
| 298 this, definitions, compiler, isConst: isConst); | 286 this, definitions, compiler, |
| 287 isConst: isConst); |
| 299 AstConstant constant = evaluator.evaluate(node); | 288 AstConstant constant = evaluator.evaluate(node); |
| 300 if (constant != null) { | 289 if (constant != null) { |
| 301 cacheConstantValue(constant.expression, constant.value); | 290 cacheConstantValue(constant.expression, constant.value); |
| 302 return constant.expression; | 291 return constant.expression; |
| 303 } | 292 } |
| 304 return null; | 293 return null; |
| 305 } | 294 } |
| 306 | 295 |
| 307 ConstantValue getConstantValue(ConstantExpression expression) { | 296 ConstantValue getConstantValue(ConstantExpression expression) { |
| 308 return constantValueMap[expression]; | 297 return constantValueMap[expression]; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 333 /// constant evaluation. | 322 /// constant evaluation. |
| 334 class DartConstantCompiler extends ConstantCompilerBase { | 323 class DartConstantCompiler extends ConstantCompilerBase { |
| 335 DartConstantCompiler(Compiler compiler) | 324 DartConstantCompiler(Compiler compiler) |
| 336 : super(compiler, const DartConstantSystem()); | 325 : super(compiler, const DartConstantSystem()); |
| 337 | 326 |
| 338 ConstantExpression getConstantForNode(Node node, TreeElements definitions) { | 327 ConstantExpression getConstantForNode(Node node, TreeElements definitions) { |
| 339 return definitions.getConstant(node); | 328 return definitions.getConstant(node); |
| 340 } | 329 } |
| 341 | 330 |
| 342 ConstantExpression compileNodeWithDefinitions( | 331 ConstantExpression compileNodeWithDefinitions( |
| 343 Node node, TreeElements definitions, {bool isConst: true}) { | 332 Node node, TreeElements definitions, |
| 333 {bool isConst: true}) { |
| 344 ConstantExpression constant = definitions.getConstant(node); | 334 ConstantExpression constant = definitions.getConstant(node); |
| 345 if (constant != null && getConstantValue(constant) != null) { | 335 if (constant != null && getConstantValue(constant) != null) { |
| 346 return constant; | 336 return constant; |
| 347 } | 337 } |
| 348 constant = | 338 constant = |
| 349 super.compileNodeWithDefinitions(node, definitions, isConst: isConst); | 339 super.compileNodeWithDefinitions(node, definitions, isConst: isConst); |
| 350 if (constant != null) { | 340 if (constant != null) { |
| 351 definitions.setConstant(node, constant); | 341 definitions.setConstant(node, constant); |
| 352 } | 342 } |
| 353 return constant; | 343 return constant; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 386 isEvaluatingConstant = oldIsEvaluatingConstant; | 376 isEvaluatingConstant = oldIsEvaluatingConstant; |
| 387 assert(result != null); | 377 assert(result != null); |
| 388 return result; | 378 return result; |
| 389 } | 379 } |
| 390 | 380 |
| 391 AstConstant visitNode(Node node) { | 381 AstConstant visitNode(Node node) { |
| 392 return signalNotCompileTimeConstant(node); | 382 return signalNotCompileTimeConstant(node); |
| 393 } | 383 } |
| 394 | 384 |
| 395 AstConstant visitLiteralBool(LiteralBool node) { | 385 AstConstant visitLiteralBool(LiteralBool node) { |
| 396 return new AstConstant(context, node, | 386 return new AstConstant( |
| 387 context, |
| 388 node, |
| 397 new BoolConstantExpression(node.value), | 389 new BoolConstantExpression(node.value), |
| 398 constantSystem.createBool(node.value)); | 390 constantSystem.createBool(node.value)); |
| 399 } | 391 } |
| 400 | 392 |
| 401 AstConstant visitLiteralDouble(LiteralDouble node) { | 393 AstConstant visitLiteralDouble(LiteralDouble node) { |
| 402 return new AstConstant(context, node, | 394 return new AstConstant( |
| 395 context, |
| 396 node, |
| 403 new DoubleConstantExpression(node.value), | 397 new DoubleConstantExpression(node.value), |
| 404 constantSystem.createDouble(node.value)); | 398 constantSystem.createDouble(node.value)); |
| 405 } | 399 } |
| 406 | 400 |
| 407 AstConstant visitLiteralInt(LiteralInt node) { | 401 AstConstant visitLiteralInt(LiteralInt node) { |
| 408 return new AstConstant(context, node, new IntConstantExpression(node.value), | 402 return new AstConstant(context, node, new IntConstantExpression(node.value), |
| 409 constantSystem.createInt(node.value)); | 403 constantSystem.createInt(node.value)); |
| 410 } | 404 } |
| 411 | 405 |
| 412 AstConstant visitLiteralList(LiteralList node) { | 406 AstConstant visitLiteralList(LiteralList node) { |
| 413 if (!node.isConst) { | 407 if (!node.isConst) { |
| 414 return signalNotCompileTimeConstant(node); | 408 return signalNotCompileTimeConstant(node); |
| 415 } | 409 } |
| 416 List<ConstantExpression> argumentExpressions = <ConstantExpression>[]; | 410 List<ConstantExpression> argumentExpressions = <ConstantExpression>[]; |
| 417 List<ConstantValue> argumentValues = <ConstantValue>[]; | 411 List<ConstantValue> argumentValues = <ConstantValue>[]; |
| 418 for (Link<Node> link = node.elements.nodes; | 412 for (Link<Node> link = node.elements.nodes; |
| 419 !link.isEmpty; | 413 !link.isEmpty; |
| 420 link = link.tail) { | 414 link = link.tail) { |
| 421 AstConstant argument = evaluateConstant(link.head); | 415 AstConstant argument = evaluateConstant(link.head); |
| 422 if (argument == null) { | 416 if (argument == null) { |
| 423 return null; | 417 return null; |
| 424 } | 418 } |
| 425 argumentExpressions.add(argument.expression); | 419 argumentExpressions.add(argument.expression); |
| 426 argumentValues.add(argument.value); | 420 argumentValues.add(argument.value); |
| 427 } | 421 } |
| 428 DartType type = elements.getType(node); | 422 DartType type = elements.getType(node); |
| 429 return new AstConstant(context, node, | 423 return new AstConstant( |
| 424 context, |
| 425 node, |
| 430 new ListConstantExpression(type, argumentExpressions), | 426 new ListConstantExpression(type, argumentExpressions), |
| 431 constantSystem.createList(type, argumentValues)); | 427 constantSystem.createList(type, argumentValues)); |
| 432 } | 428 } |
| 433 | 429 |
| 434 AstConstant visitLiteralMap(LiteralMap node) { | 430 AstConstant visitLiteralMap(LiteralMap node) { |
| 435 if (!node.isConst) { | 431 if (!node.isConst) { |
| 436 return signalNotCompileTimeConstant(node); | 432 return signalNotCompileTimeConstant(node); |
| 437 } | 433 } |
| 438 List<ConstantExpression> keyExpressions = <ConstantExpression>[]; | 434 List<ConstantExpression> keyExpressions = <ConstantExpression>[]; |
| 439 List<ConstantExpression> valueExpressions = <ConstantExpression>[]; | 435 List<ConstantExpression> valueExpressions = <ConstantExpression>[]; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 455 keyValues.add(key.value); | 451 keyValues.add(key.value); |
| 456 } else { | 452 } else { |
| 457 reporter.reportWarningMessage( | 453 reporter.reportWarningMessage( |
| 458 entry.key, MessageKind.EQUAL_MAP_ENTRY_KEY); | 454 entry.key, MessageKind.EQUAL_MAP_ENTRY_KEY); |
| 459 } | 455 } |
| 460 keyExpressions.add(key.expression); | 456 keyExpressions.add(key.expression); |
| 461 valueExpressions.add(value.expression); | 457 valueExpressions.add(value.expression); |
| 462 map[key.value] = value.value; | 458 map[key.value] = value.value; |
| 463 } | 459 } |
| 464 InterfaceType type = elements.getType(node); | 460 InterfaceType type = elements.getType(node); |
| 465 return new AstConstant(context, node, | 461 return new AstConstant( |
| 462 context, |
| 463 node, |
| 466 new MapConstantExpression(type, keyExpressions, valueExpressions), | 464 new MapConstantExpression(type, keyExpressions, valueExpressions), |
| 467 constantSystem.createMap( | 465 constantSystem.createMap( |
| 468 compiler, type, keyValues, map.values.toList())); | 466 compiler, type, keyValues, map.values.toList())); |
| 469 } | 467 } |
| 470 | 468 |
| 471 AstConstant visitLiteralNull(LiteralNull node) { | 469 AstConstant visitLiteralNull(LiteralNull node) { |
| 472 return new AstConstant(context, node, new NullConstantExpression(), | 470 return new AstConstant(context, node, new NullConstantExpression(), |
| 473 constantSystem.createNull()); | 471 constantSystem.createNull()); |
| 474 } | 472 } |
| 475 | 473 |
| 476 AstConstant visitLiteralString(LiteralString node) { | 474 AstConstant visitLiteralString(LiteralString node) { |
| 477 return new AstConstant(context, node, | 475 return new AstConstant( |
| 476 context, |
| 477 node, |
| 478 new StringConstantExpression(node.dartString.slowToString()), | 478 new StringConstantExpression(node.dartString.slowToString()), |
| 479 constantSystem.createString(node.dartString)); | 479 constantSystem.createString(node.dartString)); |
| 480 } | 480 } |
| 481 | 481 |
| 482 AstConstant visitStringJuxtaposition(StringJuxtaposition node) { | 482 AstConstant visitStringJuxtaposition(StringJuxtaposition node) { |
| 483 AstConstant left = evaluate(node.first); | 483 AstConstant left = evaluate(node.first); |
| 484 AstConstant right = evaluate(node.second); | 484 AstConstant right = evaluate(node.second); |
| 485 if (left == null || right == null) return null; | 485 if (left == null || right == null) return null; |
| 486 StringConstantValue leftValue = left.value; | 486 StringConstantValue leftValue = left.value; |
| 487 StringConstantValue rightValue = right.value; | 487 StringConstantValue rightValue = right.value; |
| 488 return new AstConstant(context, node, | 488 return new AstConstant( |
| 489 context, |
| 490 node, |
| 489 new ConcatenateConstantExpression([left.expression, right.expression]), | 491 new ConcatenateConstantExpression([left.expression, right.expression]), |
| 490 constantSystem.createString(new DartString.concat( | 492 constantSystem.createString(new DartString.concat( |
| 491 leftValue.primitiveValue, rightValue.primitiveValue))); | 493 leftValue.primitiveValue, rightValue.primitiveValue))); |
| 492 } | 494 } |
| 493 | 495 |
| 494 AstConstant visitStringInterpolation(StringInterpolation node) { | 496 AstConstant visitStringInterpolation(StringInterpolation node) { |
| 495 List<ConstantExpression> subexpressions = <ConstantExpression>[]; | 497 List<ConstantExpression> subexpressions = <ConstantExpression>[]; |
| 496 AstConstant initialString = evaluate(node.string); | 498 AstConstant initialString = evaluate(node.string); |
| 497 if (initialString == null) { | 499 if (initialString == null) { |
| 498 return null; | 500 return null; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 522 } | 524 } |
| 523 accumulator = new DartString.concat(accumulator, expressionString); | 525 accumulator = new DartString.concat(accumulator, expressionString); |
| 524 AstConstant partString = evaluate(part.string); | 526 AstConstant partString = evaluate(part.string); |
| 525 if (partString == null) return null; | 527 if (partString == null) return null; |
| 526 subexpressions.add(partString.expression); | 528 subexpressions.add(partString.expression); |
| 527 StringConstantValue partStringValue = partString.value; | 529 StringConstantValue partStringValue = partString.value; |
| 528 accumulator = | 530 accumulator = |
| 529 new DartString.concat(accumulator, partStringValue.primitiveValue); | 531 new DartString.concat(accumulator, partStringValue.primitiveValue); |
| 530 } | 532 } |
| 531 ; | 533 ; |
| 532 return new AstConstant(context, node, | 534 return new AstConstant( |
| 535 context, |
| 536 node, |
| 533 new ConcatenateConstantExpression(subexpressions), | 537 new ConcatenateConstantExpression(subexpressions), |
| 534 constantSystem.createString(accumulator)); | 538 constantSystem.createString(accumulator)); |
| 535 } | 539 } |
| 536 | 540 |
| 537 AstConstant visitLiteralSymbol(LiteralSymbol node) { | 541 AstConstant visitLiteralSymbol(LiteralSymbol node) { |
| 538 InterfaceType type = coreTypes.symbolType; | 542 InterfaceType type = coreTypes.symbolType; |
| 539 String text = node.slowNameString; | 543 String text = node.slowNameString; |
| 540 List<AstConstant> arguments = <AstConstant>[ | 544 List<AstConstant> arguments = <AstConstant>[ |
| 541 new AstConstant(context, node, new StringConstantExpression(text), | 545 new AstConstant(context, node, new StringConstantExpression(text), |
| 542 constantSystem.createString(new LiteralDartString(text))) | 546 constantSystem.createString(new LiteralDartString(text))) |
| (...skipping 30 matching lines...) Expand all Loading... |
| 573 } | 577 } |
| 574 | 578 |
| 575 // TODO(floitsch): provide better error-messages. | 579 // TODO(floitsch): provide better error-messages. |
| 576 AstConstant visitSend(Send send) { | 580 AstConstant visitSend(Send send) { |
| 577 Element element = elements[send]; | 581 Element element = elements[send]; |
| 578 if (send.isPropertyAccess) { | 582 if (send.isPropertyAccess) { |
| 579 AstConstant result; | 583 AstConstant result; |
| 580 if (Elements.isStaticOrTopLevelFunction(element)) { | 584 if (Elements.isStaticOrTopLevelFunction(element)) { |
| 581 FunctionElementX function = element; | 585 FunctionElementX function = element; |
| 582 function.computeType(resolution); | 586 function.computeType(resolution); |
| 583 result = new AstConstant(context, send, | 587 result = new AstConstant( |
| 588 context, |
| 589 send, |
| 584 new FunctionConstantExpression(function), | 590 new FunctionConstantExpression(function), |
| 585 new FunctionConstantValue(function)); | 591 new FunctionConstantValue(function)); |
| 586 } else if (Elements.isStaticOrTopLevelField(element)) { | 592 } else if (Elements.isStaticOrTopLevelField(element)) { |
| 587 ConstantExpression elementExpression; | 593 ConstantExpression elementExpression; |
| 588 if (element.isConst) { | 594 if (element.isConst) { |
| 589 elementExpression = handler.compileConstant(element); | 595 elementExpression = handler.compileConstant(element); |
| 590 } else if (element.isFinal && !isEvaluatingConstant) { | 596 } else if (element.isFinal && !isEvaluatingConstant) { |
| 591 elementExpression = handler.compileVariable(element); | 597 elementExpression = handler.compileVariable(element); |
| 592 } | 598 } |
| 593 if (elementExpression != null) { | 599 if (elementExpression != null) { |
| 594 result = new AstConstant(context, send, | 600 result = new AstConstant( |
| 601 context, |
| 602 send, |
| 595 new VariableConstantExpression(element), | 603 new VariableConstantExpression(element), |
| 596 handler.getConstantValue(elementExpression)); | 604 handler.getConstantValue(elementExpression)); |
| 597 } | 605 } |
| 598 } else if (Elements.isClass(element) || Elements.isTypedef(element)) { | 606 } else if (Elements.isClass(element) || Elements.isTypedef(element)) { |
| 599 assert(elements.isTypeLiteral(send)); | 607 assert(elements.isTypeLiteral(send)); |
| 600 DartType elementType = elements.getTypeLiteralType(send); | 608 DartType elementType = elements.getTypeLiteralType(send); |
| 601 result = new AstConstant(context, send, | 609 result = new AstConstant( |
| 610 context, |
| 611 send, |
| 602 new TypeConstantExpression(elementType), | 612 new TypeConstantExpression(elementType), |
| 603 makeTypeConstant(elementType)); | 613 makeTypeConstant(elementType)); |
| 604 } else if (send.receiver != null) { | 614 } else if (send.receiver != null) { |
| 605 if (send.selector.asIdentifier().source == "length") { | 615 if (send.selector.asIdentifier().source == "length") { |
| 606 AstConstant left = evaluate(send.receiver); | 616 AstConstant left = evaluate(send.receiver); |
| 607 if (left != null && left.value.isString) { | 617 if (left != null && left.value.isString) { |
| 608 StringConstantValue stringConstantValue = left.value; | 618 StringConstantValue stringConstantValue = left.value; |
| 609 DartString string = stringConstantValue.primitiveValue; | 619 DartString string = stringConstantValue.primitiveValue; |
| 610 IntConstantValue length = constantSystem.createInt(string.length); | 620 IntConstantValue length = constantSystem.createInt(string.length); |
| 611 result = new AstConstant(context, send, | 621 result = new AstConstant(context, send, |
| 612 new StringLengthConstantExpression(left.expression), length); | 622 new StringLengthConstantExpression(left.expression), length); |
| 613 } | 623 } |
| 614 } | 624 } |
| 615 // Fall through to error handling. | 625 // Fall through to error handling. |
| 616 } else if (!Elements.isUnresolved(element) && | 626 } else if (!Elements.isUnresolved(element) && |
| 617 element.isVariable && | 627 element.isVariable && |
| 618 element.isConst) { | 628 element.isConst) { |
| 619 ConstantExpression variableExpression = | 629 ConstantExpression variableExpression = |
| 620 handler.compileConstant(element); | 630 handler.compileConstant(element); |
| 621 if (variableExpression != null) { | 631 if (variableExpression != null) { |
| 622 result = new AstConstant(context, send, | 632 result = new AstConstant( |
| 633 context, |
| 634 send, |
| 623 new VariableConstantExpression(element), | 635 new VariableConstantExpression(element), |
| 624 handler.getConstantValue(variableExpression)); | 636 handler.getConstantValue(variableExpression)); |
| 625 } | 637 } |
| 626 } | 638 } |
| 627 if (result == null) { | 639 if (result == null) { |
| 628 return signalNotCompileTimeConstant(send); | 640 return signalNotCompileTimeConstant(send); |
| 629 } | 641 } |
| 630 if (isDeferredUse(send)) { | 642 if (isDeferredUse(send)) { |
| 631 if (isEvaluatingConstant) { | 643 if (isEvaluatingConstant) { |
| 632 reporter.reportErrorMessage( | 644 reporter.reportErrorMessage( |
| 633 send, MessageKind.DEFERRED_COMPILE_TIME_CONSTANT); | 645 send, MessageKind.DEFERRED_COMPILE_TIME_CONSTANT); |
| 634 } | 646 } |
| 635 PrefixElement prefix = | 647 PrefixElement prefix = |
| 636 compiler.deferredLoadTask.deferredPrefixElement(send, elements); | 648 compiler.deferredLoadTask.deferredPrefixElement(send, elements); |
| 637 result = new AstConstant(context, send, | 649 result = new AstConstant( |
| 650 context, |
| 651 send, |
| 638 new DeferredConstantExpression(result.expression, prefix), | 652 new DeferredConstantExpression(result.expression, prefix), |
| 639 new DeferredConstantValue(result.value, prefix)); | 653 new DeferredConstantValue(result.value, prefix)); |
| 640 compiler.deferredLoadTask.registerConstantDeferredUse( | 654 compiler.deferredLoadTask |
| 641 result.value, prefix); | 655 .registerConstantDeferredUse(result.value, prefix); |
| 642 } | 656 } |
| 643 return result; | 657 return result; |
| 644 } else if (send.isCall) { | 658 } else if (send.isCall) { |
| 645 if (element == compiler.identicalFunction && send.argumentCount() == 2) { | 659 if (element == compiler.identicalFunction && send.argumentCount() == 2) { |
| 646 AstConstant left = evaluate(send.argumentsNode.nodes.head); | 660 AstConstant left = evaluate(send.argumentsNode.nodes.head); |
| 647 AstConstant right = evaluate(send.argumentsNode.nodes.tail.head); | 661 AstConstant right = evaluate(send.argumentsNode.nodes.tail.head); |
| 648 if (left == null || right == null) { | 662 if (left == null || right == null) { |
| 649 return null; | 663 return null; |
| 650 } | 664 } |
| 651 ConstantValue result = | 665 ConstantValue result = |
| 652 constantSystem.identity.fold(left.value, right.value); | 666 constantSystem.identity.fold(left.value, right.value); |
| 653 if (result != null) { | 667 if (result != null) { |
| 654 return new AstConstant(context, send, new IdenticalConstantExpression( | 668 return new AstConstant( |
| 655 left.expression, right.expression), result); | 669 context, |
| 670 send, |
| 671 new IdenticalConstantExpression( |
| 672 left.expression, right.expression), |
| 673 result); |
| 656 } | 674 } |
| 657 } | 675 } |
| 658 return signalNotCompileTimeConstant(send); | 676 return signalNotCompileTimeConstant(send); |
| 659 } else if (send.isPrefix) { | 677 } else if (send.isPrefix) { |
| 660 assert(send.isOperator); | 678 assert(send.isOperator); |
| 661 AstConstant receiverConstant = evaluate(send.receiver); | 679 AstConstant receiverConstant = evaluate(send.receiver); |
| 662 if (receiverConstant == null) { | 680 if (receiverConstant == null) { |
| 663 return null; | 681 return null; |
| 664 } | 682 } |
| 665 Operator node = send.selector; | 683 Operator node = send.selector; |
| 666 UnaryOperator operator = UnaryOperator.parse(node.source); | 684 UnaryOperator operator = UnaryOperator.parse(node.source); |
| 667 UnaryOperation operation = constantSystem.lookupUnary(operator); | 685 UnaryOperation operation = constantSystem.lookupUnary(operator); |
| 668 if (operation == null) { | 686 if (operation == null) { |
| 669 reporter.internalError(send.selector, "Unexpected operator."); | 687 reporter.internalError(send.selector, "Unexpected operator."); |
| 670 } | 688 } |
| 671 ConstantValue folded = operation.fold(receiverConstant.value); | 689 ConstantValue folded = operation.fold(receiverConstant.value); |
| 672 if (folded == null) { | 690 if (folded == null) { |
| 673 return signalNotCompileTimeConstant(send); | 691 return signalNotCompileTimeConstant(send); |
| 674 } | 692 } |
| 675 return new AstConstant(context, send, | 693 return new AstConstant( |
| 694 context, |
| 695 send, |
| 676 new UnaryConstantExpression(operator, receiverConstant.expression), | 696 new UnaryConstantExpression(operator, receiverConstant.expression), |
| 677 folded); | 697 folded); |
| 678 } else if (send.isOperator && !send.isPostfix) { | 698 } else if (send.isOperator && !send.isPostfix) { |
| 679 assert(send.argumentCount() == 1); | 699 assert(send.argumentCount() == 1); |
| 680 AstConstant left = evaluate(send.receiver); | 700 AstConstant left = evaluate(send.receiver); |
| 681 AstConstant right = evaluate(send.argumentsNode.nodes.head); | 701 AstConstant right = evaluate(send.argumentsNode.nodes.head); |
| 682 if (left == null || right == null) { | 702 if (left == null || right == null) { |
| 683 return null; | 703 return null; |
| 684 } | 704 } |
| 685 ConstantValue leftValue = left.value; | 705 ConstantValue leftValue = left.value; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 709 default: | 729 default: |
| 710 BinaryOperation operation = constantSystem.lookupBinary(operator); | 730 BinaryOperation operation = constantSystem.lookupBinary(operator); |
| 711 if (operation != null) { | 731 if (operation != null) { |
| 712 folded = operation.fold(leftValue, rightValue); | 732 folded = operation.fold(leftValue, rightValue); |
| 713 } | 733 } |
| 714 } | 734 } |
| 715 } | 735 } |
| 716 if (folded == null) { | 736 if (folded == null) { |
| 717 return signalNotCompileTimeConstant(send); | 737 return signalNotCompileTimeConstant(send); |
| 718 } | 738 } |
| 719 return new AstConstant(context, send, new BinaryConstantExpression( | 739 return new AstConstant( |
| 720 left.expression, operator, right.expression), folded); | 740 context, |
| 741 send, |
| 742 new BinaryConstantExpression( |
| 743 left.expression, operator, right.expression), |
| 744 folded); |
| 721 } | 745 } |
| 722 return signalNotCompileTimeConstant(send); | 746 return signalNotCompileTimeConstant(send); |
| 723 } | 747 } |
| 724 | 748 |
| 725 AstConstant visitConditional(Conditional node) { | 749 AstConstant visitConditional(Conditional node) { |
| 726 AstConstant condition = evaluate(node.condition); | 750 AstConstant condition = evaluate(node.condition); |
| 727 if (condition == null) { | 751 if (condition == null) { |
| 728 return null; | 752 return null; |
| 729 } else if (!condition.value.isBool) { | 753 } else if (!condition.value.isBool) { |
| 730 DartType conditionType = condition.value.getType(coreTypes); | 754 DartType conditionType = condition.value.getType(coreTypes); |
| 731 if (isEvaluatingConstant) { | 755 if (isEvaluatingConstant) { |
| 732 reporter.reportErrorMessage( | 756 reporter.reportErrorMessage(node.condition, MessageKind.NOT_ASSIGNABLE, |
| 733 node.condition, | 757 {'fromType': conditionType, 'toType': coreTypes.boolType}); |
| 734 MessageKind.NOT_ASSIGNABLE, | |
| 735 {'fromType': conditionType, | |
| 736 'toType': coreTypes.boolType}); | |
| 737 return new ErroneousAstConstant(context, node); | 758 return new ErroneousAstConstant(context, node); |
| 738 } | 759 } |
| 739 return null; | 760 return null; |
| 740 } | 761 } |
| 741 AstConstant thenExpression = evaluate(node.thenExpression); | 762 AstConstant thenExpression = evaluate(node.thenExpression); |
| 742 AstConstant elseExpression = evaluate(node.elseExpression); | 763 AstConstant elseExpression = evaluate(node.elseExpression); |
| 743 if (thenExpression == null || elseExpression == null) { | 764 if (thenExpression == null || elseExpression == null) { |
| 744 return null; | 765 return null; |
| 745 } | 766 } |
| 746 BoolConstantValue boolCondition = condition.value; | 767 BoolConstantValue boolCondition = condition.value; |
| 747 return new AstConstant(context, node, new ConditionalConstantExpression( | 768 return new AstConstant( |
| 748 condition.expression, thenExpression.expression, | 769 context, |
| 749 elseExpression.expression), boolCondition.primitiveValue | 770 node, |
| 750 ? thenExpression.value | 771 new ConditionalConstantExpression(condition.expression, |
| 751 : elseExpression.value); | 772 thenExpression.expression, elseExpression.expression), |
| 773 boolCondition.primitiveValue |
| 774 ? thenExpression.value |
| 775 : elseExpression.value); |
| 752 } | 776 } |
| 753 | 777 |
| 754 AstConstant visitSendSet(SendSet node) { | 778 AstConstant visitSendSet(SendSet node) { |
| 755 return signalNotCompileTimeConstant(node); | 779 return signalNotCompileTimeConstant(node); |
| 756 } | 780 } |
| 757 | 781 |
| 758 /** | 782 /** |
| 759 * Returns the normalized list of constant arguments that are passed to the | 783 * Returns the normalized list of constant arguments that are passed to the |
| 760 * constructor including both the concrete arguments and default values for | 784 * constructor including both the concrete arguments and default values for |
| 761 * omitted optional arguments. | 785 * omitted optional arguments. |
| 762 * | 786 * |
| 763 * Invariant: [target] must be an implementation element. | 787 * Invariant: [target] must be an implementation element. |
| 764 */ | 788 */ |
| 765 List<AstConstant> evaluateArgumentsToConstructor(Node node, | 789 List<AstConstant> evaluateArgumentsToConstructor( |
| 766 CallStructure callStructure, Link<Node> arguments, | 790 Node node, |
| 767 ConstructorElement target, {AstConstant compileArgument(Node node)}) { | 791 CallStructure callStructure, |
| 792 Link<Node> arguments, |
| 793 ConstructorElement target, |
| 794 {AstConstant compileArgument(Node node)}) { |
| 768 assert(invariant(node, target.isImplementation)); | 795 assert(invariant(node, target.isImplementation)); |
| 769 | 796 |
| 770 AstConstant compileDefaultValue(VariableElement element) { | 797 AstConstant compileDefaultValue(VariableElement element) { |
| 771 ConstantExpression constant = handler.compileConstant(element); | 798 ConstantExpression constant = handler.compileConstant(element); |
| 772 return new AstConstant.fromDefaultValue( | 799 return new AstConstant.fromDefaultValue( |
| 773 element, constant, handler.getConstantValue(constant)); | 800 element, constant, handler.getConstantValue(constant)); |
| 774 } | 801 } |
| 775 target.computeType(resolution); | 802 target.computeType(resolution); |
| 776 | 803 |
| 777 FunctionSignature signature = target.functionSignature; | 804 FunctionSignature signature = target.functionSignature; |
| 778 if (!callStructure.signatureApplies(signature)) { | 805 if (!callStructure.signatureApplies(signature)) { |
| 779 String name = Elements.constructorNameForDiagnostics( | 806 String name = Elements.constructorNameForDiagnostics( |
| 780 target.enclosingClass.name, target.name); | 807 target.enclosingClass.name, target.name); |
| 781 reporter.reportErrorMessage( | 808 reporter.reportErrorMessage(node, |
| 782 node, MessageKind.INVALID_CONSTRUCTOR_ARGUMENTS, | 809 MessageKind.INVALID_CONSTRUCTOR_ARGUMENTS, {'constructorName': name}); |
| 783 {'constructorName': name}); | |
| 784 | 810 |
| 785 return new List<AstConstant>.filled( | 811 return new List<AstConstant>.filled( |
| 786 target.functionSignature.parameterCount, | 812 target.functionSignature.parameterCount, |
| 787 new ErroneousAstConstant(context, node)); | 813 new ErroneousAstConstant(context, node)); |
| 788 } | 814 } |
| 789 return callStructure.makeArgumentsList( | 815 return callStructure.makeArgumentsList( |
| 790 arguments, target, compileArgument, compileDefaultValue); | 816 arguments, target, compileArgument, compileDefaultValue); |
| 791 } | 817 } |
| 792 | 818 |
| 793 AstConstant visitNewExpression(NewExpression node) { | 819 AstConstant visitNewExpression(NewExpression node) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 827 // a post-process action, so we have to make sure it is done here. | 853 // a post-process action, so we have to make sure it is done here. |
| 828 compiler.resolver.resolveRedirectionChain(constructor, node); | 854 compiler.resolver.resolveRedirectionChain(constructor, node); |
| 829 | 855 |
| 830 bool isInvalid = false; | 856 bool isInvalid = false; |
| 831 InterfaceType constructedType = type; | 857 InterfaceType constructedType = type; |
| 832 ConstructorElement implementation; | 858 ConstructorElement implementation; |
| 833 if (constructor.isRedirectingFactory) { | 859 if (constructor.isRedirectingFactory) { |
| 834 if (constructor.isEffectiveTargetMalformed) { | 860 if (constructor.isEffectiveTargetMalformed) { |
| 835 isInvalid = true; | 861 isInvalid = true; |
| 836 } else { | 862 } else { |
| 837 constructedType = | 863 constructedType = constructor.computeEffectiveTargetType(type); |
| 838 constructor.computeEffectiveTargetType(type); | |
| 839 ConstructorElement target = constructor.effectiveTarget; | 864 ConstructorElement target = constructor.effectiveTarget; |
| 840 // The constructor must be an implementation to ensure that field | 865 // The constructor must be an implementation to ensure that field |
| 841 // initializers are handled correctly. | 866 // initializers are handled correctly. |
| 842 implementation = target.implementation; | 867 implementation = target.implementation; |
| 843 } | 868 } |
| 844 } else { | 869 } else { |
| 845 // The constructor must be an implementation to ensure that field | 870 // The constructor must be an implementation to ensure that field |
| 846 // initializers are handled correctly. | 871 // initializers are handled correctly. |
| 847 implementation = constructor.implementation; | 872 implementation = constructor.implementation; |
| 848 isInvalid = implementation.isMalformed; | 873 isInvalid = implementation.isMalformed; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 875 assert(normalizedArguments != null); | 900 assert(normalizedArguments != null); |
| 876 concreteArguments = normalizedArguments; | 901 concreteArguments = normalizedArguments; |
| 877 } | 902 } |
| 878 | 903 |
| 879 if (constructor == compiler.intEnvironment || | 904 if (constructor == compiler.intEnvironment || |
| 880 constructor == compiler.boolEnvironment || | 905 constructor == compiler.boolEnvironment || |
| 881 constructor == compiler.stringEnvironment) { | 906 constructor == compiler.stringEnvironment) { |
| 882 return createFromEnvironmentConstant(node, constructedType, constructor, | 907 return createFromEnvironmentConstant(node, constructedType, constructor, |
| 883 callStructure, normalizedArguments, concreteArguments); | 908 callStructure, normalizedArguments, concreteArguments); |
| 884 } else { | 909 } else { |
| 885 return makeConstructedConstant(compiler, handler, context, node, type, | 910 return makeConstructedConstant( |
| 886 constructor, constructedType, implementation, callStructure, | 911 compiler, |
| 887 concreteArguments, normalizedArguments); | 912 handler, |
| 913 context, |
| 914 node, |
| 915 type, |
| 916 constructor, |
| 917 constructedType, |
| 918 implementation, |
| 919 callStructure, |
| 920 concreteArguments, |
| 921 normalizedArguments); |
| 888 } | 922 } |
| 889 } | 923 } |
| 890 | 924 |
| 891 AstConstant createFromEnvironmentConstant(Node node, InterfaceType type, | 925 AstConstant createFromEnvironmentConstant( |
| 892 ConstructorElement constructor, CallStructure callStructure, | 926 Node node, |
| 927 InterfaceType type, |
| 928 ConstructorElement constructor, |
| 929 CallStructure callStructure, |
| 893 List<AstConstant> normalizedArguments, | 930 List<AstConstant> normalizedArguments, |
| 894 List<AstConstant> concreteArguments) { | 931 List<AstConstant> concreteArguments) { |
| 895 var firstArgument = normalizedArguments[0].value; | 932 var firstArgument = normalizedArguments[0].value; |
| 896 ConstantValue defaultValue = normalizedArguments[1].value; | 933 ConstantValue defaultValue = normalizedArguments[1].value; |
| 897 | 934 |
| 898 if (firstArgument.isNull) { | 935 if (firstArgument.isNull) { |
| 899 reporter.reportErrorMessage( | 936 reporter.reportErrorMessage( |
| 900 normalizedArguments[0].node, MessageKind.NULL_NOT_ALLOWED); | 937 normalizedArguments[0].node, MessageKind.NULL_NOT_ALLOWED); |
| 901 return null; | 938 return null; |
| 902 } | 939 } |
| 903 | 940 |
| 904 if (!firstArgument.isString) { | 941 if (!firstArgument.isString) { |
| 905 DartType type = defaultValue.getType(coreTypes); | 942 DartType type = defaultValue.getType(coreTypes); |
| 906 reporter.reportErrorMessage( | 943 reporter.reportErrorMessage( |
| 907 normalizedArguments[0].node, | 944 normalizedArguments[0].node, |
| 908 MessageKind.NOT_ASSIGNABLE, | 945 MessageKind.NOT_ASSIGNABLE, |
| 909 {'fromType': type, | 946 {'fromType': type, 'toType': coreTypes.stringType}); |
| 910 'toType': coreTypes.stringType}); | |
| 911 return null; | 947 return null; |
| 912 } | 948 } |
| 913 | 949 |
| 914 if (constructor == compiler.intEnvironment && | 950 if (constructor == compiler.intEnvironment && |
| 915 !(defaultValue.isNull || defaultValue.isInt)) { | 951 !(defaultValue.isNull || defaultValue.isInt)) { |
| 916 DartType type = defaultValue.getType(coreTypes); | 952 DartType type = defaultValue.getType(coreTypes); |
| 917 reporter.reportErrorMessage( | 953 reporter.reportErrorMessage( |
| 918 normalizedArguments[1].node, | 954 normalizedArguments[1].node, |
| 919 MessageKind.NOT_ASSIGNABLE, | 955 MessageKind.NOT_ASSIGNABLE, |
| 920 {'fromType': type, | 956 {'fromType': type, 'toType': coreTypes.intType}); |
| 921 'toType': coreTypes.intType}); | |
| 922 return null; | 957 return null; |
| 923 } | 958 } |
| 924 | 959 |
| 925 if (constructor == compiler.boolEnvironment && | 960 if (constructor == compiler.boolEnvironment && |
| 926 !(defaultValue.isNull || defaultValue.isBool)) { | 961 !(defaultValue.isNull || defaultValue.isBool)) { |
| 927 DartType type = defaultValue.getType(coreTypes); | 962 DartType type = defaultValue.getType(coreTypes); |
| 928 reporter.reportErrorMessage( | 963 reporter.reportErrorMessage( |
| 929 normalizedArguments[1].node, | 964 normalizedArguments[1].node, |
| 930 MessageKind.NOT_ASSIGNABLE, | 965 MessageKind.NOT_ASSIGNABLE, |
| 931 {'fromType': type, | 966 {'fromType': type, 'toType': coreTypes.boolType}); |
| 932 'toType': coreTypes.boolType}); | |
| 933 return null; | 967 return null; |
| 934 } | 968 } |
| 935 | 969 |
| 936 if (constructor == compiler.stringEnvironment && | 970 if (constructor == compiler.stringEnvironment && |
| 937 !(defaultValue.isNull || defaultValue.isString)) { | 971 !(defaultValue.isNull || defaultValue.isString)) { |
| 938 DartType type = defaultValue.getType(coreTypes); | 972 DartType type = defaultValue.getType(coreTypes); |
| 939 reporter.reportErrorMessage( | 973 reporter.reportErrorMessage( |
| 940 normalizedArguments[1].node, | 974 normalizedArguments[1].node, |
| 941 MessageKind.NOT_ASSIGNABLE, | 975 MessageKind.NOT_ASSIGNABLE, |
| 942 {'fromType': type, | 976 {'fromType': type, 'toType': coreTypes.stringType}); |
| 943 'toType': coreTypes.stringType}); | |
| 944 return null; | 977 return null; |
| 945 } | 978 } |
| 946 | 979 |
| 947 String name = firstArgument.primitiveValue.slowToString(); | 980 String name = firstArgument.primitiveValue.slowToString(); |
| 948 String value = compiler.fromEnvironment(name); | 981 String value = compiler.fromEnvironment(name); |
| 949 | 982 |
| 950 AstConstant createEvaluatedConstant(ConstantValue value) { | 983 AstConstant createEvaluatedConstant(ConstantValue value) { |
| 951 ConstantExpression expression; | 984 ConstantExpression expression; |
| 952 ConstantExpression name = concreteArguments[0].expression; | 985 ConstantExpression name = concreteArguments[0].expression; |
| 953 ConstantExpression defaultValue; | 986 ConstantExpression defaultValue; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 982 } else { | 1015 } else { |
| 983 return createEvaluatedConstant(defaultValue); | 1016 return createEvaluatedConstant(defaultValue); |
| 984 } | 1017 } |
| 985 } else { | 1018 } else { |
| 986 assert(constructor == compiler.stringEnvironment); | 1019 assert(constructor == compiler.stringEnvironment); |
| 987 return createEvaluatedConstant( | 1020 return createEvaluatedConstant( |
| 988 constantSystem.createString(new DartString.literal(value))); | 1021 constantSystem.createString(new DartString.literal(value))); |
| 989 } | 1022 } |
| 990 } | 1023 } |
| 991 | 1024 |
| 992 static AstConstant makeConstructedConstant(Compiler compiler, | 1025 static AstConstant makeConstructedConstant( |
| 993 ConstantCompilerBase handler, Element context, Node node, | 1026 Compiler compiler, |
| 994 InterfaceType type, ConstructorElement constructor, | 1027 ConstantCompilerBase handler, |
| 995 InterfaceType constructedType, ConstructorElement target, | 1028 Element context, |
| 996 CallStructure callStructure, List<AstConstant> concreteArguments, | 1029 Node node, |
| 1030 InterfaceType type, |
| 1031 ConstructorElement constructor, |
| 1032 InterfaceType constructedType, |
| 1033 ConstructorElement target, |
| 1034 CallStructure callStructure, |
| 1035 List<AstConstant> concreteArguments, |
| 997 List<AstConstant> normalizedArguments) { | 1036 List<AstConstant> normalizedArguments) { |
| 998 if (target.isRedirectingFactory) { | 1037 if (target.isRedirectingFactory) { |
| 999 // This happens is case of cyclic redirection. | 1038 // This happens is case of cyclic redirection. |
| 1000 assert(invariant(node, compiler.compilationFailed, | 1039 assert(invariant(node, compiler.compilationFailed, |
| 1001 message: "makeConstructedConstant can only be called with the " | 1040 message: "makeConstructedConstant can only be called with the " |
| 1002 "effective target: $constructor")); | 1041 "effective target: $constructor")); |
| 1003 return new ErroneousAstConstant(context, node); | 1042 return new ErroneousAstConstant(context, node); |
| 1004 } | 1043 } |
| 1005 assert(invariant(node, | 1044 assert(invariant( |
| 1045 node, |
| 1006 callStructure.signatureApplies(constructor.functionSignature) || | 1046 callStructure.signatureApplies(constructor.functionSignature) || |
| 1007 compiler.compilationFailed, | 1047 compiler.compilationFailed, |
| 1008 message: "Call structure $callStructure does not apply to constructor " | 1048 message: "Call structure $callStructure does not apply to constructor " |
| 1009 "$constructor.")); | 1049 "$constructor.")); |
| 1010 | 1050 |
| 1011 ConstructorEvaluator evaluator = | 1051 ConstructorEvaluator evaluator = |
| 1012 new ConstructorEvaluator(constructedType, target, handler, compiler); | 1052 new ConstructorEvaluator(constructedType, target, handler, compiler); |
| 1013 evaluator.evaluateConstructorFieldValues(normalizedArguments); | 1053 evaluator.evaluateConstructorFieldValues(normalizedArguments); |
| 1014 Map<FieldElement, AstConstant> fieldConstants = | 1054 Map<FieldElement, AstConstant> fieldConstants = |
| 1015 evaluator.buildFieldConstants(target.enclosingClass); | 1055 evaluator.buildFieldConstants(target.enclosingClass); |
| 1016 Map<FieldElement, ConstantValue> fieldValues = | 1056 Map<FieldElement, ConstantValue> fieldValues = |
| 1017 <FieldElement, ConstantValue>{}; | 1057 <FieldElement, ConstantValue>{}; |
| 1018 fieldConstants.forEach((FieldElement field, AstConstant astConstant) { | 1058 fieldConstants.forEach((FieldElement field, AstConstant astConstant) { |
| 1019 fieldValues[field] = astConstant.value; | 1059 fieldValues[field] = astConstant.value; |
| 1020 }); | 1060 }); |
| 1021 return new AstConstant(context, node, new ConstructedConstantExpression( | 1061 return new AstConstant( |
| 1022 type, constructor, callStructure, | 1062 context, |
| 1063 node, |
| 1064 new ConstructedConstantExpression(type, constructor, callStructure, |
| 1023 concreteArguments.map((e) => e.expression).toList()), | 1065 concreteArguments.map((e) => e.expression).toList()), |
| 1024 new ConstructedConstantValue(constructedType, fieldValues)); | 1066 new ConstructedConstantValue(constructedType, fieldValues)); |
| 1025 } | 1067 } |
| 1026 | 1068 |
| 1027 AstConstant visitParenthesizedExpression(ParenthesizedExpression node) { | 1069 AstConstant visitParenthesizedExpression(ParenthesizedExpression node) { |
| 1028 return node.expression.accept(this); | 1070 return node.expression.accept(this); |
| 1029 } | 1071 } |
| 1030 | 1072 |
| 1031 AstConstant signalNotCompileTimeConstant(Node node, | 1073 AstConstant signalNotCompileTimeConstant(Node node, |
| 1032 {MessageKind message: MessageKind.NOT_A_COMPILE_TIME_CONSTANT}) { | 1074 {MessageKind message: MessageKind.NOT_A_COMPILE_TIME_CONSTANT}) { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1078 return super.visitSend(send); | 1120 return super.visitSend(send); |
| 1079 } | 1121 } |
| 1080 | 1122 |
| 1081 void potentiallyCheckType(TypedElement element, AstConstant constant) { | 1123 void potentiallyCheckType(TypedElement element, AstConstant constant) { |
| 1082 if (compiler.options.enableTypeAssertions) { | 1124 if (compiler.options.enableTypeAssertions) { |
| 1083 DartType elementType = element.type.substByContext(constructedType); | 1125 DartType elementType = element.type.substByContext(constructedType); |
| 1084 DartType constantType = constant.value.getType(coreTypes); | 1126 DartType constantType = constant.value.getType(coreTypes); |
| 1085 if (!constantSystem.isSubtype( | 1127 if (!constantSystem.isSubtype( |
| 1086 compiler.types, constantType, elementType)) { | 1128 compiler.types, constantType, elementType)) { |
| 1087 reporter.withCurrentElement(constant.element, () { | 1129 reporter.withCurrentElement(constant.element, () { |
| 1088 reporter.reportErrorMessage( | 1130 reporter.reportErrorMessage(constant.node, MessageKind.NOT_ASSIGNABLE, |
| 1089 constant.node, | 1131 {'fromType': constantType, 'toType': elementType}); |
| 1090 MessageKind.NOT_ASSIGNABLE, | |
| 1091 {'fromType': constantType, | |
| 1092 'toType': elementType}); | |
| 1093 }); | 1132 }); |
| 1094 } | 1133 } |
| 1095 } | 1134 } |
| 1096 } | 1135 } |
| 1097 | 1136 |
| 1098 void updateFieldValue(Node node, TypedElement element, AstConstant constant) { | 1137 void updateFieldValue(Node node, TypedElement element, AstConstant constant) { |
| 1099 potentiallyCheckType(element, constant); | 1138 potentiallyCheckType(element, constant); |
| 1100 fieldValues[element] = constant; | 1139 fieldValues[element] = constant; |
| 1101 } | 1140 } |
| 1102 | 1141 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1120 potentiallyCheckType(parameter, argument); | 1159 potentiallyCheckType(parameter, argument); |
| 1121 definitions[parameter] = argument; | 1160 definitions[parameter] = argument; |
| 1122 } | 1161 } |
| 1123 }); | 1162 }); |
| 1124 } | 1163 } |
| 1125 | 1164 |
| 1126 void evaluateSuperOrRedirectSend( | 1165 void evaluateSuperOrRedirectSend( |
| 1127 List<AstConstant> compiledArguments, FunctionElement targetConstructor) { | 1166 List<AstConstant> compiledArguments, FunctionElement targetConstructor) { |
| 1128 ConstructorEvaluator evaluator = new ConstructorEvaluator( | 1167 ConstructorEvaluator evaluator = new ConstructorEvaluator( |
| 1129 constructedType.asInstanceOf(targetConstructor.enclosingClass), | 1168 constructedType.asInstanceOf(targetConstructor.enclosingClass), |
| 1130 targetConstructor, handler, compiler); | 1169 targetConstructor, |
| 1170 handler, |
| 1171 compiler); |
| 1131 evaluator.evaluateConstructorFieldValues(compiledArguments); | 1172 evaluator.evaluateConstructorFieldValues(compiledArguments); |
| 1132 // Copy over the fieldValues from the super/redirect-constructor. | 1173 // Copy over the fieldValues from the super/redirect-constructor. |
| 1133 // No need to go through [updateFieldValue] because the | 1174 // No need to go through [updateFieldValue] because the |
| 1134 // assignments have already been checked in checked mode. | 1175 // assignments have already been checked in checked mode. |
| 1135 evaluator.fieldValues.forEach((key, value) => fieldValues[key] = value); | 1176 evaluator.fieldValues.forEach((key, value) => fieldValues[key] = value); |
| 1136 } | 1177 } |
| 1137 | 1178 |
| 1138 /** | 1179 /** |
| 1139 * Runs through the initializers of the given [constructor] and updates | 1180 * Runs through the initializers of the given [constructor] and updates |
| 1140 * the [fieldValues] map. | 1181 * the [fieldValues] map. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1161 !link.isEmpty; | 1202 !link.isEmpty; |
| 1162 link = link.tail) { | 1203 link = link.tail) { |
| 1163 assert(link.head is Send); | 1204 assert(link.head is Send); |
| 1164 if (link.head is! SendSet) { | 1205 if (link.head is! SendSet) { |
| 1165 // A super initializer or constructor redirection. | 1206 // A super initializer or constructor redirection. |
| 1166 Send call = link.head; | 1207 Send call = link.head; |
| 1167 FunctionElement target = elements[call]; | 1208 FunctionElement target = elements[call]; |
| 1168 if (!target.isMalformed) { | 1209 if (!target.isMalformed) { |
| 1169 List<AstConstant> compiledArguments = | 1210 List<AstConstant> compiledArguments = |
| 1170 evaluateArgumentsToConstructor( | 1211 evaluateArgumentsToConstructor( |
| 1171 call, | 1212 call, |
| 1172 elements.getSelector(call).callStructure, | 1213 elements.getSelector(call).callStructure, |
| 1173 call.arguments, | 1214 call.arguments, |
| 1174 target, | 1215 target, |
| 1175 compileArgument: evaluateConstant); | 1216 compileArgument: evaluateConstant); |
| 1176 evaluateSuperOrRedirectSend(compiledArguments, target); | 1217 evaluateSuperOrRedirectSend(compiledArguments, target); |
| 1177 } | 1218 } |
| 1178 foundSuperOrRedirect = true; | 1219 foundSuperOrRedirect = true; |
| 1179 } else { | 1220 } else { |
| 1180 // A field initializer. | 1221 // A field initializer. |
| 1181 SendSet init = link.head; | 1222 SendSet init = link.head; |
| 1182 Link<Node> initArguments = init.arguments; | 1223 Link<Node> initArguments = init.arguments; |
| 1183 assert(!initArguments.isEmpty && initArguments.tail.isEmpty); | 1224 assert(!initArguments.isEmpty && initArguments.tail.isEmpty); |
| 1184 AstConstant fieldValue = evaluate(initArguments.head); | 1225 AstConstant fieldValue = evaluate(initArguments.head); |
| 1185 updateFieldValue(init, elements[init], fieldValue); | 1226 updateFieldValue(init, elements[init], fieldValue); |
| 1186 } | 1227 } |
| 1187 } | 1228 } |
| 1188 } | 1229 } |
| 1189 | 1230 |
| 1190 if (!foundSuperOrRedirect) { | 1231 if (!foundSuperOrRedirect) { |
| 1191 // No super initializer found. Try to find the default constructor if | 1232 // No super initializer found. Try to find the default constructor if |
| 1192 // the class is not Object. | 1233 // the class is not Object. |
| 1193 ClassElement enclosingClass = constructor.enclosingClass; | 1234 ClassElement enclosingClass = constructor.enclosingClass; |
| 1194 ClassElement superClass = enclosingClass.superclass; | 1235 ClassElement superClass = enclosingClass.superclass; |
| 1195 if (!enclosingClass.isObject) { | 1236 if (!enclosingClass.isObject) { |
| 1196 assert(superClass != null); | 1237 assert(superClass != null); |
| 1197 assert(superClass.isResolved); | 1238 assert(superClass.isResolved); |
| 1198 | 1239 |
| 1199 FunctionElement targetConstructor = | 1240 FunctionElement targetConstructor = |
| 1200 superClass.lookupDefaultConstructor(); | 1241 superClass.lookupDefaultConstructor(); |
| 1201 // If we do not find a default constructor, an error was reported | 1242 // If we do not find a default constructor, an error was reported |
| 1202 // already and compilation will fail anyway. So just ignore that case. | 1243 // already and compilation will fail anyway. So just ignore that case. |
| 1203 if (targetConstructor != null) { | 1244 if (targetConstructor != null) { |
| 1204 List<AstConstant> compiledArguments = evaluateArgumentsToConstructor( | 1245 List<AstConstant> compiledArguments = evaluateArgumentsToConstructor( |
| 1205 functionNode, CallStructure.NO_ARGS, const Link<Node>(), | 1246 functionNode, |
| 1247 CallStructure.NO_ARGS, |
| 1248 const Link<Node>(), |
| 1206 targetConstructor); | 1249 targetConstructor); |
| 1207 evaluateSuperOrRedirectSend(compiledArguments, targetConstructor); | 1250 evaluateSuperOrRedirectSend(compiledArguments, targetConstructor); |
| 1208 } | 1251 } |
| 1209 } | 1252 } |
| 1210 } | 1253 } |
| 1211 } | 1254 } |
| 1212 | 1255 |
| 1213 /** | 1256 /** |
| 1214 * Simulates the execution of the [constructor] with the given | 1257 * Simulates the execution of the [constructor] with the given |
| 1215 * [arguments] to obtain the field values that need to be passed to the | 1258 * [arguments] to obtain the field values that need to be passed to the |
| 1216 * native JavaScript constructor. | 1259 * native JavaScript constructor. |
| 1217 */ | 1260 */ |
| 1218 void evaluateConstructorFieldValues(List<AstConstant> arguments) { | 1261 void evaluateConstructorFieldValues(List<AstConstant> arguments) { |
| 1219 if (constructor.isMalformed) return; | 1262 if (constructor.isMalformed) return; |
| 1220 reporter.withCurrentElement(constructor, () { | 1263 reporter.withCurrentElement(constructor, () { |
| 1221 assignArgumentsToParameters(arguments); | 1264 assignArgumentsToParameters(arguments); |
| 1222 evaluateConstructorInitializers(); | 1265 evaluateConstructorInitializers(); |
| 1223 }); | 1266 }); |
| 1224 } | 1267 } |
| 1225 | 1268 |
| 1226 /// Builds a normalized list of the constant values for each field in the | 1269 /// Builds a normalized list of the constant values for each field in the |
| 1227 /// inheritance chain of [classElement]. | 1270 /// inheritance chain of [classElement]. |
| 1228 Map<FieldElement, AstConstant> buildFieldConstants( | 1271 Map<FieldElement, AstConstant> buildFieldConstants( |
| 1229 ClassElement classElement) { | 1272 ClassElement classElement) { |
| 1230 Map<FieldElement, AstConstant> fieldConstants = <FieldElement, AstConstant>{ | 1273 Map<FieldElement, AstConstant> fieldConstants = |
| 1231 }; | 1274 <FieldElement, AstConstant>{}; |
| 1232 classElement.implementation | 1275 classElement.implementation.forEachInstanceField( |
| 1233 .forEachInstanceField((ClassElement enclosing, FieldElement field) { | 1276 (ClassElement enclosing, FieldElement field) { |
| 1234 AstConstant fieldValue = fieldValues[field]; | 1277 AstConstant fieldValue = fieldValues[field]; |
| 1235 if (fieldValue == null) { | 1278 if (fieldValue == null) { |
| 1236 // Use the default value. | 1279 // Use the default value. |
| 1237 ConstantExpression fieldExpression = | 1280 ConstantExpression fieldExpression = |
| 1238 handler.internalCompileVariable(field, true, false); | 1281 handler.internalCompileVariable(field, true, false); |
| 1239 fieldValue = new AstConstant.fromDefaultValue( | 1282 fieldValue = new AstConstant.fromDefaultValue( |
| 1240 field, fieldExpression, handler.getConstantValue(fieldExpression)); | 1283 field, fieldExpression, handler.getConstantValue(fieldExpression)); |
| 1241 // TODO(het): If the field value doesn't typecheck due to the type | 1284 // TODO(het): If the field value doesn't typecheck due to the type |
| 1242 // variable in the constructor invocation, then report the error on the | 1285 // variable in the constructor invocation, then report the error on the |
| 1243 // invocation rather than the field. | 1286 // invocation rather than the field. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1261 class AstConstant { | 1304 class AstConstant { |
| 1262 final Element element; | 1305 final Element element; |
| 1263 final Node node; | 1306 final Node node; |
| 1264 final ConstantExpression expression; | 1307 final ConstantExpression expression; |
| 1265 final ConstantValue value; | 1308 final ConstantValue value; |
| 1266 | 1309 |
| 1267 AstConstant(this.element, this.node, this.expression, this.value); | 1310 AstConstant(this.element, this.node, this.expression, this.value); |
| 1268 | 1311 |
| 1269 factory AstConstant.fromDefaultValue(VariableElement element, | 1312 factory AstConstant.fromDefaultValue(VariableElement element, |
| 1270 ConstantExpression constant, ConstantValue value) { | 1313 ConstantExpression constant, ConstantValue value) { |
| 1271 return new AstConstant(element, element.initializer != null | 1314 return new AstConstant( |
| 1272 ? element.initializer | 1315 element, |
| 1273 : element.node, constant, value); | 1316 element.initializer != null ? element.initializer : element.node, |
| 1317 constant, |
| 1318 value); |
| 1274 } | 1319 } |
| 1275 | 1320 |
| 1276 String toString() => expression.toString(); | 1321 String toString() => expression.toString(); |
| 1277 } | 1322 } |
| 1278 | 1323 |
| 1279 /// A synthetic constant used to recover from errors. | 1324 /// A synthetic constant used to recover from errors. |
| 1280 class ErroneousAstConstant extends AstConstant { | 1325 class ErroneousAstConstant extends AstConstant { |
| 1281 ErroneousAstConstant(Element element, Node node) : super(element, node, | 1326 ErroneousAstConstant(Element element, Node node) |
| 1282 // TODO(johnniwinther): Return a [NonConstantValue] instead. | 1327 : super( |
| 1283 new ErroneousConstantExpression(), new NullConstantValue()); | 1328 element, |
| 1329 node, |
| 1330 // TODO(johnniwinther): Return a [NonConstantValue] instead. |
| 1331 new ErroneousConstantExpression(), |
| 1332 new NullConstantValue()); |
| 1284 } | 1333 } |
| 1285 | 1334 |
| 1286 // TODO(johnniwinther): Clean this up. | 1335 // TODO(johnniwinther): Clean this up. |
| 1287 TreeElements _analyzeElementEagerly(Compiler compiler, AstElement element) { | 1336 TreeElements _analyzeElementEagerly(Compiler compiler, AstElement element) { |
| 1288 compiler.resolution.computeWorldImpact(element.declaration); | 1337 compiler.resolution.computeWorldImpact(element.declaration); |
| 1289 return element.resolvedAst.elements; | 1338 return element.resolvedAst.elements; |
| 1290 } | 1339 } |
| 1291 | 1340 |
| 1292 class _CompilerEnvironment implements Environment { | 1341 class _CompilerEnvironment implements Environment { |
| 1293 final Compiler compiler; | 1342 final Compiler compiler; |
| 1294 | 1343 |
| 1295 _CompilerEnvironment(this.compiler); | 1344 _CompilerEnvironment(this.compiler); |
| 1296 | 1345 |
| 1297 @override | 1346 @override |
| 1298 String readFromEnvironment(String name) { | 1347 String readFromEnvironment(String name) { |
| 1299 return compiler.fromEnvironment(name); | 1348 return compiler.fromEnvironment(name); |
| 1300 } | 1349 } |
| 1301 } | 1350 } |
| OLD | NEW |