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

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

Issue 1062913003: Extract CallStructure from Selector. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 8 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
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 part of dart2js; 5 part of dart2js;
6 6
7 /// A [ConstantEnvironment] provides access for constants compiled for variable 7 /// A [ConstantEnvironment] provides access for constants compiled for variable
8 /// initializers. 8 /// initializers.
9 abstract class ConstantEnvironment { 9 abstract class ConstantEnvironment {
10 /// Returns the constant for the initializer of [element]. 10 /// Returns the constant for the initializer of [element].
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after
437 437
438 AstConstant visitLiteralSymbol(LiteralSymbol node) { 438 AstConstant visitLiteralSymbol(LiteralSymbol node) {
439 InterfaceType type = compiler.symbolClass.rawType; 439 InterfaceType type = compiler.symbolClass.rawType;
440 String text = node.slowNameString; 440 String text = node.slowNameString;
441 List<AstConstant> arguments = 441 List<AstConstant> arguments =
442 <AstConstant>[new AstConstant(context, node, 442 <AstConstant>[new AstConstant(context, node,
443 new PrimitiveConstantExpression(constantSystem.createString( 443 new PrimitiveConstantExpression(constantSystem.createString(
444 new DartString.literal(text))))]; 444 new DartString.literal(text))))];
445 AstConstant constant = makeConstructedConstant( 445 AstConstant constant = makeConstructedConstant(
446 compiler, handler, context, node, type, compiler.symbolConstructor, 446 compiler, handler, context, node, type, compiler.symbolConstructor,
447 new Selector.callConstructor('', null, 1), 447 CallStructure.ONE_ARG,
448 arguments, arguments); 448 arguments, arguments);
449 return new AstConstant( 449 return new AstConstant(
450 context, node, new SymbolConstantExpression(constant.value, text)); 450 context, node, new SymbolConstantExpression(constant.value, text));
451 } 451 }
452 452
453 AstConstant makeTypeConstant(Node node, DartType elementType) { 453 AstConstant makeTypeConstant(Node node, DartType elementType) {
454 DartType constantType = 454 DartType constantType =
455 compiler.backend.typeImplementation.computeType(compiler); 455 compiler.backend.typeImplementation.computeType(compiler);
456 return new AstConstant( 456 return new AstConstant(
457 context, node, new TypeConstantExpression( 457 context, node, new TypeConstantExpression(
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
645 645
646 /** 646 /**
647 * Returns the normalized list of constant arguments that are passed to the 647 * Returns the normalized list of constant arguments that are passed to the
648 * constructor including both the concrete arguments and default values for 648 * constructor including both the concrete arguments and default values for
649 * omitted optional arguments. 649 * omitted optional arguments.
650 * 650 *
651 * Invariant: [target] must be an implementation element. 651 * Invariant: [target] must be an implementation element.
652 */ 652 */
653 List<AstConstant> evaluateArgumentsToConstructor( 653 List<AstConstant> evaluateArgumentsToConstructor(
654 Node node, 654 Node node,
655 Selector selector, 655 CallStructure callStructure,
656 Link<Node> arguments, 656 Link<Node> arguments,
657 FunctionElement target, 657 FunctionElement target,
658 {AstConstant compileArgument(Node node)}) { 658 {AstConstant compileArgument(Node node)}) {
659 assert(invariant(node, target.isImplementation)); 659 assert(invariant(node, target.isImplementation));
660 660
661 AstConstant compileDefaultValue(VariableElement element) { 661 AstConstant compileDefaultValue(VariableElement element) {
662 ConstantExpression constant = handler.compileConstant(element); 662 ConstantExpression constant = handler.compileConstant(element);
663 return new AstConstant.fromDefaultValue(element, constant); 663 return new AstConstant.fromDefaultValue(element, constant);
664 } 664 }
665 target.computeSignature(compiler); 665 target.computeSignature(compiler);
666 666
667 if (!selector.applies(target, compiler.world)) { 667 if (!callStructure.signatureApplies(target)) {
668 String name = Elements.constructorNameForDiagnostics( 668 String name = Elements.constructorNameForDiagnostics(
669 target.enclosingClass.name, target.name); 669 target.enclosingClass.name, target.name);
670 compiler.reportError( 670 compiler.reportError(
671 node, 671 node,
672 MessageKind.INVALID_CONSTRUCTOR_ARGUMENTS, 672 MessageKind.INVALID_CONSTRUCTOR_ARGUMENTS,
673 {'constructorName': name}); 673 {'constructorName': name});
674 674
675 return new List<AstConstant>.filled( 675 return new List<AstConstant>.filled(
676 target.functionSignature.parameterCount, 676 target.functionSignature.parameterCount,
677 new ErroneousAstConstant(context, node)); 677 new ErroneousAstConstant(context, node));
678 } 678 }
679 return selector.makeArgumentsList(arguments, 679 return callStructure.makeArgumentsList(
680 target, 680 arguments,
681 compileArgument, 681 target,
682 compileDefaultValue); 682 compileArgument,
683 compileDefaultValue);
683 } 684 }
684 685
685 AstConstant visitNewExpression(NewExpression node) { 686 AstConstant visitNewExpression(NewExpression node) {
686 if (!node.isConst) { 687 if (!node.isConst) {
687 return signalNotCompileTimeConstant(node); 688 return signalNotCompileTimeConstant(node);
688 } 689 }
689 690
690 Send send = node.send; 691 Send send = node.send;
691 FunctionElement constructor = elements[send]; 692 FunctionElement constructor = elements[send];
692 if (Elements.isUnresolved(constructor)) { 693 if (Elements.isUnresolved(constructor)) {
693 return signalNotCompileTimeConstant(node); 694 return signalNotCompileTimeConstant(node);
694 } 695 }
695 696
696 // Deferred types can not be used in const instance creation expressions. 697 // Deferred types can not be used in const instance creation expressions.
697 // Check if the constructor comes from a deferred library. 698 // Check if the constructor comes from a deferred library.
698 if (isDeferredUse(node.send.selector.asSend())) { 699 if (isDeferredUse(node.send.selector.asSend())) {
699 return signalNotCompileTimeConstant(node, 700 return signalNotCompileTimeConstant(node,
700 message: MessageKind.DEFERRED_COMPILE_TIME_CONSTANT_CONSTRUCTION); 701 message: MessageKind.DEFERRED_COMPILE_TIME_CONSTANT_CONSTRUCTION);
701 } 702 }
702 703
703 // TODO(ahe): This is nasty: we must eagerly analyze the 704 // TODO(ahe): This is nasty: we must eagerly analyze the
704 // constructor to ensure the redirectionTarget has been computed 705 // constructor to ensure the redirectionTarget has been computed
705 // correctly. Find a way to avoid this. 706 // correctly. Find a way to avoid this.
706 compiler.analyzeElement(constructor.declaration); 707 compiler.analyzeElement(constructor.declaration);
707 708
708 InterfaceType type = elements.getType(node); 709 InterfaceType type = elements.getType(node);
709 Selector selector = elements.getSelector(send); 710 CallStructure callStructure = elements.getSelector(send).callStructure;
710 711
711 Map<Node, AstConstant> concreteArgumentMap = 712 Map<Node, AstConstant> concreteArgumentMap =
712 <Node, AstConstant>{}; 713 <Node, AstConstant>{};
713 for (Link<Node> link = send.arguments; !link.isEmpty; link = link.tail) { 714 for (Link<Node> link = send.arguments; !link.isEmpty; link = link.tail) {
714 Node argument = link.head; 715 Node argument = link.head;
715 NamedArgument namedArgument = argument.asNamedArgument(); 716 NamedArgument namedArgument = argument.asNamedArgument();
716 if (namedArgument != null) { 717 if (namedArgument != null) {
717 argument = namedArgument.expression; 718 argument = namedArgument.expression;
718 } 719 }
719 concreteArgumentMap[argument] = evaluateConstant(argument); 720 concreteArgumentMap[argument] = evaluateConstant(argument);
720 } 721 }
721 722
722 List<AstConstant> normalizedArguments = 723 List<AstConstant> normalizedArguments =
723 evaluateArgumentsToConstructor( 724 evaluateArgumentsToConstructor(
724 node, selector, send.arguments, constructor.implementation, 725 node, callStructure, send.arguments, constructor.implementation,
725 compileArgument: (node) => concreteArgumentMap[node]); 726 compileArgument: (node) => concreteArgumentMap[node]);
726 List<AstConstant> concreteArguments = 727 List<AstConstant> concreteArguments =
727 concreteArgumentMap.values.toList(); 728 concreteArgumentMap.values.toList();
728 729
729 if (constructor == compiler.intEnvironment || 730 if (constructor == compiler.intEnvironment ||
730 constructor == compiler.boolEnvironment || 731 constructor == compiler.boolEnvironment ||
731 constructor == compiler.stringEnvironment) { 732 constructor == compiler.stringEnvironment) {
732 733
733 AstConstant createEvaluatedConstant(ConstantValue value) { 734 AstConstant createEvaluatedConstant(ConstantValue value) {
734 return new AstConstant( 735 return new AstConstant(
735 context, node, new ConstructedConstantExpression( 736 context, node, new ConstructedConstantExpression(
736 value, 737 value,
737 type, 738 type,
738 constructor, 739 constructor,
739 elements.getSelector(send), 740 elements.getSelector(send).callStructure,
740 concreteArguments.map((e) => e.expression).toList())); 741 concreteArguments.map((e) => e.expression).toList()));
741 } 742 }
742 743
743 var firstArgument = normalizedArguments[0].value; 744 var firstArgument = normalizedArguments[0].value;
744 ConstantValue defaultValue = normalizedArguments[1].value; 745 ConstantValue defaultValue = normalizedArguments[1].value;
745 746
746 if (firstArgument.isNull) { 747 if (firstArgument.isNull) {
747 compiler.reportError( 748 compiler.reportError(
748 send.arguments.head, MessageKind.NULL_NOT_ALLOWED); 749 send.arguments.head, MessageKind.NULL_NOT_ALLOWED);
749 return null; 750 return null;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
804 return createEvaluatedConstant(defaultValue); 805 return createEvaluatedConstant(defaultValue);
805 } 806 }
806 } else { 807 } else {
807 assert(constructor == compiler.stringEnvironment); 808 assert(constructor == compiler.stringEnvironment);
808 return createEvaluatedConstant( 809 return createEvaluatedConstant(
809 constantSystem.createString(new DartString.literal(value))); 810 constantSystem.createString(new DartString.literal(value)));
810 } 811 }
811 } else { 812 } else {
812 return makeConstructedConstant( 813 return makeConstructedConstant(
813 compiler, handler, context, 814 compiler, handler, context,
814 node, type, constructor, selector, 815 node, type, constructor, callStructure,
815 concreteArguments, normalizedArguments); 816 concreteArguments, normalizedArguments);
816 } 817 }
817 } 818 }
818 819
819 static AstConstant makeConstructedConstant( 820 static AstConstant makeConstructedConstant(
820 Compiler compiler, 821 Compiler compiler,
821 ConstantCompilerBase handler, 822 ConstantCompilerBase handler,
822 Element context, 823 Element context,
823 Node node, 824 Node node,
824 InterfaceType type, 825 InterfaceType type,
825 ConstructorElement constructor, 826 ConstructorElement constructor,
826 Selector selector, 827 CallStructure callStructure,
827 List<AstConstant> concreteArguments, 828 List<AstConstant> concreteArguments,
828 List<AstConstant> normalizedArguments) { 829 List<AstConstant> normalizedArguments) {
829 assert(invariant(node, selector.applies(constructor, compiler.world) || 830 assert(invariant(node, callStructure.signatureApplies(constructor) ||
830 compiler.compilationFailed, 831 compiler.compilationFailed,
831 message: "Selector $selector does not apply to constructor " 832 message: "Call structure $callStructure does not apply to constructor "
832 "$constructor.")); 833 "$constructor."));
833 834
834 // The redirection chain of this element may not have been resolved through 835 // The redirection chain of this element may not have been resolved through
835 // a post-process action, so we have to make sure it is done here. 836 // a post-process action, so we have to make sure it is done here.
836 compiler.resolver.resolveRedirectionChain(constructor, node); 837 compiler.resolver.resolveRedirectionChain(constructor, node);
837 InterfaceType constructedType = 838 InterfaceType constructedType =
838 constructor.computeEffectiveTargetType(type); 839 constructor.computeEffectiveTargetType(type);
839 ConstructorElement target = constructor.effectiveTarget; 840 ConstructorElement target = constructor.effectiveTarget;
840 ClassElement classElement = target.enclosingClass; 841 ClassElement classElement = target.enclosingClass;
841 // The constructor must be an implementation to ensure that field 842 // The constructor must be an implementation to ensure that field
842 // initializers are handled correctly. 843 // initializers are handled correctly.
843 target = target.implementation; 844 target = target.implementation;
844 assert(invariant(node, target.isImplementation)); 845 assert(invariant(node, target.isImplementation));
845 846
846 ConstructorEvaluator evaluator = new ConstructorEvaluator( 847 ConstructorEvaluator evaluator = new ConstructorEvaluator(
847 constructedType, target, handler, compiler); 848 constructedType, target, handler, compiler);
848 evaluator.evaluateConstructorFieldValues(normalizedArguments); 849 evaluator.evaluateConstructorFieldValues(normalizedArguments);
849 List<AstConstant> fieldConstants = 850 List<AstConstant> fieldConstants =
850 evaluator.buildFieldConstants(classElement); 851 evaluator.buildFieldConstants(classElement);
851 852
852 return new AstConstant( 853 return new AstConstant(
853 context, node, new ConstructedConstantExpression( 854 context, node, new ConstructedConstantExpression(
854 new ConstructedConstantValue( 855 new ConstructedConstantValue(
855 constructedType, 856 constructedType,
856 fieldConstants.map((e) => e.value).toList()), 857 fieldConstants.map((e) => e.value).toList()),
857 type, 858 type,
858 constructor, 859 constructor,
859 selector, 860 callStructure,
860 concreteArguments.map((e) => e.expression).toList())); 861 concreteArguments.map((e) => e.expression).toList()));
861 } 862 }
862 863
863 AstConstant visitParenthesizedExpression(ParenthesizedExpression node) { 864 AstConstant visitParenthesizedExpression(ParenthesizedExpression node) {
864 return node.expression.accept(this); 865 return node.expression.accept(this);
865 } 866 }
866 867
867 error(Node node, MessageKind message) { 868 error(Node node, MessageKind message) {
868 // TODO(floitsch): get the list of constants that are currently compiled 869 // TODO(floitsch): get the list of constants that are currently compiled
869 // and present some kind of stack-trace. 870 // and present some kind of stack-trace.
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
987 * Runs through the initializers of the given [constructor] and updates 988 * Runs through the initializers of the given [constructor] and updates
988 * the [fieldValues] map. 989 * the [fieldValues] map.
989 */ 990 */
990 void evaluateConstructorInitializers() { 991 void evaluateConstructorInitializers() {
991 if (constructor.isSynthesized) { 992 if (constructor.isSynthesized) {
992 List<AstConstant> compiledArguments = <AstConstant>[]; 993 List<AstConstant> compiledArguments = <AstConstant>[];
993 994
994 Function compileArgument = (element) => definitions[element]; 995 Function compileArgument = (element) => definitions[element];
995 Function compileConstant = handler.compileConstant; 996 Function compileConstant = handler.compileConstant;
996 FunctionElement target = constructor.definingConstructor.implementation; 997 FunctionElement target = constructor.definingConstructor.implementation;
997 Selector.addForwardingElementArgumentsToList(constructor, 998 CallStructure.addForwardingElementArgumentsToList(
998 compiledArguments, 999 constructor,
999 target, 1000 compiledArguments,
1000 compileArgument, 1001 target,
1001 compileConstant, 1002 compileArgument,
1002 compiler.world); 1003 compileConstant);
1003 evaluateSuperOrRedirectSend(compiledArguments, target); 1004 evaluateSuperOrRedirectSend(compiledArguments, target);
1004 return; 1005 return;
1005 } 1006 }
1006 FunctionExpression functionNode = constructor.node; 1007 FunctionExpression functionNode = constructor.node;
1007 NodeList initializerList = functionNode.initializers; 1008 NodeList initializerList = functionNode.initializers;
1008 1009
1009 bool foundSuperOrRedirect = false; 1010 bool foundSuperOrRedirect = false;
1010 1011
1011 if (initializerList != null) { 1012 if (initializerList != null) {
1012 for (Link<Node> link = initializerList.nodes; 1013 for (Link<Node> link = initializerList.nodes;
1013 !link.isEmpty; 1014 !link.isEmpty;
1014 link = link.tail) { 1015 link = link.tail) {
1015 assert(link.head is Send); 1016 assert(link.head is Send);
1016 if (link.head is !SendSet) { 1017 if (link.head is !SendSet) {
1017 // A super initializer or constructor redirection. 1018 // A super initializer or constructor redirection.
1018 Send call = link.head; 1019 Send call = link.head;
1019 FunctionElement target = elements[call]; 1020 FunctionElement target = elements[call];
1020 List<AstConstant> compiledArguments = 1021 List<AstConstant> compiledArguments =
1021 evaluateArgumentsToConstructor( 1022 evaluateArgumentsToConstructor(
1022 call, elements.getSelector(call), call.arguments, target, 1023 call, elements.getSelector(call).callStructure,
1024 call.arguments, target,
1023 compileArgument: evaluateConstant); 1025 compileArgument: evaluateConstant);
1024 evaluateSuperOrRedirectSend(compiledArguments, target); 1026 evaluateSuperOrRedirectSend(compiledArguments, target);
1025 foundSuperOrRedirect = true; 1027 foundSuperOrRedirect = true;
1026 } else { 1028 } else {
1027 // A field initializer. 1029 // A field initializer.
1028 SendSet init = link.head; 1030 SendSet init = link.head;
1029 Link<Node> initArguments = init.arguments; 1031 Link<Node> initArguments = init.arguments;
1030 assert(!initArguments.isEmpty && initArguments.tail.isEmpty); 1032 assert(!initArguments.isEmpty && initArguments.tail.isEmpty);
1031 AstConstant fieldValue = evaluate(initArguments.head); 1033 AstConstant fieldValue = evaluate(initArguments.head);
1032 updateFieldValue(init, elements[init], fieldValue); 1034 updateFieldValue(init, elements[init], fieldValue);
1033 } 1035 }
1034 } 1036 }
1035 } 1037 }
1036 1038
1037 if (!foundSuperOrRedirect) { 1039 if (!foundSuperOrRedirect) {
1038 // No super initializer found. Try to find the default constructor if 1040 // No super initializer found. Try to find the default constructor if
1039 // the class is not Object. 1041 // the class is not Object.
1040 ClassElement enclosingClass = constructor.enclosingClass; 1042 ClassElement enclosingClass = constructor.enclosingClass;
1041 ClassElement superClass = enclosingClass.superclass; 1043 ClassElement superClass = enclosingClass.superclass;
1042 if (enclosingClass != compiler.objectClass) { 1044 if (enclosingClass != compiler.objectClass) {
1043 assert(superClass != null); 1045 assert(superClass != null);
1044 assert(superClass.resolutionState == STATE_DONE); 1046 assert(superClass.resolutionState == STATE_DONE);
1045 1047
1046 FunctionElement targetConstructor = 1048 FunctionElement targetConstructor =
1047 superClass.lookupDefaultConstructor(); 1049 superClass.lookupDefaultConstructor();
1048 // If we do not find a default constructor, an error was reported 1050 // If we do not find a default constructor, an error was reported
1049 // already and compilation will fail anyway. So just ignore that case. 1051 // already and compilation will fail anyway. So just ignore that case.
1050 if (targetConstructor != null) { 1052 if (targetConstructor != null) {
1051 Selector selector = new Selector.callDefaultConstructor();
1052 List<AstConstant> compiledArguments = evaluateArgumentsToConstructor( 1053 List<AstConstant> compiledArguments = evaluateArgumentsToConstructor(
1053 functionNode, selector, const Link<Node>(), targetConstructor); 1054 functionNode, CallStructure.NO_ARGS,
1055 const Link<Node>(), targetConstructor);
1054 evaluateSuperOrRedirectSend(compiledArguments, targetConstructor); 1056 evaluateSuperOrRedirectSend(compiledArguments, targetConstructor);
1055 } 1057 }
1056 } 1058 }
1057 } 1059 }
1058 } 1060 }
1059 1061
1060 /** 1062 /**
1061 * Simulates the execution of the [constructor] with the given 1063 * Simulates the execution of the [constructor] with the given
1062 * [arguments] to obtain the field values that need to be passed to the 1064 * [arguments] to obtain the field values that need to be passed to the
1063 * native JavaScript constructor. 1065 * native JavaScript constructor.
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1117 ConstantValue get value => expression.value; 1119 ConstantValue get value => expression.value;
1118 1120
1119 String toString() => expression.toString(); 1121 String toString() => expression.toString();
1120 } 1122 }
1121 1123
1122 /// A synthetic constant used to recover from errors. 1124 /// A synthetic constant used to recover from errors.
1123 class ErroneousAstConstant extends AstConstant { 1125 class ErroneousAstConstant extends AstConstant {
1124 ErroneousAstConstant(Element element, Node node) 1126 ErroneousAstConstant(Element element, Node node)
1125 : super(element, node, new ErroneousConstantExpression()); 1127 : super(element, node, new ErroneousConstantExpression());
1126 } 1128 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698