Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: bindings/scripts/code_generator_v8.py

Issue 581453002: Dartium Roll 38 roll (Closed) Base URL: https://dart.googlecode.com/svn/third_party/WebCore
Patch Set: Sync'd w/ r 182210 Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « bindings/scripts/blink_idl_parser.py ('k') | bindings/scripts/compute_global_objects.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 66
67 # jinja2 is in chromium's third_party directory. 67 # jinja2 is in chromium's third_party directory.
68 # Insert at 1 so at front to override system libraries, and 68 # Insert at 1 so at front to override system libraries, and
69 # after path[0] == invoking script dir 69 # after path[0] == invoking script dir
70 sys.path.insert(1, third_party_dir) 70 sys.path.insert(1, third_party_dir)
71 import jinja2 71 import jinja2
72 72
73 import idl_types 73 import idl_types
74 from idl_types import IdlType 74 from idl_types import IdlType
75 import v8_callback_interface 75 import v8_callback_interface
76 import v8_dictionary
76 from v8_globals import includes, interfaces 77 from v8_globals import includes, interfaces
77 import v8_interface 78 import v8_interface
78 import v8_types 79 import v8_types
79 from v8_utilities import capitalize, cpp_name, conditional_string, v8_class_name 80 from v8_utilities import capitalize, cpp_name, conditional_string, v8_class_name
80 81
81 82
83 def render_template(interface_info, header_template, cpp_template,
84 template_context):
85 template_context['code_generator'] = module_pyname
86
87 # Add includes for any dependencies
88 template_context['header_includes'] = sorted(
89 template_context['header_includes'])
90 includes.update(interface_info.get('dependencies_include_paths', []))
91 template_context['cpp_includes'] = sorted(includes)
92
93 header_text = header_template.render(template_context)
94 cpp_text = cpp_template.render(template_context)
95 return header_text, cpp_text
96
97
82 class CodeGeneratorV8(object): 98 class CodeGeneratorV8(object):
83 def __init__(self, interfaces_info, cache_dir): 99 def __init__(self, interfaces_info, cache_dir, output_dir):
84 interfaces_info = interfaces_info or {} 100 interfaces_info = interfaces_info or {}
85 self.interfaces_info = interfaces_info 101 self.interfaces_info = interfaces_info
86 self.jinja_env = initialize_jinja_env(cache_dir) 102 self.jinja_env = initialize_jinja_env(cache_dir)
103 self.output_dir = output_dir
87 104
88 # Set global type info 105 # Set global type info
89 idl_types.set_ancestors(dict( 106 idl_types.set_ancestors(dict(
90 (interface_name, interface_info['ancestors']) 107 (interface_name, interface_info['ancestors'])
91 for interface_name, interface_info in interfaces_info.iteritems() 108 for interface_name, interface_info in interfaces_info.iteritems()
92 if interface_info['ancestors'])) 109 if interface_info['ancestors']))
93 IdlType.set_callback_interfaces(set( 110 IdlType.set_callback_interfaces(set(
94 interface_name 111 interface_name
95 for interface_name, interface_info in interfaces_info.iteritems() 112 for interface_name, interface_info in interfaces_info.iteritems()
96 if interface_info['is_callback_interface'])) 113 if interface_info['is_callback_interface']))
114 IdlType.set_dictionaries(set(
115 dictionary_name
116 for dictionary_name, interface_info in interfaces_info.iteritems()
117 if interface_info['is_dictionary']))
97 IdlType.set_implemented_as_interfaces(dict( 118 IdlType.set_implemented_as_interfaces(dict(
98 (interface_name, interface_info['implemented_as']) 119 (interface_name, interface_info['implemented_as'])
99 for interface_name, interface_info in interfaces_info.iteritems() 120 for interface_name, interface_info in interfaces_info.iteritems()
100 if interface_info['implemented_as'])) 121 if interface_info['implemented_as']))
101 IdlType.set_garbage_collected_types(set( 122 IdlType.set_garbage_collected_types(set(
102 interface_name 123 interface_name
103 for interface_name, interface_info in interfaces_info.iteritems() 124 for interface_name, interface_info in interfaces_info.iteritems()
104 if 'GarbageCollected' in interface_info['inherited_extended_attribut es'])) 125 if 'GarbageCollected' in interface_info['inherited_extended_attribut es']))
105 IdlType.set_will_be_garbage_collected_types(set( 126 IdlType.set_will_be_garbage_collected_types(set(
106 interface_name 127 interface_name
107 for interface_name, interface_info in interfaces_info.iteritems() 128 for interface_name, interface_info in interfaces_info.iteritems()
108 if 'WillBeGarbageCollected' in interface_info['inherited_extended_at tributes'])) 129 if 'WillBeGarbageCollected' in interface_info['inherited_extended_at tributes']))
109 v8_types.set_component_dirs(dict( 130 v8_types.set_component_dirs(dict(
110 (interface_name, interface_info['component_dir']) 131 (interface_name, interface_info['component_dir'])
111 for interface_name, interface_info in interfaces_info.iteritems())) 132 for interface_name, interface_info in interfaces_info.iteritems()))
112 133
113 def generate_code(self, definitions, interface_name): 134 def output_paths_for_bindings(self, definition_name):
135 header_path = posixpath.join(self.output_dir,
136 'V8%s.h' % definition_name)
137 cpp_path = posixpath.join(self.output_dir, 'V8%s.cpp' % definition_name)
138 return header_path, cpp_path
139
140 def output_paths_for_impl(self, definition_name):
141 header_path = posixpath.join(self.output_dir, '%s.h' % definition_name)
142 cpp_path = posixpath.join(self.output_dir, '%s.cpp' % definition_name)
143 return header_path, cpp_path
144
145 def generate_code(self, definitions, definition_name):
114 """Returns .h/.cpp code as (header_text, cpp_text).""" 146 """Returns .h/.cpp code as (header_text, cpp_text)."""
115 try:
116 interface = definitions.interfaces[interface_name]
117 except KeyError:
118 raise Exception('%s not in IDL definitions' % interface_name)
119
120 # Store other interfaces for introspection
121 interfaces.update(definitions.interfaces)
122
123 # Set local type info 147 # Set local type info
124 IdlType.set_callback_functions(definitions.callback_functions.keys()) 148 IdlType.set_callback_functions(definitions.callback_functions.keys())
125 IdlType.set_enums((enum.name, enum.values) 149 IdlType.set_enums((enum.name, enum.values)
126 for enum in definitions.enumerations.values()) 150 for enum in definitions.enumerations.values())
127 151
152 if definition_name in definitions.interfaces:
153 return self.generate_interface_code(
154 definitions, definition_name,
155 definitions.interfaces[definition_name])
156 if definition_name in definitions.dictionaries:
157 return self.generate_dictionary_code(
158 definitions, definition_name,
159 definitions.dictionaries[definition_name])
160 raise ValueError('%s is not in IDL definitions' % definition_name)
161
162 def generate_interface_code(self, definitions, interface_name, interface):
163 # Store other interfaces for introspection
164 interfaces.update(definitions.interfaces)
165
128 # Select appropriate Jinja template and contents function 166 # Select appropriate Jinja template and contents function
129 if interface.is_callback: 167 if interface.is_callback:
130 header_template_filename = 'callback_interface.h' 168 header_template_filename = 'callback_interface.h'
131 cpp_template_filename = 'callback_interface.cpp' 169 cpp_template_filename = 'callback_interface.cpp'
132 generate_contents = v8_callback_interface.generate_callback_interfac e 170 interface_context = v8_callback_interface.callback_interface_context
133 else: 171 else:
134 header_template_filename = 'interface.h' 172 header_template_filename = 'interface.h'
135 cpp_template_filename = 'interface.cpp' 173 cpp_template_filename = 'interface.cpp'
136 generate_contents = v8_interface.generate_interface 174 interface_context = v8_interface.interface_context
137 header_template = self.jinja_env.get_template(header_template_filename) 175 header_template = self.jinja_env.get_template(header_template_filename)
138 cpp_template = self.jinja_env.get_template(cpp_template_filename) 176 cpp_template = self.jinja_env.get_template(cpp_template_filename)
139 177
140 # Generate contents (input parameters for Jinja) 178 interface_info = self.interfaces_info[interface_name]
141 template_contents = generate_contents(interface)
142 template_contents['code_generator'] = module_pyname
143 179
144 # Add includes for interface itself and any dependencies 180 template_context = interface_context(interface)
145 interface_info = self.interfaces_info[interface_name] 181 # Add the include for interface itself
146 template_contents['header_includes'].add(interface_info['include_path']) 182 template_context['header_includes'].add(interface_info['include_path'])
147 template_contents['header_includes'] = sorted(template_contents['header_ includes']) 183 header_text, cpp_text = render_template(
148 includes.update(interface_info.get('dependencies_include_paths', [])) 184 interface_info, header_template, cpp_template, template_context)
149 template_contents['cpp_includes'] = sorted(includes) 185 header_path, cpp_path = self.output_paths_for_bindings(interface_name)
186 return (
187 (header_path, header_text),
188 (cpp_path, cpp_text),
189 )
150 190
151 # Render Jinja templates 191 def generate_dictionary_code(self, definitions, dictionary_name,
152 header_text = header_template.render(template_contents) 192 dictionary):
153 cpp_text = cpp_template.render(template_contents) 193 interface_info = self.interfaces_info[dictionary_name]
154 return header_text, cpp_text 194 bindings_results = self.generate_dictionary_bindings(
195 dictionary_name, interface_info, dictionary)
196 impl_results = self.generate_dictionary_impl(
197 dictionary_name, interface_info, dictionary)
198 return bindings_results + impl_results
199
200 def generate_dictionary_bindings(self, dictionary_name,
201 interface_info, dictionary):
202 header_template = self.jinja_env.get_template('dictionary_v8.h')
203 cpp_template = self.jinja_env.get_template('dictionary_v8.cpp')
204 template_context = v8_dictionary.dictionary_context(dictionary)
205 # Add the include for interface itself
206 template_context['header_includes'].add(interface_info['include_path'])
207 header_text, cpp_text = render_template(
208 interface_info, header_template, cpp_template, template_context)
209 header_path, cpp_path = self.output_paths_for_bindings(dictionary_name)
210 return (
211 (header_path, header_text),
212 (cpp_path, cpp_text),
213 )
214
215 def generate_dictionary_impl(self, dictionary_name,
216 interface_info, dictionary):
217 header_template = self.jinja_env.get_template('dictionary_impl.h')
218 cpp_template = self.jinja_env.get_template('dictionary_impl.cpp')
219 template_context = v8_dictionary.dictionary_impl_context(
220 dictionary, self.interfaces_info)
221 header_text, cpp_text = render_template(
222 interface_info, header_template, cpp_template, template_context)
223 header_path, cpp_path = self.output_paths_for_impl(dictionary_name)
224 return (
225 (header_path, header_text),
226 (cpp_path, cpp_text),
227 )
155 228
156 229
157 def initialize_jinja_env(cache_dir): 230 def initialize_jinja_env(cache_dir):
158 jinja_env = jinja2.Environment( 231 jinja_env = jinja2.Environment(
159 loader=jinja2.FileSystemLoader(templates_dir), 232 loader=jinja2.FileSystemLoader(templates_dir),
160 # Bytecode cache is not concurrency-safe unless pre-cached: 233 # Bytecode cache is not concurrency-safe unless pre-cached:
161 # if pre-cached this is read-only, but writing creates a race condition. 234 # if pre-cached this is read-only, but writing creates a race condition.
162 bytecode_cache=jinja2.FileSystemBytecodeCache(cache_dir), 235 bytecode_cache=jinja2.FileSystemBytecodeCache(cache_dir),
163 keep_trailing_newline=True, # newline-terminate generated files 236 keep_trailing_newline=True, # newline-terminate generated files
164 lstrip_blocks=True, # so can indent control flow tags 237 lstrip_blocks=True, # so can indent control flow tags
165 trim_blocks=True) 238 trim_blocks=True)
166 jinja_env.filters.update({ 239 jinja_env.filters.update({
167 'blink_capitalize': capitalize, 240 'blink_capitalize': capitalize,
168 'conditional': conditional_if_endif, 241 'conditional': conditional_if_endif,
242 'exposed': exposed_if,
243 'per_context_enabled': per_context_enabled_if,
169 'runtime_enabled': runtime_enabled_if, 244 'runtime_enabled': runtime_enabled_if,
170 }) 245 })
171 return jinja_env 246 return jinja_env
172 247
173 248
249 def generate_indented_conditional(code, conditional):
250 # Indent if statement to level of original code
251 indent = re.match(' *', code).group(0)
252 return ('%sif (%s) {\n' % (indent, conditional) +
253 ' %s\n' % '\n '.join(code.splitlines()) +
254 '%s}\n' % indent)
255
256
174 # [Conditional] 257 # [Conditional]
175 def conditional_if_endif(code, conditional_string): 258 def conditional_if_endif(code, conditional_string):
176 # Jinja2 filter to generate if/endif directive blocks 259 # Jinja2 filter to generate if/endif directive blocks
177 if not conditional_string: 260 if not conditional_string:
178 return code 261 return code
179 return ('#if %s\n' % conditional_string + 262 return ('#if %s\n' % conditional_string +
180 code + 263 code +
181 '#endif // %s\n' % conditional_string) 264 '#endif // %s\n' % conditional_string)
182 265
183 266
267 # [Exposed]
268 def exposed_if(code, exposed_test):
269 if not exposed_test:
270 return code
271 return generate_indented_conditional(code, 'context && (%s)' % exposed_test)
272
273
274 # [PerContextEnabled]
275 def per_context_enabled_if(code, per_context_enabled_function):
276 if not per_context_enabled_function:
277 return code
278 return generate_indented_conditional(code, 'context && context->isDocument() && %s(toDocument(context))' % per_context_enabled_function)
279
280
184 # [RuntimeEnabled] 281 # [RuntimeEnabled]
185 def runtime_enabled_if(code, runtime_enabled_function_name): 282 def runtime_enabled_if(code, runtime_enabled_function_name):
186 if not runtime_enabled_function_name: 283 if not runtime_enabled_function_name:
187 return code 284 return code
188 # Indent if statement to level of original code 285 return generate_indented_conditional(code, '%s()' % runtime_enabled_function _name)
189 indent = re.match(' *', code).group(0)
190 return ('%sif (%s()) {\n' % (indent, runtime_enabled_function_name) +
191 ' %s\n' % '\n '.join(code.splitlines()) +
192 '%s}\n' % indent)
193 286
194 287
195 ################################################################################ 288 ################################################################################
196 289
197 def main(argv): 290 def main(argv):
198 # If file itself executed, cache templates 291 # If file itself executed, cache templates
199 try: 292 try:
200 cache_dir = argv[1] 293 cache_dir = argv[1]
201 dummy_filename = argv[2] 294 dummy_filename = argv[2]
202 except IndexError as err: 295 except IndexError as err:
(...skipping 10 matching lines...) Expand all
213 306
214 # Create a dummy file as output for the build system, 307 # Create a dummy file as output for the build system,
215 # since filenames of individual cache files are unpredictable and opaque 308 # since filenames of individual cache files are unpredictable and opaque
216 # (they are hashes of the template path, which varies based on environment) 309 # (they are hashes of the template path, which varies based on environment)
217 with open(dummy_filename, 'w') as dummy_file: 310 with open(dummy_filename, 'w') as dummy_file:
218 pass # |open| creates or touches the file 311 pass # |open| creates or touches the file
219 312
220 313
221 if __name__ == '__main__': 314 if __name__ == '__main__':
222 sys.exit(main(sys.argv)) 315 sys.exit(main(sys.argv))
OLDNEW
« no previous file with comments | « bindings/scripts/blink_idl_parser.py ('k') | bindings/scripts/compute_global_objects.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698