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 Resolution; | 8 import 'common/resolution.dart' show Resolution; |
9 import 'common/tasks.dart' show CompilerTask, Measurer; | 9 import 'common/tasks.dart' show CompilerTask, Measurer; |
10 import 'compiler.dart' show Compiler; | 10 import 'compiler.dart' show Compiler; |
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
407 : this.isEvaluatingConstant = isConst; | 407 : this.isEvaluatingConstant = isConst; |
408 | 408 |
409 ConstantSystem get constantSystem => handler.constantSystem; | 409 ConstantSystem get constantSystem => handler.constantSystem; |
410 Resolution get resolution => compiler.resolution; | 410 Resolution get resolution => compiler.resolution; |
411 CoreTypes get coreTypes => compiler.coreTypes; | 411 CoreTypes get coreTypes => compiler.coreTypes; |
412 DiagnosticReporter get reporter => compiler.reporter; | 412 DiagnosticReporter get reporter => compiler.reporter; |
413 | 413 |
414 AstConstant evaluate(Node node) { | 414 AstConstant evaluate(Node node) { |
415 // TODO(johnniwinther): should there be a visitErrorNode? | 415 // TODO(johnniwinther): should there be a visitErrorNode? |
416 if (node is ErrorNode) return new ErroneousAstConstant(context, node); | 416 if (node is ErrorNode) return new ErroneousAstConstant(context, node); |
417 return node.accept(this); | 417 AstConstant result = node.accept(this); |
| 418 assert(invariant(node, !isEvaluatingConstant || result != null, |
| 419 message: "No AstConstant computed for the node.")); |
| 420 return result; |
418 } | 421 } |
419 | 422 |
420 AstConstant evaluateConstant(Node node) { | 423 AstConstant evaluateConstant(Node node) { |
421 bool oldIsEvaluatingConstant = isEvaluatingConstant; | 424 bool oldIsEvaluatingConstant = isEvaluatingConstant; |
422 isEvaluatingConstant = true; | 425 isEvaluatingConstant = true; |
423 AstConstant result = node.accept(this); | 426 AstConstant result = node.accept(this); |
424 isEvaluatingConstant = oldIsEvaluatingConstant; | 427 isEvaluatingConstant = oldIsEvaluatingConstant; |
425 assert(result != null); | 428 assert(invariant(node, result != null, |
| 429 message: "No AstConstant computed for the node.")); |
426 return result; | 430 return result; |
427 } | 431 } |
428 | 432 |
429 AstConstant visitNode(Node node) { | 433 AstConstant visitNode(Node node) { |
430 return signalNotCompileTimeConstant(node); | 434 return signalNotCompileTimeConstant(node); |
431 } | 435 } |
432 | 436 |
433 AstConstant visitLiteralBool(LiteralBool node) { | 437 AstConstant visitLiteralBool(LiteralBool node) { |
434 return new AstConstant( | 438 return new AstConstant( |
435 context, | 439 context, |
(...skipping 18 matching lines...) Expand all Loading... |
454 AstConstant visitLiteralList(LiteralList node) { | 458 AstConstant visitLiteralList(LiteralList node) { |
455 if (!node.isConst) { | 459 if (!node.isConst) { |
456 return signalNotCompileTimeConstant(node); | 460 return signalNotCompileTimeConstant(node); |
457 } | 461 } |
458 List<ConstantExpression> argumentExpressions = <ConstantExpression>[]; | 462 List<ConstantExpression> argumentExpressions = <ConstantExpression>[]; |
459 List<ConstantValue> argumentValues = <ConstantValue>[]; | 463 List<ConstantValue> argumentValues = <ConstantValue>[]; |
460 for (Link<Node> link = node.elements.nodes; | 464 for (Link<Node> link = node.elements.nodes; |
461 !link.isEmpty; | 465 !link.isEmpty; |
462 link = link.tail) { | 466 link = link.tail) { |
463 AstConstant argument = evaluateConstant(link.head); | 467 AstConstant argument = evaluateConstant(link.head); |
464 if (argument == null) { | 468 if (argument == null || argument.isError) { |
465 return null; | 469 return argument; |
466 } | 470 } |
467 argumentExpressions.add(argument.expression); | 471 argumentExpressions.add(argument.expression); |
468 argumentValues.add(argument.value); | 472 argumentValues.add(argument.value); |
469 } | 473 } |
470 DartType type = elements.getType(node); | 474 DartType type = elements.getType(node); |
471 return new AstConstant( | 475 return new AstConstant( |
472 context, | 476 context, |
473 node, | 477 node, |
474 new ListConstantExpression(type, argumentExpressions), | 478 new ListConstantExpression(type, argumentExpressions), |
475 constantSystem.createList(type, argumentValues)); | 479 constantSystem.createList(type, argumentValues)); |
476 } | 480 } |
477 | 481 |
478 AstConstant visitLiteralMap(LiteralMap node) { | 482 AstConstant visitLiteralMap(LiteralMap node) { |
479 if (!node.isConst) { | 483 if (!node.isConst) { |
480 return signalNotCompileTimeConstant(node); | 484 return signalNotCompileTimeConstant(node); |
481 } | 485 } |
482 List<ConstantExpression> keyExpressions = <ConstantExpression>[]; | 486 List<ConstantExpression> keyExpressions = <ConstantExpression>[]; |
483 List<ConstantExpression> valueExpressions = <ConstantExpression>[]; | 487 List<ConstantExpression> valueExpressions = <ConstantExpression>[]; |
484 List<ConstantValue> keyValues = <ConstantValue>[]; | 488 List<ConstantValue> keyValues = <ConstantValue>[]; |
485 Map<ConstantValue, ConstantValue> map = <ConstantValue, ConstantValue>{}; | 489 Map<ConstantValue, ConstantValue> map = <ConstantValue, ConstantValue>{}; |
486 for (Link<Node> link = node.entries.nodes; | 490 for (Link<Node> link = node.entries.nodes; |
487 !link.isEmpty; | 491 !link.isEmpty; |
488 link = link.tail) { | 492 link = link.tail) { |
489 LiteralMapEntry entry = link.head; | 493 LiteralMapEntry entry = link.head; |
490 AstConstant key = evaluateConstant(entry.key); | 494 AstConstant key = evaluateConstant(entry.key); |
491 if (key == null) { | 495 if (key == null || key.isError) { |
492 return null; | 496 return key; |
493 } | 497 } |
494 AstConstant value = evaluateConstant(entry.value); | 498 AstConstant value = evaluateConstant(entry.value); |
495 if (value == null) { | 499 if (value == null || value.isError) { |
496 return null; | 500 return value; |
497 } | 501 } |
498 if (!map.containsKey(key.value)) { | 502 if (!map.containsKey(key.value)) { |
499 keyValues.add(key.value); | 503 keyValues.add(key.value); |
500 } else { | 504 } else { |
501 reporter.reportWarningMessage( | 505 reporter.reportWarningMessage( |
502 entry.key, MessageKind.EQUAL_MAP_ENTRY_KEY); | 506 entry.key, MessageKind.EQUAL_MAP_ENTRY_KEY); |
503 } | 507 } |
504 keyExpressions.add(key.expression); | 508 keyExpressions.add(key.expression); |
505 valueExpressions.add(value.expression); | 509 valueExpressions.add(value.expression); |
506 map[key.value] = value.value; | 510 map[key.value] = value.value; |
(...skipping 16 matching lines...) Expand all Loading... |
523 return new AstConstant( | 527 return new AstConstant( |
524 context, | 528 context, |
525 node, | 529 node, |
526 new StringConstantExpression(node.dartString.slowToString()), | 530 new StringConstantExpression(node.dartString.slowToString()), |
527 constantSystem.createString(node.dartString)); | 531 constantSystem.createString(node.dartString)); |
528 } | 532 } |
529 | 533 |
530 AstConstant visitStringJuxtaposition(StringJuxtaposition node) { | 534 AstConstant visitStringJuxtaposition(StringJuxtaposition node) { |
531 AstConstant left = evaluate(node.first); | 535 AstConstant left = evaluate(node.first); |
532 AstConstant right = evaluate(node.second); | 536 AstConstant right = evaluate(node.second); |
533 if (left == null || right == null) return null; | 537 if (left == null || left.isError) { |
| 538 return left; |
| 539 } |
| 540 if (right == null || right.isError) { |
| 541 return right; |
| 542 } |
534 StringConstantValue leftValue = left.value; | 543 StringConstantValue leftValue = left.value; |
535 StringConstantValue rightValue = right.value; | 544 StringConstantValue rightValue = right.value; |
536 return new AstConstant( | 545 return new AstConstant( |
537 context, | 546 context, |
538 node, | 547 node, |
539 new ConcatenateConstantExpression([left.expression, right.expression]), | 548 new ConcatenateConstantExpression([left.expression, right.expression]), |
540 constantSystem.createString(new DartString.concat( | 549 constantSystem.createString(new DartString.concat( |
541 leftValue.primitiveValue, rightValue.primitiveValue))); | 550 leftValue.primitiveValue, rightValue.primitiveValue))); |
542 } | 551 } |
543 | 552 |
544 AstConstant visitStringInterpolation(StringInterpolation node) { | 553 AstConstant visitStringInterpolation(StringInterpolation node) { |
545 List<ConstantExpression> subexpressions = <ConstantExpression>[]; | 554 List<ConstantExpression> subexpressions = <ConstantExpression>[]; |
546 AstConstant initialString = evaluate(node.string); | 555 AstConstant initialString = evaluate(node.string); |
547 if (initialString == null) { | 556 if (initialString == null || initialString.isError) { |
548 return null; | 557 return initialString; |
549 } | 558 } |
550 subexpressions.add(initialString.expression); | 559 subexpressions.add(initialString.expression); |
551 StringConstantValue initialStringValue = initialString.value; | 560 StringConstantValue initialStringValue = initialString.value; |
552 DartString accumulator = initialStringValue.primitiveValue; | 561 DartString accumulator = initialStringValue.primitiveValue; |
553 for (StringInterpolationPart part in node.parts) { | 562 for (StringInterpolationPart part in node.parts) { |
554 AstConstant subexpression = evaluate(part.expression); | 563 AstConstant subexpression = evaluate(part.expression); |
555 if (subexpression == null) { | 564 if (subexpression == null || subexpression.isError) { |
556 return null; | 565 return subexpression; |
557 } | 566 } |
558 subexpressions.add(subexpression.expression); | 567 subexpressions.add(subexpression.expression); |
559 ConstantValue expression = subexpression.value; | 568 ConstantValue expression = subexpression.value; |
560 DartString expressionString; | 569 DartString expressionString; |
561 if (expression.isNum || expression.isBool || expression.isNull) { | 570 if (expression.isNum || expression.isBool || expression.isNull) { |
562 PrimitiveConstantValue primitive = expression; | 571 PrimitiveConstantValue primitive = expression; |
563 expressionString = | 572 expressionString = |
564 new DartString.literal(primitive.primitiveValue.toString()); | 573 new DartString.literal(primitive.primitiveValue.toString()); |
565 } else if (expression.isString) { | 574 } else if (expression.isString) { |
566 PrimitiveConstantValue primitive = expression; | 575 PrimitiveConstantValue primitive = expression; |
567 expressionString = primitive.primitiveValue; | 576 expressionString = primitive.primitiveValue; |
568 } else { | 577 } else { |
569 // TODO(johnniwinther): Specialize message to indicated that the problem | 578 // TODO(johnniwinther): Specialize message to indicated that the problem |
570 // is not constness but the types of the const expressions. | 579 // is not constness but the types of the const expressions. |
571 return signalNotCompileTimeConstant(part.expression); | 580 return signalNotCompileTimeConstant(part.expression); |
572 } | 581 } |
573 accumulator = new DartString.concat(accumulator, expressionString); | 582 accumulator = new DartString.concat(accumulator, expressionString); |
574 AstConstant partString = evaluate(part.string); | 583 AstConstant partString = evaluate(part.string); |
575 if (partString == null) return null; | 584 if (partString == null) return null; |
576 subexpressions.add(partString.expression); | 585 subexpressions.add(partString.expression); |
577 StringConstantValue partStringValue = partString.value; | 586 StringConstantValue partStringValue = partString.value; |
578 accumulator = | 587 accumulator = |
579 new DartString.concat(accumulator, partStringValue.primitiveValue); | 588 new DartString.concat(accumulator, partStringValue.primitiveValue); |
580 } | 589 } |
581 ; | |
582 return new AstConstant( | 590 return new AstConstant( |
583 context, | 591 context, |
584 node, | 592 node, |
585 new ConcatenateConstantExpression(subexpressions), | 593 new ConcatenateConstantExpression(subexpressions), |
586 constantSystem.createString(accumulator)); | 594 constantSystem.createString(accumulator)); |
587 } | 595 } |
588 | 596 |
589 AstConstant visitLiteralSymbol(LiteralSymbol node) { | 597 AstConstant visitLiteralSymbol(LiteralSymbol node) { |
590 InterfaceType type = coreTypes.symbolType; | 598 InterfaceType type = coreTypes.symbolType; |
591 String text = node.slowNameString; | 599 String text = node.slowNameString; |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
718 send, | 726 send, |
719 new IdenticalConstantExpression( | 727 new IdenticalConstantExpression( |
720 left.expression, right.expression), | 728 left.expression, right.expression), |
721 result); | 729 result); |
722 } | 730 } |
723 } | 731 } |
724 return signalNotCompileTimeConstant(send); | 732 return signalNotCompileTimeConstant(send); |
725 } else if (send.isPrefix) { | 733 } else if (send.isPrefix) { |
726 assert(send.isOperator); | 734 assert(send.isOperator); |
727 AstConstant receiverConstant = evaluate(send.receiver); | 735 AstConstant receiverConstant = evaluate(send.receiver); |
728 if (receiverConstant == null) { | 736 if (receiverConstant == null || receiverConstant.isError) { |
729 return null; | 737 return receiverConstant; |
730 } | 738 } |
731 Operator node = send.selector; | 739 Operator node = send.selector; |
732 UnaryOperator operator = UnaryOperator.parse(node.source); | 740 UnaryOperator operator = UnaryOperator.parse(node.source); |
733 UnaryOperation operation = constantSystem.lookupUnary(operator); | 741 UnaryOperation operation = constantSystem.lookupUnary(operator); |
734 if (operation == null) { | 742 if (operation == null) { |
735 reporter.internalError(send.selector, "Unexpected operator."); | 743 reporter.internalError(send.selector, "Unexpected operator."); |
736 } | 744 } |
737 ConstantValue folded = operation.fold(receiverConstant.value); | 745 ConstantValue folded = operation.fold(receiverConstant.value); |
738 if (folded == null) { | 746 if (folded == null) { |
739 return signalNotCompileTimeConstant(send); | 747 return signalNotCompileTimeConstant(send); |
740 } | 748 } |
741 return new AstConstant( | 749 return new AstConstant( |
742 context, | 750 context, |
743 send, | 751 send, |
744 new UnaryConstantExpression(operator, receiverConstant.expression), | 752 new UnaryConstantExpression(operator, receiverConstant.expression), |
745 folded); | 753 folded); |
746 } else if (send.isOperator && !send.isPostfix) { | 754 } else if (send.isOperator && !send.isPostfix) { |
747 assert(send.argumentCount() == 1); | 755 assert(send.argumentCount() == 1); |
748 AstConstant left = evaluate(send.receiver); | 756 AstConstant left = evaluate(send.receiver); |
749 AstConstant right = evaluate(send.argumentsNode.nodes.head); | 757 AstConstant right = evaluate(send.argumentsNode.nodes.head); |
750 if (left == null || right == null) { | 758 if (left == null || left.isError) { |
751 return null; | 759 return left; |
| 760 } |
| 761 if (right == null || right.isError) { |
| 762 return right; |
752 } | 763 } |
753 ConstantValue leftValue = left.value; | 764 ConstantValue leftValue = left.value; |
754 ConstantValue rightValue = right.value; | 765 ConstantValue rightValue = right.value; |
755 Operator node = send.selector.asOperator(); | 766 Operator node = send.selector.asOperator(); |
756 BinaryOperator operator = BinaryOperator.parse(node.source); | 767 BinaryOperator operator = BinaryOperator.parse(node.source); |
757 ConstantValue folded = null; | 768 ConstantValue folded = null; |
758 // operator is null when `node=="is"` | 769 // operator is null when `node=="is"` |
759 if (operator != null) { | 770 if (operator != null) { |
760 switch (operator.kind) { | 771 switch (operator.kind) { |
761 case BinaryOperatorKind.EQ: | 772 case BinaryOperatorKind.EQ: |
(...skipping 27 matching lines...) Expand all Loading... |
789 send, | 800 send, |
790 new BinaryConstantExpression( | 801 new BinaryConstantExpression( |
791 left.expression, operator, right.expression), | 802 left.expression, operator, right.expression), |
792 folded); | 803 folded); |
793 } | 804 } |
794 return signalNotCompileTimeConstant(send); | 805 return signalNotCompileTimeConstant(send); |
795 } | 806 } |
796 | 807 |
797 AstConstant visitConditional(Conditional node) { | 808 AstConstant visitConditional(Conditional node) { |
798 AstConstant condition = evaluate(node.condition); | 809 AstConstant condition = evaluate(node.condition); |
799 if (condition == null) { | 810 if (condition == null || condition.isError) { |
800 return null; | 811 return condition; |
801 } else if (!condition.value.isBool) { | 812 } else if (!condition.value.isBool) { |
802 DartType conditionType = condition.value.getType(coreTypes); | 813 DartType conditionType = condition.value.getType(coreTypes); |
803 if (isEvaluatingConstant) { | 814 if (isEvaluatingConstant) { |
804 reporter.reportErrorMessage(node.condition, MessageKind.NOT_ASSIGNABLE, | 815 reporter.reportErrorMessage(node.condition, MessageKind.NOT_ASSIGNABLE, |
805 {'fromType': conditionType, 'toType': coreTypes.boolType}); | 816 {'fromType': conditionType, 'toType': coreTypes.boolType}); |
806 return new ErroneousAstConstant(context, node); | 817 return new ErroneousAstConstant(context, node); |
807 } | 818 } |
808 return null; | 819 return null; |
809 } | 820 } |
810 AstConstant thenExpression = evaluate(node.thenExpression); | 821 AstConstant thenExpression = evaluate(node.thenExpression); |
811 AstConstant elseExpression = evaluate(node.elseExpression); | 822 AstConstant elseExpression = evaluate(node.elseExpression); |
812 if (thenExpression == null || elseExpression == null) { | 823 if (thenExpression == null || thenExpression.isError) { |
813 return null; | 824 return thenExpression; |
| 825 } |
| 826 if (elseExpression == null || elseExpression.isError) { |
| 827 return elseExpression; |
814 } | 828 } |
815 BoolConstantValue boolCondition = condition.value; | 829 BoolConstantValue boolCondition = condition.value; |
816 return new AstConstant( | 830 return new AstConstant( |
817 context, | 831 context, |
818 node, | 832 node, |
819 new ConditionalConstantExpression(condition.expression, | 833 new ConditionalConstantExpression(condition.expression, |
820 thenExpression.expression, elseExpression.expression), | 834 thenExpression.expression, elseExpression.expression), |
821 boolCondition.primitiveValue | 835 boolCondition.primitiveValue |
822 ? thenExpression.value | 836 ? thenExpression.value |
823 : elseExpression.value); | 837 : elseExpression.value); |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
971 Node node, | 985 Node node, |
972 InterfaceType type, | 986 InterfaceType type, |
973 ConstructorElement constructor, | 987 ConstructorElement constructor, |
974 CallStructure callStructure, | 988 CallStructure callStructure, |
975 List<AstConstant> normalizedArguments, | 989 List<AstConstant> normalizedArguments, |
976 List<AstConstant> concreteArguments) { | 990 List<AstConstant> concreteArguments) { |
977 var firstArgument = normalizedArguments[0].value; | 991 var firstArgument = normalizedArguments[0].value; |
978 ConstantValue defaultValue = normalizedArguments[1].value; | 992 ConstantValue defaultValue = normalizedArguments[1].value; |
979 | 993 |
980 if (firstArgument.isNull) { | 994 if (firstArgument.isNull) { |
981 reporter.reportErrorMessage( | 995 return reportNotCompileTimeConstant( |
982 normalizedArguments[0].node, MessageKind.NULL_NOT_ALLOWED); | 996 normalizedArguments[0].node, MessageKind.NULL_NOT_ALLOWED); |
983 return null; | |
984 } | 997 } |
985 | 998 |
986 if (!firstArgument.isString) { | 999 if (!firstArgument.isString) { |
987 DartType type = defaultValue.getType(coreTypes); | 1000 DartType type = defaultValue.getType(coreTypes); |
988 reporter.reportErrorMessage( | 1001 return reportNotCompileTimeConstant( |
989 normalizedArguments[0].node, | 1002 normalizedArguments[0].node, |
990 MessageKind.NOT_ASSIGNABLE, | 1003 MessageKind.NOT_ASSIGNABLE, |
991 {'fromType': type, 'toType': coreTypes.stringType}); | 1004 {'fromType': type, 'toType': coreTypes.stringType}); |
992 return null; | |
993 } | 1005 } |
994 | 1006 |
995 if (constructor.isIntFromEnvironmentConstructor && | 1007 if (constructor.isIntFromEnvironmentConstructor && |
996 !(defaultValue.isNull || defaultValue.isInt)) { | 1008 !(defaultValue.isNull || defaultValue.isInt)) { |
997 DartType type = defaultValue.getType(coreTypes); | 1009 DartType type = defaultValue.getType(coreTypes); |
998 reporter.reportErrorMessage( | 1010 return reportNotCompileTimeConstant( |
999 normalizedArguments[1].node, | 1011 normalizedArguments[1].node, |
1000 MessageKind.NOT_ASSIGNABLE, | 1012 MessageKind.NOT_ASSIGNABLE, |
1001 {'fromType': type, 'toType': coreTypes.intType}); | 1013 {'fromType': type, 'toType': coreTypes.intType}); |
1002 return null; | |
1003 } | 1014 } |
1004 | 1015 |
1005 if (constructor.isBoolFromEnvironmentConstructor && | 1016 if (constructor.isBoolFromEnvironmentConstructor && |
1006 !(defaultValue.isNull || defaultValue.isBool)) { | 1017 !(defaultValue.isNull || defaultValue.isBool)) { |
1007 DartType type = defaultValue.getType(coreTypes); | 1018 DartType type = defaultValue.getType(coreTypes); |
1008 reporter.reportErrorMessage( | 1019 return reportNotCompileTimeConstant( |
1009 normalizedArguments[1].node, | 1020 normalizedArguments[1].node, |
1010 MessageKind.NOT_ASSIGNABLE, | 1021 MessageKind.NOT_ASSIGNABLE, |
1011 {'fromType': type, 'toType': coreTypes.boolType}); | 1022 {'fromType': type, 'toType': coreTypes.boolType}); |
1012 return null; | |
1013 } | 1023 } |
1014 | 1024 |
1015 if (constructor.isStringFromEnvironmentConstructor && | 1025 if (constructor.isStringFromEnvironmentConstructor && |
1016 !(defaultValue.isNull || defaultValue.isString)) { | 1026 !(defaultValue.isNull || defaultValue.isString)) { |
1017 DartType type = defaultValue.getType(coreTypes); | 1027 DartType type = defaultValue.getType(coreTypes); |
1018 reporter.reportErrorMessage( | 1028 return reportNotCompileTimeConstant( |
1019 normalizedArguments[1].node, | 1029 normalizedArguments[1].node, |
1020 MessageKind.NOT_ASSIGNABLE, | 1030 MessageKind.NOT_ASSIGNABLE, |
1021 {'fromType': type, 'toType': coreTypes.stringType}); | 1031 {'fromType': type, 'toType': coreTypes.stringType}); |
1022 return null; | |
1023 } | 1032 } |
1024 | 1033 |
1025 String name = firstArgument.primitiveValue.slowToString(); | 1034 String name = firstArgument.primitiveValue.slowToString(); |
1026 String value = compiler.fromEnvironment(name); | 1035 String value = compiler.fromEnvironment(name); |
1027 | 1036 |
1028 AstConstant createEvaluatedConstant(ConstantValue value) { | 1037 AstConstant createEvaluatedConstant(ConstantValue value) { |
1029 ConstantExpression expression; | 1038 ConstantExpression expression; |
1030 ConstantExpression name = concreteArguments[0].expression; | 1039 ConstantExpression name = concreteArguments[0].expression; |
1031 ConstantExpression defaultValue; | 1040 ConstantExpression defaultValue; |
1032 if (concreteArguments.length > 1) { | 1041 if (concreteArguments.length > 1) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1096 ConstructorEvaluator evaluator = | 1105 ConstructorEvaluator evaluator = |
1097 new ConstructorEvaluator(constructedType, target, handler, compiler); | 1106 new ConstructorEvaluator(constructedType, target, handler, compiler); |
1098 evaluator.evaluateConstructorFieldValues(normalizedArguments); | 1107 evaluator.evaluateConstructorFieldValues(normalizedArguments); |
1099 Map<FieldElement, AstConstant> fieldConstants = | 1108 Map<FieldElement, AstConstant> fieldConstants = |
1100 evaluator.buildFieldConstants(target.enclosingClass); | 1109 evaluator.buildFieldConstants(target.enclosingClass); |
1101 Map<FieldElement, ConstantValue> fieldValues = | 1110 Map<FieldElement, ConstantValue> fieldValues = |
1102 <FieldElement, ConstantValue>{}; | 1111 <FieldElement, ConstantValue>{}; |
1103 fieldConstants.forEach((FieldElement field, AstConstant astConstant) { | 1112 fieldConstants.forEach((FieldElement field, AstConstant astConstant) { |
1104 fieldValues[field] = astConstant.value; | 1113 fieldValues[field] = astConstant.value; |
1105 }); | 1114 }); |
| 1115 for (AstConstant fieldValue in fieldConstants.values) { |
| 1116 if (fieldValue.isError) { |
| 1117 return fieldValue; |
| 1118 } |
| 1119 } |
1106 return new AstConstant( | 1120 return new AstConstant( |
1107 context, | 1121 context, |
1108 node, | 1122 node, |
1109 new ConstructedConstantExpression(type, constructor, callStructure, | 1123 new ConstructedConstantExpression(type, constructor, callStructure, |
1110 concreteArguments.map((e) => e.expression).toList()), | 1124 concreteArguments.map((e) => e.expression).toList()), |
1111 new ConstructedConstantValue(constructedType, fieldValues)); | 1125 new ConstructedConstantValue(constructedType, fieldValues)); |
1112 } | 1126 } |
1113 | 1127 |
1114 AstConstant visitParenthesizedExpression(ParenthesizedExpression node) { | 1128 AstConstant visitParenthesizedExpression(ParenthesizedExpression node) { |
1115 return node.expression.accept(this); | 1129 return node.expression.accept(this); |
1116 } | 1130 } |
1117 | 1131 |
| 1132 AstConstant reportNotCompileTimeConstant(Node node, MessageKind message, |
| 1133 [Map arguments = const {}]) { |
| 1134 reporter.reportErrorMessage(node, message, arguments); |
| 1135 return new AstConstant(context, node, new ErroneousConstantExpression(), |
| 1136 new NullConstantValue()); |
| 1137 } |
| 1138 |
1118 AstConstant signalNotCompileTimeConstant(Node node, | 1139 AstConstant signalNotCompileTimeConstant(Node node, |
1119 {MessageKind message: MessageKind.NOT_A_COMPILE_TIME_CONSTANT}) { | 1140 {MessageKind message: MessageKind.NOT_A_COMPILE_TIME_CONSTANT, |
| 1141 Map arguments: const {}}) { |
1120 if (isEvaluatingConstant) { | 1142 if (isEvaluatingConstant) { |
1121 reporter.reportErrorMessage(node, message); | 1143 return reportNotCompileTimeConstant(node, message, arguments); |
1122 | |
1123 return new AstConstant(context, node, new ErroneousConstantExpression(), | |
1124 new NullConstantValue()); | |
1125 } | 1144 } |
1126 // Else we don't need to do anything. The final handler is only | 1145 // Else we don't need to do anything. The final handler is only |
1127 // optimistically trying to compile constants. So it is normal that we | 1146 // optimistically trying to compile constants. So it is normal that we |
1128 // sometimes see non-compile time constants. | 1147 // sometimes see non-compile time constants. |
1129 // Simply return [:null:] which is used to propagate a failing | 1148 // Simply return [:null:] which is used to propagate a failing |
1130 // compile-time compilation. | 1149 // compile-time compilation. |
1131 return null; | 1150 return null; |
1132 } | 1151 } |
1133 } | 1152 } |
1134 | 1153 |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1365 | 1384 |
1366 factory AstConstant.fromDefaultValue(VariableElement element, | 1385 factory AstConstant.fromDefaultValue(VariableElement element, |
1367 ConstantExpression constant, ConstantValue value) { | 1386 ConstantExpression constant, ConstantValue value) { |
1368 return new AstConstant( | 1387 return new AstConstant( |
1369 element, | 1388 element, |
1370 element.initializer != null ? element.initializer : element.node, | 1389 element.initializer != null ? element.initializer : element.node, |
1371 constant, | 1390 constant, |
1372 value); | 1391 value); |
1373 } | 1392 } |
1374 | 1393 |
| 1394 bool get isError => expression.kind == ConstantExpressionKind.ERRONEOUS; |
| 1395 |
1375 String toString() => expression.toString(); | 1396 String toString() => expression.toString(); |
1376 } | 1397 } |
1377 | 1398 |
1378 /// A synthetic constant used to recover from errors. | 1399 /// A synthetic constant used to recover from errors. |
1379 class ErroneousAstConstant extends AstConstant { | 1400 class ErroneousAstConstant extends AstConstant { |
1380 ErroneousAstConstant(Element element, Node node) | 1401 ErroneousAstConstant(Element element, Node node) |
1381 : super( | 1402 : super( |
1382 element, | 1403 element, |
1383 node, | 1404 node, |
1384 // TODO(johnniwinther): Return a [NonConstantValue] instead. | 1405 // TODO(johnniwinther): Return a [NonConstantValue] instead. |
1385 new ErroneousConstantExpression(), | 1406 new ErroneousConstantExpression(), |
1386 new NullConstantValue()); | 1407 new NullConstantValue()); |
1387 } | 1408 } |
1388 | 1409 |
1389 class _CompilerEnvironment implements Environment { | 1410 class _CompilerEnvironment implements Environment { |
1390 final Compiler compiler; | 1411 final Compiler compiler; |
1391 | 1412 |
1392 _CompilerEnvironment(this.compiler); | 1413 _CompilerEnvironment(this.compiler); |
1393 | 1414 |
1394 @override | 1415 @override |
1395 String readFromEnvironment(String name) { | 1416 String readFromEnvironment(String name) { |
1396 return compiler.fromEnvironment(name); | 1417 return compiler.fromEnvironment(name); |
1397 } | 1418 } |
1398 } | 1419 } |
OLD | NEW |