| 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 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 931 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 942 return folded; | 942 return folded; |
| 943 } | 943 } |
| 944 return super.visitSend(send); | 944 return super.visitSend(send); |
| 945 } | 945 } |
| 946 | 946 |
| 947 visitSendSet(SendSet node) { | 947 visitSendSet(SendSet node) { |
| 948 error(node); | 948 error(node); |
| 949 } | 949 } |
| 950 | 950 |
| 951 /** Returns the list of constants that are passed to the static function. */ | 951 /** Returns the list of constants that are passed to the static function. */ |
| 952 List<Constant> evaluateArgumentsToConstructor(Send send, | 952 List<Constant> evaluateArgumentsToConstructor(Selector selector, |
| 953 Link<Node> arguments, |
| 953 FunctionElement target) { | 954 FunctionElement target) { |
| 954 FunctionParameters parameters = target.computeParameters(compiler); | 955 FunctionParameters parameters = target.computeParameters(compiler); |
| 955 List<Constant> arguments = <Constant>[]; | 956 List<Constant> compiledArguments = <Constant>[]; |
| 956 Selector selector = elements.getSelector(send); | |
| 957 | 957 |
| 958 Function compileArgument = evaluate; | 958 Function compileArgument = evaluate; |
| 959 Function compileConstant = compiler.compileVariable; | 959 Function compileConstant = compiler.compileVariable; |
| 960 bool succeeded = selector.addSendArgumentsToList( | 960 bool succeeded = selector.addArgumentsToList(arguments, compiledArguments, |
| 961 send, arguments, parameters, compileArgument, compileConstant); | 961 parameters, compileArgument, |
| 962 if (!succeeded) error(send); | 962 compileConstant); |
| 963 return arguments; | 963 assert(succeeded); |
| 964 return compiledArguments; |
| 964 } | 965 } |
| 965 | 966 |
| 966 Constant visitNewExpression(NewExpression node) { | 967 Constant visitNewExpression(NewExpression node) { |
| 967 if (!node.isConst()) error(node); | 968 if (!node.isConst()) error(node); |
| 968 | 969 |
| 969 FunctionElement constructor = elements[node.send]; | 970 Send send = node.send; |
| 971 FunctionElement constructor = elements[send]; |
| 970 ClassElement classElement = constructor.enclosingElement; | 972 ClassElement classElement = constructor.enclosingElement; |
| 971 if (classElement.isInterface()) { | 973 if (classElement.isInterface()) { |
| 972 compiler.resolver.resolveMethodElement(constructor); | 974 compiler.resolver.resolveMethodElement(constructor); |
| 973 constructor = constructor.defaultImplementation; | 975 constructor = constructor.defaultImplementation; |
| 974 classElement = constructor.enclosingElement; | 976 classElement = constructor.enclosingElement; |
| 975 } | 977 } |
| 976 | 978 |
| 979 Selector selector = elements.getSelector(send); |
| 977 List<Constant> arguments = | 980 List<Constant> arguments = |
| 978 evaluateArgumentsToConstructor(node.send, constructor); | 981 evaluateArgumentsToConstructor(selector, send.arguments, constructor); |
| 979 ConstructorEvaluator evaluator = | 982 ConstructorEvaluator evaluator = |
| 980 new ConstructorEvaluator(constructor, compiler); | 983 new ConstructorEvaluator(constructor, compiler); |
| 981 evaluator.evaluateConstructorFieldValues(arguments); | 984 evaluator.evaluateConstructorFieldValues(arguments); |
| 982 List<Constant>jsNewArguments = evaluator.buildJsNewArguments(classElement); | 985 List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement); |
| 983 | 986 |
| 984 compiler.registerInstantiatedClass(classElement); | 987 compiler.registerInstantiatedClass(classElement); |
| 985 // TODO(floitsch): take generic types into account. | 988 // TODO(floitsch): take generic types into account. |
| 986 Type type = classElement.computeType(compiler); | 989 Type type = classElement.computeType(compiler); |
| 987 Constant constant = new ConstructedConstant(type, jsNewArguments); | 990 Constant constant = new ConstructedConstant(type, jsNewArguments); |
| 988 compiler.constantHandler.registerCompileTimeConstant(constant); | 991 compiler.constantHandler.registerCompileTimeConstant(constant); |
| 989 return constant; | 992 return constant; |
| 990 } | 993 } |
| 991 | 994 |
| 992 Constant visitParenthesizedExpression(ParenthesizedExpression node) { | 995 Constant visitParenthesizedExpression(ParenthesizedExpression node) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1037 parameters.forEachParameter((Element parameter) { | 1040 parameters.forEachParameter((Element parameter) { |
| 1038 Constant argument = arguments[index++]; | 1041 Constant argument = arguments[index++]; |
| 1039 definitions[parameter] = argument; | 1042 definitions[parameter] = argument; |
| 1040 if (parameter.kind == ElementKind.FIELD_PARAMETER) { | 1043 if (parameter.kind == ElementKind.FIELD_PARAMETER) { |
| 1041 FieldParameterElement fieldParameterElement = parameter; | 1044 FieldParameterElement fieldParameterElement = parameter; |
| 1042 fieldValues[fieldParameterElement.fieldElement] = argument; | 1045 fieldValues[fieldParameterElement.fieldElement] = argument; |
| 1043 } | 1046 } |
| 1044 }); | 1047 }); |
| 1045 } | 1048 } |
| 1046 | 1049 |
| 1047 void evaluateSuperOrRedirectSend(FunctionElement targetConstructor, | 1050 void evaluateSuperOrRedirectSend(Selector selector, |
| 1048 List<Constant> targetArguments) { | 1051 Link<Node> arguments, |
| 1052 FunctionElement targetConstructor) { |
| 1053 List<Constant> compiledArguments = |
| 1054 evaluateArgumentsToConstructor(selector, arguments, targetConstructor); |
| 1055 |
| 1049 ConstructorEvaluator evaluator = | 1056 ConstructorEvaluator evaluator = |
| 1050 new ConstructorEvaluator(targetConstructor, compiler); | 1057 new ConstructorEvaluator(targetConstructor, compiler); |
| 1051 evaluator.evaluateConstructorFieldValues(targetArguments); | 1058 evaluator.evaluateConstructorFieldValues(compiledArguments); |
| 1052 // Copy over the fieldValues from the super/redirect-constructor. | 1059 // Copy over the fieldValues from the super/redirect-constructor. |
| 1053 evaluator.fieldValues.forEach((key, value) => fieldValues[key] = value); | 1060 evaluator.fieldValues.forEach((key, value) => fieldValues[key] = value); |
| 1054 } | 1061 } |
| 1055 | 1062 |
| 1056 /** | 1063 /** |
| 1057 * Runs through the initializers of the given [constructor] and updates | 1064 * Runs through the initializers of the given [constructor] and updates |
| 1058 * the [fieldValues] map. | 1065 * the [fieldValues] map. |
| 1059 */ | 1066 */ |
| 1060 void evaluateConstructorInitializers() { | 1067 void evaluateConstructorInitializers() { |
| 1061 FunctionExpression functionNode = constructor.parseNode(compiler); | 1068 FunctionExpression functionNode = constructor.parseNode(compiler); |
| 1062 NodeList initializerList = functionNode.initializers; | 1069 NodeList initializerList = functionNode.initializers; |
| 1063 | 1070 |
| 1064 bool foundSuperOrRedirect = false; | 1071 bool foundSuperOrRedirect = false; |
| 1065 | 1072 |
| 1066 if (initializerList !== null) { | 1073 if (initializerList !== null) { |
| 1067 for (Link<Node> link = initializerList.nodes; | 1074 for (Link<Node> link = initializerList.nodes; |
| 1068 !link.isEmpty(); | 1075 !link.isEmpty(); |
| 1069 link = link.tail) { | 1076 link = link.tail) { |
| 1070 assert(link.head is Send); | 1077 assert(link.head is Send); |
| 1071 if (link.head is !SendSet) { | 1078 if (link.head is !SendSet) { |
| 1072 // A super initializer or constructor redirection. | 1079 // A super initializer or constructor redirection. |
| 1073 Send call = link.head; | 1080 Send call = link.head; |
| 1074 FunctionElement targetConstructor = elements[call]; | 1081 FunctionElement targetConstructor = elements[call]; |
| 1075 List<Constant> targetArguments = | 1082 Selector selector = elements.getSelector(call); |
| 1076 evaluateArgumentsToConstructor(call, targetConstructor); | 1083 Link<Node> arguments = call.arguments; |
| 1077 evaluateSuperOrRedirectSend(targetConstructor, targetArguments); | 1084 evaluateSuperOrRedirectSend(selector, arguments, targetConstructor); |
| 1078 foundSuperOrRedirect = true; | 1085 foundSuperOrRedirect = true; |
| 1079 } else { | 1086 } else { |
| 1080 // A field initializer. | 1087 // A field initializer. |
| 1081 SendSet init = link.head; | 1088 SendSet init = link.head; |
| 1082 Link<Node> initArguments = init.arguments; | 1089 Link<Node> initArguments = init.arguments; |
| 1083 assert(!initArguments.isEmpty() && initArguments.tail.isEmpty()); | 1090 assert(!initArguments.isEmpty() && initArguments.tail.isEmpty()); |
| 1084 Constant fieldValue = evaluate(initArguments.head); | 1091 Constant fieldValue = evaluate(initArguments.head); |
| 1085 fieldValues[elements[init]] = fieldValue; | 1092 fieldValues[elements[init]] = fieldValue; |
| 1086 } | 1093 } |
| 1087 } | 1094 } |
| 1088 } | 1095 } |
| 1089 | 1096 |
| 1090 if (!foundSuperOrRedirect) { | 1097 if (!foundSuperOrRedirect) { |
| 1091 // No super initializer found. Try to find the default constructor if | 1098 // No super initializer found. Try to find the default constructor if |
| 1092 // the class is not Object. | 1099 // the class is not Object. |
| 1093 ClassElement enclosingClass = constructor.enclosingElement; | 1100 ClassElement enclosingClass = constructor.enclosingElement; |
| 1094 ClassElement superClass = enclosingClass.superclass; | 1101 ClassElement superClass = enclosingClass.superclass; |
| 1095 if (enclosingClass != compiler.objectClass) { | 1102 if (enclosingClass != compiler.objectClass) { |
| 1096 assert(superClass !== null); | 1103 assert(superClass !== null); |
| 1097 assert(superClass.isResolved); | 1104 assert(superClass.isResolved); |
| 1098 FunctionElement targetConstructor = | 1105 FunctionElement targetConstructor = |
| 1099 superClass.lookupConstructor(superClass.name); | 1106 superClass.lookupConstructor(superClass.name); |
| 1100 if (targetConstructor === null) { | 1107 if (targetConstructor === null) { |
| 1101 compiler.internalError("no default constructor available"); | 1108 compiler.internalError("no default constructor available", |
| 1109 node: functionNode); |
| 1102 } | 1110 } |
| 1103 evaluateSuperOrRedirectSend(targetConstructor, const <Constant>[]); | 1111 |
| 1112 evaluateSuperOrRedirectSend(Selector.INVOCATION_0, |
| 1113 const EmptyLink<Node>(), |
| 1114 targetConstructor); |
| 1104 } | 1115 } |
| 1105 } | 1116 } |
| 1106 } | 1117 } |
| 1107 | 1118 |
| 1108 /** | 1119 /** |
| 1109 * Simulates the execution of the [constructor] with the given | 1120 * Simulates the execution of the [constructor] with the given |
| 1110 * [arguments] to obtain the field values that need to be passed to the | 1121 * [arguments] to obtain the field values that need to be passed to the |
| 1111 * native JavaScript constructor. | 1122 * native JavaScript constructor. |
| 1112 */ | 1123 */ |
| 1113 void evaluateConstructorFieldValues(List<Constant> arguments) { | 1124 void evaluateConstructorFieldValues(List<Constant> arguments) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1126 Constant fieldValue = fieldValues[field]; | 1137 Constant fieldValue = fieldValues[field]; |
| 1127 if (fieldValue === null) { | 1138 if (fieldValue === null) { |
| 1128 // Use the default value. | 1139 // Use the default value. |
| 1129 fieldValue = compiler.compileVariable(field); | 1140 fieldValue = compiler.compileVariable(field); |
| 1130 } | 1141 } |
| 1131 jsNewArguments.add(fieldValue); | 1142 jsNewArguments.add(fieldValue); |
| 1132 }); | 1143 }); |
| 1133 return jsNewArguments; | 1144 return jsNewArguments; |
| 1134 } | 1145 } |
| 1135 } | 1146 } |
| OLD | NEW |