OLD | NEW |
---|---|
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 2 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
3 # for details. All rights reserved. Use of this source code is governed by a | 3 # for details. All rights reserved. Use of this source code is governed by a |
4 # BSD-style license that can be found in the LICENSE file. | 4 # BSD-style license that can be found in the LICENSE file. |
5 | 5 |
6 """This module generates Dart APIs from the IDL database.""" | 6 """This module generates Dart APIs from the IDL database.""" |
7 | 7 |
8 import emitter | 8 import emitter |
9 import idlnode | 9 import idlnode |
10 import logging | 10 import logging |
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
358 interface.parents = filter(HasAnnotations, interface.parents) | 358 interface.parents = filter(HasAnnotations, interface.parents) |
359 else: | 359 else: |
360 database.DeleteInterface(interface.id) | 360 database.DeleteInterface(interface.id) |
361 | 361 |
362 self.FilterMembersWithUnidentifiedTypes(database) | 362 self.FilterMembersWithUnidentifiedTypes(database) |
363 | 363 |
364 | 364 |
365 def Generate(self, database, output_dir, | 365 def Generate(self, database, output_dir, |
366 module_source_preference=[], source_filter=None, | 366 module_source_preference=[], source_filter=None, |
367 super_database=None, common_prefix=None, super_map={}, | 367 super_database=None, common_prefix=None, super_map={}, |
368 lib_dir = None): | 368 lib_dir=None, native=False): |
369 """Generates Dart and JS files for the loaded interfaces. | 369 """Generates Dart and JS files for the loaded interfaces. |
370 | 370 |
371 Args: | 371 Args: |
372 database -- database containing interfaces to generate code for. | 372 database -- database containing interfaces to generate code for. |
373 output_dir -- directory to write generated files to. | 373 output_dir -- directory to write generated files to. |
374 module_source_preference -- priority order list of source annotations to | 374 module_source_preference -- priority order list of source annotations to |
375 use when choosing a module name, if none specified uses the module name | 375 use when choosing a module name, if none specified uses the module name |
376 from the database. | 376 from the database. |
377 source_filter -- if specified, only outputs interfaces that have one of | 377 source_filter -- if specified, only outputs interfaces that have one of |
378 these source annotation and rewrites the names of superclasses not | 378 these source annotation and rewrites the names of superclasses not |
379 marked with this source to use the common prefix. | 379 marked with this source to use the common prefix. |
380 super_database -- database containing super interfaces that the generated | 380 super_database -- database containing super interfaces that the generated |
381 interfaces should extend. | 381 interfaces should extend. |
382 common_prefix -- prefix for the common library, if any. | 382 common_prefix -- prefix for the common library, if any. |
383 lib_file_path -- filename for generated .lib file, None if not required. | 383 lib_file_path -- filename for generated .lib file, None if not required. |
384 lib_template -- template file in this directory for generated lib file. | 384 lib_template -- template file in this directory for generated lib file. |
385 """ | 385 """ |
386 | 386 |
387 self._emitters = multiemitter.MultiEmitter() | 387 self._emitters = multiemitter.MultiEmitter() |
388 self._database = database | 388 self._database = database |
389 self._output_dir = output_dir | 389 self._output_dir = output_dir |
390 | 390 |
391 self._ComputeInheritanceClosure() | 391 self._ComputeInheritanceClosure() |
392 | 392 |
393 self._systems = [] | |
394 | |
393 interface_system = InterfacesSystem( | 395 interface_system = InterfacesSystem( |
394 TemplateLoader(self._template_dir, ['dom/interface', 'dom', '']), | 396 TemplateLoader(self._template_dir, ['dom/interface', 'dom', '']), |
395 self._database, self._emitters, self._output_dir) | 397 self._database, self._emitters, self._output_dir) |
398 self._systems.append(interface_system) | |
396 | 399 |
397 wrapping_system = WrappingImplementationSystem( | 400 if native: |
398 TemplateLoader(self._template_dir, ['dom/wrapping', 'dom', '']), | 401 native_system = NativeImplementationSystem( |
399 self._database, self._emitters, self._output_dir) | 402 TemplateLoader(self._template_dir, ['dom/native', 'dom', '']), |
403 self._database, self._emitters, self._auxiliary_dir, | |
404 self._output_dir) | |
405 self._systems.append(native_system) | |
406 else: | |
407 wrapping_system = WrappingImplementationSystem( | |
408 TemplateLoader(self._template_dir, ['dom/wrapping', 'dom', '']), | |
409 self._database, self._emitters, self._output_dir) | |
400 | 410 |
401 # Makes interface files available for listing in the library for the | 411 # Makes interface files available for listing in the library for the |
402 # wrapping implementation. | 412 # wrapping implementation. |
403 | 413 |
404 wrapping_system._interface_system = interface_system | 414 wrapping_system._interface_system = interface_system |
415 self._systems.append(wrapping_system) | |
405 | 416 |
406 frog_system = FrogSystem( | 417 frog_system = FrogSystem( |
407 TemplateLoader(self._template_dir, ['dom/frog', 'dom', '']), | 418 TemplateLoader(self._template_dir, ['dom/frog', 'dom', '']), |
408 self._database, self._emitters, self._output_dir) | 419 self._database, self._emitters, self._output_dir) |
409 | 420 |
410 frog_system._interface_system = interface_system | 421 frog_system._interface_system = interface_system |
422 self._systems.append(frog_system) | |
411 | 423 |
412 self._systems = [interface_system, | |
413 wrapping_system, | |
414 frog_system] | |
415 | 424 |
416 # Render all interfaces into Dart and save them in files. | 425 # Render all interfaces into Dart and save them in files. |
417 for interface in database.GetInterfaces(): | 426 for interface in database.GetInterfaces(): |
418 | 427 |
419 super_interface = None | 428 super_interface = None |
420 super_name = interface.id | 429 super_name = interface.id |
421 | 430 |
422 if not _MatchSourceFilter(source_filter, interface): | 431 if not _MatchSourceFilter(source_filter, interface): |
423 # Skip this interface since it's not present in the required source | 432 # Skip this interface since it's not present in the required source |
424 _logger.info('Omitting interface - %s' % interface.id) | 433 _logger.info('Omitting interface - %s' % interface.id) |
(...skipping 873 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1298 | 1307 |
1299 | 1308 |
1300 def StartInterface(self): | 1309 def StartInterface(self): |
1301 interface = self._interface | 1310 interface = self._interface |
1302 interface_name = interface.id | 1311 interface_name = interface.id |
1303 | 1312 |
1304 self._class_name = self._ImplClassName(interface_name) | 1313 self._class_name = self._ImplClassName(interface_name) |
1305 self._type_map.Emit(' "$INTERFACE": native_$(CLASS)_create_$(CLASS),\n', | 1314 self._type_map.Emit(' "$INTERFACE": native_$(CLASS)_create_$(CLASS),\n', |
1306 INTERFACE=interface_name, CLASS=self._class_name) | 1315 INTERFACE=interface_name, CLASS=self._class_name) |
1307 | 1316 |
1308 base = 'DOMWrapperBase' | 1317 base = self._BaseClassName(interface) |
1309 if interface.parents: | |
1310 supertype = interface.parents[0].type.id | |
1311 # FIXME: We're currently injecting List<..> and EventTarget as | |
1312 # supertypes in dart.idl. We should annotate/preserve as | |
1313 # attributes instead. For now, this hack lets the interfaces | |
1314 # inherit, but not the classes. | |
1315 if (not _IsDartListType(supertype) and | |
1316 not supertype == 'EventTarget'): | |
1317 base = self._ImplClassName(supertype) | |
1318 if _IsDartCollectionType(supertype): | |
1319 # List methods are injected in AddIndexer. | |
1320 pass | |
1321 elif supertype == 'EventTarget': | |
1322 # Most implementors of EventTarget specify the EventListener operations | |
1323 # again. If the operations are not specified, try to inherit from the | |
1324 # EventTarget implementation. | |
1325 # | |
1326 # Applies to MessagePort. | |
1327 if not [op for op in interface.operations if op.id == 'addEventListener' ]: | |
1328 base = self._ImplClassName(supertype) | |
1329 else: | |
1330 base = self._ImplClassName(supertype) | |
1331 | 1318 |
1332 (self._members_emitter, | 1319 (self._members_emitter, |
1333 self._top_level_emitter) = self._dart_code.Emit( | 1320 self._top_level_emitter) = self._dart_code.Emit( |
1334 '\n' | 1321 '\n' |
1335 'class $CLASS extends $BASE implements $INTERFACE {\n' | 1322 'class $CLASS extends $BASE implements $INTERFACE {\n' |
1336 ' $CLASS() : super() {}\n' | 1323 ' $CLASS() : super() {}\n' |
1337 '\n' | 1324 '\n' |
1338 ' static create_$CLASS() native {\n' | 1325 ' static create_$CLASS() native {\n' |
1339 ' return new $CLASS();\n' | 1326 ' return new $CLASS();\n' |
1340 ' }\n' | 1327 ' }\n' |
1341 '$!MEMBERS' | 1328 '$!MEMBERS' |
1342 '\n' | 1329 '\n' |
1343 ' String get typeName() { return "$INTERFACE"; }\n' | 1330 ' String get typeName() { return "$INTERFACE"; }\n' |
1344 '}\n' | 1331 '}\n' |
1345 '$!TOP_LEVEL', | 1332 '$!TOP_LEVEL', |
1346 CLASS=self._class_name, BASE=base, INTERFACE=interface_name) | 1333 CLASS=self._class_name, BASE=base, INTERFACE=interface_name) |
1347 | 1334 |
1348 def _ImplClassName(self, type_name): | 1335 def _ImplClassName(self, type_name): |
1349 return '_' + type_name + 'WrappingImplementation' | 1336 return '_' + type_name + 'WrappingImplementation' |
1350 | 1337 |
1338 def _BaseClassName(self, interface): | |
1339 if not interface.parents: | |
1340 return 'DOMWrapperBase' | |
1341 | |
1342 supertype = interface.parents[0].type.id | |
1343 # FIXME: We're currently injecting List<..> and EventTarget as | |
1344 # supertypes in dart.idl. We should annotate/preserve as | |
1345 # attributes instead. For now, this hack lets the interfaces | |
1346 # inherit, but not the classes. | |
1347 if (not _IsDartListType(supertype) and | |
1348 not supertype == 'EventTarget'): | |
1349 return self._ImplClassName(supertype) | |
1350 | |
1351 if _IsDartCollectionType(supertype): | |
1352 # List methods are injected in AddIndexer. | |
1353 return 'DOMWrapperBase' | |
1354 | |
1355 if supertype == 'EventTarget': | |
1356 # Most implementors of EventTarget specify the EventListener operations | |
1357 # again. If the operations are not specified, try to inherit from the | |
1358 # EventTarget implementation. | |
1359 # | |
1360 # Applies to MessagePort. | |
1361 if not [op for op in interface.operations if op.id == 'addEventListener']: | |
1362 return self._ImplClassName(supertype) | |
1363 else: | |
1364 return self._ImplClassName(supertype) | |
1365 | |
1366 return 'DOMWrapperBase' | |
1367 | |
1351 def FinishInterface(self): | 1368 def FinishInterface(self): |
1352 """.""" | 1369 """.""" |
1353 pass | 1370 pass |
1354 | 1371 |
1355 def AddConstant(self, constant): | 1372 def AddConstant(self, constant): |
1356 # Constants are already defined on the interface. | 1373 # Constants are already defined on the interface. |
1357 pass | 1374 pass |
1358 | 1375 |
1359 def _MethodName(self, prefix, name): | 1376 def _MethodName(self, prefix, name): |
1360 method_name = prefix + name | 1377 method_name = prefix + name |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1434 # interface Y extends X, List<T> ... | 1451 # interface Y extends X, List<T> ... |
1435 # | 1452 # |
1436 # In the non-root case we have to choose between: | 1453 # In the non-root case we have to choose between: |
1437 # | 1454 # |
1438 # class YImpl extends XImpl { add List<T> methods; } | 1455 # class YImpl extends XImpl { add List<T> methods; } |
1439 # | 1456 # |
1440 # and | 1457 # and |
1441 # | 1458 # |
1442 # class YImpl extends ListBase<T> { copies of transitive XImpl methods; } | 1459 # class YImpl extends ListBase<T> { copies of transitive XImpl methods; } |
1443 # | 1460 # |
1444 if ('HasIndexGetter' in self._interface.ext_attrs or | 1461 if self._HasNativeIndexGetter(self._interface): |
1445 'HasNumericIndexGetter' in self._interface.ext_attrs): | 1462 self._EmitNativeIndexGetter(self._interface, element_type) |
1446 method_name = '_index' | |
1447 self._members_emitter.Emit( | |
1448 '\n' | |
1449 ' $TYPE operator[](int index) { return $METHOD(this, index); }\n' | |
1450 ' static $TYPE $METHOD(var _this, int index) native;\n', | |
1451 TYPE=element_type, METHOD=method_name) | |
1452 self._js_code.Emit( | |
1453 '\n' | |
1454 'function native_$(CLASS)_$(METHOD)(_this, index) {\n' | |
1455 ' try {\n' | |
1456 ' return __dom_wrap(_this.$dom[index]);\n' | |
1457 ' } catch (e) {\n' | |
1458 ' throw __dom_wrap_exception(e);\n' | |
1459 ' }\n' | |
1460 '}\n', | |
1461 CLASS=self._class_name, METHOD=method_name) | |
1462 else: | 1463 else: |
1463 self._members_emitter.Emit( | 1464 self._members_emitter.Emit( |
1464 '\n' | 1465 '\n' |
1465 ' $TYPE operator[](int index) {\n' | 1466 ' $TYPE operator[](int index) {\n' |
1466 ' return item(index);\n' | 1467 ' return item(index);\n' |
1467 ' }\n', | 1468 ' }\n', |
1468 TYPE=element_type) | 1469 TYPE=element_type) |
1469 | 1470 |
1470 | 1471 if self._HasNativeIndexSetter(self._interface): |
1471 if 'HasCustomIndexSetter' in self._interface.ext_attrs: | 1472 self._EmitNativeIndexSetter(self._interface, element_type) |
1472 method_name = '_set_index' | |
1473 self._members_emitter.Emit( | |
1474 '\n' | |
1475 ' void operator[]=(int index, $TYPE value) {\n' | |
1476 ' return $METHOD(this, index, value);\n' | |
1477 ' }\n' | |
1478 ' static $METHOD(_this, index, value) native;\n', | |
1479 TYPE=element_type, METHOD=method_name) | |
1480 self._js_code.Emit( | |
1481 '\n' | |
1482 'function native_$(CLASS)_$(METHOD)(_this, index, value) {\n' | |
1483 ' try {\n' | |
1484 ' return _this.$dom[index] = __dom_unwrap(value);\n' | |
1485 ' } catch (e) {\n' | |
1486 ' throw __dom_wrap_exception(e);\n' | |
1487 ' }\n' | |
1488 '}\n', | |
1489 CLASS=self._class_name, METHOD=method_name) | |
1490 else: | 1473 else: |
1491 self._members_emitter.Emit( | 1474 self._members_emitter.Emit( |
1492 '\n' | 1475 '\n' |
1493 ' void operator[]=(int index, $TYPE value) {\n' | 1476 ' void operator[]=(int index, $TYPE value) {\n' |
1494 ' throw new UnsupportedOperationException("Cannot assign element of immutable List.");\n' | 1477 ' throw new UnsupportedOperationException("Cannot assign element of immutable List.");\n' |
1495 ' }\n', | 1478 ' }\n', |
1496 TYPE=element_type) | 1479 TYPE=element_type) |
1497 | 1480 |
1498 self._members_emitter.Emit( | 1481 self._members_emitter.Emit( |
1499 '\n' | 1482 '\n' |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1577 '\n' | 1560 '\n' |
1578 ' bool isEmpty() {\n' | 1561 ' bool isEmpty() {\n' |
1579 ' return length == 0;\n' | 1562 ' return length == 0;\n' |
1580 ' }\n' | 1563 ' }\n' |
1581 '\n' | 1564 '\n' |
1582 ' Iterator<$TYPE> iterator() {\n' | 1565 ' Iterator<$TYPE> iterator() {\n' |
1583 ' return new _FixedSizeListIterator<$TYPE>(this);\n' | 1566 ' return new _FixedSizeListIterator<$TYPE>(this);\n' |
1584 ' }\n', | 1567 ' }\n', |
1585 TYPE=element_type) | 1568 TYPE=element_type) |
1586 | 1569 |
1570 def _HasNativeIndexGetter(self, interface): | |
1571 return ('HasIndexGetter' in interface.ext_attrs or | |
1572 'HasNumericIndexGetter' in interface.ext_attrs) | |
1573 | |
1574 def _EmitNativeIndexGetter(self, interface, element_type): | |
1575 method_name = '_index' | |
1576 self._members_emitter.Emit( | |
1577 '\n' | |
1578 ' $TYPE operator[](int index) { return $METHOD(this, index); }\n' | |
1579 ' static $TYPE $METHOD(var _this, int index) native;\n', | |
1580 TYPE=element_type, METHOD=method_name) | |
1581 self._js_code.Emit( | |
1582 '\n' | |
1583 'function native_$(CLASS)_$(METHOD)(_this, index) {\n' | |
1584 ' try {\n' | |
1585 ' return __dom_wrap(_this.$dom[index]);\n' | |
1586 ' } catch (e) {\n' | |
1587 ' throw __dom_wrap_exception(e);\n' | |
1588 ' }\n' | |
1589 '}\n', | |
1590 CLASS=self._class_name, METHOD=method_name) | |
1591 | |
1592 def _HasNativeIndexSetter(self, interface): | |
1593 return 'HasCustomIndexSetter' in interface.ext_attrs | |
1594 | |
1595 def _EmitNativeIndexSetter(self, interface, element_type): | |
1596 method_name = '_set_index' | |
1597 self._members_emitter.Emit( | |
1598 '\n' | |
1599 ' void operator[]=(int index, $TYPE value) {\n' | |
1600 ' return $METHOD(this, index, value);\n' | |
1601 ' }\n' | |
1602 ' static $METHOD(_this, index, value) native;\n', | |
1603 TYPE=element_type, METHOD=method_name) | |
1604 self._js_code.Emit( | |
1605 '\n' | |
1606 'function native_$(CLASS)_$(METHOD)(_this, index, value) {\n' | |
1607 ' try {\n' | |
1608 ' return _this.$dom[index] = __dom_unwrap(value);\n' | |
1609 ' } catch (e) {\n' | |
1610 ' throw __dom_wrap_exception(e);\n' | |
1611 ' }\n' | |
1612 '}\n', | |
1613 CLASS=self._class_name, METHOD=method_name) | |
1614 | |
1587 def AddOperation(self, info): | 1615 def AddOperation(self, info): |
1588 """ | 1616 """ |
1589 Arguments: | 1617 Arguments: |
1590 info: An OperationInfo object. | 1618 info: An OperationInfo object. |
1591 """ | 1619 """ |
1592 body = self._members_emitter.Emit( | 1620 body = self._members_emitter.Emit( |
1593 '\n' | 1621 '\n' |
1594 ' $TYPE $NAME($PARAMS) {\n' | 1622 ' $TYPE $NAME($PARAMS) {\n' |
1595 '$!BODY' | 1623 '$!BODY' |
1596 ' }\n', | 1624 ' }\n', |
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2027 info: An OperationInfo object. | 2055 info: An OperationInfo object. |
2028 """ | 2056 """ |
2029 # TODO(vsm): Handle overloads. | 2057 # TODO(vsm): Handle overloads. |
2030 self._members_emitter.Emit( | 2058 self._members_emitter.Emit( |
2031 '\n' | 2059 '\n' |
2032 ' $TYPE $NAME($PARAMS) native;\n', | 2060 ' $TYPE $NAME($PARAMS) native;\n', |
2033 TYPE=self._NarrowOutputType(info.type_name), | 2061 TYPE=self._NarrowOutputType(info.type_name), |
2034 NAME=info.name, | 2062 NAME=info.name, |
2035 PARAMS=info.ParametersImplementationDeclaration( | 2063 PARAMS=info.ParametersImplementationDeclaration( |
2036 lambda type_name: self._NarrowInputType(type_name))) | 2064 lambda type_name: self._NarrowInputType(type_name))) |
2065 | |
2066 | |
2067 # ------------------------------------------------------------------------------ | |
2068 | |
2069 class NativeImplementationSystem(System): | |
2070 | |
2071 def __init__(self, templates, database, emitters, auxiliary_dir, output_dir): | |
2072 super(NativeImplementationSystem, self).__init__( | |
2073 templates, database, emitters, output_dir) | |
2074 | |
2075 self._auxiliary_dir = auxiliary_dir | |
2076 | |
2077 self._dom_public_imports_emitter = emitter.Emitter() | |
2078 self._dom_impl_imports_emitter = emitter.Emitter() | |
2079 | |
2080 def InterfaceGenerator(self, | |
2081 interface, | |
2082 common_prefix, | |
2083 super_interface_name, | |
2084 source_filter): | |
2085 interface_name = interface.id | |
2086 | |
2087 self._dom_public_imports_emitter.Emit('#source("$PATH");\n', | |
2088 PATH=self._FilePathForDartInterface(interface_name)) | |
2089 self._dom_impl_imports_emitter.Emit('#source("$PATH");\n', | |
2090 PATH=self._FilePathForDartImpl(interface_name)) | |
2091 | |
2092 dart_impl_path = os.path.join(self._output_dir, | |
2093 self._FilePathForDartImpl(interface_name)) | |
2094 dart_impl_emitter = self._emitters.FileEmitter(dart_impl_path) | |
2095 | |
2096 return NativeImplementationGenerator(interface, super_interface_name, | |
2097 dart_impl_emitter, | |
2098 self._BaseDefines(interface), | |
2099 self._templates) | |
2100 | |
2101 def ProcessCallback(self, interface, info): | |
2102 self._dom_public_imports_emitter.Emit('#source("$PATH");\n', | |
2103 PATH=self._FilePathForDartInterface(interface.id)) | |
2104 | |
2105 def GenerateLibraries(self, lib_dir): | |
2106 auxiliary_dir = os.path.relpath(self._auxiliary_dir, self._output_dir) | |
2107 | |
2108 # Generate dom_public.dart | |
antonm
2012/01/26 14:32:05
nit: do not we need a trailing dot here?
podivilov
2012/01/26 14:52:37
Done.
| |
2109 dom_public_path = os.path.join(self._output_dir, 'dom_public.dart') | |
2110 dom_public_emitter = self._emitters.FileEmitter(dom_public_path) | |
2111 dom_public_emitter.Emit(self._templates.Load('dom_public.darttemplate'), | |
2112 AUXILIARY_DIR=auxiliary_dir, | |
2113 SOURCES=self._dom_public_imports_emitter.Fragments()) | |
2114 | |
2115 # Generate dom_impl.dart | |
antonm
2012/01/26 14:32:05
ditto
podivilov
2012/01/26 14:52:37
Done.
| |
2116 dom_impl_path = os.path.join(self._output_dir, 'dom_impl.dart') | |
2117 dom_impl_emitter = self._emitters.FileEmitter(dom_impl_path) | |
2118 dom_impl_emitter.Emit(self._templates.Load('dom_impl.darttemplate'), | |
2119 AUXILIARY_DIR=auxiliary_dir, | |
2120 SOURCES=self._dom_impl_imports_emitter.Fragments()) | |
2121 | |
2122 def Finish(self): | |
2123 pass | |
2124 | |
2125 def _FilePathForDartInterface(self, interface_name): | |
2126 return os.path.join('src', 'interface', '%s.dart' % interface_name) | |
2127 | |
2128 def _FilePathForDartImpl(self, interface_name): | |
2129 return os.path.join('dart', '%sImplementation.dart' % interface_name) | |
2130 | |
2131 | |
2132 class NativeImplementationGenerator(WrappingInterfaceGenerator): | |
2133 """Generates Dart implementation for one DOM IDL interface.""" | |
2134 | |
2135 def __init__(self, interface, super_interface, dart_impl_emitter, | |
2136 base_members, templates): | |
2137 """Generates Dart code for the given interface. | |
2138 | |
2139 Args: | |
2140 | |
2141 interface: an IDLInterface instance. It is assumed that all types have | |
2142 been converted to Dart types (e.g. int, String), unless they are in | |
2143 the same package as the interface. | |
2144 super_interface: A string or None, the name of the common interface that | |
2145 this interface implements, if any. | |
2146 dart_impl_emitter: an Emitter for the file containing the Dart | |
2147 implementation class. | |
2148 base_members: a set of names of members defined in a base class. This is | |
2149 used to avoid static member 'overriding' in the generated Dart code. | |
2150 """ | |
2151 self._interface = interface | |
2152 self._super_interface = super_interface | |
2153 self._dart_impl_emitter = dart_impl_emitter | |
2154 self._base_members = base_members | |
2155 self._templates = templates | |
2156 self._current_secondary_parent = None | |
2157 | |
2158 def StartInterface(self): | |
2159 self._class_name = self._ImplClassName(self._interface.id) | |
2160 self._members_emitter = emitter.Emitter() | |
2161 | |
2162 def _ImplClassName(self, type_name): | |
2163 return type_name + 'Implementation' | |
2164 | |
2165 def FinishInterface(self): | |
2166 interface = self._interface | |
2167 interface_name = interface.id | |
2168 | |
2169 base = self._BaseClassName(interface) | |
2170 self._dart_impl_emitter.Emit( | |
2171 self._templates.Load('dart_implementation.darttemplate'), | |
2172 CLASS=self._class_name, BASE=base, INTERFACE=interface_name, | |
2173 MEMBERS=self._members_emitter.Fragments()) | |
2174 | |
2175 def AddGetter(self, attr): | |
2176 self._members_emitter.Emit( | |
2177 '\n' | |
2178 ' $TYPE get $NAME() native "$(INTERFACE)_$(NAME)_Getter";\n', | |
2179 NAME=attr.id, TYPE=attr.type.id, INTERFACE=self._interface.id) | |
2180 | |
2181 def AddSetter(self, attr): | |
2182 self._members_emitter.Emit( | |
2183 '\n' | |
2184 ' void set $NAME($TYPE) native "$(INTERFACE)_$(NAME)_Setter";\n', | |
2185 NAME=attr.id, TYPE=attr.type.id, INTERFACE=self._interface.id) | |
2186 | |
2187 def _HasNativeIndexGetter(self, interface): | |
antonm
2012/01/26 14:32:05
why do not you repeat _HasNativeIndexSetter?
podivilov
2012/01/26 14:52:37
_HasNativeIndexGetter has a different implementati
| |
2188 return ('HasCustomIndexGetter' in interface.ext_attrs or | |
2189 'HasNumericIndexGetter' in interface.ext_attrs) | |
2190 | |
2191 def _EmitNativeIndexGetter(self, interface, element_type): | |
2192 native_binding = '%s_numericIndexGetter_Callback' % interface.id | |
2193 self._members_emitter.Emit( | |
2194 '\n' | |
2195 ' $TYPE operator[](int index) native "$NATIVE_BINDING";\n', | |
2196 TYPE=element_type, NATIVE_BINDING=native_binding) | |
2197 | |
2198 def _EmitNativeIndexSetter(self, interface, element_type): | |
2199 native_binding = '%s_numericIndexSetter_Callback' % self._interface.id | |
2200 self._members_emitter.Emit( | |
2201 '\n' | |
2202 ' void operator[]=(int index, $TYPE value) native "$NATIVE_BINDING";\n' , | |
2203 TYPE=element_type, NATIVE_BINDING=native_binding) | |
2204 | |
2205 def AddOperation(self, info): | |
2206 """ | |
2207 Arguments: | |
2208 info: An OperationInfo object. | |
2209 """ | |
2210 | |
2211 if 'Custom' in info.overloads[0].ext_attrs: | |
2212 self._members_emitter.Emit( | |
2213 '\n' | |
2214 ' $TYPE $NAME($PARAMETERS) native "$(INTERFACE)_$(NAME)_Callback";\ n', | |
2215 TYPE=info.type_name, | |
2216 NAME=info.name, | |
2217 PARAMETERS=info.ParametersImplementationDeclaration(), | |
2218 INTERFACE=self._interface.id) | |
2219 return | |
2220 | |
2221 body = self._members_emitter.Emit( | |
2222 '\n' | |
2223 ' $TYPE $NAME($PARAMETERS) {\n' | |
2224 '$!BODY' | |
2225 ' }\n', | |
2226 TYPE=info.type_name, | |
2227 NAME=info.name, | |
2228 PARAMETERS=info.ParametersImplementationDeclaration()) | |
2229 | |
2230 # Process in order of ascending number of arguments to ensure missing | |
2231 # optional arguments are processed early. | |
2232 overloads = sorted(info.overloads, | |
2233 key=lambda overload: len(overload.arguments)) | |
2234 self._native_version = 0 | |
2235 fallthrough = self.GenerateDispatch(body, info, ' ', 0, overloads) | |
2236 if fallthrough: | |
2237 body.Emit(' throw "Incorrect number or type of arguments";\n'); | |
2238 | |
2239 def GenerateSingleOperation(self, emitter, info, indent, operation): | |
2240 """Generates a call to a single operation. | |
2241 | |
2242 Arguments: | |
2243 emitter: an Emitter for the body of a block of code. | |
2244 info: the compound information about the operation and its overloads. | |
2245 indent: an indentation string for generated code. | |
2246 operation: the IDLOperation to call. | |
2247 """ | |
2248 | |
2249 arg_names = [info.arg_infos[i][0] | |
2250 for (i, arg) in enumerate(operation.arguments)] | |
2251 | |
2252 self._native_version += 1 | |
2253 native_name = '_%s' % info.name | |
2254 if self._native_version > 1: | |
2255 native_name = '%s_%s' % (native_name, self._native_version) | |
2256 | |
2257 argument_expressions = ', '.join(arg_names) | |
2258 if info.type_name != 'void': | |
2259 emitter.Emit('$(INDENT)return $NATIVENAME($ARGS);\n', | |
2260 INDENT=indent, | |
2261 NATIVENAME=native_name, | |
2262 ARGS=argument_expressions) | |
2263 else: | |
2264 emitter.Emit('$(INDENT)$NATIVENAME($ARGS);\n' | |
2265 '$(INDENT)return;\n', | |
2266 INDENT=indent, | |
2267 NATIVENAME=native_name, | |
2268 ARGS=argument_expressions) | |
2269 | |
2270 self._members_emitter.Emit(' $TYPE $NATIVE_NAME($PARAMS) native "$(INTERFAC E)$(NATIVE_NAME)_Callback";\n', | |
2271 NATIVE_NAME=native_name, | |
2272 TYPE=info.type_name, | |
2273 PARAMS=', '.join(arg_names), | |
2274 INTERFACE=self._interface.id) | |
OLD | NEW |