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

Side by Side Diff: bindings/dart/scripts/code_generator_dart.py

Issue 959933002: Move IDLs to 39 roll (Closed) Base URL: https://dart.googlecode.com/svn/third_party/WebCore
Patch Set: Created 5 years, 9 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/README ('k') | bindings/dart/scripts/compiler.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 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 sys.path.extend([script_path]) 77 sys.path.extend([script_path])
78 78
79 import jinja2 79 import jinja2
80 80
81 import idl_types 81 import idl_types
82 from idl_types import IdlType 82 from idl_types import IdlType
83 import dart_callback_interface 83 import dart_callback_interface
84 import dart_interface 84 import dart_interface
85 import dart_types 85 import dart_types
86 from dart_utilities import DartUtilities 86 from dart_utilities import DartUtilities
87 from utilities import write_pickle_file 87 from utilities import write_pickle_file, idl_filename_to_interface_name
88 import dart_dictionary
88 from v8_globals import includes, interfaces 89 from v8_globals import includes, interfaces
89 90
90 # TODO(jacobr): remove this hacked together list. 91
91 INTERFACES_WITHOUT_RESOLVERS = frozenset([ 92 def render_template(interface_info, header_template, cpp_template,
92 'TypeConversions', 93 template_context):
93 'GCObservation', 94 template_context['code_generator'] = module_pyname
94 'InternalProfilers', 95
95 'InternalRuntimeFlags', 96 # Add includes for any dependencies
96 'InternalSettings', 97 template_context['header_includes'] = sorted(
97 'InternalSettingsGenerated', 98 template_context['header_includes'])
98 'Internals', 99 includes.update(interface_info.get('dependencies_include_paths', []))
99 'LayerRect', 100 template_context['cpp_includes'] = sorted(includes)
100 'LayerRectList', 101
101 'MallocStatistics', 102 header_text = header_template.render(template_context)
102 'TypeConversions']) 103 cpp_text = cpp_template.render(template_context)
104 return header_text, cpp_text
103 105
104 class CodeGeneratorDart(object): 106 class CodeGeneratorDart(object):
105 def __init__(self, interfaces_info, cache_dir): 107 def __init__(self, interfaces_info, cache_dir):
106 interfaces_info = interfaces_info or {} 108 interfaces_info = interfaces_info or {}
107 self.interfaces_info = interfaces_info 109 self.interfaces_info = interfaces_info
108 self.jinja_env = initialize_jinja_env(cache_dir) 110 self.jinja_env = initialize_jinja_env(cache_dir)
109 111
110 # Set global type info 112 # Set global type info
111 idl_types.set_ancestors(dict( 113 if 'ancestors' in interfaces_info:
112 (interface_name, interface_info['ancestors']) 114 idl_types.set_ancestors(interfaces_info['ancestors'])
113 for interface_name, interface_info in interfaces_info.iteritems() 115 if 'callback_interfaces' in interfaces_info:
114 if interface_info['ancestors'])) 116 IdlType.set_callback_interfaces(interfaces_info['callback_interfaces '])
115 IdlType.set_callback_interfaces(set( 117 if 'dictionaries' in interfaces_info:
116 interface_name 118 IdlType.set_dictionaries(interfaces_info['dictionaries'])
117 for interface_name, interface_info in interfaces_info.iteritems() 119 if 'implemented_as_interfaces' in interfaces_info:
118 if interface_info['is_callback_interface'])) 120 IdlType.set_implemented_as_interfaces(interfaces_info['implemented_a s_interfaces'])
119 IdlType.set_implemented_as_interfaces(dict( 121 if 'garbage_collected_interfaces' in interfaces_info:
120 (interface_name, interface_info['implemented_as']) 122 IdlType.set_garbage_collected_types(interfaces_info['garbage_collect ed_interfaces'])
121 for interface_name, interface_info in interfaces_info.iteritems() 123 if 'will_be_garbage_collected_interfaces' in interfaces_info:
122 if interface_info['implemented_as'])) 124 IdlType.set_will_be_garbage_collected_types(interfaces_info['will_be _garbage_collected_interfaces'])
123 IdlType.set_garbage_collected_types(set( 125 if 'component_dirs' in interfaces_info:
124 interface_name 126 dart_types.set_component_dirs(interfaces_info['component_dirs'])
125 for interface_name, interface_info in interfaces_info.iteritems()
126 if 'GarbageCollected' in interface_info['inherited_extended_attribut es']))
127 IdlType.set_will_be_garbage_collected_types(set(
128 interface_name
129 for interface_name, interface_info in interfaces_info.iteritems()
130 if 'WillBeGarbageCollected' in interface_info['inherited_extended_at tributes']))
131 dart_types.set_component_dirs(dict(
132 (interface_name, interface_info['component_dir'])
133 for interface_name, interface_info in interfaces_info.iteritems()))
134 127
135 def generate_code(self, definitions, interface_name, idl_pickle_filename, 128 def generate_code(self, definitions, interface_name, idl_pickle_filename,
136 only_if_changed): 129 only_if_changed):
137 """Returns .h/.cpp code as (header_text, cpp_text).""" 130 """Returns .h/.cpp code as (header_text, cpp_text)."""
138 try: 131
132 IdlType.set_enums((enum.name, enum.values)
133 for enum in definitions.enumerations.values())
134
135 if interface_name in definitions.interfaces:
139 interface = definitions.interfaces[interface_name] 136 interface = definitions.interfaces[interface_name]
140 except KeyError: 137 elif interface_name in definitions.dictionaries:
141 raise Exception('%s not in IDL definitions' % interface_name) 138 output_code_list = self.generate_dictionary_code(
139 definitions, interface_name,
140 definitions.dictionaries[interface_name])
141
142 # Pickle the dictionary information...
143 idl_world = self.load_idl_pickle_file(idl_pickle_filename)
144 idl_world['dictionary'] = {'name': interface_name}
145 write_pickle_file(idl_pickle_filename, idl_world, only_if_changed)
146
147 return output_code_list
148 else:
149 raise ValueError('%s is not in IDL definitions' % interface_name)
142 150
143 # Store other interfaces for introspection 151 # Store other interfaces for introspection
144 interfaces.update(definitions.interfaces) 152 interfaces.update(definitions.interfaces)
145 153
146 # Set local type info 154 # Set local type info
147 IdlType.set_callback_functions(definitions.callback_functions.keys()) 155 IdlType.set_callback_functions(definitions.callback_functions.keys())
148 IdlType.set_enums((enum.name, enum.values)
149 for enum in definitions.enumerations.values())
150 156
151 # Select appropriate Jinja template and contents function 157 # Select appropriate Jinja template and contents function
152 if interface.is_callback: 158 if interface.is_callback:
153 header_template_filename = 'callback_interface_h.template' 159 header_template_filename = 'callback_interface_h.template'
154 cpp_template_filename = 'callback_interface_cpp.template' 160 cpp_template_filename = 'callback_interface_cpp.template'
155 generate_contents = dart_callback_interface.generate_callback_interf ace 161 generate_contents = dart_callback_interface.generate_callback_interf ace
156 else: 162 else:
157 header_template_filename = 'interface_h.template' 163 header_template_filename = 'interface_h.template'
158 cpp_template_filename = 'interface_cpp.template' 164 cpp_template_filename = 'interface_cpp.template'
159 generate_contents = dart_interface.generate_interface 165 generate_contents = dart_interface.interface_context
160 header_template = self.jinja_env.get_template(header_template_filename) 166 header_template = self.jinja_env.get_template(header_template_filename)
161 cpp_template = self.jinja_env.get_template(cpp_template_filename) 167 cpp_template = self.jinja_env.get_template(cpp_template_filename)
162 168
163 # Generate contents (input parameters for Jinja) 169 # Generate contents (input parameters for Jinja)
164 template_contents = generate_contents(interface) 170 template_contents = generate_contents(interface)
165 template_contents['code_generator'] = module_pyname 171 template_contents['code_generator'] = module_pyname
166 172
167 # Add includes for interface itself and any dependencies 173 # Add includes for interface itself and any dependencies
168 interface_info = self.interfaces_info[interface_name] 174 interface_info = self.interfaces_info[interface_name]
169 template_contents['header_includes'].add(interface_info['include_path']) 175 template_contents['header_includes'].add(interface_info['include_path'])
170 template_contents['header_includes'] = sorted(template_contents['header_ includes']) 176 template_contents['header_includes'] = sorted(template_contents['header_ includes'])
171 includes.update(interface_info.get('dependencies_include_paths', [])) 177 includes.update(interface_info.get('dependencies_include_paths', []))
172 178
173 # Remove includes that are not needed for Dart and trigger fatal 179 # Remove includes that are not needed for Dart and trigger fatal
174 # compile warnings if included. These IDL files need to be 180 # compile warnings if included. These IDL files need to be
175 # imported by Dart to generate the list of events but the 181 # imported by Dart to generate the list of events but the
176 # associated header files do not contain any code used by Dart. 182 # associated header files do not contain any code used by Dart.
177 includes.discard('core/dom/GlobalEventHandlers.h') 183 includes.discard('core/dom/GlobalEventHandlers.h')
178 includes.discard('core/frame/DOMWindowEventHandlers.h') 184 includes.discard('core/frame/DOMWindowEventHandlers.h')
179 185
186 # Remove v8 usages not needed.
187 includes.discard('core/frame/UseCounter.h')
188 includes.discard('bindings/core/v8/V8ScriptState.h')
189 includes.discard('bindings/core/v8/V8DOMActivityLogger.h')
190 includes.discard('bindings/core/v8/V8DOMConfiguration.h')
191 includes.discard('bindings/core/v8/V8ExceptionState.h')
192 includes.discard('bindings/core/v8/V8HiddenValue.h')
193 includes.discard('bindings/core/v8/V8ObjectConstructor.h')
194 includes.discard('core/dom/ContextFeatures.h')
195 includes.discard('core/dom/Document.h')
196 includes.discard('platform/RuntimeEnabledFeatures.h')
197 includes.discard('platform/TraceEvent.h')
198
180 template_contents['cpp_includes'] = sorted(includes) 199 template_contents['cpp_includes'] = sorted(includes)
181 200
182 idl_world = {'interface': None, 'callback': None} 201 idl_world = self.load_idl_pickle_file(idl_pickle_filename)
183
184 # Load the pickle file for this IDL.
185 if os.path.isfile(idl_pickle_filename):
186 with open(idl_pickle_filename) as idl_pickle_file:
187 idl_global_data = pickle.load(idl_pickle_file)
188 idl_pickle_file.close()
189 idl_world['interface'] = idl_global_data['interface']
190 idl_world['callback'] = idl_global_data['callback']
191 202
192 if 'interface_name' in template_contents: 203 if 'interface_name' in template_contents:
193 interface_global = {'component_dir': interface_info['component_dir'] , 204 # interfaces no longer remember there component_dir re-compute based
194 'name': template_contents['interface_name'], 205 # on relative_dir (first directory is the component).
206 component_dir = split_path(interface_info['relative_dir'])[0]
207 interface_global = {'name': template_contents['interface_name'],
195 'parent_interface': template_contents['parent_in terface'], 208 'parent_interface': template_contents['parent_in terface'],
196 'is_active_dom_object': template_contents['is_ac tive_dom_object'], 209 'is_active_dom_object': template_contents['is_ac tive_dom_object'],
197 'is_event_target': template_contents['is_event_t arget'], 210 'is_event_target': template_contents['is_event_t arget'],
198 'has_resolver': template_contents['interface_nam e'] not in INTERFACES_WITHOUT_RESOLVERS, 211 'has_resolver': template_contents['interface_nam e'],
212 'native_entries': sorted(template_contents['nati ve_entries'], key=lambda(x): x['blink_entry']),
199 'is_node': template_contents['is_node'], 213 'is_node': template_contents['is_node'],
200 'conditional_string': template_contents['conditi onal_string'], 214 'conditional_string': template_contents['conditi onal_string'],
215 'component_dir': component_dir,
201 } 216 }
202 idl_world['interface'] = interface_global 217 idl_world['interface'] = interface_global
203 else: 218 else:
204 callback_global = {'name': template_contents['cpp_class']} 219 callback_global = {'name': template_contents['cpp_class']}
205 idl_world['callback'] = callback_global 220 idl_world['callback'] = callback_global
206 221
207 write_pickle_file(idl_pickle_filename, idl_world, only_if_changed) 222 write_pickle_file(idl_pickle_filename, idl_world, only_if_changed)
208 223
209 # Render Jinja templates 224 # Render Jinja templates
210 header_text = header_template.render(template_contents) 225 header_text = header_template.render(template_contents)
211 cpp_text = cpp_template.render(template_contents) 226 cpp_text = cpp_template.render(template_contents)
212 return header_text, cpp_text 227 return header_text, cpp_text
213 228
214 # Generates global file for all interfaces. 229 def load_idl_pickle_file(self, idl_pickle_filename):
215 def generate_globals(self, global_pickle_directories, output_directory): 230 # Pickle the dictionary information...
216 header_template_filename = 'global_h.template' 231 idl_world = {'interface': None, 'callback': None, 'dictionary': None}
217 cpp_template_filename = 'global_cpp.template'
218 232
219 # Delete the global pickle file we'll rebuild from each pickle generated 233 # Load the pickle file for this IDL.
220 # for each IDL file '(%s_globals.pickle) % interface_name'. 234 if os.path.isfile(idl_pickle_filename):
221 global_pickle_filename = os.path.join(output_directory, 'global.pickle') 235 with open(idl_pickle_filename) as idl_pickle_file:
222 if os.path.isfile(global_pickle_filename): 236 idl_global_data = pickle.load(idl_pickle_file)
223 os.remove(global_pickle_filename) 237 idl_pickle_file.close()
238 idl_world['interface'] = idl_global_data['interface']
239 idl_world['callback'] = idl_global_data['callback']
240 idl_world['dictionary'] = idl_global_data['dictionary']
224 241
242 return idl_world
243
244 def generate_dictionary_code(self, definitions, dictionary_name,
245 dictionary):
246 interface_info = self.interfaces_info[dictionary_name]
247 bindings_results = self.generate_dictionary_bindings(
248 dictionary_name, interface_info, dictionary)
249 impl_results = self.generate_dictionary_impl(
250 dictionary_name, interface_info, dictionary)
251 return bindings_results + impl_results
252
253 def generate_dictionary_bindings(self, dictionary_name,
254 interface_info, dictionary):
255 header_template = self.jinja_env.get_template('dictionary_dart_h.templat e')
256 cpp_template = self.jinja_env.get_template('dictionary_dart_cpp.template ')
257 template_context = dart_dictionary.dictionary_context(dictionary)
258 # Add the include for interface itself
259 template_context['header_includes'].add(interface_info['include_path'])
260 header_text, cpp_text = render_template(
261 interface_info, header_template, cpp_template, template_context)
262 return (header_text, cpp_text)
263
264 def generate_dictionary_impl(self, dictionary_name,
265 interface_info, dictionary):
266 header_template = self.jinja_env.get_template('dictionary_impl_h.templat e')
267 cpp_template = self.jinja_env.get_template('dictionary_impl_cpp.template ')
268 template_context = dart_dictionary.dictionary_impl_context(
269 dictionary, self.interfaces_info)
270 header_text, cpp_text = render_template(
271 interface_info, header_template, cpp_template, template_context)
272 return (header_text, cpp_text)
273
274 def load_global_pickles(self, global_entries):
225 # List of all interfaces and callbacks for global code generation. 275 # List of all interfaces and callbacks for global code generation.
226 world = {'interfaces': [], 'callbacks': []} 276 world = {'interfaces': [], 'callbacks': [], 'dictionary': []}
227 277
228 # Load all pickled data for each interface. 278 # Load all pickled data for each interface.
229 for pickle_directory in global_pickle_directories: 279 for (directory, file_list) in global_entries:
230 listing = os.listdir(pickle_directory) 280 for idl_filename in file_list:
231 for filename in listing: 281 interface_name = idl_filename_to_interface_name(idl_filename)
232 if filename.endswith('_globals.pickle'): 282 idl_pickle_filename = interface_name + "_globals.pickle"
233 idl_filename = os.path.join(pickle_directory, filename) 283 idl_pickle_filename = os.path.join(directory, idl_pickle_filenam e)
234 with open(idl_filename) as idl_pickle_file: 284 with open(idl_pickle_filename) as idl_pickle_file:
235 idl_world = pickle.load(idl_pickle_file) 285 idl_world = pickle.load(idl_pickle_file)
236 if 'interface' in idl_world: 286 if 'interface' in idl_world:
237 # FIXME: Why are some of these None? 287 # FIXME: Why are some of these None?
238 if idl_world['interface']: 288 if idl_world['interface']:
239 world['interfaces'].append(idl_world['interface' ]) 289 world['interfaces'].append(idl_world['interface'])
240 if 'callbacks' in idl_world: 290 if 'callbacks' in idl_world:
241 # FIXME: Why are some of these None? 291 # FIXME: Why are some of these None?
242 if idl_world['callbacks']: 292 if idl_world['callbacks']:
243 world['callbacks'].append(idl_world['callback']) 293 world['callbacks'].append(idl_world['callback'])
244 idl_pickle_file.close() 294 if 'dictionary' in idl_world:
245 295 # It's an IDL dictionary
296 if idl_world['dictionary']:
297 world['dictionary'].append(idl_world['dictionary'])
246 world['interfaces'] = sorted(world['interfaces'], key=lambda (x): x['nam e']) 298 world['interfaces'] = sorted(world['interfaces'], key=lambda (x): x['nam e'])
247 world['callbacks'] = sorted(world['callbacks'], key=lambda (x): x['name' ]) 299 world['callbacks'] = sorted(world['callbacks'], key=lambda (x): x['name' ])
300 world['dictionary'] = sorted(world['dictionary'], key=lambda (x): x['nam e'])
301 return world
248 302
249 template_contents = world 303 # Generates global file for all interfaces.
304 def generate_globals(self, global_entries):
305 template_contents = self.load_global_pickles(global_entries)
250 template_contents['code_generator'] = module_pyname 306 template_contents['code_generator'] = module_pyname
251 307
308 header_template_filename = 'global_h.template'
252 header_template = self.jinja_env.get_template(header_template_filename) 309 header_template = self.jinja_env.get_template(header_template_filename)
253 header_text = header_template.render(template_contents) 310 header_text = header_template.render(template_contents)
254 311
312 cpp_template_filename = 'global_cpp.template'
255 cpp_template = self.jinja_env.get_template(cpp_template_filename) 313 cpp_template = self.jinja_env.get_template(cpp_template_filename)
256 cpp_text = cpp_template.render(template_contents) 314 cpp_text = cpp_template.render(template_contents)
315
257 return header_text, cpp_text 316 return header_text, cpp_text
258 317
318 # Generates global dart blink file for all interfaces.
319 def generate_dart_blink(self, global_entries):
320 template_contents = self.load_global_pickles(global_entries)
321 template_contents['code_generator'] = module_pyname
322
323 template_filename = 'dart_blink.template'
324 template = self.jinja_env.get_template(template_filename)
325
326 text = template.render(template_contents)
327 return text
328
259 329
260 def initialize_jinja_env(cache_dir): 330 def initialize_jinja_env(cache_dir):
261 jinja_env = jinja2.Environment( 331 jinja_env = jinja2.Environment(
262 loader=jinja2.FileSystemLoader(templates_dir), 332 loader=jinja2.FileSystemLoader(templates_dir),
263 # Bytecode cache is not concurrency-safe unless pre-cached: 333 # Bytecode cache is not concurrency-safe unless pre-cached:
264 # if pre-cached this is read-only, but writing creates a race condition. 334 # if pre-cached this is read-only, but writing creates a race condition.
265 # bytecode_cache=jinja2.FileSystemBytecodeCache(cache_dir), 335 # bytecode_cache=jinja2.FileSystemBytecodeCache(cache_dir),
266 keep_trailing_newline=True, # newline-terminate generated files 336 keep_trailing_newline=True, # newline-terminate generated files
267 lstrip_blocks=True, # so can indent control flow tags 337 lstrip_blocks=True, # so can indent control flow tags
268 trim_blocks=True) 338 trim_blocks=True)
(...skipping 18 matching lines...) Expand all
287 # [RuntimeEnabled] 357 # [RuntimeEnabled]
288 def runtime_enabled_if(code, runtime_enabled_function_name): 358 def runtime_enabled_if(code, runtime_enabled_function_name):
289 if not runtime_enabled_function_name: 359 if not runtime_enabled_function_name:
290 return code 360 return code
291 # Indent if statement to level of original code 361 # Indent if statement to level of original code
292 indent = re.match(' *', code).group(0) 362 indent = re.match(' *', code).group(0)
293 return ('%sif (%s())\n' % (indent, runtime_enabled_function_name) + 363 return ('%sif (%s())\n' % (indent, runtime_enabled_function_name) +
294 ' %s' % code) 364 ' %s' % code)
295 365
296 366
367 def split_path(path):
368 path_list = []
369 while os.path.basename(path):
370 path_list.append(os.path.basename(path))
371 path = os.path.dirname(path)
372 path_list.reverse()
373 return path_list
374
375
297 ################################################################################ 376 ################################################################################
298 377
299 def main(argv): 378 def main(argv):
300 # If file itself executed, cache templates 379 # If file itself executed, cache templates
301 try: 380 try:
302 cache_dir = argv[1] 381 cache_dir = argv[1]
303 dummy_filename = argv[2] 382 dummy_filename = argv[2]
304 except IndexError as err: 383 except IndexError as err:
305 print 'Usage: %s OUTPUT_DIR DUMMY_FILENAME' % argv[0] 384 print 'Usage: %s OUTPUT_DIR DUMMY_FILENAME' % argv[0]
306 return 1 385 return 1
307 386
308 # Cache templates 387 # Cache templates
309 jinja_env = initialize_jinja_env(cache_dir) 388 jinja_env = initialize_jinja_env(cache_dir)
310 template_filenames = [filename for filename in os.listdir(templates_dir) 389 template_filenames = [filename for filename in os.listdir(templates_dir)
311 # Skip .svn, directories, etc. 390 # Skip .svn, directories, etc.
312 if filename.endswith(('.cpp', '.h', '.template'))] 391 if filename.endswith(('.cpp', '.h', '.template'))]
313 for template_filename in template_filenames: 392 for template_filename in template_filenames:
314 jinja_env.get_template(template_filename) 393 jinja_env.get_template(template_filename)
315 394
316 # Create a dummy file as output for the build system, 395 # Create a dummy file as output for the build system,
317 # since filenames of individual cache files are unpredictable and opaque 396 # since filenames of individual cache files are unpredictable and opaque
318 # (they are hashes of the template path, which varies based on environment) 397 # (they are hashes of the template path, which varies based on environment)
319 with open(dummy_filename, 'w') as dummy_file: 398 with open(dummy_filename, 'w') as dummy_file:
320 pass # |open| creates or touches the file 399 pass # |open| creates or touches the file
321 400
322 401
323 if __name__ == '__main__': 402 if __name__ == '__main__':
324 sys.exit(main(sys.argv)) 403 sys.exit(main(sys.argv))
OLDNEW
« no previous file with comments | « bindings/README ('k') | bindings/dart/scripts/compiler.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698