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