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

Side by Side Diff: sky/engine/bindings2/scripts/idl_definitions.py

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

Powered by Google App Engine
This is Rietveld 408576698