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

Side by Side Diff: frog/leg/compile_time_constants.dart

Issue 9753001: super and this in compile-time constants. (Closed) Base URL: /home/flo/programming/dart2/../dart/dart@master
Patch Set: Improvements Created 8 years, 9 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
« no previous file with comments | « no previous file | frog/leg/compiler.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 class Constant implements Hashable { 5 class Constant implements Hashable {
6 const Constant(); 6 const Constant();
7 7
8 bool isNull() => false; 8 bool isNull() => false;
9 bool isBool() => false; 9 bool isBool() => false;
10 bool isTrue() => false; 10 bool isTrue() => false;
(...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after
676 final TreeElements elements; 676 final TreeElements elements;
677 final Compiler compiler; 677 final Compiler compiler;
678 final Map<Element, Constant> definitions = null; 678 final Map<Element, Constant> definitions = null;
679 679
680 CompileTimeConstantEvaluator(this.constantHandler, 680 CompileTimeConstantEvaluator(this.constantHandler,
681 this.elements, 681 this.elements,
682 this.compiler); 682 this.compiler);
683 683
684 CompileTimeConstantEvaluator.insideConstructor(this.constantHandler, 684 CompileTimeConstantEvaluator.insideConstructor(this.constantHandler,
685 this.elements, 685 this.elements,
686 this.compiler, 686 this.compiler)
687 this.definitions); 687 : definitions = new Map<Element, Constant>();
688 688
689 bool insideConstructor() => definitions !== null; 689 bool insideConstructor() => definitions !== null;
690 690
691 Constant evaluate(Node node) { 691 Constant evaluate(Node node) {
692 return node.accept(this); 692 return node.accept(this);
693 } 693 }
694 694
695 visitNode(Node node) { 695 visitNode(Node node) {
696 compiler.unimplemented("CompileTimeConstantEvaluator", node: node); 696 compiler.unimplemented("CompileTimeConstantEvaluator", node: node);
697 } 697 }
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
926 if (folded === null) error(send); 926 if (folded === null) error(send);
927 return folded; 927 return folded;
928 } 928 }
929 return super.visitSend(send); 929 return super.visitSend(send);
930 } 930 }
931 931
932 visitSendSet(SendSet node) { 932 visitSendSet(SendSet node) {
933 error(node); 933 error(node);
934 } 934 }
935 935
936 Constant visitNewExpression(NewExpression node) { 936 List<Constant> evaluateConstructorArguments(Send send,
937 void assignArgumentsToParameters( 937 FunctionElement constructor) {
938 FunctionParameters parameters, 938 FunctionParameters parameters = constructor.computeParameters(compiler);
939 Map<Element, Constant> constructorDefinitions, 939 if (send.arguments.isEmpty() && parameters.parameterCount == 0) {
940 Map<Element, Constant> fieldValues) { 940 return const <Constant>[];
941 Send send = node.send; 941 }
942 if (send.arguments.isEmpty() && parameters.parameterCount == 0) return; 942 List<Constant> arguments = <Constant>[];
943 List<Constant> arguments = <Constant>[]; 943 Selector selector = elements.getSelector(send);
944 Selector selector = elements.getSelector(send);
945 944
946 Function compileArgument = evaluate; 945 Function compileArgument = (x) => evaluate(x);
947 Function compileConstant = constantHandler.compileVariable; 946 Function compileConstant = (x) => compiler.compileVariable(x);
ahe 2012/03/23 10:56:15 What is up with this? Is there a VM bug? I have no
948 bool succeeded = selector.addSendArgumentsToList( 947 bool succeeded = selector.addSendArgumentsToList(
949 send, arguments, parameters, compileArgument, compileConstant); 948 send, arguments, parameters, compileArgument, compileConstant);
950 if (!succeeded) error(node); 949 if (!succeeded) error(send);
950 return arguments;
951 }
951 952
952 int index = 0; 953 void assignConstructorArgumentsToParameters(
953 parameters.forEachParameter((Element parameter) { 954 FunctionElement constructor, List<Constant> arguments,
954 Constant argument = arguments[index++]; 955 Map<Element, Constant> fieldValues) {
955 constructorDefinitions[parameter] = argument; 956 // Assign arguments to parameters.
956 if (parameter.kind == ElementKind.FIELD_PARAMETER) { 957 FunctionParameters parameters = constructor.computeParameters(compiler);
957 FieldParameterElement fieldParameterElement = parameter; 958 int index = 0;
958 fieldValues[fieldParameterElement.fieldElement] = argument; 959 parameters.forEachParameter((Element parameter) {
959 } 960 Constant argument = arguments[index++];
960 }); 961 definitions[parameter] = argument;
962 if (parameter.kind == ElementKind.FIELD_PARAMETER) {
963 FieldParameterElement fieldParameterElement = parameter;
964 fieldValues[fieldParameterElement.fieldElement] = argument;
965 }
966 });
967 }
968
969 void evaluateConstructorInitializers(
970 FunctionElement constructor,
971 Set<FunctionElement> executedConstructors,
972 Map<Element, Constant> fieldValues) {
973
974 void evaluateSuperOrRedirectSend(FunctionElement targetConstructor,
975 List<Constant> targetArguments) {
976 compiler.withCurrentElement(targetConstructor, () {
977 evaluateConstructorFieldValues(
978 targetConstructor, targetArguments, executedConstructors,
979 fieldValues);
980 });
961 } 981 }
962 982
963 void compileInitializers(Link<Node> initializers, 983 FunctionExpression functionNode = constructor.parseNode(compiler);
964 CompileTimeConstantEvaluator evaluator, 984 NodeList initializerList = functionNode.initializers;
965 TreeElements constructorElements, 985
966 Map<Element, Constant> constructorDefinitions, 986 bool foundSuperOrRedirect = false;
967 Map<Element, Constant> fieldValues) { 987
968 for (Link<Node> link = initializers; !link.isEmpty(); link = link.tail) { 988 if (initializerList !== null) {
989 for (Link<Node> link = initializerList.nodes;
990 !link.isEmpty();
991 link = link.tail) {
969 assert(link.head is Send); 992 assert(link.head is Send);
970 if (link.head is !SendSet) { 993 if (link.head is !SendSet) {
971 // A super initializer or constructor redirection. 994 // A super initializer or constructor redirection.
972 Send call = link.head; 995 Send call = link.head;
973 assert(Initializers.isSuperConstructorCall(call) || 996 FunctionElement targetConstructor = elements[call];
974 Initializers.isConstructorRedirect(call)); 997 List<Constant> targetArguments =
975 compiler.unimplemented("ConstantHandler with this or super", 998 evaluateConstructorArguments(call, targetConstructor);
976 node: call); 999 evaluateSuperOrRedirectSend(targetConstructor, targetArguments);
1000 foundSuperOrRedirect = true;
977 } else { 1001 } else {
978 // A field initializer. 1002 // A field initializer.
979 SendSet init = link.head; 1003 SendSet init = link.head;
980 Link<Node> arguments = init.arguments; 1004 Link<Node> initArguments = init.arguments;
981 assert(!arguments.isEmpty() && arguments.tail.isEmpty()); 1005 assert(!initArguments.isEmpty() && initArguments.tail.isEmpty());
982 Constant fieldValue = evaluator.evaluate(arguments.head); 1006 Constant fieldValue = evaluate(initArguments.head);
983 fieldValues[constructorElements[init]] = fieldValue; 1007 fieldValues[elements[init]] = fieldValue;
984 } 1008 }
985 } 1009 }
986 } 1010 }
987 1011
1012 if (!foundSuperOrRedirect) {
1013 // No super initializer found. Try to find the default constructor if
1014 // the class is not Object.
1015 ClassElement enclosingClass = constructor.enclosingElement;
1016 ClassElement superClass = enclosingClass.superclass;
1017 if (enclosingClass != compiler.objectClass) {
1018 assert(superClass !== null);
1019 assert(superClass.isResolved);
1020 FunctionElement targetConstructor =
1021 superClass.lookupConstructor(superClass.name);
1022 if (targetConstructor === null) {
1023 compiler.internalError("no default constructor available");
1024 }
1025 evaluateSuperOrRedirectSend(targetConstructor, const <Constant>[]);
1026 }
1027 }
1028 }
1029
1030 void evaluateConstructorFieldValues(FunctionElement constructor,
1031 List<Constant> arguments,
1032 Set<FunctionElement> executedConstructors,
1033 Map<Element, Constant> fieldValues) {
1034 compiler.withCurrentElement(constructor, () {
1035 if (executedConstructors.contains(constructor)) {
1036 MessageKind kind = MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE;
1037 compiler.reportError(constructor.parseNode(compiler),
1038 new CompileTimeConstantError(kind, const []));
1039 }
1040 executedConstructors.add(constructor);
1041
1042 TreeElements constructorElements =
1043 compiler.resolver.resolveMethodElement(constructor);
1044 CompileTimeConstantEvaluator evaluator =
1045 new CompileTimeConstantEvaluator.insideConstructor(
1046 constantHandler, constructorElements, compiler);
1047
1048 evaluator.assignConstructorArgumentsToParameters(
1049 constructor, arguments, fieldValues);
1050 evaluator.evaluateConstructorInitializers(
1051 constructor, executedConstructors, fieldValues);
1052 });
1053 }
1054
1055 Constant visitNewExpression(NewExpression node) {
988 List<Constant> buildJsNewArguments(ClassElement classElement, 1056 List<Constant> buildJsNewArguments(ClassElement classElement,
989 Map<Element, Constant> fieldValues) { 1057 Map<Element, Constant> fieldValues) {
990 List<Constant> jsNewArguments = <Constant>[]; 1058 List<Constant> jsNewArguments = <Constant>[];
991 for (Element member in classElement.members) { 1059 // TODO(floitsch): share this code with the emitter, so that we don't
992 if (member.isInstanceMember() && member.kind == ElementKind.FIELD) { 1060 // need to care about the order of fields here.
993 Constant fieldValue = fieldValues[member]; 1061 while (classElement != compiler.objectClass) {
994 if (fieldValue === null) { 1062 for (Element member in classElement.members) {
995 // Use the default value. 1063 if (member.isInstanceMember() && member.kind == ElementKind.FIELD) {
996 fieldValue = constantHandler.compileVariable(member); 1064 Constant fieldValue = fieldValues[member];
1065 if (fieldValue === null) {
1066 // Use the default value.
1067 fieldValue = constantHandler.compileVariable(member);
1068 }
1069 jsNewArguments.add(fieldValue);
997 } 1070 }
998 jsNewArguments.add(fieldValue);
999 } 1071 }
1000 } 1072 classElement = classElement.superclass;
1001 if (classElement.superclass != compiler.coreLibrary.find(Types.OBJECT)) { 1073 }
1002 compiler.unimplemented("ConstantHandler with super", node: node);
1003 }
1004 return jsNewArguments; 1074 return jsNewArguments;
1005 } 1075 }
1006 1076
1007 if (!node.isConst()) error(node); 1077 if (!node.isConst()) error(node);
1008 1078
1009 FunctionElement constructor = elements[node.send]; 1079 FunctionElement constructor = elements[node.send];
1010 TreeElements constructorElements = 1080 ClassElement classElement = constructor.enclosingElement;
1011 compiler.resolver.resolveMethodElement(constructor); 1081 if (classElement.isInterface()) {
1012 if (constructor != constructor.defaultImplementation) { 1082 compiler.resolver.resolveMethodElement(constructor);
1013 constructor = constructor.defaultImplementation; 1083 constructor = constructor.defaultImplementation;
1014 constructorElements = 1084 classElement = constructor.enclosingElement;
1015 compiler.resolver.resolveMethodElement(constructor);
1016 } 1085 }
1017 1086
1018 List<Constant> jsNewArguments; 1087 List<Constant> jsNewArguments;
1019 ClassElement classElement = constructor.enclosingElement;
1020 compiler.withCurrentElement(constructor, () { 1088 compiler.withCurrentElement(constructor, () {
1021 FunctionExpression functionNode = constructor.parseNode(compiler); 1089 // We use a set to avoid cyclic redirection constructors.
1022 NodeList initializerList = functionNode.initializers; 1090 Set<FunctionElement> executedConstructors = new Set<FunctionElement>();
1023 FunctionParameters parameters = constructor.computeParameters(compiler);
1024
1025 Map<Element, Constant> fieldValues = new Map<Element, Constant>(); 1091 Map<Element, Constant> fieldValues = new Map<Element, Constant>();
1026 Map<Element, Constant> constructorDefinitions = 1092 List<Constant> arguments =
1027 new Map<Element, Constant>(); 1093 evaluateConstructorArguments(node.send, constructor);
1028 1094 evaluateConstructorFieldValues(
1029 assignArgumentsToParameters(parameters, constructorDefinitions, 1095 constructor, arguments, executedConstructors, fieldValues);
1030 fieldValues);
1031 CompileTimeConstantEvaluator initializerEvaluator =
1032 new CompileTimeConstantEvaluator.insideConstructor(
1033 constantHandler, constructorElements, compiler,
1034 constructorDefinitions);
1035 if (initializerList !== null) {
1036 Link<Node> initializers = functionNode.initializers.nodes;
1037 compileInitializers(initializers,
1038 initializerEvaluator,
1039 constructorElements,
1040 constructorDefinitions,
1041 fieldValues);
1042 }
1043 jsNewArguments = buildJsNewArguments(classElement, fieldValues); 1096 jsNewArguments = buildJsNewArguments(classElement, fieldValues);
1044 }); 1097 });
1045 1098
1046
1047 compiler.registerInstantiatedClass(classElement); 1099 compiler.registerInstantiatedClass(classElement);
1048 // TODO(floitsch): take generic types into account. 1100 // TODO(floitsch): take generic types into account.
1049 Type type = classElement.computeType(compiler); 1101 Type type = classElement.computeType(compiler);
1050 Constant constant = new ConstructedConstant(type, jsNewArguments); 1102 Constant constant = new ConstructedConstant(type, jsNewArguments);
1051 constantHandler.registerCompileTimeConstant(constant); 1103 constantHandler.registerCompileTimeConstant(constant);
1052 return constant; 1104 return constant;
1053 } 1105 }
1054 1106
1055 error(Node node) { 1107 error(Node node) {
1056 // TODO(floitsch): get the list of constants that are currently compiled 1108 // TODO(floitsch): get the list of constants that are currently compiled
1057 // and present some kind of stack-trace. 1109 // and present some kind of stack-trace.
1058 MessageKind kind = MessageKind.NOT_A_COMPILE_TIME_CONSTANT; 1110 MessageKind kind = MessageKind.NOT_A_COMPILE_TIME_CONSTANT;
1059 compiler.reportError(node, new CompileTimeConstantError(kind, const [])); 1111 compiler.reportError(node, new CompileTimeConstantError(kind, const []));
1060 } 1112 }
1061 } 1113 }
OLDNEW
« no previous file with comments | « no previous file | frog/leg/compiler.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698