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 1153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 """; |
OLD | NEW |