Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 /** A formal parameter to a [Method]. */ | 5 /** A formal parameter to a [Method]. */ |
| 6 class Parameter { | 6 class Parameter { |
| 7 FormalNode definition; | 7 FormalNode definition; |
| 8 | 8 |
| 9 String name; | 9 String name; |
| 10 Type type; | 10 Type type; |
| (...skipping 842 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 853 | 853 |
| 854 Arguments.removeTrailingNulls(argsCode); | 854 Arguments.removeTrailingNulls(argsCode); |
| 855 } | 855 } |
| 856 | 856 |
| 857 var argsString = Strings.join(argsCode, ', '); | 857 var argsString = Strings.join(argsCode, ', '); |
| 858 | 858 |
| 859 if (isConstructor) { | 859 if (isConstructor) { |
| 860 return _invokeConstructor(context, node, target, args, argsString); | 860 return _invokeConstructor(context, node, target, args, argsString); |
| 861 } | 861 } |
| 862 | 862 |
| 863 // TODO(jimhug): target really shouldn't ever be null... | |
|
Jennifer Messerly
2011/11/07 21:29:53
It's null for constructors, factories, and static
| |
| 864 if (target != null && target.isSuper) { | |
| 865 return new Value(returnType, | |
| 866 '${declaringType.jsname}.prototype.$jsname.call($argsString)'); | |
| 867 } | |
| 868 | |
| 863 if (name.startsWith('\$')) { | 869 if (name.startsWith('\$')) { |
| 864 return _invokeBuiltin(context, node, target, args, argsCode); | 870 return _invokeBuiltin(context, node, target, args, argsCode); |
| 865 } | 871 } |
| 866 | 872 |
| 867 // TODO(jmesserly): can target ever be null in super call? | |
| 868 if (target != null && target.isSuper) { | |
| 869 return new Value(returnType, | |
| 870 '${declaringType.jsname}.prototype.$jsname.call($argsString)'); | |
| 871 } | |
| 872 | |
| 873 if (isFactory) { | 873 if (isFactory) { |
| 874 return new Value(returnType, '$generatedFactoryName($argsString)'); | 874 return new Value(returnType, '$generatedFactoryName($argsString)'); |
| 875 } | 875 } |
| 876 | 876 |
| 877 if (isStatic) { | 877 if (isStatic) { |
| 878 if (declaringType.isTop) { | 878 if (declaringType.isTop) { |
| 879 // TODO(jimhug): Explore moving libraries into their own namespaces | 879 // TODO(jimhug): Explore moving libraries into their own namespaces |
| 880 return new Value(returnType, '$jsname($argsString)'); | 880 return new Value(returnType, '$jsname($argsString)'); |
| 881 } | 881 } |
| 882 return new Value(returnType, | 882 return new Value(returnType, |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1024 | 1024 |
| 1025 return world.gen.globalForConst( | 1025 return world.gen.globalForConst( |
| 1026 new ConstObjectValue(declaringType, fields, code, node.span), | 1026 new ConstObjectValue(declaringType, fields, code, node.span), |
| 1027 args.values); | 1027 args.values); |
| 1028 } | 1028 } |
| 1029 | 1029 |
| 1030 | 1030 |
| 1031 Value _invokeBuiltin(MethodGenerator context, Node node, Value target, | 1031 Value _invokeBuiltin(MethodGenerator context, Node node, Value target, |
| 1032 Arguments args, argsCode) { | 1032 Arguments args, argsCode) { |
| 1033 var allConst = target.isConst && args.values.every((arg) => arg.isConst); | 1033 var allConst = target.isConst && args.values.every((arg) => arg.isConst); |
| 1034 // TODO(jimhug): Handle super calls on special methods. | |
| 1035 // Handle some fast paths for Number, String, List and DOM. | 1034 // Handle some fast paths for Number, String, List and DOM. |
| 1036 if (declaringType.isNum) { | 1035 if (declaringType.isNum) { |
| 1037 // TODO(jimhug): This fails in bad ways when argsCode[1] is not num. | 1036 // TODO(jimhug): This fails in bad ways when argsCode[1] is not num. |
| 1038 // TODO(jimhug): What about null? | 1037 // TODO(jimhug): What about null? |
| 1039 if (!allConst) { | 1038 if (!allConst) { |
| 1040 var code; | 1039 var code; |
| 1041 if (name == '\$negate') { | 1040 if (name == '\$negate') { |
| 1042 code = '-${target.code}'; | 1041 code = '-${target.code}'; |
| 1043 } else if (name == '\$bit_not') { | 1042 } else if (name == '\$bit_not') { |
| 1044 code = '~${target.code}'; | 1043 code = '~${target.code}'; |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1130 return new EvaluatedValue(world.boolType, | 1129 return new EvaluatedValue(world.boolType, |
| 1131 newVal, "$newVal", node.span); | 1130 newVal, "$newVal", node.span); |
| 1132 } | 1131 } |
| 1133 // Optimize test when null is on the rhs. | 1132 // Optimize test when null is on the rhs. |
| 1134 if (argsCode[0] == 'null') { | 1133 if (argsCode[0] == 'null') { |
| 1135 return new Value(returnType, '${target.code} $op null'); | 1134 return new Value(returnType, '${target.code} $op null'); |
| 1136 } else if (target.type.isNum || target.type.isString) { | 1135 } else if (target.type.isNum || target.type.isString) { |
| 1137 // TODO(jimhug): Maybe check rhs. | 1136 // TODO(jimhug): Maybe check rhs. |
| 1138 return new Value(returnType, '${target.code} $op ${argsCode[0]}'); | 1137 return new Value(returnType, '${target.code} $op ${argsCode[0]}'); |
| 1139 } | 1138 } |
| 1140 return new Value(returnType, | 1139 return new Value(returnType, '$name(${target.code}, ${argsCode[0]})'); |
| 1141 '$name(${target.code}, ${argsCode[0]})'); | |
| 1142 } | 1140 } |
| 1143 | 1141 |
| 1144 if (name == '\$call') { | 1142 if (name == '\$call') { |
| 1145 declaringType.markUsed(); | 1143 declaringType.markUsed(); |
| 1146 return new Value(returnType, | 1144 return new Value(returnType, |
| 1147 '${target.code}(${Strings.join(argsCode, ", ")})'); | 1145 '${target.code}(${Strings.join(argsCode, ", ")})'); |
| 1148 } | 1146 } |
| 1149 | 1147 |
| 1150 return target.invokeSpecial(jsname, args, returnType); | 1148 // Fall back to normal method invocation. |
| 1149 var argsString = Strings.join(argsCode, ', '); | |
| 1150 return new Value(returnType, '${target.code}.$jsname($argsString)'); | |
| 1151 } | 1151 } |
| 1152 | 1152 |
| 1153 | 1153 |
| 1154 resolve(Type inType) { | 1154 resolve(Type inType) { |
| 1155 // TODO(jimhug): cut-and-paste-and-edit from Field.resolve | 1155 // TODO(jimhug): cut-and-paste-and-edit from Field.resolve |
| 1156 isStatic = inType.isTop; | 1156 isStatic = inType.isTop; |
| 1157 isConst = false; | 1157 isConst = false; |
| 1158 isFactory = false; | 1158 isFactory = false; |
| 1159 isAbstract = !declaringType.isClass; | 1159 isAbstract = !declaringType.isClass; |
| 1160 if (definition.modifiers != null) { | 1160 if (definition.modifiers != null) { |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 1187 } else { | 1187 } else { |
| 1188 world.error('${mod} modifier not allowed on method', mod.span); | 1188 world.error('${mod} modifier not allowed on method', mod.span); |
| 1189 } | 1189 } |
| 1190 } | 1190 } |
| 1191 } | 1191 } |
| 1192 | 1192 |
| 1193 if (isFactory) { | 1193 if (isFactory) { |
| 1194 isStatic = true; | 1194 isStatic = true; |
| 1195 } | 1195 } |
| 1196 | 1196 |
| 1197 // TODO(jimhug): need a better annotation for being an operator method | |
|
Jennifer Messerly
2011/11/07 21:29:53
+1 :)
| |
| 1198 if (name.startsWith('\$') && !name.startsWith('\$call') && isStatic) { | |
| 1199 world.error('operator method may not be static "${name}"', span); | |
| 1200 } | |
| 1201 | |
| 1197 if (isAbstract) { | 1202 if (isAbstract) { |
| 1198 if (definition.body != null && | 1203 if (definition.body != null && |
| 1199 declaringType.definition is! FunctionTypeDefinition) { | 1204 declaringType.definition is! FunctionTypeDefinition) { |
| 1200 // TODO(jimhug): Creating function types for concrete methods is | 1205 // TODO(jimhug): Creating function types for concrete methods is |
| 1201 // steadily feeling uglier... | 1206 // steadily feeling uglier... |
| 1202 world.error('abstract method can not have a body', | 1207 world.error('abstract method can not have a body', span); |
| 1203 definition.body.span); | |
| 1204 } | 1208 } |
| 1205 if (isStatic && | 1209 if (isStatic && |
| 1206 declaringType.definition is! FunctionTypeDefinition) { | 1210 declaringType.definition is! FunctionTypeDefinition) { |
| 1207 world.error('static method can not be abstract', definition.span); | 1211 world.error('static method can not be abstract', span); |
| 1208 } | 1212 } |
| 1209 } else { | 1213 } else { |
| 1210 if (definition.body == null && !isConstructor) { | 1214 if (definition.body == null && !isConstructor) { |
| 1211 world.error('method needs a body', span); | 1215 world.error('method needs a body', span); |
| 1212 } | 1216 } |
| 1213 } | 1217 } |
| 1214 | 1218 |
| 1215 if (isConstructor) { | 1219 if (isConstructor) { |
| 1216 returnType = declaringType; | 1220 returnType = declaringType; |
| 1217 } else { | 1221 } else { |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1505 } | 1509 } |
| 1506 | 1510 |
| 1507 void forEach(void f(Member member)) { | 1511 void forEach(void f(Member member)) { |
| 1508 factories.forEach((_, Map constructors) { | 1512 factories.forEach((_, Map constructors) { |
| 1509 constructors.forEach((_, Member member) { | 1513 constructors.forEach((_, Member member) { |
| 1510 f(member); | 1514 f(member); |
| 1511 }); | 1515 }); |
| 1512 }); | 1516 }); |
| 1513 } | 1517 } |
| 1514 } | 1518 } |
| OLD | NEW |