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 part of js_backend; | 5 part of js_backend; |
6 | 6 |
7 /** | 7 /** |
8 * Assigns JavaScript identifiers to Dart variables, class-names and members. | 8 * Assigns JavaScript identifiers to Dart variables, class-names and members. |
9 */ | 9 */ |
10 class Namer implements ClosureNamer { | 10 class Namer implements ClosureNamer { |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
166 if (_jsVariableReserved == null) { | 166 if (_jsVariableReserved == null) { |
167 _jsVariableReserved = new Set<String>(); | 167 _jsVariableReserved = new Set<String>(); |
168 _jsVariableReserved.addAll(javaScriptKeywords); | 168 _jsVariableReserved.addAll(javaScriptKeywords); |
169 _jsVariableReserved.addAll(reservedPropertySymbols); | 169 _jsVariableReserved.addAll(reservedPropertySymbols); |
170 _jsVariableReserved.addAll(reservedGlobalSymbols); | 170 _jsVariableReserved.addAll(reservedGlobalSymbols); |
171 } | 171 } |
172 return _jsVariableReserved; | 172 return _jsVariableReserved; |
173 } | 173 } |
174 | 174 |
175 final String CURRENT_ISOLATE; | 175 final String CURRENT_ISOLATE; |
176 String get SETUP_OBJECT => CURRENT_ISOLATE; | |
176 | 177 |
177 final String getterPrefix = r'get$'; | 178 final String getterPrefix = r'get$'; |
178 final String setterPrefix = r'set$'; | 179 final String setterPrefix = r'set$'; |
179 final String metadataField = '@'; | 180 final String metadataField = '@'; |
180 | 181 |
181 /** | 182 /** |
182 * Map from top-level or static elements to their unique identifiers provided | 183 * Map from top-level or static elements to their unique identifiers provided |
183 * by [getName]. | 184 * by [getName]. |
184 * | 185 * |
185 * Invariant: Keys must be declaration elements. | 186 * Invariant: Keys must be declaration elements. |
(...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
759 } | 760 } |
760 | 761 |
761 String isolateStaticClosureAccess(Element element) { | 762 String isolateStaticClosureAccess(Element element) { |
762 return "$CURRENT_ISOLATE.${getStaticClosureName(element)}"; | 763 return "$CURRENT_ISOLATE.${getStaticClosureName(element)}"; |
763 } | 764 } |
764 | 765 |
765 String operatorIsPrefix() => r'$is'; | 766 String operatorIsPrefix() => r'$is'; |
766 | 767 |
767 String operatorAsPrefix() => r'$as'; | 768 String operatorAsPrefix() => r'$as'; |
768 | 769 |
770 String operatorSignature() => r'$signature'; | |
771 | |
772 String functionTypeTag() => r'func'; | |
773 | |
774 String functionTypeVoidReturnTag() => r'void'; | |
775 | |
776 String functionTypeReturnTypeTag() => r'ret'; | |
777 | |
778 String functionTypeRequiredParametersTag() => r'args'; | |
779 | |
780 String functionTypeOptionalParametersTag() => r'opt'; | |
781 | |
782 String functionTypeNamedParametersTag() => r'named'; | |
783 | |
784 Map<FunctionType,String> functionTypeNameMap = | |
785 new Map<FunctionType,String>(); | |
786 FunctionTypeNamer functionTypeNamer = new FunctionTypeNamer(); | |
787 | |
788 String getFunctionTypeName(FunctionType functionType) { | |
789 return functionTypeNameMap.putIfAbsent(functionType, () { | |
790 String proposedName = functionTypeNamer.computeName(functionType); | |
791 String freshName = getFreshName(proposedName, usedInstanceNames, | |
792 suggestedInstanceNames, ensureSafe: true); | |
793 return freshName; | |
794 }); | |
795 } | |
796 | |
797 String operatorIsType(DartType type) { | |
karlklose
2013/06/19 14:37:05
Would it make sense to replace operatorIs with a v
Johnni Winther
2013/06/21 12:19:15
I tried, but it made several of the original call
| |
798 if (type.kind == TypeKind.FUNCTION) { | |
799 // TODO(erikcorry): Reduce from $isx to ix when we are minifying. | |
800 return '${operatorIsPrefix()}_${getFunctionTypeName(type)}'; | |
801 } | |
802 return operatorIs(type.element); | |
803 } | |
804 | |
769 String operatorIs(Element element) { | 805 String operatorIs(Element element) { |
770 // TODO(erikcorry): Reduce from $isx to ix when we are minifying. | 806 // TODO(erikcorry): Reduce from $isx to ix when we are minifying. |
771 return '${operatorIsPrefix()}${getRuntimeTypeName(element)}'; | 807 return '${operatorIsPrefix()}${getRuntimeTypeName(element)}'; |
772 } | 808 } |
773 | 809 |
774 /* | 810 /* |
775 * Returns a name that does not clash with reserved JS keywords, | 811 * Returns a name that does not clash with reserved JS keywords, |
776 * and also ensures it won't clash with other identifiers. | 812 * and also ensures it won't clash with other identifiers. |
777 */ | 813 */ |
778 String _safeName(String name, Set<String> reserved) { | 814 String _safeName(String name, Set<String> reserved) { |
779 if (reserved.contains(name) || name.startsWith(r'$')) { | 815 if (reserved.contains(name) || name.startsWith(r'$')) { |
780 name = '\$$name'; | 816 name = '\$$name'; |
781 } | 817 } |
782 assert(!reserved.contains(name)); | 818 assert(!reserved.contains(name)); |
783 return name; | 819 return name; |
784 } | 820 } |
785 | 821 |
786 String substitutionName(Element element) { | 822 String substitutionName(Element element) { |
787 return '${operatorAsPrefix()}${getName(element)}'; | 823 return '${operatorAsPrefix()}${getName(element)}'; |
788 } | 824 } |
789 | 825 |
826 String signatureLocation(FunctionType type) { | |
827 ClassElement classElement = Types.getClassContext(type); | |
828 if (classElement != null) { | |
829 return '${isolateAccess(classElement)}'; | |
830 } else { | |
831 return '${SETUP_OBJECT}'; | |
832 } | |
833 } | |
834 | |
835 String signatureName(FunctionType type) { | |
836 String signature = '${operatorSignature()}_${getFunctionTypeName(type)}'; | |
837 return '${signatureLocation(type)}.$signature'; | |
838 } | |
839 | |
790 String safeName(String name) => _safeName(name, jsReserved); | 840 String safeName(String name) => _safeName(name, jsReserved); |
791 String safeVariableName(String name) => _safeName(name, jsVariableReserved); | 841 String safeVariableName(String name) => _safeName(name, jsVariableReserved); |
792 | 842 |
793 SourceString operatorNameToIdentifier(SourceString name) { | 843 SourceString operatorNameToIdentifier(SourceString name) { |
794 if (name == null) return null; | 844 if (name == null) return null; |
795 String value = name.stringValue; | 845 String value = name.stringValue; |
796 if (value == null) { | 846 if (value == null) { |
797 return name; | 847 return name; |
798 } else if (value == '==') { | 848 } else if (value == '==') { |
799 return const SourceString(r'$eq'); | 849 return const SourceString(r'$eq'); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
834 } else if (value == '-') { | 884 } else if (value == '-') { |
835 return const SourceString(r'$sub'); | 885 return const SourceString(r'$sub'); |
836 } else if (value == 'unary-') { | 886 } else if (value == 'unary-') { |
837 return const SourceString(r'$negate'); | 887 return const SourceString(r'$negate'); |
838 } else { | 888 } else { |
839 return name; | 889 return name; |
840 } | 890 } |
841 } | 891 } |
842 } | 892 } |
843 | 893 |
844 | |
karlklose
2013/06/19 14:37:05
Is this intentional? See also l. 1018.
Johnni Winther
2013/06/21 12:19:15
No. I often accidentally create too many blank lin
| |
845 /** | 894 /** |
846 * Generator of names for [Constant] values. | 895 * Generator of names for [Constant] values. |
847 * | 896 * |
848 * The names are stable under perturbations of the source. The name is either a | 897 * The names are stable under perturbations of the source. The name is either a |
849 * short sequence of words, if this can be found from the constant, or a type | 898 * short sequence of words, if this can be found from the constant, or a type |
850 * followed by a hash tag. | 899 * followed by a hash tag. |
851 * | 900 * |
852 * List_imX // A List, with hash tag. | 901 * List_imX // A List, with hash tag. |
853 * C_Sentinel // const Sentinel(), "C_" added to avoid clash | 902 * C_Sentinel // const Sentinel(), "C_" added to avoid clash |
854 * // with class name. | 903 * // with class name. |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1008 String name = backend.rti.getRawTypeRepresentation(type); | 1057 String name = backend.rti.getRawTypeRepresentation(type); |
1009 addIdentifier(name); | 1058 addIdentifier(name); |
1010 } | 1059 } |
1011 | 1060 |
1012 visitInterceptor(InterceptorConstant constant) { | 1061 visitInterceptor(InterceptorConstant constant) { |
1013 addRoot(constant.dispatchedType.element.name.slowToString()); | 1062 addRoot(constant.dispatchedType.element.name.slowToString()); |
1014 add('methods'); | 1063 add('methods'); |
1015 } | 1064 } |
1016 } | 1065 } |
1017 | 1066 |
1018 | |
1019 /** | 1067 /** |
1020 * Generates canonical hash values for [Constant]s. | 1068 * Generates canonical hash values for [Constant]s. |
1021 * | 1069 * |
1022 * Unfortunately, [Constant.hashCode] is not stable under minor perturbations, | 1070 * Unfortunately, [Constant.hashCode] is not stable under minor perturbations, |
1023 * so it can't be used for generating names. This hasher keeps consistency | 1071 * so it can't be used for generating names. This hasher keeps consistency |
1024 * between runs by basing hash values of the names of elements, rather than | 1072 * between runs by basing hash values of the names of elements, rather than |
1025 * their hashCodes. | 1073 * their hashCodes. |
1026 */ | 1074 */ |
1027 class ConstantCanonicalHasher implements ConstantVisitor<int> { | 1075 class ConstantCanonicalHasher implements ConstantVisitor<int> { |
1028 | 1076 |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1154 hash = hash ^ (hash >> 6); | 1202 hash = hash ^ (hash >> 6); |
1155 return hash; | 1203 return hash; |
1156 } | 1204 } |
1157 | 1205 |
1158 static int _finish(int hash) { | 1206 static int _finish(int hash) { |
1159 hash = _MASK & (hash + (((_MASK >> 3) & hash) << 3)); | 1207 hash = _MASK & (hash + (((_MASK >> 3) & hash) << 3)); |
1160 hash = hash & (hash >> 11); | 1208 hash = hash & (hash >> 11); |
1161 return _MASK & (hash + (((_MASK >> 15) & hash) << 15)); | 1209 return _MASK & (hash + (((_MASK >> 15) & hash) << 15)); |
1162 } | 1210 } |
1163 } | 1211 } |
1212 | |
1213 class FunctionTypeNamer extends DartTypeVisitor { | |
1214 StringBuffer sb; | |
1215 | |
1216 String computeName(DartType type) { | |
1217 sb = new StringBuffer(); | |
1218 visit(type); | |
1219 return sb.toString(); | |
1220 } | |
1221 | |
1222 visit(DartType type) { | |
1223 type.accept(this, null); | |
1224 } | |
1225 | |
1226 visitType(DartType type, _) { | |
1227 sb.write(type.name.slowToString()); | |
1228 } | |
1229 | |
1230 visitFunctionType(FunctionType type, _) { | |
1231 visit(type.returnType); | |
1232 sb.write('_'); | |
1233 for (Link<DartType> link = type.parameterTypes; | |
1234 !link.isEmpty; | |
1235 link = link.tail) { | |
1236 sb.write('_'); | |
1237 visit(link.head); | |
1238 } | |
1239 bool first = false; | |
1240 for (Link<DartType> link = type.optionalParameterTypes; | |
1241 !link.isEmpty; | |
1242 link = link.tail) { | |
1243 if (!first) { | |
1244 sb.write('_'); | |
1245 } | |
1246 sb.write('_'); | |
1247 visit(link.head); | |
1248 first = true; | |
1249 } | |
1250 if (!type.namedParameterTypes.isEmpty) { | |
1251 first = false; | |
1252 for (Link<DartType> link = type.namedParameterTypes; | |
1253 !link.isEmpty; | |
1254 link = link.tail) { | |
1255 if (!first) { | |
1256 sb.write('_'); | |
1257 } | |
1258 sb.write('_'); | |
1259 visit(link.head); | |
1260 first = true; | |
1261 } | |
1262 } | |
1263 } | |
1264 } | |
OLD | NEW |