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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart

Issue 12051056: Allow native classes to mixin behavior from an ordinary Dart class. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Add comments. Created 7 years, 11 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 | Annotate | Revision Log
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 part of js_backend; 5 part of js_backend;
6 6
7 /** 7 /**
8 * A function element that represents a closure call. The signature is copied 8 * A function element that represents a closure call. The signature is copied
9 * from the given element. 9 * from the given element.
10 */ 10 */
(...skipping 717 matching lines...) Expand 10 before | Expand all | Expand 10 after
728 void emitInstanceMembers(ClassElement classElement, 728 void emitInstanceMembers(ClassElement classElement,
729 ClassBuilder builder) { 729 ClassBuilder builder) {
730 assert(invariant(classElement, classElement.isDeclaration)); 730 assert(invariant(classElement, classElement.isDeclaration));
731 JavaScriptBackend backend = compiler.backend; 731 JavaScriptBackend backend = compiler.backend;
732 if (classElement == backend.objectInterceptorClass) { 732 if (classElement == backend.objectInterceptorClass) {
733 emitInterceptorMethods(builder); 733 emitInterceptorMethods(builder);
734 // The ObjectInterceptor does not have any instance methods. 734 // The ObjectInterceptor does not have any instance methods.
735 return; 735 return;
736 } 736 }
737 737
738 void visitMember(ClassElement enclosing, Element member) {
739 assert(invariant(classElement, member.isDeclaration));
740 if (member.isInstanceMember()) {
741 addInstanceMember(member, builder);
742 }
743 }
744
745 // TODO(kasperl): We should make sure to only emit one version of
746 // overridden methods. Right now, we rely on the ordering so the
747 // methods pulled in from mixins are replaced with the members
748 // from the class definition, but it is broken if you a chain of
749 // mixin applications.
750
751 // If the class is a native class, we have to add the instance
752 // members defined in the non-native mixin applications used by
753 // the class.
754 if (classElement.isNative()) {
755 ClassElement superclass = classElement.superclass;
756 while (superclass.isMixinApplication) {
757 assert(!superclass.isNative());
758 superclass.forEachMember(
759 visitMember,
760 includeBackendMembers: true,
761 includeSuperMembers: false);
762 superclass = superclass.superclass;
763 }
764 }
765
738 classElement.implementation.forEachMember( 766 classElement.implementation.forEachMember(
739 (ClassElement enclosing, Element member) { 767 visitMember,
740 assert(invariant(classElement, member.isDeclaration)); 768 includeBackendMembers: true,
741 if (member.isInstanceMember()) { 769 includeSuperMembers: false);
742 addInstanceMember(member, builder);
743 }
744 },
745 includeBackendMembers: true);
746 770
747 generateIsTestsOn(classElement, (Element other) { 771 generateIsTestsOn(classElement, (Element other) {
748 js.Expression code; 772 js.Expression code;
749 if (compiler.objectClass == other) return; 773 if (compiler.objectClass == other) return;
750 if (nativeEmitter.requiresNativeIsCheck(other)) { 774 if (nativeEmitter.requiresNativeIsCheck(other)) {
751 code = js.fun([], js.block1(js.return_(new js.LiteralBool(true)))); 775 code = js.fun([], js.block1(js.return_(new js.LiteralBool(true))));
752 } else { 776 } else {
753 code = new js.LiteralBool(true); 777 code = new js.LiteralBool(true);
754 } 778 }
755 builder.addProperty(namer.operatorIs(other), code); 779 builder.addProperty(namer.operatorIs(other), code);
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
884 // Getters and setters with suffixes will be generated dynamically. 908 // Getters and setters with suffixes will be generated dynamically.
885 addField(member, 909 addField(member,
886 fieldName, 910 fieldName,
887 accessorName, 911 accessorName,
888 needsGetter, 912 needsGetter,
889 needsSetter, 913 needsSetter,
890 needsCheckedSetter); 914 needsCheckedSetter);
891 } 915 }
892 } 916 }
893 917
918 // TODO(kasperl): We should make sure to only emit one version of
919 // overridden fields. Right now, we rely on the ordering so the
920 // fields pulled in from mixins are replaced with the fields from
921 // the class definition, but it is broken if you a chain of mixin
922 // applications.
923
924 // If the class is a native class, we have to add the fields
925 // defined in the non-native mixin applications used by the class.
926 if (classElement.isNative()) {
927 ClassElement superclass = classElement.superclass;
928 while (superclass.isMixinApplication) {
929 assert(!superclass.isNative());
930 superclass.forEachInstanceField(
931 visitField,
932 includeBackendMembers: true,
933 includeSuperMembers: false);
934 superclass = superclass.superclass;
935 }
936 }
937
894 // If a class is not instantiated then we add the field just so we can 938 // If a class is not instantiated then we add the field just so we can
895 // generate the field getter/setter dynamically. Since this is only 939 // generate the field getter/setter dynamically. Since this is only
896 // allowed on fields that are in [classElement] we don't need to visit 940 // allowed on fields that are in [classElement] we don't need to visit
897 // superclasses for non-instantiated classes. 941 // superclasses for non-instantiated classes.
898 classElement.implementation.forEachInstanceField( 942 classElement.implementation.forEachInstanceField(
899 visitField, 943 visitField,
900 includeBackendMembers: true, 944 includeBackendMembers: true,
901 includeSuperMembers: isInstantiated && !classElement.isNative()); 945 includeSuperMembers: isInstantiated && !classElement.isNative());
902 } 946 }
903 947
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
1061 return; 1105 return;
1062 } else { 1106 } else {
1063 // TODO(ngeoffray): Instead of switching between buffer, we 1107 // TODO(ngeoffray): Instead of switching between buffer, we
1064 // should create code sections, and decide where to emit them at 1108 // should create code sections, and decide where to emit them at
1065 // the end. 1109 // the end.
1066 buffer = mainBuffer; 1110 buffer = mainBuffer;
1067 } 1111 }
1068 1112
1069 needsDefineClass = true; 1113 needsDefineClass = true;
1070 String className = namer.getName(classElement); 1114 String className = namer.getName(classElement);
1115
1116 // Find the first non-native superclass.
1071 ClassElement superclass = classElement.superclass; 1117 ClassElement superclass = classElement.superclass;
1118 while (superclass != null && superclass.isNative()) {
1119 superclass = superclass.superclass;
1120 }
1121
1072 String superName = ""; 1122 String superName = "";
1073 if (superclass != null) { 1123 if (superclass != null) {
1074 superName = namer.getName(superclass); 1124 superName = namer.getName(superclass);
1075 } 1125 }
1076 1126
1077 ClassBuilder builder = new ClassBuilder(); 1127 ClassBuilder builder = new ClassBuilder();
1078 1128
1079 emitClassConstructor(classElement, builder); 1129 emitClassConstructor(classElement, builder);
1080 emitSuper(superName, builder); 1130 emitSuper(superName, builder);
1081 emitClassFields(classElement, builder, 1131 emitClassFields(classElement, builder,
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
1156 call = cls.lookupBackendMember(Compiler.CALL_OPERATOR_NAME); 1206 call = cls.lookupBackendMember(Compiler.CALL_OPERATOR_NAME);
1157 } 1207 }
1158 if (call != null) { 1208 if (call != null) {
1159 generateInterfacesIsTests(compiler.functionClass, 1209 generateInterfacesIsTests(compiler.functionClass,
1160 emitIsTest, 1210 emitIsTest,
1161 generated); 1211 generated);
1162 getTypedefChecksOn(call.computeType(compiler)).forEach(emitIsTest); 1212 getTypedefChecksOn(call.computeType(compiler)).forEach(emitIsTest);
1163 } 1213 }
1164 } 1214 }
1165 for (DartType interfaceType in cls.interfaces) { 1215 for (DartType interfaceType in cls.interfaces) {
1166 generateInterfacesIsTests(interfaceType.element, emitIsTest, generated); 1216 ClassElement interfaceElement = interfaceType.element;
1217 generateInterfacesIsTests(interfaceElement, emitIsTest, generated);
1167 } 1218 }
1219
1220 // For native classes, we also have to run through their
1221 // non-native mixin applications and make sure we deal with 'is'
1222 // tests correctly for those.
1223 if (cls.isNative()) {
1224 ClassElement superclass = cls.superclass;
1225 while (superclass != null && superclass.isMixinApplication) {
1226 assert(!superclass.isNative());
1227 for (DartType interfaceType in superclass.interfaces) {
1228 ClassElement interfaceElement = interfaceType.element;
1229 generateInterfacesIsTests(interfaceElement, emitIsTest, generated);
1230 }
1231 superclass = superclass.superclass;
1232 }
1233 }
1234
1168 } 1235 }
1169 1236
1170 /** 1237 /**
1171 * Generate "is tests" where [cls] is being implemented. 1238 * Generate "is tests" where [cls] is being implemented.
1172 */ 1239 */
1173 void generateInterfacesIsTests(ClassElement cls, 1240 void generateInterfacesIsTests(ClassElement cls,
1174 void emitIsTest(ClassElement element), 1241 void emitIsTest(ClassElement element),
1175 Set<Element> alreadyGenerated) { 1242 Set<Element> alreadyGenerated) {
1176 void tryEmitTest(ClassElement cls) { 1243 void tryEmitTest(ClassElement cls) {
1177 if (!alreadyGenerated.contains(cls) && checkedClasses.contains(cls)) { 1244 if (!alreadyGenerated.contains(cls) && checkedClasses.contains(cls)) {
(...skipping 1000 matching lines...) Expand 10 before | Expand all | Expand 10 after
2178 """; 2245 """;
2179 const String HOOKS_API_USAGE = """ 2246 const String HOOKS_API_USAGE = """
2180 // The code supports the following hooks: 2247 // The code supports the following hooks:
2181 // dartPrint(message) - if this function is defined it is called 2248 // dartPrint(message) - if this function is defined it is called
2182 // instead of the Dart [print] method. 2249 // instead of the Dart [print] method.
2183 // dartMainRunner(main) - if this function is defined, the Dart [main] 2250 // dartMainRunner(main) - if this function is defined, the Dart [main]
2184 // method will not be invoked directly. 2251 // method will not be invoked directly.
2185 // Instead, a closure that will invoke [main] is 2252 // Instead, a closure that will invoke [main] is
2186 // passed to [dartMainRunner]. 2253 // passed to [dartMainRunner].
2187 """; 2254 """;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698