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

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

Issue 540533002: Roll IDL to Dartium37 (r181268) (Closed) Base URL: https://dart.googlecode.com/svn/third_party/WebCore
Patch Set: 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/idl_compiler.py ('k') | bindings/scripts/idl_reader.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 """Blink IDL Intermediate Representation (IR) classes.
30
31 Classes are primarily constructors, which build an IdlDefinitions object
32 (and various contained objects) from an AST (produced by blink_idl_parser).
33
34 This is in two steps:
35 * Constructors walk the AST, creating objects.
36 * Typedef resolution.
37
38 Typedefs are all resolved here, and not stored in IR.
39
40 Typedef resolution uses some auxiliary classes and OOP techniques to make this
41 a generic call, via the resolve_typedefs() method.
42
43 Class hierarchy (mostly containment, '<' for inheritance):
44
45 IdlDefinitions
46 IdlCallbackFunction < TypedObject
47 IdlEnum :: FIXME: remove, just use a dict for enums
48 IdlInterface
49 IdlAttribute < TypedObject
50 IdlConstant < TypedObject
51 IdlOperation < TypedObject
52 IdlArgument < TypedObject
53 IdlException < IdlInterface
54 (same contents as IdlInterface)
55
56 TypedObject :: mixin for typedef resolution
57
58 Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
59 """
60
61 import abc
62
63 from idl_types import IdlType, IdlUnionType
64
65 SPECIAL_KEYWORD_LIST = ['GETTER', 'SETTER', 'DELETER']
66 STANDARD_TYPEDEFS = {
67 # http://www.w3.org/TR/WebIDL/#common-DOMTimeStamp
68 'DOMTimeStamp': 'unsigned long long',
69 }
70
71
72 ################################################################################
73 # TypedObject (mixin for typedef resolution)
74 ################################################################################
75
76 class TypedObject(object):
77 """Object with a type, such as an Attribute or Operation (return value).
78
79 The type can be an actual type, or can be a typedef, which must be resolved
80 before passing data to the code generator.
81 """
82 __metaclass__ = abc.ABCMeta
83 idl_type = None
84
85 def resolve_typedefs(self, typedefs):
86 """Resolve typedefs to actual types in the object."""
87 # Constructors don't have their own return type, because it's the
88 # interface itself.
89 if not self.idl_type:
90 return
91 # Need to re-assign self.idl_type, not just mutate idl_type,
92 # since type(idl_type) may change.
93 self.idl_type = self.idl_type.resolve_typedefs(typedefs)
94
95
96 ################################################################################
97 # Definitions (main container class)
98 ################################################################################
99
100 class IdlDefinitions(object):
101 def __init__(self, node):
102 """Args: node: AST root node, class == 'File'"""
103 self.callback_functions = {}
104 self.dictionaries = {}
105 self.enumerations = {}
106 self.interfaces = {}
107
108 node_class = node.GetClass()
109 if node_class != 'File':
110 raise ValueError('Unrecognized node class: %s' % node_class)
111
112 typedefs = dict((typedef_name, IdlType(type_name))
113 for typedef_name, type_name in
114 STANDARD_TYPEDEFS.iteritems())
115
116 children = node.GetChildren()
117 for child in children:
118 child_class = child.GetClass()
119 if child_class == 'Interface':
120 interface = IdlInterface(child)
121 self.interfaces[interface.name] = interface
122 elif child_class == 'Exception':
123 exception = IdlException(child)
124 # For simplicity, treat exceptions as interfaces
125 self.interfaces[exception.name] = exception
126 elif child_class == 'Typedef':
127 type_name = child.GetName()
128 typedefs[type_name] = typedef_node_to_type(child)
129 elif child_class == 'Enum':
130 enumeration = IdlEnum(child)
131 self.enumerations[enumeration.name] = enumeration
132 elif child_class == 'Callback':
133 callback_function = IdlCallbackFunction(child)
134 self.callback_functions[callback_function.name] = callback_funct ion
135 elif child_class == 'Implements':
136 # Implements is handled at the interface merging step
137 pass
138 elif child_class == 'Dictionary':
139 dictionary = IdlDictionary(child)
140 self.dictionaries[dictionary.name] = dictionary
141 else:
142 raise ValueError('Unrecognized node class: %s' % child_class)
143
144 # Typedefs are not stored in IR:
145 # Resolve typedefs with the actual types and then discard the Typedefs.
146 # http://www.w3.org/TR/WebIDL/#idl-typedefs
147 self.resolve_typedefs(typedefs)
148
149 def resolve_typedefs(self, typedefs):
150 for callback_function in self.callback_functions.itervalues():
151 callback_function.resolve_typedefs(typedefs)
152 for interface in self.interfaces.itervalues():
153 interface.resolve_typedefs(typedefs)
154
155 def update(self, other):
156 """Update with additional IdlDefinitions."""
157 for interface_name, new_interface in other.interfaces.iteritems():
158 if not new_interface.is_partial:
159 # Add as new interface
160 self.interfaces[interface_name] = new_interface
161 continue
162
163 # Merge partial to existing interface
164 try:
165 self.interfaces[interface_name].merge(new_interface)
166 except KeyError:
167 raise Exception('Tried to merge partial interface for {0}, '
168 'but no existing interface by that name'
169 .format(interface_name))
170
171 # Merge callbacks and enumerations
172 self.enumerations.update(other.enumerations)
173 self.callback_functions.update(other.callback_functions)
174
175
176 ################################################################################
177 # Callback Functions
178 ################################################################################
179
180 class IdlCallbackFunction(TypedObject):
181 def __init__(self, node):
182 children = node.GetChildren()
183 num_children = len(children)
184 if num_children != 2:
185 raise ValueError('Expected 2 children, got %s' % num_children)
186 type_node, arguments_node = children
187 arguments_node_class = arguments_node.GetClass()
188 if arguments_node_class != 'Arguments':
189 raise ValueError('Expected Arguments node, got %s' % arguments_node_ class)
190
191 self.name = node.GetName()
192 self.idl_type = type_node_to_type(type_node)
193 self.arguments = arguments_node_to_arguments(arguments_node)
194
195 def resolve_typedefs(self, typedefs):
196 TypedObject.resolve_typedefs(self, typedefs)
197 for argument in self.arguments:
198 argument.resolve_typedefs(typedefs)
199
200
201 ################################################################################
202 # Dictionary
203 ################################################################################
204
205 class IdlDictionary(object):
206 def __init__(self, node):
207 self.parent = None
208 self.name = node.GetName()
209 self.members = []
210 for child in node.GetChildren():
211 child_class = child.GetClass()
212 if child_class == 'Inherit':
213 self.parent = child.GetName()
214 elif child_class == 'Key':
215 self.members.append(IdlDictionaryMember(child))
216 else:
217 raise ValueError('Unrecognized node class: %s' % child_class)
218
219
220 class IdlDictionaryMember(object):
221 def __init__(self, node):
222 self.default_value = None
223 self.extended_attributes = {}
224 self.idl_type = None
225 self.name = node.GetName()
226 for child in node.GetChildren():
227 child_class = child.GetClass()
228 if child_class == 'Type':
229 self.idl_type = type_node_to_type(child)
230 elif child_class == 'Default':
231 self.default_value = child.GetProperty('VALUE')
232 elif child_class == 'ExtAttributes':
233 self.extended_attributes = ext_attributes_node_to_extended_attri butes(child)
234 else:
235 raise ValueError('Unrecognized node class: %s' % child_class)
236
237
238 ################################################################################
239 # Enumerations
240 ################################################################################
241
242 class IdlEnum(object):
243 # FIXME: remove, just treat enums as a dictionary
244 def __init__(self, node):
245 self.name = node.GetName()
246 self.values = []
247 for child in node.GetChildren():
248 self.values.append(child.GetName())
249
250
251 ################################################################################
252 # Interfaces and Exceptions
253 ################################################################################
254
255 class IdlInterface(object):
256 def __init__(self, node=None):
257 self.attributes = []
258 self.constants = []
259 self.constructors = []
260 self.custom_constructors = []
261 self.extended_attributes = {}
262 self.operations = []
263 self.parent = None
264 if not node: # Early exit for IdlException.__init__
265 return
266
267 self.is_callback = node.GetProperty('CALLBACK') or False
268 self.is_exception = False
269 # FIXME: uppercase 'Partial' => 'PARTIAL' in base IDL parser
270 self.is_partial = node.GetProperty('Partial') or False
271 self.name = node.GetName()
272
273 children = node.GetChildren()
274 for child in children:
275 child_class = child.GetClass()
276 if child_class == 'Attribute':
277 self.attributes.append(IdlAttribute(child))
278 elif child_class == 'Const':
279 self.constants.append(IdlConstant(child))
280 elif child_class == 'ExtAttributes':
281 extended_attributes = ext_attributes_node_to_extended_attributes (child)
282 self.constructors, self.custom_constructors = (
283 extended_attributes_to_constructors(extended_attributes))
284 clear_constructor_attributes(extended_attributes)
285 self.extended_attributes = extended_attributes
286 elif child_class == 'Operation':
287 self.operations.append(IdlOperation(child))
288 elif child_class == 'Inherit':
289 self.parent = child.GetName()
290 else:
291 raise ValueError('Unrecognized node class: %s' % child_class)
292
293 def resolve_typedefs(self, typedefs):
294 for attribute in self.attributes:
295 attribute.resolve_typedefs(typedefs)
296 for constant in self.constants:
297 constant.resolve_typedefs(typedefs)
298 for constructor in self.constructors:
299 constructor.resolve_typedefs(typedefs)
300 for custom_constructor in self.custom_constructors:
301 custom_constructor.resolve_typedefs(typedefs)
302 for operation in self.operations:
303 operation.resolve_typedefs(typedefs)
304
305 def merge(self, other):
306 """Merge in another interface's members (e.g., partial interface)"""
307 self.attributes.extend(other.attributes)
308 self.constants.extend(other.constants)
309 self.operations.extend(other.operations)
310
311
312 class IdlException(IdlInterface):
313 # Properly exceptions and interfaces are distinct, and thus should inherit a
314 # common base class (say, "IdlExceptionOrInterface").
315 # However, there is only one exception (DOMException), and new exceptions
316 # are not expected. Thus it is easier to implement exceptions as a
317 # restricted subclass of interfaces.
318 # http://www.w3.org/TR/WebIDL/#idl-exceptions
319 def __init__(self, node):
320 # Exceptions are similar to Interfaces, but simpler
321 IdlInterface.__init__(self)
322 self.is_callback = False
323 self.is_exception = True
324 self.is_partial = False
325 self.name = node.GetName()
326
327 children = node.GetChildren()
328 for child in children:
329 child_class = child.GetClass()
330 if child_class == 'Attribute':
331 attribute = IdlAttribute(child)
332 self.attributes.append(attribute)
333 elif child_class == 'Const':
334 self.constants.append(IdlConstant(child))
335 elif child_class == 'ExtAttributes':
336 self.extended_attributes = ext_attributes_node_to_extended_attri butes(child)
337 elif child_class == 'ExceptionOperation':
338 self.operations.append(IdlOperation.from_exception_operation_nod e(child))
339 else:
340 raise ValueError('Unrecognized node class: %s' % child_class)
341
342
343 ################################################################################
344 # Attributes
345 ################################################################################
346
347 class IdlAttribute(TypedObject):
348 def __init__(self, node):
349 self.is_read_only = node.GetProperty('READONLY') or False
350 self.is_static = node.GetProperty('STATIC') or False
351 self.name = node.GetName()
352 # Defaults, overridden below
353 self.idl_type = None
354 self.extended_attributes = {}
355
356 children = node.GetChildren()
357 for child in children:
358 child_class = child.GetClass()
359 if child_class == 'Type':
360 self.idl_type = type_node_to_type(child)
361 elif child_class == 'ExtAttributes':
362 self.extended_attributes = ext_attributes_node_to_extended_attri butes(child)
363 else:
364 raise ValueError('Unrecognized node class: %s' % child_class)
365
366
367 ################################################################################
368 # Constants
369 ################################################################################
370
371 class IdlConstant(TypedObject):
372 def __init__(self, node):
373 children = node.GetChildren()
374 num_children = len(children)
375 if num_children < 2 or num_children > 3:
376 raise ValueError('Expected 2 or 3 children, got %s' % num_children)
377 type_node = children[0]
378 value_node = children[1]
379 value_node_class = value_node.GetClass()
380 if value_node_class != 'Value':
381 raise ValueError('Expected Value node, got %s' % value_node_class)
382
383 self.name = node.GetName()
384 # ConstType is more limited than Type, so subtree is smaller and
385 # we don't use the full type_node_to_type function.
386 self.idl_type = type_node_inner_to_type(type_node)
387 self.value = value_node.GetName()
388
389 if num_children == 3:
390 ext_attributes_node = children[2]
391 self.extended_attributes = ext_attributes_node_to_extended_attribute s(ext_attributes_node)
392 else:
393 self.extended_attributes = {}
394
395
396 ################################################################################
397 # Literals
398 ################################################################################
399
400 class IdlLiteral(object):
401 def __init__(self, idl_type, value):
402 self.idl_type = idl_type
403 self.value = value
404 self.is_null = False
405
406 def __str__(self):
407 if self.idl_type == 'DOMString':
408 return 'String("%s")' % self.value
409 if self.idl_type == 'integer':
410 return '%d' % self.value
411 if self.idl_type == 'float':
412 return '%g' % self.value
413 if self.idl_type == 'boolean':
414 return 'true' if self.value else 'false'
415 raise ValueError('Unsupported literal type: %s' % self.idl_type)
416
417
418 class IdlLiteralNull(IdlLiteral):
419 def __init__(self):
420 self.idl_type = 'NULL'
421 self.value = None
422 self.is_null = True
423
424 def __str__(self):
425 return 'nullptr'
426
427
428 def default_node_to_idl_literal(node):
429 # FIXME: This code is unnecessarily complicated due to the rather
430 # inconsistent way the upstream IDL parser outputs default values.
431 # http://crbug.com/374178
432 idl_type = node.GetProperty('TYPE')
433 if idl_type == 'DOMString':
434 value = node.GetProperty('NAME')
435 if '"' in value or '\\' in value:
436 raise ValueError('Unsupported string value: %r' % value)
437 return IdlLiteral(idl_type, value)
438 if idl_type == 'integer':
439 return IdlLiteral(idl_type, int(node.GetProperty('NAME')))
440 if idl_type == 'float':
441 return IdlLiteral(idl_type, float(node.GetProperty('VALUE')))
442 if idl_type == 'boolean':
443 return IdlLiteral(idl_type, node.GetProperty('VALUE'))
444 if idl_type == 'NULL':
445 return IdlLiteralNull()
446 raise ValueError('Unrecognized default value type: %s' % idl_type)
447
448
449 ################################################################################
450 # Operations
451 ################################################################################
452
453 class IdlOperation(TypedObject):
454 def __init__(self, node=None):
455 self.arguments = []
456 self.extended_attributes = {}
457 self.specials = []
458 self.is_constructor = False
459
460 if not node:
461 self.is_static = False
462 return
463 self.name = node.GetName() # FIXME: should just be: or ''
464 # FIXME: AST should use None internally
465 if self.name == '_unnamed_':
466 self.name = ''
467
468 self.is_static = node.GetProperty('STATIC') or False
469 property_dictionary = node.GetProperties()
470 for special_keyword in SPECIAL_KEYWORD_LIST:
471 if special_keyword in property_dictionary:
472 self.specials.append(special_keyword.lower())
473
474 self.idl_type = None
475 children = node.GetChildren()
476 for child in children:
477 child_class = child.GetClass()
478 if child_class == 'Arguments':
479 self.arguments = arguments_node_to_arguments(child)
480 elif child_class == 'Type':
481 self.idl_type = type_node_to_type(child)
482 elif child_class == 'ExtAttributes':
483 self.extended_attributes = ext_attributes_node_to_extended_attri butes(child)
484 else:
485 raise ValueError('Unrecognized node class: %s' % child_class)
486
487 @classmethod
488 def from_exception_operation_node(cls, node):
489 # Needed to handle one case in DOMException.idl:
490 # // Override in a Mozilla compatible format
491 # [NotEnumerable] DOMString toString();
492 # FIXME: can we remove this? replace with a stringifier?
493 operation = cls()
494 operation.name = node.GetName()
495 children = node.GetChildren()
496 if len(children) < 1 or len(children) > 2:
497 raise ValueError('ExceptionOperation node with %s children, expected 1 or 2' % len(children))
498
499 type_node = children[0]
500 operation.idl_type = type_node_to_type(type_node)
501
502 if len(children) > 1:
503 ext_attributes_node = children[1]
504 operation.extended_attributes = ext_attributes_node_to_extended_attr ibutes(ext_attributes_node)
505
506 return operation
507
508 @classmethod
509 def constructor_from_arguments_node(cls, name, arguments_node):
510 constructor = cls()
511 constructor.name = name
512 constructor.arguments = arguments_node_to_arguments(arguments_node)
513 constructor.is_constructor = True
514 return constructor
515
516 def resolve_typedefs(self, typedefs):
517 TypedObject.resolve_typedefs(self, typedefs)
518 for argument in self.arguments:
519 argument.resolve_typedefs(typedefs)
520
521
522 ################################################################################
523 # Arguments
524 ################################################################################
525
526 class IdlArgument(TypedObject):
527 def __init__(self, node):
528 self.extended_attributes = {}
529 self.idl_type = None
530 self.is_optional = node.GetProperty('OPTIONAL') # syntax: (optional T)
531 self.is_variadic = False # syntax: (T...)
532 self.name = node.GetName()
533 self.default_value = None
534
535 children = node.GetChildren()
536 for child in children:
537 child_class = child.GetClass()
538 if child_class == 'Type':
539 self.idl_type = type_node_to_type(child)
540 elif child_class == 'ExtAttributes':
541 self.extended_attributes = ext_attributes_node_to_extended_attri butes(child)
542 elif child_class == 'Argument':
543 child_name = child.GetName()
544 if child_name != '...':
545 raise ValueError('Unrecognized Argument node; expected "..." , got "%s"' % child_name)
546 self.is_variadic = child.GetProperty('ELLIPSIS') or False
547 elif child_class == 'Default':
548 self.default_value = default_node_to_idl_literal(child)
549 else:
550 raise ValueError('Unrecognized node class: %s' % child_class)
551
552
553 def arguments_node_to_arguments(node):
554 # [Constructor] and [CustomConstructor] without arguments (the bare form)
555 # have None instead of an arguments node, but have the same meaning as using
556 # an empty argument list, [Constructor()], so special-case this.
557 # http://www.w3.org/TR/WebIDL/#Constructor
558 if node is None:
559 return []
560 return [IdlArgument(argument_node)
561 for argument_node in node.GetChildren()]
562
563
564 ################################################################################
565 # Extended attributes
566 ################################################################################
567
568 def ext_attributes_node_to_extended_attributes(node):
569 """
570 Returns:
571 Dictionary of {ExtAttributeName: ExtAttributeValue}.
572 Value is usually a string, with three exceptions:
573 Constructors: value is a list of Arguments nodes, corresponding to
574 possible signatures of the constructor.
575 CustomConstructors: value is a list of Arguments nodes, corresponding to
576 possible signatures of the custom constructor.
577 NamedConstructor: value is a Call node, corresponding to the single
578 signature of the named constructor.
579 """
580 # Primarily just make a dictionary from the children.
581 # The only complexity is handling various types of constructors:
582 # Constructors and Custom Constructors can have duplicate entries due to
583 # overloading, and thus are stored in temporary lists.
584 # However, Named Constructors cannot be overloaded, and thus do not have
585 # a list.
586 # FIXME: move Constructor logic into separate function, instead of modifying
587 # extended attributes in-place.
588 constructors = []
589 custom_constructors = []
590 extended_attributes = {}
591
592 def child_node(extended_attribute_node):
593 children = extended_attribute_node.GetChildren()
594 if not children:
595 return None
596 if len(children) > 1:
597 raise ValueError('ExtAttributes node with %s children, expected at m ost 1' % len(children))
598 return children[0]
599
600 extended_attribute_node_list = node.GetChildren()
601 for extended_attribute_node in extended_attribute_node_list:
602 name = extended_attribute_node.GetName()
603 child = child_node(extended_attribute_node)
604 child_class = child and child.GetClass()
605 if name == 'Constructor':
606 if child_class and child_class != 'Arguments':
607 raise ValueError('Constructor only supports Arguments as child, but has child of class: %s' % child_class)
608 constructors.append(child)
609 elif name == 'CustomConstructor':
610 if child_class and child_class != 'Arguments':
611 raise ValueError('[CustomConstructor] only supports Arguments as child, but has child of class: %s' % child_class)
612 custom_constructors.append(child)
613 elif name == 'NamedConstructor':
614 if child_class and child_class != 'Call':
615 raise ValueError('[NamedConstructor] only supports Call as child , but has child of class: %s' % child_class)
616 extended_attributes[name] = child
617 elif name == 'SetWrapperReferenceTo':
618 if not child:
619 raise ValueError('[SetWrapperReferenceTo] requires a child, but has none.')
620 if child_class != 'Arguments':
621 raise ValueError('[SetWrapperReferenceTo] only supports Argument s as child, but has child of class: %s' % child_class)
622 extended_attributes[name] = arguments_node_to_arguments(child)
623 elif child:
624 raise ValueError('ExtAttributes node with unexpected children: %s' % name)
625 else:
626 value = extended_attribute_node.GetProperty('VALUE')
627 extended_attributes[name] = value
628
629 # Store constructors and custom constructors in special list attributes,
630 # which are deleted later. Note plural in key.
631 if constructors:
632 extended_attributes['Constructors'] = constructors
633 if custom_constructors:
634 extended_attributes['CustomConstructors'] = custom_constructors
635
636 return extended_attributes
637
638
639 def extended_attributes_to_constructors(extended_attributes):
640 """Returns constructors and custom_constructors (lists of IdlOperations).
641
642 Auxiliary function for IdlInterface.__init__.
643 """
644
645 constructor_list = extended_attributes.get('Constructors', [])
646 constructors = [
647 IdlOperation.constructor_from_arguments_node('Constructor', arguments_no de)
648 for arguments_node in constructor_list]
649
650 custom_constructor_list = extended_attributes.get('CustomConstructors', [])
651 custom_constructors = [
652 IdlOperation.constructor_from_arguments_node('CustomConstructor', argume nts_node)
653 for arguments_node in custom_constructor_list]
654
655 if 'NamedConstructor' in extended_attributes:
656 # FIXME: support overloaded named constructors, and make homogeneous
657 name = 'NamedConstructor'
658 call_node = extended_attributes['NamedConstructor']
659 extended_attributes['NamedConstructor'] = call_node.GetName()
660 children = call_node.GetChildren()
661 if len(children) != 1:
662 raise ValueError('NamedConstructor node expects 1 child, got %s.' % len(children))
663 arguments_node = children[0]
664 named_constructor = IdlOperation.constructor_from_arguments_node('NamedC onstructor', arguments_node)
665 # FIXME: should return named_constructor separately; appended for Perl
666 constructors.append(named_constructor)
667
668 return constructors, custom_constructors
669
670
671 def clear_constructor_attributes(extended_attributes):
672 # Deletes Constructor*s* (plural), sets Constructor (singular)
673 if 'Constructors' in extended_attributes:
674 del extended_attributes['Constructors']
675 extended_attributes['Constructor'] = None
676 if 'CustomConstructors' in extended_attributes:
677 del extended_attributes['CustomConstructors']
678 extended_attributes['CustomConstructor'] = None
679
680
681 ################################################################################
682 # Types
683 ################################################################################
684
685 def type_node_to_type(node):
686 children = node.GetChildren()
687 if len(children) < 1 or len(children) > 2:
688 raise ValueError('Type node expects 1 or 2 children (type + optional arr ay []), got %s (multi-dimensional arrays are not supported).' % len(children))
689
690 type_node_child = children[0]
691
692 if len(children) == 2:
693 array_node = children[1]
694 array_node_class = array_node.GetClass()
695 if array_node_class != 'Array':
696 raise ValueError('Expected Array node as TypeSuffix, got %s node.' % array_node_class)
697 # FIXME: use IdlArrayType instead of is_array, once have that
698 is_array = True
699 else:
700 is_array = False
701
702 is_nullable = node.GetProperty('NULLABLE') or False # syntax: T?
703
704 return type_node_inner_to_type(type_node_child, is_array=is_array, is_nullab le=is_nullable)
705
706
707 def type_node_inner_to_type(node, is_array=False, is_nullable=False):
708 # FIXME: remove is_array and is_nullable once have IdlArrayType and IdlNulla bleType
709 node_class = node.GetClass()
710 # Note Type*r*ef, not Typedef, meaning the type is an identifier, thus
711 # either a typedef shorthand (but not a Typedef declaration itself) or an
712 # interface type. We do not distinguish these, and just use the type name.
713 if node_class in ['PrimitiveType', 'Typeref']:
714 # unrestricted syntax: unrestricted double | unrestricted float
715 is_unrestricted = node.GetProperty('UNRESTRICTED') or False
716 return IdlType(node.GetName(), is_array=is_array, is_nullable=is_nullabl e, is_unrestricted=is_unrestricted)
717 elif node_class == 'Any':
718 return IdlType('any', is_array=is_array, is_nullable=is_nullable)
719 elif node_class == 'Sequence':
720 if is_array:
721 raise ValueError('Arrays of sequences are not supported')
722 return sequence_node_to_type(node, is_nullable=is_nullable)
723 elif node_class == 'UnionType':
724 if is_array:
725 raise ValueError('Arrays of unions are not supported')
726 return union_type_node_to_idl_union_type(node, is_nullable=is_nullable)
727 raise ValueError('Unrecognized node class: %s' % node_class)
728
729
730 def sequence_node_to_type(node, is_nullable=False):
731 children = node.GetChildren()
732 if len(children) != 1:
733 raise ValueError('Sequence node expects exactly 1 child, got %s' % len(c hildren))
734 sequence_child = children[0]
735 sequence_child_class = sequence_child.GetClass()
736 if sequence_child_class != 'Type':
737 raise ValueError('Unrecognized node class: %s' % sequence_child_class)
738 element_type = type_node_to_type(sequence_child).base_type
739 return IdlType(element_type, is_sequence=True, is_nullable=is_nullable)
740
741
742 def typedef_node_to_type(node):
743 children = node.GetChildren()
744 if len(children) != 1:
745 raise ValueError('Typedef node with %s children, expected 1' % len(child ren))
746 child = children[0]
747 child_class = child.GetClass()
748 if child_class != 'Type':
749 raise ValueError('Unrecognized node class: %s' % child_class)
750 return type_node_to_type(child)
751
752
753 def union_type_node_to_idl_union_type(node, is_nullable=False):
754 member_types = [type_node_to_type(member_type_node)
755 for member_type_node in node.GetChildren()]
756 return IdlUnionType(member_types, is_nullable=is_nullable)
OLDNEW
« no previous file with comments | « bindings/scripts/idl_compiler.py ('k') | bindings/scripts/idl_reader.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698