OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 """; |
OLD | NEW |