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

Side by Side Diff: Source/bindings/scripts/unstable/idl_definitions_builder.py

Issue 181513006: IDL compiler: delete Perl compiler, remove unstable/ directory (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 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
OLDNEW
(Empty)
1 # Copyright (C) 2013 Google Inc. All rights reserved.
2 #
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions are
5 # met:
6 #
7 # * Redistributions of source code must retain the above copyright
8 # notice, this list of conditions and the following disclaimer.
9 # * Redistributions in binary form must reproduce the above
10 # copyright notice, this list of conditions and the following disclaimer
11 # in the documentation and/or other materials provided with the
12 # distribution.
13 # * Neither the name of Google Inc. nor the names of its
14 # contributors may be used to endorse or promote products derived from
15 # this software without specific prior written permission.
16 #
17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
28
29 """Builds an IdlDefinitions object from an AST (produced by blink_idl_parser)."" "
30
31 import os
32
33 from idl_definitions import IdlDefinitions, IdlInterface, IdlException, IdlOpera tion, IdlCallbackFunction, IdlArgument, IdlAttribute, IdlConstant, IdlEnum, IdlU nionType
34
35 SPECIAL_KEYWORD_LIST = ['GETTER', 'SETTER', 'DELETER']
36 STANDARD_TYPEDEFS = {
37 # http://www.w3.org/TR/WebIDL/#common-DOMTimeStamp
38 'DOMTimeStamp': 'unsigned long long',
39 }
40
41 def build_idl_definitions_from_ast(node):
42 if node is None:
43 return None
44 node_class = node.GetClass()
45 if node_class != 'File':
46 raise ValueError('Unrecognized node class: %s' % node_class)
47 return file_node_to_idl_definitions(node)
48
49
50 def file_node_to_idl_definitions(node):
51 callback_functions = {}
52 enumerations = {}
53 interfaces = {}
54 typedefs = STANDARD_TYPEDEFS
55
56 # FIXME: only needed for Perl, remove later
57 file_name = os.path.abspath(node.GetName())
58
59 children = node.GetChildren()
60 for child in children:
61 child_class = child.GetClass()
62 if child_class == 'Interface':
63 interface = interface_node_to_idl_interface(child)
64 interfaces[interface.name] = interface
65 elif child_class == 'Exception':
66 exception = exception_node_to_idl_exception(child)
67 # For simplicity, treat exceptions as interfaces
68 interfaces[exception.name] = exception
69 elif child_class == 'Typedef':
70 type_name = child.GetName()
71 typedefs[type_name] = typedef_node_to_type(child)
72 elif child_class == 'Enum':
73 enumeration = enum_node_to_idl_enum(child)
74 enumerations[enumeration.name] = enumeration
75 elif child_class == 'Callback':
76 callback_function = callback_node_to_idl_callback_function(child)
77 callback_functions[callback_function.name] = callback_function
78 elif child_class == 'Implements':
79 # Implements is handled at the interface merging step
80 pass
81 else:
82 raise ValueError('Unrecognized node class: %s' % child_class)
83
84 return IdlDefinitions(callback_functions=callback_functions, enumerations=en umerations, file_name=file_name, interfaces=interfaces, typedefs=typedefs)
85
86 # Constructors for Interface definitions and interface members
87
88
89 def interface_node_to_idl_interface(node):
90 attributes = []
91 constants = []
92 constructors = None
93 custom_constructors = None
94 extended_attributes = None
95 operations = []
96 is_callback = node.GetProperty('CALLBACK') or False
97 # FIXME: uppercase 'Partial' => 'PARTIAL' in base IDL parser
98 is_partial = node.GetProperty('Partial') or False
99 name = node.GetName()
100 parent = None
101
102 children = node.GetChildren()
103 for child in children:
104 child_class = child.GetClass()
105 if child_class == 'Attribute':
106 attributes.append(attribute_node_to_idl_attribute(child))
107 elif child_class == 'Const':
108 constants.append(constant_node_to_idl_constant(child))
109 elif child_class == 'ExtAttributes':
110 extended_attributes = ext_attributes_node_to_extended_attributes(chi ld)
111 constructors, custom_constructors = extended_attributes_to_construct ors(extended_attributes)
112 clear_constructor_attributes(extended_attributes)
113 elif child_class == 'Operation':
114 operations.append(operation_node_to_idl_operation(child))
115 elif child_class == 'Inherit':
116 parent = child.GetName()
117 else:
118 raise ValueError('Unrecognized node class: %s' % child_class)
119
120 return IdlInterface(name=name, attributes=attributes, constants=constants, c onstructors=constructors, custom_constructors=custom_constructors, extended_attr ibutes=extended_attributes, operations=operations, is_callback=is_callback, is_p artial=is_partial, parent=parent)
121
122
123 def attribute_node_to_idl_attribute(node):
124 idl_type = None
125 extended_attributes = {}
126 is_nullable = False
127 is_read_only = node.GetProperty('READONLY') or False
128 is_static = node.GetProperty('STATIC') or False
129 name = node.GetName()
130
131 children = node.GetChildren()
132 for child in children:
133 child_class = child.GetClass()
134 if child_class == 'Type':
135 idl_type = type_node_to_type(child)
136 is_nullable = child.GetProperty('NULLABLE') or False
137 elif child_class == 'ExtAttributes':
138 extended_attributes = ext_attributes_node_to_extended_attributes(chi ld)
139 else:
140 raise ValueError('Unrecognized node class: %s' % child_class)
141
142 return IdlAttribute(idl_type=idl_type, extended_attributes=extended_attribut es, is_nullable=is_nullable, is_read_only=is_read_only, is_static=is_static, nam e=name)
143
144
145 def constant_node_to_idl_constant(node):
146 name = node.GetName()
147
148 children = node.GetChildren()
149 num_children = len(children)
150 if num_children < 2 or num_children > 3:
151 raise ValueError('Expected 2 or 3 children, got %s' % num_children)
152
153 type_node = children[0]
154 # ConstType is more limited than Type, so subtree is smaller and we don't
155 # use the full type_node_to_type function.
156 idl_type = type_node_inner_to_type(type_node)
157
158 value_node = children[1]
159 value_node_class = value_node.GetClass()
160 if value_node_class != 'Value':
161 raise ValueError('Expected Value node, got %s' % value_node_class)
162 value = value_node.GetName()
163
164 extended_attributes = None
165 if num_children == 3:
166 ext_attributes_node = children[2]
167 extended_attributes = ext_attributes_node_to_extended_attributes(ext_att ributes_node)
168
169 return IdlConstant(idl_type=idl_type, extended_attributes=extended_attribute s, name=name, value=value)
170
171
172 def operation_node_to_idl_operation(node):
173 name = node.GetName()
174 # FIXME: AST should use None internally
175 if name == '_unnamed_':
176 name = None
177
178 is_static = node.GetProperty('STATIC') or False
179 specials = []
180 property_dictionary = node.GetProperties()
181 for special_keyword in SPECIAL_KEYWORD_LIST:
182 if special_keyword in property_dictionary:
183 specials.append(special_keyword.lower())
184
185 extended_attributes = None
186 arguments = []
187 return_type = None
188 children = node.GetChildren()
189 for child in children:
190 child_class = child.GetClass()
191 if child_class == 'Arguments':
192 arguments = arguments_node_to_arguments(child)
193 elif child_class == 'Type':
194 return_type = type_node_to_type(child)
195 elif child_class == 'ExtAttributes':
196 extended_attributes = ext_attributes_node_to_extended_attributes(chi ld)
197 else:
198 raise ValueError('Unrecognized node class: %s' % child_class)
199
200 return IdlOperation(name=name, idl_type=return_type, extended_attributes=ext ended_attributes, is_static=is_static, arguments=arguments, specials=specials)
201
202
203 def arguments_node_to_arguments(node):
204 # [Constructor] and [CustomConstructor] without arguments (the bare form)
205 # have None instead of an arguments node, but have the same meaning as using
206 # an empty argument list, [Constructor()], so special-case this.
207 # http://www.w3.org/TR/WebIDL/#Constructor
208 if node is None:
209 return []
210 arguments = []
211 argument_node_list = node.GetChildren()
212 for argument_node in argument_node_list:
213 arguments.append(argument_node_to_idl_argument(argument_node))
214 return arguments
215
216
217 def argument_node_to_idl_argument(node):
218 name = node.GetName()
219
220 idl_type = None
221 extended_attributes = {}
222 # FIXME: Boolean values are inconsistent due to Perl compatibility.
223 # Make all default to False once Perl removed.
224 is_nullable = False
225 is_optional = node.GetProperty('OPTIONAL')
226 is_variadic = None
227 children = node.GetChildren()
228 for child in children:
229 child_class = child.GetClass()
230 if child_class == 'Type':
231 idl_type = type_node_to_type(child)
232 # FIXME: Doesn't handle nullable arrays (Foo[]?), and arrays of
233 # nullable (Foo?[]) are treated as nullable arrays. No actual use.
234 is_nullable = child.GetProperty('NULLABLE')
235 elif child_class == 'ExtAttributes':
236 extended_attributes = ext_attributes_node_to_extended_attributes(chi ld)
237 elif child_class == 'Argument':
238 child_name = child.GetName()
239 if child_name != '...':
240 raise ValueError('Unrecognized Argument node; expected "...", go t "%s"' % child_name)
241 is_variadic = child.GetProperty('ELLIPSIS') or False
242 else:
243 raise ValueError('Unrecognized node class: %s' % child_class)
244
245 return IdlArgument(name=name, idl_type=idl_type, extended_attributes=extende d_attributes, is_nullable=is_nullable, is_optional=is_optional, is_variadic=is_v ariadic)
246
247 # Constructors for for non-interface definitions
248
249
250 def callback_node_to_idl_callback_function(node):
251 name = node.GetName()
252 children = node.GetChildren()
253 num_children = len(children)
254 if num_children != 2:
255 raise ValueError('Expected 2 children, got %s' % num_children)
256
257 type_node = children[0]
258 idl_type = type_node_to_type(type_node)
259
260 arguments_node = children[1]
261 arguments_node_class = arguments_node.GetClass()
262 if arguments_node_class != 'Arguments':
263 raise ValueError('Expected Value node, got %s' % arguments_node_class)
264 arguments = arguments_node_to_arguments(arguments_node)
265
266 return IdlCallbackFunction(name=name, idl_type=idl_type, arguments=arguments )
267
268
269 def enum_node_to_idl_enum(node):
270 name = node.GetName()
271 values = []
272 for child in node.GetChildren():
273 values.append(child.GetName())
274 return IdlEnum(name=name, values=values)
275
276
277 def exception_operation_node_to_idl_operation(node):
278 # Needed to handle one case in DOMException.idl:
279 # // Override in a Mozilla compatible format
280 # [NotEnumerable] DOMString toString();
281 # FIXME: can we remove this? replace with a stringifier?
282 extended_attributes = {}
283 name = node.GetName()
284 children = node.GetChildren()
285 if len(children) < 1 or len(children) > 2:
286 raise ValueError('ExceptionOperation node with %s children, expected 1 o r 2' % len(children))
287
288 type_node = children[0]
289 return_type = type_node_to_type(type_node)
290
291 if len(children) > 1:
292 ext_attributes_node = children[1]
293 extended_attributes = ext_attributes_node_to_extended_attributes(ext_att ributes_node)
294
295 return IdlOperation(name=name, idl_type=return_type, extended_attributes=ext ended_attributes)
296
297
298 def exception_node_to_idl_exception(node):
299 # Exceptions are similar to Interfaces, but simpler
300 attributes = []
301 constants = []
302 extended_attributes = None
303 operations = []
304 name = node.GetName()
305
306 children = node.GetChildren()
307 for child in children:
308 child_class = child.GetClass()
309 if child_class == 'Attribute':
310 attribute = attribute_node_to_idl_attribute(child)
311 attributes.append(attribute)
312 elif child_class == 'Const':
313 constants.append(constant_node_to_idl_constant(child))
314 elif child_class == 'ExtAttributes':
315 extended_attributes = ext_attributes_node_to_extended_attributes(chi ld)
316 elif child_class == 'ExceptionOperation':
317 operations.append(exception_operation_node_to_idl_operation(child))
318 else:
319 raise ValueError('Unrecognized node class: %s' % child_class)
320
321 return IdlException(name=name, attributes=attributes, constants=constants, e xtended_attributes=extended_attributes, operations=operations)
322
323
324 def typedef_node_to_type(node):
325 children = node.GetChildren()
326 if len(children) != 1:
327 raise ValueError('Typedef node with %s children, expected 1' % len(child ren))
328 child = children[0]
329 child_class = child.GetClass()
330 if child_class != 'Type':
331 raise ValueError('Unrecognized node class: %s' % child_class)
332 return type_node_to_type(child)
333
334 # Extended attributes
335
336
337 def ext_attributes_node_to_extended_attributes(node):
338 """
339 Returns:
340 Dictionary of {ExtAttributeName: ExtAttributeValue}.
341 Value is usually a string, with three exceptions:
342 Constructors: value is a list of Arguments nodes, corresponding to
343 possibly signatures of the constructor.
344 CustomConstructors: value is a list of Arguments nodes, corresponding to
345 possibly signatures of the custom constructor.
346 NamedConstructor: value is a Call node, corresponding to the single
347 signature of the named constructor.
348 """
349 # Primarily just make a dictionary from the children.
350 # The only complexity is handling various types of constructors:
351 # Constructors and Custom Constructors can have duplicate entries due to
352 # overloading, and thus are stored in temporary lists.
353 # However, Named Constructors cannot be overloaded, and thus do not have
354 # a list.
355 # FIXME: move Constructor logic into separate function, instead of modifying
356 # extended attributes in-place.
357 constructors = []
358 custom_constructors = []
359 extended_attributes = {}
360
361 def child_node(extended_attribute_node):
362 children = extended_attribute_node.GetChildren()
363 if not children:
364 return None
365 if len(children) > 1:
366 raise ValueError('ExtAttributes node with %s children, expected at m ost 1' % len(children))
367 return children[0]
368
369 extended_attribute_node_list = node.GetChildren()
370 for extended_attribute_node in extended_attribute_node_list:
371 name = extended_attribute_node.GetName()
372 child = child_node(extended_attribute_node)
373 child_class = child and child.GetClass()
374 if name == 'Constructor':
375 if child_class and child_class != 'Arguments':
376 raise ValueError('Constructor only supports Arguments as child, but has child of class: %s' % child_class)
377 constructors.append(child)
378 elif name == 'CustomConstructor':
379 if child_class and child_class != 'Arguments':
380 raise ValueError('[CustomConstructor] only supports Arguments as child, but has child of class: %s' % child_class)
381 custom_constructors.append(child)
382 elif name == 'NamedConstructor':
383 if child_class and child_class != 'Call':
384 raise ValueError('[NamedConstructor] only supports Call as child , but has child of class: %s' % child_class)
385 extended_attributes[name] = child
386 elif name == 'SetWrapperReferenceTo':
387 if not child:
388 raise ValueError('[SetWrapperReferenceTo] requires a child, but has none.')
389 if child_class != 'Arguments':
390 raise ValueError('[SetWrapperReferenceTo] only supports Argument s as child, but has child of class: %s' % child_class)
391 extended_attributes[name] = arguments_node_to_arguments(child)
392 elif child:
393 raise ValueError('ExtAttributes node with unexpected children: %s' % name)
394 else:
395 value = extended_attribute_node.GetProperty('VALUE')
396 extended_attributes[name] = value
397
398 # Store constructors and custom constructors in special list attributes,
399 # which are deleted later. Note plural in key.
400 if constructors:
401 extended_attributes['Constructors'] = constructors
402 if custom_constructors:
403 extended_attributes['CustomConstructors'] = custom_constructors
404
405 return extended_attributes
406
407
408 def extended_attributes_to_constructors(extended_attributes):
409 """Returns constructors and custom_constructors (lists of IdlOperations).
410
411 Auxiliary function for interface_node_to_idl_interface.
412 """
413 constructors = []
414 custom_constructors = []
415 if 'Constructors' in extended_attributes:
416 constructor_list = extended_attributes['Constructors']
417 # If not overloaded, have index 0, otherwise index from 1
418 overloaded_index = 0 if len(constructor_list) == 1 else 1
419 for arguments_node in constructor_list:
420 name = 'Constructor'
421 arguments = arguments_node_to_arguments(arguments_node)
422 constructor = IdlOperation(name=name, extended_attributes=extended_a ttributes, overloaded_index=overloaded_index, arguments=arguments)
423 constructors.append(constructor)
424 overloaded_index += 1
425
426 if 'CustomConstructors' in extended_attributes:
427 custom_constructor_list = extended_attributes['CustomConstructors']
428 # If not overloaded, have index 0, otherwise index from 1
429 overloaded_index = 0 if len(custom_constructor_list) == 1 else 1
430 for arguments_node in custom_constructor_list:
431 name = 'CustomConstructor'
432 arguments = arguments_node_to_arguments(arguments_node)
433 custom_constructor = IdlOperation(name=name, extended_attributes=ext ended_attributes, overloaded_index=overloaded_index, arguments=arguments)
434 custom_constructors.append(custom_constructor)
435 overloaded_index += 1
436
437 if 'NamedConstructor' in extended_attributes:
438 name = 'NamedConstructor'
439 call_node = extended_attributes['NamedConstructor']
440 extended_attributes['NamedConstructor'] = call_node.GetName()
441 overloaded_index = None # named constructors are not overloaded
442 children = call_node.GetChildren()
443 if len(children) != 1:
444 raise ValueError('NamedConstructor node expects 1 child, got %s.' % len(children))
445 arguments_node = children[0]
446 arguments = arguments_node_to_arguments(arguments_node)
447 named_constructor = IdlOperation(name=name, extended_attributes=extended _attributes, overloaded_index=overloaded_index, arguments=arguments)
448 # FIXME: should return named_constructor separately; appended for Perl
449 constructors.append(named_constructor)
450
451 return constructors, custom_constructors
452
453
454 def clear_constructor_attributes(extended_attributes):
455 # Deletes Constructor*s* (plural), sets Constructor (singular)
456 if 'Constructors' in extended_attributes:
457 del extended_attributes['Constructors']
458 extended_attributes['Constructor'] = None
459 if 'CustomConstructors' in extended_attributes:
460 del extended_attributes['CustomConstructors']
461 extended_attributes['CustomConstructor'] = None
462
463
464 # Types
465
466
467 def type_node_to_type(node):
468 children = node.GetChildren()
469 if len(children) < 1 or len(children) > 2:
470 raise ValueError('Type node expects 1 or 2 children (type + optional arr ay []), got %s (multi-dimensional arrays are not supported).' % len(children))
471
472 type_node_child = children[0]
473 idl_type = type_node_inner_to_type(type_node_child)
474
475 if len(children) == 2:
476 array_node = children[1]
477 array_node_class = array_node.GetClass()
478 if array_node_class != 'Array':
479 raise ValueError('Expected Array node as TypeSuffix, got %s node.' % array_node_class)
480 idl_type += '[]'
481
482 return idl_type
483
484
485 def type_node_inner_to_type(node):
486 node_class = node.GetClass()
487 # Note Type*r*ef, not Typedef, meaning the type is an identifier, thus
488 # either a typedef shorthand (but not a Typedef declaration itself) or an
489 # interface type. We do not distinguish these, and just use the type name.
490 if node_class in ['PrimitiveType', 'Typeref']:
491 return node.GetName()
492 elif node_class == 'Any':
493 return 'any'
494 elif node_class == 'Sequence':
495 return sequence_node_to_type(node)
496 elif node_class == 'UnionType':
497 return union_type_node_to_idl_union_type(node)
498 raise ValueError('Unrecognized node class: %s' % node_class)
499
500
501 def sequence_node_to_type(node):
502 children = node.GetChildren()
503 if len(children) != 1:
504 raise ValueError('Sequence node expects exactly 1 child, got %s' % len(c hildren))
505 sequence_child = children[0]
506 sequence_child_class = sequence_child.GetClass()
507 if sequence_child_class != 'Type':
508 raise ValueError('Unrecognized node class: %s' % sequence_child_class)
509 sequence_type = type_node_to_type(sequence_child)
510 return 'sequence<%s>' % sequence_type
511
512
513 def union_type_node_to_idl_union_type(node):
514 union_member_types = []
515 for member_type_node in node.GetChildren():
516 member_type = type_node_to_type(member_type_node)
517 union_member_types.append(member_type)
518 return IdlUnionType(union_member_types=union_member_types)
OLDNEW
« no previous file with comments | « Source/bindings/scripts/unstable/idl_definitions.py ('k') | Source/bindings/scripts/unstable/idl_reader.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698