Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 2 # Copyright (c) 2011, 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 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 394 interface.parents = filter(HasAnnotations, interface.parents) | 394 interface.parents = filter(HasAnnotations, interface.parents) |
| 395 else: | 395 else: |
| 396 database.DeleteInterface(interface.id) | 396 database.DeleteInterface(interface.id) |
| 397 | 397 |
| 398 self.FilterMembersWithUnidentifiedTypes(database) | 398 self.FilterMembersWithUnidentifiedTypes(database) |
| 399 | 399 |
| 400 | 400 |
| 401 def Generate(self, database, output_dir, | 401 def Generate(self, database, output_dir, |
| 402 module_source_preference=[], source_filter=None, | 402 module_source_preference=[], source_filter=None, |
| 403 super_database=None, common_prefix=None, super_map={}, | 403 super_database=None, common_prefix=None, super_map={}, |
| 404 lib_dir = None): | 404 lib_dir=None, native=False): |
| 405 """Generates Dart and JS files for the loaded interfaces. | 405 """Generates Dart and JS files for the loaded interfaces. |
| 406 | 406 |
| 407 Args: | 407 Args: |
| 408 database -- database containing interfaces to generate code for. | 408 database -- database containing interfaces to generate code for. |
| 409 output_dir -- directory to write generated files to. | 409 output_dir -- directory to write generated files to. |
| 410 module_source_preference -- priority order list of source annotations to | 410 module_source_preference -- priority order list of source annotations to |
| 411 use when choosing a module name, if none specified uses the module name | 411 use when choosing a module name, if none specified uses the module name |
| 412 from the database. | 412 from the database. |
| 413 source_filter -- if specified, only outputs interfaces that have one of | 413 source_filter -- if specified, only outputs interfaces that have one of |
| 414 these source annotation and rewrites the names of superclasses not | 414 these source annotation and rewrites the names of superclasses not |
| 415 marked with this source to use the common prefix. | 415 marked with this source to use the common prefix. |
| 416 super_database -- database containing super interfaces that the generated | 416 super_database -- database containing super interfaces that the generated |
| 417 interfaces should extend. | 417 interfaces should extend. |
| 418 common_prefix -- prefix for the common library, if any. | 418 common_prefix -- prefix for the common library, if any. |
| 419 lib_file_path -- filename for generated .lib file, None if not required. | 419 lib_file_path -- filename for generated .lib file, None if not required. |
| 420 lib_template -- template file in this directory for generated lib file. | 420 lib_template -- template file in this directory for generated lib file. |
| 421 """ | 421 """ |
| 422 | 422 |
| 423 self._emitters = multiemitter.MultiEmitter() | 423 self._emitters = multiemitter.MultiEmitter() |
| 424 self._database = database | 424 self._database = database |
| 425 self._output_dir = output_dir | 425 self._output_dir = output_dir |
| 426 | 426 |
| 427 self._ComputeInheritanceClosure() | 427 self._ComputeInheritanceClosure() |
| 428 | 428 |
| 429 self._systems = [] | |
| 430 | |
| 429 interface_system = InterfacesSystem( | 431 interface_system = InterfacesSystem( |
| 430 TemplateLoader(self._template_dir, ['dom/interface', 'dom', '']), | 432 TemplateLoader(self._template_dir, ['dom/interface', 'dom', '']), |
| 431 self._database, self._emitters, self._output_dir) | 433 self._database, self._emitters, self._output_dir) |
| 434 self._systems.append(interface_system) | |
| 432 | 435 |
| 433 wrapping_system = WrappingImplementationSystem( | 436 if native: |
| 434 TemplateLoader(self._template_dir, ['dom/wrapping', 'dom', '']), | 437 native_system = NativeImplementationSystem( |
| 435 self._database, self._emitters, self._output_dir) | 438 TemplateLoader(self._template_dir, ['dom/native', 'dom', '']), |
| 439 self._database, self._emitters, self._auxiliary_dir, | |
| 440 self._output_dir) | |
| 441 self._systems.append(native_system) | |
| 442 else: | |
|
sra1
2012/01/26 05:35:30
Is it possible to generate everything at once?
podivilov
2012/01/26 08:28:51
Yes, but it would be a little bit slower, will pro
sra1
2012/01/26 18:32:16
I want to make sure that all targets *can* be gene
podivilov
2012/01/30 19:23:50
Added --systems switch. It defaults to 'frog,wrapp
| |
| 443 wrapping_system = WrappingImplementationSystem( | |
| 444 TemplateLoader(self._template_dir, ['dom/wrapping', 'dom', '']), | |
| 445 self._database, self._emitters, self._output_dir) | |
| 436 | 446 |
| 437 # Makes interface files available for listing in the library for the | 447 # Makes interface files available for listing in the library for the |
| 438 # wrapping implementation. | 448 # wrapping implementation. |
| 439 | 449 |
| 440 wrapping_system._interface_system = interface_system | 450 wrapping_system._interface_system = interface_system |
| 451 self._systems.append(wrapping_system) | |
| 441 | 452 |
| 442 frog_system = FrogSystem( | 453 frog_system = FrogSystem( |
| 443 TemplateLoader(self._template_dir, ['dom/frog', 'dom', '']), | 454 TemplateLoader(self._template_dir, ['dom/frog', 'dom', '']), |
| 444 self._database, self._emitters, self._output_dir) | 455 self._database, self._emitters, self._output_dir) |
| 445 | 456 |
| 446 frog_system._interface_system = interface_system | 457 frog_system._interface_system = interface_system |
| 458 self._systems.append(frog_system) | |
| 447 | 459 |
| 448 self._systems = [interface_system, | |
| 449 wrapping_system, | |
| 450 frog_system] | |
| 451 | 460 |
| 452 # Render all interfaces into Dart and save them in files. | 461 # Render all interfaces into Dart and save them in files. |
| 453 for interface in database.GetInterfaces(): | 462 for interface in database.GetInterfaces(): |
| 454 | 463 |
| 455 super_interface = None | 464 super_interface = None |
| 456 super_name = interface.id | 465 super_name = interface.id |
| 457 | 466 |
| 458 if not _MatchSourceFilter(source_filter, interface): | 467 if not _MatchSourceFilter(source_filter, interface): |
| 459 # Skip this interface since it's not present in the required source | 468 # Skip this interface since it's not present in the required source |
| 460 _logger.info('Omitting interface - %s' % interface.id) | 469 _logger.info('Omitting interface - %s' % interface.id) |
| (...skipping 862 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1323 | 1332 |
| 1324 | 1333 |
| 1325 def StartInterface(self): | 1334 def StartInterface(self): |
| 1326 interface = self._interface | 1335 interface = self._interface |
| 1327 interface_name = interface.id | 1336 interface_name = interface.id |
| 1328 | 1337 |
| 1329 self._class_name = self._ImplClassName(interface_name) | 1338 self._class_name = self._ImplClassName(interface_name) |
| 1330 self._type_map.Emit(' "$INTERFACE": native_$(CLASS)_create_$(CLASS),\n', | 1339 self._type_map.Emit(' "$INTERFACE": native_$(CLASS)_create_$(CLASS),\n', |
| 1331 INTERFACE=interface_name, CLASS=self._class_name) | 1340 INTERFACE=interface_name, CLASS=self._class_name) |
| 1332 | 1341 |
| 1333 base = 'DOMWrapperBase' | 1342 base = self._BaseClassName(interface) |
| 1334 if interface.parents: | |
| 1335 supertype = interface.parents[0].type.id | |
| 1336 # FIXME: We're currently injecting List<..> and EventTarget as | |
| 1337 # supertypes in dart.idl. We should annotate/preserve as | |
| 1338 # attributes instead. For now, this hack lets the interfaces | |
| 1339 # inherit, but not the classes. | |
| 1340 if (not _IsDartListType(supertype) and | |
| 1341 not supertype == 'EventTarget'): | |
| 1342 base = self._ImplClassName(supertype) | |
| 1343 if _IsDartCollectionType(supertype): | |
| 1344 # List methods are injected in AddIndexer. | |
| 1345 pass | |
| 1346 elif supertype == 'EventTarget': | |
| 1347 # Most implementors of EventTarget specify the EventListener operations | |
| 1348 # again. If the operations are not specified, try to inherit from the | |
| 1349 # EventTarget implementation. | |
| 1350 # | |
| 1351 # Applies to MessagePort. | |
| 1352 if not [op for op in interface.operations if op.id == 'addEventListener' ]: | |
| 1353 base = self._ImplClassName(supertype) | |
| 1354 else: | |
| 1355 base = self._ImplClassName(supertype) | |
| 1356 | 1343 |
| 1357 (self._members_emitter, | 1344 (self._members_emitter, |
| 1358 self._top_level_emitter) = self._dart_code.Emit( | 1345 self._top_level_emitter) = self._dart_code.Emit( |
| 1359 '\n' | 1346 '\n' |
| 1360 'class $CLASS extends $BASE implements $INTERFACE {\n' | 1347 'class $CLASS extends $BASE implements $INTERFACE {\n' |
| 1361 ' $CLASS() : super() {}\n' | 1348 ' $CLASS() : super() {}\n' |
| 1362 '\n' | 1349 '\n' |
| 1363 ' static create_$CLASS() native {\n' | 1350 ' static create_$CLASS() native {\n' |
| 1364 ' return new $CLASS();\n' | 1351 ' return new $CLASS();\n' |
| 1365 ' }\n' | 1352 ' }\n' |
| 1366 '$!MEMBERS' | 1353 '$!MEMBERS' |
| 1367 '\n' | 1354 '\n' |
| 1368 ' String get typeName() { return "$INTERFACE"; }\n' | 1355 ' String get typeName() { return "$INTERFACE"; }\n' |
| 1369 '}\n' | 1356 '}\n' |
| 1370 '$!TOP_LEVEL', | 1357 '$!TOP_LEVEL', |
| 1371 CLASS=self._class_name, BASE=base, INTERFACE=interface_name) | 1358 CLASS=self._class_name, BASE=base, INTERFACE=interface_name) |
| 1372 | 1359 |
| 1373 def _ImplClassName(self, type_name): | 1360 def _ImplClassName(self, type_name): |
| 1374 return '_' + type_name + 'WrappingImplementation' | 1361 return '_' + type_name + 'WrappingImplementation' |
| 1375 | 1362 |
| 1363 def _BaseClassName(self, interface): | |
|
antonm
2012/01/26 11:06:14
it looks like you can simplify this function w/ ea
podivilov
2012/01/26 14:18:57
Done.
| |
| 1364 base = 'DOMWrapperBase' | |
| 1365 | |
| 1366 if not interface.parents: | |
| 1367 return base | |
| 1368 | |
| 1369 supertype = interface.parents[0].type.id | |
| 1370 # FIXME: We're currently injecting List<..> and EventTarget as | |
| 1371 # supertypes in dart.idl. We should annotate/preserve as | |
| 1372 # attributes instead. For now, this hack lets the interfaces | |
| 1373 # inherit, but not the classes. | |
| 1374 if (not _IsDartListType(supertype) and | |
| 1375 not supertype == 'EventTarget'): | |
| 1376 base = self._ImplClassName(supertype) | |
| 1377 if _IsDartCollectionType(supertype): | |
| 1378 # List methods are injected in AddIndexer. | |
| 1379 pass | |
| 1380 elif supertype == 'EventTarget': | |
| 1381 # Most implementors of EventTarget specify the EventListener operations | |
| 1382 # again. If the operations are not specified, try to inherit from the | |
| 1383 # EventTarget implementation. | |
| 1384 # | |
| 1385 # Applies to MessagePort. | |
| 1386 if not [op for op in interface.operations if op.id == 'addEventListener']: | |
| 1387 base = self._ImplClassName(supertype) | |
| 1388 else: | |
| 1389 base = self._ImplClassName(supertype) | |
| 1390 | |
| 1391 return base | |
| 1392 | |
| 1376 def FinishInterface(self): | 1393 def FinishInterface(self): |
| 1377 """.""" | 1394 """.""" |
| 1378 pass | 1395 pass |
| 1379 | 1396 |
| 1380 def AddConstant(self, constant): | 1397 def AddConstant(self, constant): |
| 1381 # Constants are already defined on the interface. | 1398 # Constants are already defined on the interface. |
| 1382 pass | 1399 pass |
| 1383 | 1400 |
| 1384 def _MethodName(self, prefix, name): | 1401 def _MethodName(self, prefix, name): |
| 1385 method_name = prefix + name | 1402 method_name = prefix + name |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1459 # interface Y extends X, List<T> ... | 1476 # interface Y extends X, List<T> ... |
| 1460 # | 1477 # |
| 1461 # In the non-root case we have to choose between: | 1478 # In the non-root case we have to choose between: |
| 1462 # | 1479 # |
| 1463 # class YImpl extends XImpl { add List<T> methods; } | 1480 # class YImpl extends XImpl { add List<T> methods; } |
| 1464 # | 1481 # |
| 1465 # and | 1482 # and |
| 1466 # | 1483 # |
| 1467 # class YImpl extends ListBase<T> { copies of transitive XImpl methods; } | 1484 # class YImpl extends ListBase<T> { copies of transitive XImpl methods; } |
| 1468 # | 1485 # |
| 1469 if ('HasIndexGetter' in self._interface.ext_attrs or | 1486 if (self._HasNativeIndexGetter(self._interface)): |
|
antonm
2012/01/26 11:06:14
nit: no need in extra ()
podivilov
2012/01/26 14:18:57
Done.
| |
| 1470 'HasNumericIndexGetter' in self._interface.ext_attrs): | 1487 self._EmitNativeIndexGetter(self._interface, element_type) |
| 1471 method_name = '_index' | |
| 1472 self._members_emitter.Emit( | |
| 1473 '\n' | |
| 1474 ' $TYPE operator[](int index) { return $METHOD(this, index); }\n' | |
| 1475 ' static $TYPE $METHOD(var _this, int index) native;\n', | |
| 1476 TYPE=element_type, METHOD=method_name) | |
| 1477 self._js_code.Emit( | |
| 1478 '\n' | |
| 1479 'function native_$(CLASS)_$(METHOD)(_this, index) {\n' | |
| 1480 ' try {\n' | |
| 1481 ' return __dom_wrap(_this.$dom[index]);\n' | |
| 1482 ' } catch (e) {\n' | |
| 1483 ' throw __dom_wrap_exception(e);\n' | |
| 1484 ' }\n' | |
| 1485 '}\n', | |
| 1486 CLASS=self._class_name, METHOD=method_name) | |
| 1487 else: | 1488 else: |
| 1488 self._members_emitter.Emit( | 1489 self._members_emitter.Emit( |
| 1489 '\n' | 1490 '\n' |
| 1490 ' $TYPE operator[](int index) {\n' | 1491 ' $TYPE operator[](int index) {\n' |
| 1491 ' return item(index);\n' | 1492 ' return item(index);\n' |
| 1492 ' }\n', | 1493 ' }\n', |
| 1493 TYPE=element_type) | 1494 TYPE=element_type) |
| 1494 | 1495 |
| 1495 | 1496 |
| 1496 if 'HasCustomIndexSetter' in self._interface.ext_attrs: | 1497 if 'HasCustomIndexSetter' in self._interface.ext_attrs: |
|
antonm
2012/01/26 11:06:14
for symmetry, shouldn't you add _HasNativeIndexSet
podivilov
2012/01/26 14:18:57
Done.
| |
| 1497 method_name = '_set_index' | 1498 self._EmitNativeIndexSetter(self._interface, element_type) |
| 1498 self._members_emitter.Emit( | |
| 1499 '\n' | |
| 1500 ' void operator[]=(int index, $TYPE value) {\n' | |
| 1501 ' return $METHOD(this, index, value);\n' | |
| 1502 ' }\n' | |
| 1503 ' static $METHOD(_this, index, value) native;\n', | |
| 1504 TYPE=element_type, METHOD=method_name) | |
| 1505 self._js_code.Emit( | |
| 1506 '\n' | |
| 1507 'function native_$(CLASS)_$(METHOD)(_this, index, value) {\n' | |
| 1508 ' try {\n' | |
| 1509 ' return _this.$dom[index] = __dom_unwrap(value);\n' | |
| 1510 ' } catch (e) {\n' | |
| 1511 ' throw __dom_wrap_exception(e);\n' | |
| 1512 ' }\n' | |
| 1513 '}\n', | |
| 1514 CLASS=self._class_name, METHOD=method_name) | |
| 1515 else: | 1499 else: |
| 1516 self._members_emitter.Emit( | 1500 self._members_emitter.Emit( |
| 1517 '\n' | 1501 '\n' |
| 1518 ' void operator[]=(int index, $TYPE value) {\n' | 1502 ' void operator[]=(int index, $TYPE value) {\n' |
| 1519 ' throw new UnsupportedOperationException("Cannot assign element of immutable List.");\n' | 1503 ' throw new UnsupportedOperationException("Cannot assign element of immutable List.");\n' |
| 1520 ' }\n', | 1504 ' }\n', |
| 1521 TYPE=element_type) | 1505 TYPE=element_type) |
| 1522 | 1506 |
| 1523 self._members_emitter.Emit( | 1507 self._members_emitter.Emit( |
| 1524 '\n' | 1508 '\n' |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1602 '\n' | 1586 '\n' |
| 1603 ' bool isEmpty() {\n' | 1587 ' bool isEmpty() {\n' |
| 1604 ' return length == 0;\n' | 1588 ' return length == 0;\n' |
| 1605 ' }\n' | 1589 ' }\n' |
| 1606 '\n' | 1590 '\n' |
| 1607 ' Iterator<$TYPE> iterator() {\n' | 1591 ' Iterator<$TYPE> iterator() {\n' |
| 1608 ' return new _FixedSizeListIterator<$TYPE>(this);\n' | 1592 ' return new _FixedSizeListIterator<$TYPE>(this);\n' |
| 1609 ' }\n', | 1593 ' }\n', |
| 1610 TYPE=element_type) | 1594 TYPE=element_type) |
| 1611 | 1595 |
| 1596 def _HasNativeIndexGetter(self, interface): | |
| 1597 return ('HasIndexGetter' in interface.ext_attrs or | |
| 1598 'HasNumericIndexGetter' in interface.ext_attrs) | |
| 1599 | |
| 1600 def _EmitNativeIndexGetter(self, interface, element_type): | |
| 1601 method_name = '_index' | |
| 1602 self._members_emitter.Emit( | |
| 1603 '\n' | |
|
antonm
2012/01/26 11:06:14
looks like if you keep a blank line before $MEMBER
podivilov
2012/01/26 14:18:57
You could not rely on ordering here, native index
| |
| 1604 ' $TYPE operator[](int index) { return $METHOD(this, index); }\n' | |
|
antonm
2012/01/26 11:06:14
$TYPE operator[](int index) => $METHOD(this, index
podivilov
2012/01/26 14:18:57
This change should produce zero diff in wrapping d
| |
| 1605 ' static $TYPE $METHOD(var _this, int index) native;\n', | |
| 1606 TYPE=element_type, METHOD=method_name) | |
| 1607 self._js_code.Emit( | |
| 1608 '\n' | |
| 1609 'function native_$(CLASS)_$(METHOD)(_this, index) {\n' | |
| 1610 ' try {\n' | |
| 1611 ' return __dom_wrap(_this.$dom[index]);\n' | |
| 1612 ' } catch (e) {\n' | |
| 1613 ' throw __dom_wrap_exception(e);\n' | |
| 1614 ' }\n' | |
| 1615 '}\n', | |
| 1616 CLASS=self._class_name, METHOD=method_name) | |
| 1617 | |
| 1618 def _EmitNativeIndexSetter(self, interface, element_type): | |
| 1619 method_name = '_set_index' | |
| 1620 self._members_emitter.Emit( | |
| 1621 '\n' | |
| 1622 ' void operator[]=(int index, $TYPE value) {\n' | |
| 1623 ' return $METHOD(this, index, value);\n' | |
| 1624 ' }\n' | |
| 1625 ' static $METHOD(_this, index, value) native;\n', | |
| 1626 TYPE=element_type, METHOD=method_name) | |
| 1627 self._js_code.Emit( | |
| 1628 '\n' | |
| 1629 'function native_$(CLASS)_$(METHOD)(_this, index, value) {\n' | |
| 1630 ' try {\n' | |
| 1631 ' return _this.$dom[index] = __dom_unwrap(value);\n' | |
| 1632 ' } catch (e) {\n' | |
| 1633 ' throw __dom_wrap_exception(e);\n' | |
| 1634 ' }\n' | |
| 1635 '}\n', | |
| 1636 CLASS=self._class_name, METHOD=method_name) | |
| 1637 | |
| 1612 def AddOperation(self, info): | 1638 def AddOperation(self, info): |
| 1613 """ | 1639 """ |
| 1614 Arguments: | 1640 Arguments: |
| 1615 info: An OperationInfo object. | 1641 info: An OperationInfo object. |
| 1616 """ | 1642 """ |
| 1617 body = self._members_emitter.Emit( | 1643 body = self._members_emitter.Emit( |
| 1618 '\n' | 1644 '\n' |
| 1619 ' $TYPE $NAME($PARAMS) {\n' | 1645 ' $TYPE $NAME($PARAMS) {\n' |
| 1620 '$!BODY' | 1646 '$!BODY' |
| 1621 ' }\n', | 1647 ' }\n', |
| (...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2056 info: An OperationInfo object. | 2082 info: An OperationInfo object. |
| 2057 """ | 2083 """ |
| 2058 # TODO(vsm): Handle overloads. | 2084 # TODO(vsm): Handle overloads. |
| 2059 self._members_emitter.Emit( | 2085 self._members_emitter.Emit( |
| 2060 '\n' | 2086 '\n' |
| 2061 ' $TYPE $NAME($PARAMS) native;\n', | 2087 ' $TYPE $NAME($PARAMS) native;\n', |
| 2062 TYPE=self._NarrowOutputType(info.type_name), | 2088 TYPE=self._NarrowOutputType(info.type_name), |
| 2063 NAME=info.name, | 2089 NAME=info.name, |
| 2064 PARAMS=info.ParametersImplementationDeclaration( | 2090 PARAMS=info.ParametersImplementationDeclaration( |
| 2065 lambda type_name: self._NarrowInputType(type_name))) | 2091 lambda type_name: self._NarrowInputType(type_name))) |
| 2092 | |
| 2093 | |
| 2094 # ------------------------------------------------------------------------------ | |
| 2095 | |
| 2096 class NativeImplementationSystem(System): | |
| 2097 | |
| 2098 def __init__(self, templates, database, emitters, auxiliary_dir, output_dir): | |
| 2099 super(NativeImplementationSystem, self).__init__( | |
| 2100 templates, database, emitters, output_dir) | |
| 2101 | |
| 2102 self._auxiliary_dir = auxiliary_dir | |
| 2103 | |
| 2104 self._dom_public_imports_emitter = emitter.Emitter() | |
| 2105 self._dom_impl_imports_emitter = emitter.Emitter() | |
| 2106 | |
| 2107 def InterfaceGenerator(self, | |
| 2108 interface, | |
| 2109 common_prefix, | |
| 2110 super_interface_name, | |
| 2111 source_filter): | |
| 2112 interface_name = interface.id | |
| 2113 | |
| 2114 self._dom_public_imports_emitter.Emit('#source("$PATH");\n', | |
| 2115 PATH=self._FilePathForDartInterface(interface_name)) | |
| 2116 self._dom_impl_imports_emitter.Emit('#source("$PATH");\n', | |
| 2117 PATH=self._FilePathForDartImpl(interface_name)) | |
| 2118 | |
| 2119 dart_impl_path = os.path.join(self._output_dir, | |
| 2120 self._FilePathForDartImpl(interface_name)) | |
|
antonm
2012/01/26 11:06:14
do you want to invoke this _FilePathForDartImpl tw
| |
| 2121 dart_impl_emitter = self._emitters.FileEmitter(dart_impl_path) | |
| 2122 | |
| 2123 return NativeImplementationGenerator(interface, super_interface_name, | |
| 2124 dart_impl_emitter, | |
| 2125 self._BaseDefines(interface), | |
| 2126 self._templates) | |
| 2127 | |
| 2128 def ProcessCallback(self, interface, info): | |
| 2129 self._dom_public_imports_emitter.Emit('#source("$PATH");\n', | |
| 2130 PATH=self._FilePathForDartInterface(interface.id)) | |
| 2131 | |
| 2132 def GenerateLibraries(self, lib_dir): | |
| 2133 auxiliary_dir = os.path.relpath(self._auxiliary_dir, self._output_dir) | |
| 2134 | |
| 2135 # Generate dom_public.dart | |
| 2136 dom_public_path = os.path.join(self._output_dir, 'dom_public.dart') | |
| 2137 dom_public_emitter = self._emitters.FileEmitter(dom_public_path) | |
| 2138 dom_public_emitter.Emit(self._templates.Load('dom_public.darttemplate'), | |
| 2139 AUXILIARY_DIR=auxiliary_dir, | |
| 2140 SOURCES=self._dom_public_imports_emitter.Fragments()) | |
| 2141 | |
| 2142 # Generate dom_impl.dart | |
| 2143 dom_impl_path = os.path.join(self._output_dir, 'dom_impl.dart') | |
| 2144 dom_impl_emitter = self._emitters.FileEmitter(dom_impl_path) | |
| 2145 dom_impl_emitter.Emit(self._templates.Load('dom_impl.darttemplate'), | |
| 2146 AUXILIARY_DIR=auxiliary_dir, | |
| 2147 SOURCES=self._dom_impl_imports_emitter.Fragments()) | |
| 2148 | |
| 2149 def Finish(self): | |
| 2150 pass | |
| 2151 | |
| 2152 def _FilePathForDartInterface(self, interface_name): | |
| 2153 return os.path.join('src', 'interface', '%s.dart' % interface_name) | |
| 2154 | |
| 2155 def _FilePathForDartImpl(self, interface_name): | |
| 2156 return os.path.join('dart', '%sImplementation.dart' % interface_name) | |
| 2157 | |
| 2158 | |
| 2159 class NativeImplementationGenerator(WrappingInterfaceGenerator): | |
| 2160 """Generates Dart and c++ implementation for one DOM IDL interface.""" | |
|
antonm
2012/01/26 11:06:14
nit: C++
podivilov
2012/01/26 14:18:57
Done.
| |
| 2161 | |
| 2162 def __init__(self, interface, super_interface, dart_impl_emitter, | |
| 2163 base_members, templates): | |
| 2164 """Generates Dart code for the given interface. | |
| 2165 | |
| 2166 Args: | |
| 2167 | |
| 2168 interface: an IDLInterface instance. It is assumed that all types have | |
| 2169 been converted to Dart types (e.g. int, String), unless they are in | |
| 2170 the same package as the interface. | |
| 2171 super_interface: A string or None, the name of the common interface that | |
| 2172 this interface implements, if any. | |
| 2173 dart_impl_emitter: an Emitter for the file containing the Dart | |
| 2174 implementation class. | |
| 2175 base_members: a set of names of members defined in a base class. This is | |
| 2176 used to avoid static member 'overriding' in the generated Dart code. | |
| 2177 """ | |
| 2178 self._interface = interface | |
| 2179 self._super_interface = super_interface | |
| 2180 self._dart_impl_emitter = dart_impl_emitter | |
| 2181 self._base_members = base_members | |
| 2182 self._templates = templates | |
| 2183 self._current_secondary_parent = None | |
| 2184 | |
| 2185 def StartInterface(self): | |
| 2186 self._class_name = self._ImplClassName(self._interface.id) | |
| 2187 self._members_emitter = emitter.Emitter() | |
| 2188 | |
| 2189 def _ImplClassName(self, type_name): | |
| 2190 return type_name + 'Implementation' | |
| 2191 | |
| 2192 def FinishInterface(self): | |
| 2193 interface = self._interface | |
| 2194 interface_name = interface.id | |
| 2195 | |
| 2196 base = self._BaseClassName(interface) | |
| 2197 self._dart_impl_emitter.Emit( | |
| 2198 self._templates.Load('dart_implementation.darttemplate'), | |
| 2199 CLASS=self._class_name, BASE=base, INTERFACE=interface_name, | |
| 2200 MEMBERS=self._members_emitter.Fragments()) | |
| 2201 | |
| 2202 def AddGetter(self, attr): | |
| 2203 self._members_emitter.Emit( | |
| 2204 '\n' | |
| 2205 ' $TYPE get $NAME() native "$(INTERFACE)_$(NAME)_Getter";\n', | |
| 2206 NAME=attr.id, TYPE=attr.type.id, INTERFACE=self._interface.id) | |
| 2207 | |
| 2208 def AddSetter(self, attr): | |
| 2209 self._members_emitter.Emit( | |
| 2210 '\n' | |
| 2211 ' void set $NAME($TYPE) native "$(INTERFACE)_$(NAME)_Setter";\n', | |
| 2212 NAME=attr.id, TYPE=attr.type.id, INTERFACE=self._interface.id) | |
| 2213 | |
| 2214 def _HasNativeIndexGetter(self, interface): | |
|
antonm
2012/01/26 11:06:14
do you need this override?
podivilov
2012/01/26 14:18:57
Yes, it repeats the logic in CodeGeneratorDart.pm.
| |
| 2215 return ('HasCustomIndexGetter' in interface.ext_attrs or | |
| 2216 'HasNumericIndexGetter' in interface.ext_attrs) | |
| 2217 | |
| 2218 def _EmitNativeIndexGetter(self, interface, element_type): | |
| 2219 native_binding = '%s_numericIndexGetter_Callback' % interface.id | |
| 2220 self._members_emitter.Emit( | |
| 2221 '\n' | |
| 2222 ' $TYPE operator[](int index) native "$NATIVE_BINDING";\n', | |
| 2223 TYPE=element_type, NATIVE_BINDING=native_binding) | |
| 2224 | |
| 2225 def _EmitNativeIndexSetter(self, interface, element_type): | |
| 2226 native_binding = '%s_numericIndexSetter_Callback' % self._interface.id | |
| 2227 self._members_emitter.Emit( | |
| 2228 '\n' | |
| 2229 ' void operator[]=(int index, $TYPE value) native "$NATIVE_BINDING";\n' , | |
| 2230 TYPE=element_type, NATIVE_BINDING=native_binding) | |
| 2231 | |
| 2232 def AddOperation(self, info): | |
| 2233 """ | |
| 2234 Arguments: | |
| 2235 info: An OperationInfo object. | |
| 2236 """ | |
| 2237 | |
| 2238 if 'Custom' in info.overloads[0].ext_attrs: | |
| 2239 self._members_emitter.Emit( | |
| 2240 '\n' | |
| 2241 ' $TYPE $NAME($PARAMETERS) native "$(INTERFACE)_$(NAME)_Callback";\ n', | |
| 2242 TYPE=info.type_name, | |
| 2243 NAME=info.name, | |
| 2244 PARAMETERS=info.ParametersImplementationDeclaration(), | |
| 2245 INTERFACE=self._interface.id) | |
| 2246 return | |
| 2247 | |
| 2248 body = self._members_emitter.Emit( | |
| 2249 '\n' | |
| 2250 ' $TYPE $NAME($PARAMETERS) {\n' | |
| 2251 '$!BODY' | |
| 2252 ' }\n', | |
| 2253 TYPE=info.type_name, | |
| 2254 NAME=info.name, | |
| 2255 PARAMETERS=info.ParametersImplementationDeclaration()) | |
| 2256 | |
| 2257 # Process in order of ascending number of arguments to ensure missing | |
| 2258 # optional arguments are processed early. | |
| 2259 overloads = sorted(info.overloads, | |
| 2260 key=lambda overload: len(overload.arguments)) | |
| 2261 self._native_version = 0 | |
| 2262 fallthrough = self.GenerateDispatch(body, info, ' ', 0, overloads) | |
| 2263 if fallthrough: | |
| 2264 body.Emit(' throw "Incorrect number or type of arguments";\n'); | |
| 2265 | |
| 2266 def GenerateSingleOperation(self, emitter, info, indent, operation): | |
| 2267 """Generates a call to a single operation. | |
| 2268 | |
| 2269 Arguments: | |
| 2270 emitter: an Emitter for the body of a block of code. | |
| 2271 info: the compound information about the operation and its overloads. | |
| 2272 indent: an indentation string for generated code. | |
| 2273 operation: the IDLOperation to call. | |
| 2274 """ | |
| 2275 | |
| 2276 arg_names = [info.arg_infos[i][0] | |
| 2277 for (i, arg) in enumerate(operation.arguments)] | |
| 2278 | |
| 2279 self._native_version += 1 | |
| 2280 native_name = '_%s' % info.name | |
| 2281 if self._native_version > 1: | |
| 2282 native_name = '%s_%s' % (native_name, self._native_version) | |
| 2283 | |
| 2284 argument_expressions = ', '.join(arg_names) | |
| 2285 if info.type_name != 'void': | |
|
antonm
2012/01/26 11:06:14
do you need this if? Maybe introduce prefix which
podivilov
2012/01/26 14:18:57
Note that else clause has additional return statem
| |
| 2286 emitter.Emit('$(INDENT)return $NATIVENAME($ARGS);\n', | |
| 2287 INDENT=indent, | |
| 2288 NATIVENAME=native_name, | |
| 2289 ARGS=argument_expressions) | |
| 2290 else: | |
| 2291 emitter.Emit('$(INDENT)$NATIVENAME($ARGS);\n' | |
| 2292 '$(INDENT)return;\n', | |
| 2293 INDENT=indent, | |
| 2294 NATIVENAME=native_name, | |
| 2295 ARGS=argument_expressions) | |
| 2296 | |
| 2297 self._members_emitter.Emit(' $TYPE $NATIVE_NAME($PARAMS) native "$(INTERFAC E)$(NATIVE_NAME)_Callback";\n', | |
| 2298 NATIVE_NAME=native_name, | |
| 2299 TYPE=info.type_name, | |
| 2300 PARAMS=', '.join(arg_names), | |
| 2301 INTERFACE=self._interface.id) | |
| OLD | NEW |