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

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

Issue 13685022: Make mixins work on native classes. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 8 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 1153 matching lines...) Expand 10 before | Expand all | Expand 10 after
1164 ClassBuilder builder) { 1164 ClassBuilder builder) {
1165 assert(invariant(classElement, classElement.isDeclaration)); 1165 assert(invariant(classElement, classElement.isDeclaration));
1166 1166
1167 void visitMember(ClassElement enclosing, Element member) { 1167 void visitMember(ClassElement enclosing, Element member) {
1168 assert(invariant(classElement, member.isDeclaration)); 1168 assert(invariant(classElement, member.isDeclaration));
1169 if (member.isInstanceMember()) { 1169 if (member.isInstanceMember()) {
1170 addInstanceMember(member, builder); 1170 addInstanceMember(member, builder);
1171 } 1171 }
1172 } 1172 }
1173 1173
1174 // TODO(kasperl): We should make sure to only emit one version of
1175 // overridden methods. Right now, we rely on the ordering so the
1176 // methods pulled in from mixins are replaced with the members
1177 // from the class definition.
1178
1179 // If the class is a native class, we have to add the instance
1180 // members defined in the non-native mixin applications used by
1181 // the class.
1182 visitNativeMixins(classElement, (MixinApplicationElement mixin) {
1183 mixin.forEachMember(
1184 visitMember,
1185 includeBackendMembers: true,
1186 includeSuperMembers: false);
1187 });
1188
1189 classElement.implementation.forEachMember( 1174 classElement.implementation.forEachMember(
1190 visitMember, 1175 visitMember,
1191 includeBackendMembers: true, 1176 includeBackendMembers: true,
1192 includeSuperMembers: false); 1177 includeSuperMembers: false);
1193 1178
1194 void generateIsTest(Element other) { 1179 void generateIsTest(Element other) {
1195 jsAst.Expression code; 1180 jsAst.Expression code;
1196 if (other == compiler.objectClass && other != classElement) { 1181 if (other == compiler.objectClass && other != classElement) {
1197 // Avoid emitting [:$isObject:] on all classes but [Object]. 1182 // Avoid emitting [:$isObject:] on all classes but [Object].
1198 return; 1183 return;
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
1289 for (ClassElement check in typeChecks[cls]) { 1274 for (ClassElement check in typeChecks[cls]) {
1290 buffer.write('$holder.${namer.operatorIs(check)}$_=${_}true$N'); 1275 buffer.write('$holder.${namer.operatorIs(check)}$_=${_}true$N');
1291 String body = rti.getSupertypeSubstitution(cls, check); 1276 String body = rti.getSupertypeSubstitution(cls, check);
1292 if (body != null) { 1277 if (body != null) {
1293 buffer.write('$holder.${namer.substitutionName(check)}$_=${_}$body$N') ; 1278 buffer.write('$holder.${namer.substitutionName(check)}$_=${_}$body$N') ;
1294 } 1279 }
1295 }; 1280 };
1296 } 1281 }
1297 } 1282 }
1298 1283
1299 void visitNativeMixins(ClassElement classElement,
1300 void visit(MixinApplicationElement mixinApplication)) {
1301 if (!classElement.isNative()) return;
1302 // Use recursion to make sure to visit the superclasses before the
1303 // subclasses. Once we start keeping track of the emitted fields
1304 // and members, we're going to want to visit these in the other
1305 // order so we get the most specialized definition first.
1306 void recurse(ClassElement cls) {
1307 if (cls == null || !cls.isMixinApplication) return;
1308 recurse(cls.superclass);
1309 assert(!cls.isNative());
1310 visit(cls);
1311 }
1312 recurse(classElement.superclass);
1313 }
1314
1315 /** 1284 /**
1316 * Documentation wanted -- johnniwinther 1285 * Documentation wanted -- johnniwinther
1317 * 1286 *
1318 * Invariant: [classElement] must be a declaration element. 1287 * Invariant: [classElement] must be a declaration element.
1319 */ 1288 */
1320 void visitClassFields(ClassElement classElement, 1289 void visitClassFields(ClassElement classElement,
1321 void addField(Element member, 1290 void addField(Element member,
1322 String name, 1291 String name,
1323 String accessorName, 1292 String accessorName,
1324 bool needsGetter, 1293 bool needsGetter,
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1382 needsSetter, 1351 needsSetter,
1383 needsCheckedSetter); 1352 needsCheckedSetter);
1384 } 1353 }
1385 } 1354 }
1386 1355
1387 // TODO(kasperl): We should make sure to only emit one version of 1356 // TODO(kasperl): We should make sure to only emit one version of
1388 // overridden fields. Right now, we rely on the ordering so the 1357 // overridden fields. Right now, we rely on the ordering so the
1389 // fields pulled in from mixins are replaced with the fields from 1358 // fields pulled in from mixins are replaced with the fields from
1390 // the class definition. 1359 // the class definition.
1391 1360
1392 // If the class is a native class, we have to add the fields
1393 // defined in the non-native mixin applications used by the class.
1394 visitNativeMixins(classElement, (MixinApplicationElement mixin) {
1395 mixin.forEachInstanceField(
1396 visitField,
1397 includeBackendMembers: true,
1398 includeSuperMembers: false);
1399 });
1400
1401 // If a class is not instantiated then we add the field just so we can 1361 // If a class is not instantiated then we add the field just so we can
1402 // generate the field getter/setter dynamically. Since this is only 1362 // generate the field getter/setter dynamically. Since this is only
1403 // allowed on fields that are in [classElement] we don't need to visit 1363 // allowed on fields that are in [classElement] we don't need to visit
1404 // superclasses for non-instantiated classes. 1364 // superclasses for non-instantiated classes.
1405 classElement.implementation.forEachInstanceField( 1365 classElement.implementation.forEachInstanceField(
1406 visitField, 1366 visitField,
1407 includeBackendMembers: true, 1367 includeBackendMembers: true,
1408 includeSuperMembers: isInstantiated && !classElement.isNative()); 1368 includeSuperMembers: isInstantiated);
1409 } 1369 }
1410 1370
1411 void generateGetter(Element member, String fieldName, String accessorName, 1371 void generateGetter(Element member, String fieldName, String accessorName,
1412 ClassBuilder builder) { 1372 ClassBuilder builder) {
1413 String getterName = namer.getterNameFromAccessorName(accessorName); 1373 String getterName = namer.getterNameFromAccessorName(accessorName);
1414 String receiver = backend.isInterceptorClass(member.getEnclosingClass()) 1374 String receiver = backend.isInterceptorClass(member.getEnclosingClass())
1415 ? 'receiver' : 'this'; 1375 ? 'receiver' : 'this';
1416 List<String> args = backend.isInterceptedMethod(member) 1376 List<String> args = backend.isInterceptedMethod(member)
1417 ? ['receiver'] 1377 ? ['receiver']
1418 : []; 1378 : [];
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
1583 * 1543 *
1584 * Invariant: [classElement] must be a declaration element. 1544 * Invariant: [classElement] must be a declaration element.
1585 */ 1545 */
1586 void generateClass(ClassElement classElement, CodeBuffer buffer) { 1546 void generateClass(ClassElement classElement, CodeBuffer buffer) {
1587 assert(invariant(classElement, classElement.isDeclaration)); 1547 assert(invariant(classElement, classElement.isDeclaration));
1588 assert(invariant(classElement, !classElement.isNative())); 1548 assert(invariant(classElement, !classElement.isNative()));
1589 1549
1590 needsDefineClass = true; 1550 needsDefineClass = true;
1591 String className = namer.getName(classElement); 1551 String className = namer.getName(classElement);
1592 1552
1593 // Find the first non-native superclass.
1594 ClassElement superclass = classElement.superclass; 1553 ClassElement superclass = classElement.superclass;
1595 while (superclass != null && superclass.isNative()) {
1596 superclass = superclass.superclass;
1597 }
1598
1599 String superName = ""; 1554 String superName = "";
1600 if (superclass != null) { 1555 if (superclass != null) {
1601 superName = namer.getName(superclass); 1556 superName = namer.getName(superclass);
1602 } 1557 }
1603 1558
1604 ClassBuilder builder = new ClassBuilder(); 1559 ClassBuilder builder = new ClassBuilder();
1605 1560
1606 emitClassConstructor(classElement, builder); 1561 emitClassConstructor(classElement, builder);
1607 emitSuper(superName, builder); 1562 emitSuper(superName, builder);
1608 emitClassFields(classElement, builder, 1563 emitClassFields(classElement, builder,
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
1718 emitSubstitution, 1673 emitSubstitution,
1719 generated); 1674 generated);
1720 getTypedefChecksOn(call.computeType(compiler)).forEach(emitIsTest); 1675 getTypedefChecksOn(call.computeType(compiler)).forEach(emitIsTest);
1721 } 1676 }
1722 } 1677 }
1723 1678
1724 for (DartType interfaceType in cls.interfaces) { 1679 for (DartType interfaceType in cls.interfaces) {
1725 generateInterfacesIsTests(interfaceType.element, emitIsTest, 1680 generateInterfacesIsTests(interfaceType.element, emitIsTest,
1726 emitSubstitution, generated); 1681 emitSubstitution, generated);
1727 } 1682 }
1728
1729 // For native classes, we also have to run through their mixin
1730 // applications and make sure we deal with 'is' tests correctly
1731 // for those.
1732 visitNativeMixins(cls, (MixinApplicationElement mixin) {
1733 for (DartType interfaceType in mixin.interfaces) {
1734 ClassElement interfaceElement = interfaceType.element;
1735 generateInterfacesIsTests(interfaceType.element, emitIsTest,
1736 emitSubstitution, generated);
1737 }
1738 });
1739 } 1683 }
1740 1684
1741 /** 1685 /**
1742 * Generate "is tests" where [cls] is being implemented. 1686 * Generate "is tests" where [cls] is being implemented.
1743 */ 1687 */
1744 void generateInterfacesIsTests(ClassElement cls, 1688 void generateInterfacesIsTests(ClassElement cls,
1745 void emitIsTest(ClassElement element), 1689 void emitIsTest(ClassElement element),
1746 void emitSubstitution(ClassElement element), 1690 void emitSubstitution(ClassElement element),
1747 Set<Element> alreadyGenerated) { 1691 Set<Element> alreadyGenerated) {
1748 void tryEmitTest(ClassElement check) { 1692 void tryEmitTest(ClassElement check) {
(...skipping 1371 matching lines...) Expand 10 before | Expand all | Expand 10 after
3120 """; 3064 """;
3121 const String HOOKS_API_USAGE = """ 3065 const String HOOKS_API_USAGE = """
3122 // The code supports the following hooks: 3066 // The code supports the following hooks:
3123 // dartPrint(message) - if this function is defined it is called 3067 // dartPrint(message) - if this function is defined it is called
3124 // instead of the Dart [print] method. 3068 // instead of the Dart [print] method.
3125 // dartMainRunner(main) - if this function is defined, the Dart [main] 3069 // dartMainRunner(main) - if this function is defined, the Dart [main]
3126 // method will not be invoked directly. 3070 // method will not be invoked directly.
3127 // Instead, a closure that will invoke [main] is 3071 // Instead, a closure that will invoke [main] is
3128 // passed to [dartMainRunner]. 3072 // passed to [dartMainRunner].
3129 """; 3073 """;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698