Index: Source/bindings/scripts/code_generator_v8.py |
diff --git a/Source/bindings/scripts/code_generator_v8.py b/Source/bindings/scripts/code_generator_v8.py |
index d2f933044a5a171b5f1109ef2dc94fa95f660842..881f1c90046942b769c164a839f4f11c79219b0e 100644 |
--- a/Source/bindings/scripts/code_generator_v8.py |
+++ b/Source/bindings/scripts/code_generator_v8.py |
@@ -30,27 +30,143 @@ |
Input: An object of class IdlDefinitions, containing an IDL interface X |
Output: V8X.h and V8X.cpp |
- |
-FIXME: Currently a stub, as part of landing the parser and code generator |
-incrementally. Only implements generation of dummy .cpp and .h files. |
""" |
-import os.path |
+import os |
+import posixpath |
+import re |
+import sys |
+ |
+import idl_definitions |
+ |
+# jinja2 is in chromium's third_party directory. |
+module_path, module_name = os.path.split(__file__) |
+third_party = os.path.join(module_path, os.pardir, os.pardir, os.pardir, os.pardir) |
+sys.path.append(third_party) |
+import jinja2 |
+ |
+ |
+def apply_template(path_to_template, contents): |
+ dirname, basename = os.path.split(path_to_template) |
+ jinja_env = jinja2.Environment(trim_blocks=True, loader=jinja2.FileSystemLoader([dirname])) |
+ template = jinja_env.get_template(basename) |
+ return template.render(contents) |
+ |
+ |
+def v8_class_name(interface): |
+ return 'V8' + interface.name |
+ |
+ |
+def cpp_type(data_type): |
+ """Returns the C++ type corresponding to the IDL type.""" |
+ if data_type == 'boolean': |
+ return 'bool' |
+ raise Exception('Not supported') |
+ |
+def callback_argument_declaration(operation): |
+ arguments = ['%s %s' % (cpp_type(argument.data_type), argument.name) for argument in operation.arguments] |
+ return ', '.join(arguments) |
-def generate_dummy_header_and_cpp(target_interface_name, output_directory): |
- header_basename = 'V8%s.h' % target_interface_name |
- cpp_basename = 'V8%s.cpp' % target_interface_name |
- header_fullname = os.path.join(output_directory, header_basename) |
- cpp_fullname = os.path.join(output_directory, cpp_basename) |
- contents = """/* |
+ |
+class CodeGeneratorV8: |
+ def __init__(self, definitions, interface_name, output_directory, idl_directories, verbose=False): |
+ self.idl_definitions = definitions |
+ self.interface_name = interface_name |
+ self.idl_directories = idl_directories |
+ self.output_directory = output_directory |
+ self.verbose = verbose |
+ self.interface = None |
+ |
+ def cpp_class_header_filename(self): |
+ """Returns relative path from bindings/ of webcore header of the interface""" |
+ # FIXME: parser will prepare posix form relative path from Source/bindings in IdlInterface.rel_path_posix |
+ idl_filename = self.idl_definitions.file_name |
+ idl_rel_path_local = os.path.relpath(idl_filename) |
+ idl_rel_path_posix = idl_rel_path_local.replace(os.path.sep, posixpath.sep) |
+ |
+ idl_dir_posix = posixpath.join('bindings', posixpath.dirname(idl_rel_path_posix)) |
+ return posixpath.join(idl_dir_posix, self.interface.name + '.h') |
+ |
+ def write_dummy_header_and_cpp(self): |
+ target_interface_name = self.interface_name |
+ header_basename = 'V8%s.h' % target_interface_name |
+ cpp_basename = 'V8%s.cpp' % target_interface_name |
+ header_fullname = os.path.join(self.output_directory, header_basename) |
+ cpp_fullname = os.path.join(self.output_directory, cpp_basename) |
+ contents = """/* |
This file is generated just to tell build scripts that {header_basename} and |
{cpp_basename} are created for {target_interface_name}.idl, and thus |
prevent the build scripts from trying to generate {header_basename} and |
{cpp_basename} at every build. This file must not be tried to compile. |
*/ |
""".format(**locals()) |
- with open(header_fullname, 'w') as header_file: |
- header_file.write(contents) |
- with open(cpp_fullname, 'w') as cpp_file: |
- cpp_file.write(contents) |
+ self.write_header_code(header_basename, contents) |
+ self.write_cpp_code(cpp_basename, contents) |
+ |
+ def write_header_and_cpp(self): |
+ if self.interface_name not in self.idl_definitions.interfaces: |
+ raise Exception('%s not in IDL definitions' % self.interface_name) |
+ self.interface = self.idl_definitions.interfaces[self.interface_name] |
+ header_basename = v8_class_name(self.interface) + '.h' |
+ cpp_basename = v8_class_name(self.interface) + '.cpp' |
+ if self.interface.is_callback: |
+ template_contents = self.generate_callback_interface() |
+ header_file_text = apply_template('templates/callback.h', template_contents) |
+ cpp_file_text = apply_template('templates/callback.cpp', template_contents) |
+ else: |
+ # FIXME: Implement. |
+ header_file_text = "" |
+ cpp_file_text = "" |
+ self.write_header_code(header_basename, header_file_text) |
+ self.write_cpp_code(cpp_basename, cpp_file_text) |
+ |
+ def write_header_code(self, header_basename, header_file_text): |
+ header_filename = os.path.join(self.output_directory, header_basename) |
+ with open(header_filename, 'w') as header_file: |
+ header_file.write(header_file_text) |
+ |
+ def write_cpp_code(self, cpp_basename, cpp_file_text): |
+ cpp_filename = os.path.join(self.output_directory, cpp_basename) |
+ with open(cpp_filename, 'w') as cpp_file: |
+ cpp_file.write(cpp_file_text) |
+ |
+ def generate_callback_interface(self): |
+ cpp_includes = set([ |
+ 'core/dom/ScriptExecutionContext.h', |
+ 'bindings/v8/V8Binding.h', |
+ 'bindings/v8/V8Callback.h', |
+ 'wtf/Assertions.h', |
+ ]) |
+ header_includes = set([ |
+ 'bindings/v8/ActiveDOMCallback.h', |
+ 'bindings/v8/DOMWrapperWorld.h', |
+ 'bindings/v8/ScopedPersistent.h', |
+ ]) |
+ header_includes.add(self.cpp_class_header_filename()) |
+ |
+ def operation_to_method(operation): |
+ method = {} |
+ if 'Custom' not in operation.extended_attributes: |
+ if operation.data_type != 'boolean': |
+ raise Exception("We don't yet support callbacks that return non-boolean values.") |
+ if len(operation.arguments): |
+ raise Exception('Not supported') |
+ method = { |
+ 'return_type': cpp_type(operation.data_type), |
+ 'name': operation.name, |
+ 'arguments': [], |
+ 'argument_declaration': callback_argument_declaration(operation), |
+ 'custom': None, |
+ } |
+ return method |
+ |
+ methods = [operation_to_method(operation) for operation in self.interface.operations] |
+ template_contents = { |
+ 'cpp_class_name': self.interface.name, |
+ 'v8_class_name': v8_class_name(self.interface), |
+ 'cpp_includes': sorted(list(cpp_includes)), |
+ 'header_includes': sorted(list(header_includes)), |
+ 'methods': methods, |
+ } |
+ return template_contents |