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