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

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

Powered by Google App Engine
This is Rietveld 408576698