OLD | NEW |
---|---|
1 # Copyright (C) 2013 Google Inc. All rights reserved. | 1 # Copyright (C) 2013 Google Inc. All rights reserved. |
2 # | 2 # |
3 # Redistribution and use in source and binary forms, with or without | 3 # Redistribution and use in source and binary forms, with or without |
4 # modification, are permitted provided that the following conditions are | 4 # modification, are permitted provided that the following conditions are |
5 # met: | 5 # met: |
6 # | 6 # |
7 # * Redistributions of source code must retain the above copyright | 7 # * Redistributions of source code must retain the above copyright |
8 # notice, this list of conditions and the following disclaimer. | 8 # notice, this list of conditions and the following disclaimer. |
9 # * Redistributions in binary form must reproduce the above | 9 # * Redistributions in binary form must reproduce the above |
10 # copyright notice, this list of conditions and the following disclaimer | 10 # copyright notice, this list of conditions and the following disclaimer |
(...skipping 12 matching lines...) Expand all Loading... | |
23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
28 | 28 |
29 """Generate Blink V8 bindings (.h and .cpp files). | 29 """Generate Blink V8 bindings (.h and .cpp files). |
30 | 30 |
31 Input: An object of class IdlDefinitions, containing an IDL interface X | 31 Input: An object of class IdlDefinitions, containing an IDL interface X |
32 Output: V8X.h and V8X.cpp | 32 Output: V8X.h and V8X.cpp |
33 | |
34 FIXME: Currently a stub, as part of landing the parser and code generator | |
35 incrementally. Only implements generation of dummy .cpp and .h files. | |
36 """ | 33 """ |
37 | 34 |
38 import os.path | 35 import os |
36 import posixpath | |
37 import re | |
38 import sys | |
39 | |
40 import idl_definitions | |
41 | |
42 # jinja2 is in chromium's third_party directory. | |
43 module_path, module_name = os.path.split(__file__) | |
44 third_party = os.path.join(module_path, os.pardir, os.pardir, os.pardir, os.pard ir) | |
45 sys.path.append(third_party) | |
46 import jinja2 | |
47 | |
48 | |
49 def apply_template(path_to_template, contents): | |
50 dirname, basename = os.path.split(path_to_template) | |
51 jinja_env = jinja2.Environment(trim_blocks=True, loader=jinja2.FileSystemLoa der([dirname])) | |
52 template = jinja_env.get_template(basename) | |
53 return template.render(contents) | |
54 | |
55 | |
56 def v8_class_name(interface): | |
57 return 'V8' + interface.name | |
58 | |
59 | |
60 def cpp_class_name(interface_or_function): | |
haraken
2013/07/26 07:47:11
interface_or_function => interface (or interface_o
do-not-use
2013/07/26 07:55:41
The naming cpp_class_name() only makes sense if th
kojih
2013/07/26 10:04:31
This function will return [ImplementedAs] value or
| |
61 return interface_or_function.name | |
62 | |
63 | |
64 def cpp_type(data_type): | |
65 """Returns the cpp type corresponds to the IDL type.""" | |
haraken
2013/07/26 07:47:11
Nit: corresponds => corresponding
Nils Barth (inactive)
2013/07/26 10:27:47
cpp → C++
(Only need cpp in variable names, not co
| |
66 if data_type == 'boolean': | |
67 return 'bool' | |
68 raise Exception('Not supported') | |
69 | |
70 | |
71 def callback_argument_declaration(operation): | |
72 parameters = ['%s %s' % (cpp_type(parameter.data_type), parameter.name) for parameter in operation.arguments] | |
haraken
2013/07/26 07:47:11
Did you decide to use "argument" in the IDL side a
kojih
2013/07/26 10:04:31
ok I'll use 'argument' also in C++.
Nils Barth (inactive)
2013/07/26 10:27:47
This function's names + signature is weird:
usuall
| |
73 return ', '.join(parameters) | |
74 | |
75 | |
76 class CodeGeneratorV8: | |
77 def __init__(self, definitions, interface_name, output_directory, idl_direct ories, verbose=False): | |
78 self.idl_definitions = definitions | |
79 self.interface_name = interface_name | |
80 self.idl_directories = idl_directories | |
81 self.output_directory = output_directory | |
82 self.verbose = verbose | |
83 self.header_file_text = '' | |
84 self.cpp_file_text = '' | |
haraken
2013/07/26 07:47:11
Do you need to make these instance variables?
kojih
2013/07/26 10:04:31
No, made those local variables.
Nils Barth (inactive)
2013/07/26 10:27:47
Agreed, these should just be local variables in ge
| |
85 self.interface = None | |
86 | |
87 def cpp_class_header(self): | |
haraken
2013/07/26 07:47:11
Nit: cpp_class_header_filename ?
kojih
2013/07/26 10:04:31
done.
Nils Barth (inactive)
2013/07/26 10:27:47
In fact, how about putting this in __init__ as wel
kojih
2013/07/29 03:43:21
I'd like to leave this part as it is.
Because I th
Nils Barth (inactive)
2013/07/29 04:11:09
Got it -- once we compute the path name in the par
| |
88 """Returns relative path from bindings/ of webcore header of the interfa ce""" | |
89 # FIXME: parser will prepare posix form relative path from Source/bindin gs in IdlInterface.file_name | |
Nils Barth (inactive)
2013/07/26 10:27:47
Exactly.
I'll probably call it IdlInterface.rel_pa
| |
90 idl_filename = self.idl_definitions.file_name | |
91 idl_rel_path_local = os.path.relpath(idl_filename) | |
92 idl_rel_path_posix = idl_rel_path_local.replace(os.path.sep, posixpath.s ep) | |
93 | |
94 idl_dir_posix = posixpath.join('bindings', posixpath.dirname(idl_rel_pat h_posix)) | |
95 return posixpath.join(idl_dir_posix, cpp_class_name(self.interface) + '. h') | |
Nils Barth (inactive)
2013/07/26 10:27:47
self.interface_name instead of cpp_class_name(self
| |
96 | |
97 def generate_header_and_cpp(self): | |
Nils Barth (inactive)
2013/07/26 10:27:47
Shall we call this (and the generate_dummy functio
kojih
2013/07/29 03:43:21
ok.
| |
98 if self.interface_name not in self.idl_definitions.interfaces: | |
99 raise Exception('%s not in IDL definitions' % self.interface_name) | |
100 self.interface = self.idl_definitions.interfaces[self.interface_name] | |
haraken
2013/07/26 07:47:11
How about moving these 3 lines into __init__ ?
kojih
2013/07/26 10:04:31
done.
| |
101 if self.interface.is_callback: | |
102 template_contents = {} | |
103 template_contents.update(self.generate_callback_functions()) | |
Nils Barth (inactive)
2013/07/26 10:27:47
How about:
template_contents = self.generate_callb
kojih
2013/07/29 03:43:21
done.
(but I'll use template_contents.update again
| |
104 self.header_file_text = apply_template('templates/callback.h', templ ate_contents) | |
105 self.cpp_file_text = apply_template('templates/callback.cpp', templa te_contents) | |
106 else: | |
107 # FIXME: Implement. | |
108 self.header_file_text = "" | |
109 self.cpp_file_text = "" | |
110 header_filename = os.path.join(self.output_directory, v8_class_name(self .interface) + '.h') | |
haraken
2013/07/26 07:47:11
You might want to factor out the code to write_gen
kojih
2013/07/26 10:04:31
done.
Nils Barth (inactive)
2013/07/26 10:27:47
BTW, this is clearest as nested functions at the t
| |
111 with open(header_filename, 'w') as header_file: | |
112 header_file.write(self.header_file_text) | |
113 cpp_filename = os.path.join(self.output_directory, v8_class_name(self.in terface) + '.cpp') | |
114 with open(cpp_filename, 'w') as cpp_file: | |
115 cpp_file.write(self.cpp_file_text) | |
116 | |
117 def generate_callback_functions(self): | |
haraken
2013/07/26 07:47:11
generate_callback_functions => generate_callback_i
kojih
2013/07/26 10:04:31
done.
| |
118 methods = [] | |
Nils Barth (inactive)
2013/07/26 10:27:47
I'd put methods = [] *directly* before the loop:
t
kojih
2013/07/29 03:43:21
I agree, I think list comprehension has a good poi
| |
119 cpp_includes = set([ | |
120 'core/dom/ScriptExecutionContext.h', | |
121 'bindings/v8/V8Binding.h', | |
122 'bindings/v8/V8Callback.h', | |
123 'wtf/Assertions.h', | |
124 ]) | |
125 header_includes = set([ | |
126 'bindings/v8/ActiveDOMCallback.h', | |
127 'bindings/v8/DOMWrapperWorld.h', | |
128 'bindings/v8/ScopedPersistent.h', | |
129 ]) | |
130 header_includes.add(self.cpp_class_header()) | |
131 for operation in self.interface.operations: | |
132 custom = 'Custom' in operation.extended_attributes | |
haraken
2013/07/26 07:47:11
Remove this.
| |
133 method = {} | |
134 if 'Custom' not in operation.extended_attributes: | |
135 if operation.data_type != 'boolean': | |
136 raise Exception("We don't yet support callbacks that return non-boolean values.") | |
137 if len(operation.arguments): | |
138 raise Exception('Not supported') | |
139 method = { | |
140 'return_type': cpp_type(operation.data_type), | |
haraken
2013/07/26 07:47:11
nbarth: Probably do you want to rename operation.d
Nils Barth (inactive)
2013/07/26 10:27:47
Good point. Will do (in followup).
| |
141 'name': operation.name, | |
142 'parameter_declaration': callback_argument_declaration(opera tion), | |
143 'custom': custom, | |
haraken
2013/07/26 07:47:11
'custom': None
| |
144 } | |
145 methods.append(method) | |
146 template_contents = { | |
147 'cpp_class_name': cpp_class_name(self.interface), | |
Nils Barth (inactive)
2013/07/26 10:27:47
self.interface_name?
| |
148 'v8_class_name': v8_class_name(self.interface), | |
Nils Barth (inactive)
2013/07/26 10:27:47
'V8' + self.interface_name ?
| |
149 'cpp_includes': sorted(list(cpp_includes)), | |
150 'header_includes': sorted(list(header_includes)), | |
151 'methods': methods, | |
152 } | |
153 return template_contents | |
39 | 154 |
40 | 155 |
41 def generate_dummy_header_and_cpp(target_interface_name, output_directory): | 156 def generate_dummy_header_and_cpp(target_interface_name, output_directory): |
42 header_basename = 'V8%s.h' % target_interface_name | 157 header_basename = 'V8%s.h' % target_interface_name |
43 cpp_basename = 'V8%s.cpp' % target_interface_name | 158 cpp_basename = 'V8%s.cpp' % target_interface_name |
44 header_fullname = os.path.join(output_directory, header_basename) | 159 header_fullname = os.path.join(output_directory, header_basename) |
45 cpp_fullname = os.path.join(output_directory, cpp_basename) | 160 cpp_fullname = os.path.join(output_directory, cpp_basename) |
46 contents = """/* | 161 contents = """/* |
47 This file is generated just to tell build scripts that {header_basename} and | 162 This file is generated just to tell build scripts that {header_basename} and |
48 {cpp_basename} are created for {target_interface_name}.idl, and thus | 163 {cpp_basename} are created for {target_interface_name}.idl, and thus |
49 prevent the build scripts from trying to generate {header_basename} and | 164 prevent the build scripts from trying to generate {header_basename} and |
50 {cpp_basename} at every build. This file must not be tried to compile. | 165 {cpp_basename} at every build. This file must not be tried to compile. |
51 */ | 166 */ |
52 """.format(**locals()) | 167 """.format(**locals()) |
53 with open(header_fullname, 'w') as header_file: | 168 with open(header_fullname, 'w') as header_file: |
54 header_file.write(contents) | 169 header_file.write(contents) |
55 with open(cpp_fullname, 'w') as cpp_file: | 170 with open(cpp_fullname, 'w') as cpp_file: |
56 cpp_file.write(contents) | 171 cpp_file.write(contents) |
OLD | NEW |