Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(656)

Side by Side Diff: pkg/compiler/lib/src/compile_time_constants.dart

Issue 1118423003: Handle default values on constant redirecting factories. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | pkg/compiler/lib/src/js_backend/type_variable_handler.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library dart2js.compile_time_constant_evaluator; 5 library dart2js.compile_time_constant_evaluator;
6 6
7 import 'constant_system_dart.dart'; 7 import 'constant_system_dart.dart';
8 import 'constants/constant_system.dart'; 8 import 'constants/constant_system.dart';
9 import 'constants/expressions.dart'; 9 import 'constants/expressions.dart';
10 import 'constants/values.dart'; 10 import 'constants/values.dart';
11 import 'dart_types.dart'; 11 import 'dart_types.dart';
12 import 'dart2jslib.dart' show Compiler, CompilerTask, MessageKind, invariant; 12 import 'dart2jslib.dart' show Compiler, CompilerTask, MessageKind, invariant;
13 import 'elements/elements.dart'; 13 import 'elements/elements.dart';
14 import 'elements/modelx.dart' show FunctionElementX; 14 import 'elements/modelx.dart' show FunctionElementX;
15 import 'helpers/helpers.dart';
15 import 'resolution/resolution.dart'; 16 import 'resolution/resolution.dart';
16 import 'resolution/operators.dart'; 17 import 'resolution/operators.dart';
17 import 'tree/tree.dart'; 18 import 'tree/tree.dart';
18 import 'util/util.dart' show Link; 19 import 'util/util.dart' show Link;
19 import 'universe/universe.dart' show CallStructure; 20 import 'universe/universe.dart' show CallStructure;
20 21
21 /// A [ConstantEnvironment] provides access for constants compiled for variable 22 /// A [ConstantEnvironment] provides access for constants compiled for variable
22 /// initializers. 23 /// initializers.
23 abstract class ConstantEnvironment { 24 abstract class ConstantEnvironment {
24 /// Returns the constant for the initializer of [element]. 25 /// Returns the constant for the initializer of [element].
(...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 } 455 }
455 456
456 AstConstant visitLiteralSymbol(LiteralSymbol node) { 457 AstConstant visitLiteralSymbol(LiteralSymbol node) {
457 InterfaceType type = compiler.symbolClass.rawType; 458 InterfaceType type = compiler.symbolClass.rawType;
458 String text = node.slowNameString; 459 String text = node.slowNameString;
459 List<AstConstant> arguments = 460 List<AstConstant> arguments =
460 <AstConstant>[new AstConstant(context, node, 461 <AstConstant>[new AstConstant(context, node,
461 new StringConstantExpression( 462 new StringConstantExpression(
462 text, 463 text,
463 constantSystem.createString(new LiteralDartString(text))))]; 464 constantSystem.createString(new LiteralDartString(text))))];
464 AstConstant constant = makeConstructedConstant( 465 ConstructorElement constructor = compiler.symbolConstructor;
465 compiler, handler, context, node, type, compiler.symbolConstructor, 466 AstConstant constant = createConstructorInvocation(
466 CallStructure.ONE_ARG, 467 node, type, constructor, CallStructure.ONE_ARG,
467 arguments, arguments); 468 normalizedArguments: arguments);
468 return new AstConstant( 469 return new AstConstant(
469 context, node, new SymbolConstantExpression(constant.value, text)); 470 context, node, new SymbolConstantExpression(constant.value, text));
470 } 471 }
471 472
472 AstConstant makeTypeConstant(Node node, DartType elementType) { 473 AstConstant makeTypeConstant(Node node, DartType elementType) {
473 DartType constantType = 474 DartType constantType =
474 compiler.backend.typeImplementation.computeType(compiler); 475 compiler.backend.typeImplementation.computeType(compiler);
475 return new AstConstant( 476 return new AstConstant(
476 context, node, new TypeConstantExpression( 477 context, node, new TypeConstantExpression(
477 new TypeConstantValue(elementType, constantType), 478 new TypeConstantValue(elementType, constantType),
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 compileArgument, 707 compileArgument,
707 compileDefaultValue); 708 compileDefaultValue);
708 } 709 }
709 710
710 AstConstant visitNewExpression(NewExpression node) { 711 AstConstant visitNewExpression(NewExpression node) {
711 if (!node.isConst) { 712 if (!node.isConst) {
712 return signalNotCompileTimeConstant(node); 713 return signalNotCompileTimeConstant(node);
713 } 714 }
714 715
715 Send send = node.send; 716 Send send = node.send;
716 FunctionElement constructor = elements[send]; 717 ConstructorElement constructor = elements[send];
717 if (Elements.isUnresolved(constructor)) { 718 if (Elements.isUnresolved(constructor)) {
718 return signalNotCompileTimeConstant(node); 719 return signalNotCompileTimeConstant(node);
719 } 720 }
720 721
721 // Deferred types can not be used in const instance creation expressions. 722 // Deferred types can not be used in const instance creation expressions.
722 // Check if the constructor comes from a deferred library. 723 // Check if the constructor comes from a deferred library.
723 if (isDeferredUse(node.send.selector.asSend())) { 724 if (isDeferredUse(node.send.selector.asSend())) {
724 return signalNotCompileTimeConstant(node, 725 return signalNotCompileTimeConstant(node,
725 message: MessageKind.DEFERRED_COMPILE_TIME_CONSTANT_CONSTRUCTION); 726 message: MessageKind.DEFERRED_COMPILE_TIME_CONSTANT_CONSTRUCTION);
726 } 727 }
727 728
729 InterfaceType type = elements.getType(node);
730 CallStructure callStructure = elements.getSelector(send).callStructure;
731
732 return createConstructorInvocation(
733 node, type, constructor, callStructure,
734 arguments: node.send.arguments);
735 }
736
737 AstConstant createConstructorInvocation(
738 Node node,
739 InterfaceType type,
740 ConstructorElement constructor,
741 CallStructure callStructure,
742 {Link<Node> arguments,
743 List<AstConstant> normalizedArguments}) {
728 // TODO(ahe): This is nasty: we must eagerly analyze the 744 // TODO(ahe): This is nasty: we must eagerly analyze the
729 // constructor to ensure the redirectionTarget has been computed 745 // constructor to ensure the redirectionTarget has been computed
730 // correctly. Find a way to avoid this. 746 // correctly. Find a way to avoid this.
731 compiler.analyzeElement(constructor.declaration); 747 compiler.analyzeElement(constructor.declaration);
732 748
733 InterfaceType type = elements.getType(node); 749 // The redirection chain of this element may not have been resolved through
734 CallStructure callStructure = elements.getSelector(send).callStructure; 750 // a post-process action, so we have to make sure it is done here.
751 compiler.resolver.resolveRedirectionChain(constructor, node);
752 InterfaceType constructedType =
753 constructor.computeEffectiveTargetType(type);
754 ConstructorElement target = constructor.effectiveTarget;
755 // The constructor must be an implementation to ensure that field
756 // initializers are handled correctly.
757 ConstructorElement implementation = target.implementation;
735 758
736 Map<Node, AstConstant> concreteArgumentMap = 759 if (implementation.isErroneous) {
737 <Node, AstConstant>{}; 760 return new AstConstant(
738 for (Link<Node> link = send.arguments; !link.isEmpty; link = link.tail) { 761 context, node, new ConstructedConstantExpression(
739 Node argument = link.head; 762 new ConstructedConstantValue(
740 NamedArgument namedArgument = argument.asNamedArgument(); 763 constructedType, const <FieldElement, ConstantValue>{}),
741 if (namedArgument != null) { 764 type,
742 argument = namedArgument.expression; 765 constructor,
743 } 766 callStructure,
744 concreteArgumentMap[argument] = evaluateConstant(argument); 767 const <ConstantExpression>[]));
745 } 768 }
746 769
747 List<AstConstant> normalizedArguments = 770 List<AstConstant> concreteArguments;
748 evaluateArgumentsToConstructor( 771 if (arguments != null) {
749 node, callStructure, send.arguments, constructor.implementation, 772 Map<Node, AstConstant> concreteArgumentMap =
750 compileArgument: (node) => concreteArgumentMap[node]); 773 <Node, AstConstant>{};
751 List<AstConstant> concreteArguments = 774 for (Link<Node> link = arguments; !link.isEmpty; link = link.tail) {
752 concreteArgumentMap.values.toList(); 775 Node argument = link.head;
753 776 NamedArgument namedArgument = argument.asNamedArgument();
754 if (constructor == compiler.intEnvironment || 777 if (namedArgument != null) {
755 constructor == compiler.boolEnvironment || 778 argument = namedArgument.expression;
756 constructor == compiler.stringEnvironment) { 779 }
757 780 concreteArgumentMap[argument] = evaluateConstant(argument);
758 AstConstant createEvaluatedConstant(ConstantValue value) {
759 return new AstConstant(
760 context, node, new ConstructedConstantExpression(
761 value,
762 type,
763 constructor,
764 elements.getSelector(send).callStructure,
765 concreteArguments.map((e) => e.expression).toList()));
766 } 781 }
767 782
768 var firstArgument = normalizedArguments[0].value; 783 normalizedArguments = evaluateArgumentsToConstructor(
769 ConstantValue defaultValue = normalizedArguments[1].value; 784 node, callStructure, arguments, implementation,
785 compileArgument: (node) => concreteArgumentMap[node]);
786 concreteArguments = concreteArgumentMap.values.toList();
787 } else {
788 assert(normalizedArguments != null);
789 concreteArguments = normalizedArguments;
790 }
770 791
771 if (firstArgument.isNull) { 792 if (target == compiler.intEnvironment ||
772 compiler.reportError( 793 target == compiler.boolEnvironment ||
773 send.arguments.head, MessageKind.NULL_NOT_ALLOWED); 794 target == compiler.stringEnvironment) {
774 return null; 795 return createFromEnvironmentConstant(
775 } 796 node, constructedType, target,
776 797 callStructure, normalizedArguments, concreteArguments);
777 if (!firstArgument.isString) {
778 DartType type = defaultValue.getType(compiler.coreTypes);
779 compiler.reportError(
780 send.arguments.head, MessageKind.NOT_ASSIGNABLE,
781 {'fromType': type, 'toType': compiler.stringClass.rawType});
782 return null;
783 }
784
785 if (constructor == compiler.intEnvironment &&
786 !(defaultValue.isNull || defaultValue.isInt)) {
787 DartType type = defaultValue.getType(compiler.coreTypes);
788 compiler.reportError(
789 send.arguments.tail.head, MessageKind.NOT_ASSIGNABLE,
790 {'fromType': type, 'toType': compiler.intClass.rawType});
791 return null;
792 }
793
794 if (constructor == compiler.boolEnvironment &&
795 !(defaultValue.isNull || defaultValue.isBool)) {
796 DartType type = defaultValue.getType(compiler.coreTypes);
797 compiler.reportError(
798 send.arguments.tail.head, MessageKind.NOT_ASSIGNABLE,
799 {'fromType': type, 'toType': compiler.boolClass.rawType});
800 return null;
801 }
802
803 if (constructor == compiler.stringEnvironment &&
804 !(defaultValue.isNull || defaultValue.isString)) {
805 DartType type = defaultValue.getType(compiler.coreTypes);
806 compiler.reportError(
807 send.arguments.tail.head, MessageKind.NOT_ASSIGNABLE,
808 {'fromType': type, 'toType': compiler.stringClass.rawType});
809 return null;
810 }
811
812 String value =
813 compiler.fromEnvironment(firstArgument.primitiveValue.slowToString());
814
815 if (value == null) {
816 return createEvaluatedConstant(defaultValue);
817 } else if (constructor == compiler.intEnvironment) {
818 int number = int.parse(value, onError: (_) => null);
819 return createEvaluatedConstant(
820 (number == null)
821 ? defaultValue
822 : constantSystem.createInt(number));
823 } else if (constructor == compiler.boolEnvironment) {
824 if (value == 'true') {
825 return createEvaluatedConstant(constantSystem.createBool(true));
826 } else if (value == 'false') {
827 return createEvaluatedConstant(constantSystem.createBool(false));
828 } else {
829 return createEvaluatedConstant(defaultValue);
830 }
831 } else {
832 assert(constructor == compiler.stringEnvironment);
833 return createEvaluatedConstant(
834 constantSystem.createString(new DartString.literal(value)));
835 }
836 } else { 798 } else {
837 return makeConstructedConstant( 799 return makeConstructedConstant(
838 compiler, handler, context, 800 compiler, handler, context, node,
839 node, type, constructor, callStructure, 801 type, constructor,
840 concreteArguments, normalizedArguments); 802 constructedType, implementation,
803 callStructure, concreteArguments, normalizedArguments);
841 } 804 }
842 } 805 }
843 806
807 AstConstant createFromEnvironmentConstant(
808 Node node,
809 InterfaceType type,
810 ConstructorElement constructor,
811 CallStructure callStructure,
812 List<AstConstant> normalizedArguments,
813 List<AstConstant> concreteArguments) {
814 AstConstant createEvaluatedConstant(ConstantValue value) {
815 return new AstConstant(
816 context, node, new ConstructedConstantExpression(
817 value,
818 type,
819 constructor,
820 callStructure,
821 concreteArguments.map((e) => e.expression).toList()));
822 }
823
824 var firstArgument = normalizedArguments[0].value;
825 ConstantValue defaultValue = normalizedArguments[1].value;
826
827 if (firstArgument.isNull) {
828 compiler.reportError(
829 normalizedArguments[0].node, MessageKind.NULL_NOT_ALLOWED);
830 return null;
831 }
832
833 if (!firstArgument.isString) {
834 DartType type = defaultValue.getType(compiler.coreTypes);
835 compiler.reportError(
836 normalizedArguments[0].node, MessageKind.NOT_ASSIGNABLE,
837 {'fromType': type, 'toType': compiler.stringClass.rawType});
838 return null;
839 }
840
841 if (constructor == compiler.intEnvironment &&
842 !(defaultValue.isNull || defaultValue.isInt)) {
843 DartType type = defaultValue.getType(compiler.coreTypes);
844 compiler.reportError(
845 normalizedArguments[1].node, MessageKind.NOT_ASSIGNABLE,
846 {'fromType': type, 'toType': compiler.intClass.rawType});
847 return null;
848 }
849
850 if (constructor == compiler.boolEnvironment &&
851 !(defaultValue.isNull || defaultValue.isBool)) {
852 DartType type = defaultValue.getType(compiler.coreTypes);
853 compiler.reportError(
854 normalizedArguments[1].node, MessageKind.NOT_ASSIGNABLE,
855 {'fromType': type, 'toType': compiler.boolClass.rawType});
856 return null;
857 }
858
859 if (constructor == compiler.stringEnvironment &&
860 !(defaultValue.isNull || defaultValue.isString)) {
861 DartType type = defaultValue.getType(compiler.coreTypes);
862 compiler.reportError(
863 normalizedArguments[1].node, MessageKind.NOT_ASSIGNABLE,
864 {'fromType': type, 'toType': compiler.stringClass.rawType});
865 return null;
866 }
867
868 String value =
869 compiler.fromEnvironment(firstArgument.primitiveValue.slowToString());
870
871 if (value == null) {
872 return createEvaluatedConstant(defaultValue);
873 } else if (constructor == compiler.intEnvironment) {
874 int number = int.parse(value, onError: (_) => null);
875 return createEvaluatedConstant(
876 (number == null)
877 ? defaultValue
878 : constantSystem.createInt(number));
879 } else if (constructor == compiler.boolEnvironment) {
880 if (value == 'true') {
881 return createEvaluatedConstant(constantSystem.createBool(true));
882 } else if (value == 'false') {
883 return createEvaluatedConstant(constantSystem.createBool(false));
884 } else {
885 return createEvaluatedConstant(defaultValue);
886 }
887 } else {
888 assert(constructor == compiler.stringEnvironment);
889 return createEvaluatedConstant(
890 constantSystem.createString(new DartString.literal(value)));
891 }
892 }
893
844 static AstConstant makeConstructedConstant( 894 static AstConstant makeConstructedConstant(
845 Compiler compiler, 895 Compiler compiler,
846 ConstantCompilerBase handler, 896 ConstantCompilerBase handler,
847 Element context, 897 Element context,
848 Node node, 898 Node node,
849 InterfaceType type, 899 InterfaceType type,
850 ConstructorElement constructor, 900 ConstructorElement constructor,
901 InterfaceType constructedType,
902 ConstructorElement target,
851 CallStructure callStructure, 903 CallStructure callStructure,
852 List<AstConstant> concreteArguments, 904 List<AstConstant> concreteArguments,
853 List<AstConstant> normalizedArguments) { 905 List<AstConstant> normalizedArguments) {
906 assert(invariant(node, !target.isRedirectingFactory,
907 message: "makeConstructedConstant can only be called with the "
908 "effective target: $constructor"));
854 assert(invariant(node, callStructure.signatureApplies(constructor) || 909 assert(invariant(node, callStructure.signatureApplies(constructor) ||
855 compiler.compilationFailed, 910 compiler.compilationFailed,
856 message: "Call structure $callStructure does not apply to constructor " 911 message: "Call structure $callStructure does not apply to constructor "
857 "$constructor.")); 912 "$constructor."));
858 913
859 // The redirection chain of this element may not have been resolved through
860 // a post-process action, so we have to make sure it is done here.
861 compiler.resolver.resolveRedirectionChain(constructor, node);
862 InterfaceType constructedType =
863 constructor.computeEffectiveTargetType(type);
864 ConstructorElement target = constructor.effectiveTarget;
865 ClassElement classElement = target.enclosingClass;
866 // The constructor must be an implementation to ensure that field
867 // initializers are handled correctly.
868 target = target.implementation;
869 assert(invariant(node, target.isImplementation));
870
871 ConstructorEvaluator evaluator = new ConstructorEvaluator( 914 ConstructorEvaluator evaluator = new ConstructorEvaluator(
872 constructedType, target, handler, compiler); 915 constructedType, target, handler, compiler);
873 evaluator.evaluateConstructorFieldValues(normalizedArguments); 916 evaluator.evaluateConstructorFieldValues(normalizedArguments);
874 Map<FieldElement, AstConstant> fieldConstants = 917 Map<FieldElement, AstConstant> fieldConstants =
875 evaluator.buildFieldConstants(classElement); 918 evaluator.buildFieldConstants(target.enclosingClass);
876 Map<FieldElement, ConstantValue> fieldValues = 919 Map<FieldElement, ConstantValue> fieldValues =
877 <FieldElement, ConstantValue>{}; 920 <FieldElement, ConstantValue>{};
878 fieldConstants.forEach((FieldElement field, AstConstant astConstant) { 921 fieldConstants.forEach((FieldElement field, AstConstant astConstant) {
879 fieldValues[field] = astConstant.value; 922 fieldValues[field] = astConstant.value;
880 }); 923 });
881 return new AstConstant( 924 return new AstConstant(
882 context, node, new ConstructedConstantExpression( 925 context, node, new ConstructedConstantExpression(
883 new ConstructedConstantValue(constructedType, fieldValues), 926 new ConstructedConstantValue(constructedType, fieldValues),
884 type, 927 type,
885 constructor, 928 constructor,
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
1147 ConstantValue get value => expression.value; 1190 ConstantValue get value => expression.value;
1148 1191
1149 String toString() => expression.toString(); 1192 String toString() => expression.toString();
1150 } 1193 }
1151 1194
1152 /// A synthetic constant used to recover from errors. 1195 /// A synthetic constant used to recover from errors.
1153 class ErroneousAstConstant extends AstConstant { 1196 class ErroneousAstConstant extends AstConstant {
1154 ErroneousAstConstant(Element element, Node node) 1197 ErroneousAstConstant(Element element, Node node)
1155 : super(element, node, new ErroneousConstantExpression()); 1198 : super(element, node, new ErroneousConstantExpression());
1156 } 1199 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/js_backend/type_variable_handler.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698