| Index: Source/bindings/scripts/idl_definitions.py
|
| diff --git a/Source/bindings/scripts/idl_definitions.py b/Source/bindings/scripts/idl_definitions.py
|
| index b0fe3a34f028500fdfacabd0ed694f3ca73b41d8..ab57c5b2237eec867466947bb376160f7b257498 100644
|
| --- a/Source/bindings/scripts/idl_definitions.py
|
| +++ b/Source/bindings/scripts/idl_definitions.py
|
| @@ -26,7 +26,40 @@
|
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
| -"""Blink IDL Intermediate Representation (IR) classes."""
|
| +"""Blink IDL Intermediate Representation (IR) classes.
|
| +
|
| +Classes are primarily constructors, which build an IdlDefinitions object
|
| +(and various contained objects) from an AST (produced by blink_idl_parser).
|
| +
|
| +This is in two steps:
|
| +* Constructors walk the AST, creating objects.
|
| +* Typedef resolution.
|
| +
|
| +Typedefs are all resolved here, and not stored in IR.
|
| +
|
| +Typedef resolution uses some auxiliary classes and OOP techniques to make this
|
| +a generic call, via the resolve_typedefs() method.
|
| +
|
| +Class hierarchy (mostly containment, '<' for inheritance):
|
| +
|
| +IdlDefinitions
|
| + IdlCallbackFunction < TypedObject
|
| + IdlEnum :: FIXME: remove
|
| + IdlInterface
|
| + IdlAttribute < TypedObject
|
| + IdlConstant < TypedObject
|
| + IdlOperation < TypedObject
|
| + IdlArgument < TypedObject
|
| + IdlException < IdlInterface
|
| + (same contents as IdlInterface)
|
| +
|
| +IdlUnionType :: FIXME: remove
|
| +
|
| +Auxiliary classes for typedef resolution:
|
| +IdlType
|
| +TypedObject
|
| +"""
|
| +
|
|
|
| # pylint doesn't understand ABCs.
|
| # pylint: disable=W0232, E0203, W0201
|
| @@ -35,7 +68,42 @@ import abc
|
| import re
|
|
|
|
|
| -# Type classes
|
| +SPECIAL_KEYWORD_LIST = ['GETTER', 'SETTER', 'DELETER']
|
| +STANDARD_TYPEDEFS = {
|
| + # http://www.w3.org/TR/WebIDL/#common-DOMTimeStamp
|
| + 'DOMTimeStamp': 'unsigned long long',
|
| +}
|
| +
|
| +
|
| +################################################################################
|
| +# Type classes (for typedef resolution)
|
| +################################################################################
|
| +
|
| +class TypedObject(object):
|
| + """Object with a type, such as an Attribute or Operation (return value).
|
| +
|
| + The type can be an actual type, or can be a typedef, which must be resolved
|
| + before passing data to the code generator.
|
| + """
|
| + __metaclass__ = abc.ABCMeta
|
| + idl_type = None
|
| + extended_attributes = None
|
| +
|
| + def resolve_typedefs(self, typedefs):
|
| + """Resolve typedefs to actual types in the object."""
|
| + # Constructors don't have their own return type, because it's the
|
| + # interface itself.
|
| + if not self.idl_type:
|
| + return
|
| + # (Types are represented either as strings or as IdlUnionType objects.)
|
| + # Union types are objects, which have a member function for this
|
| + if isinstance(self.idl_type, IdlUnionType):
|
| + # Method 'resolve_typedefs' call is ok, but pylint can't infer this
|
| + # pylint: disable=E1101
|
| + self.idl_type.resolve_typedefs(typedefs)
|
| + return
|
| + # Otherwise, IDL type is represented as string, so use a function
|
| + self.idl_type = resolve_typedefs(self.idl_type, typedefs)
|
|
|
| class IdlType(object):
|
| # FIXME: replace type strings with these objects,
|
| @@ -86,8 +154,9 @@ class IdlType(object):
|
|
|
| class IdlUnionType(object):
|
| # FIXME: remove class, just treat as tuple
|
| - def __init__(self, union_member_types=None):
|
| - self.union_member_types = union_member_types or []
|
| + def __init__(self, node):
|
| + self.union_member_types = [type_node_to_type(member_type_node)
|
| + for member_type_node in node.GetChildren()]
|
|
|
| def resolve_typedefs(self, typedefs):
|
| self.union_member_types = [
|
| @@ -95,33 +164,6 @@ class IdlUnionType(object):
|
| for union_member_type in self.union_member_types]
|
|
|
|
|
| -class TypedObject(object):
|
| - """Object with a type, such as an Attribute or Operation (return value).
|
| -
|
| - The type can be an actual type, or can be a typedef, which must be resolved
|
| - before passing data to the code generator.
|
| - """
|
| - __metaclass__ = abc.ABCMeta
|
| - idl_type = None
|
| - extended_attributes = None
|
| -
|
| - def resolve_typedefs(self, typedefs):
|
| - """Resolve typedefs to actual types in the object."""
|
| - # Constructors don't have their own return type, because it's the
|
| - # interface itself.
|
| - if not self.idl_type:
|
| - return
|
| - # (Types are represented either as strings or as IdlUnionType objects.)
|
| - # Union types are objects, which have a member function for this
|
| - if isinstance(self.idl_type, IdlUnionType):
|
| - # Method 'resolve_typedefs' call is ok, but pylint can't infer this
|
| - # pylint: disable=E1101
|
| - self.idl_type.resolve_typedefs(typedefs)
|
| - return
|
| - # Otherwise, IDL type is represented as string, so use a function
|
| - self.idl_type = resolve_typedefs(self.idl_type, typedefs)
|
| -
|
| -
|
| def resolve_typedefs(idl_type, typedefs):
|
| """Return an IDL type (as string) with typedefs resolved."""
|
| # FIXME: merge into above, as only one use
|
| @@ -132,19 +174,52 @@ def resolve_typedefs(idl_type, typedefs):
|
| return str(IdlType.from_string(idl_type).resolve_typedefs(typedefs))
|
|
|
|
|
| -# IDL classes
|
| -
|
| +################################################################################
|
| +# Definitions (main container class)
|
| +################################################################################
|
|
|
| class IdlDefinitions(object):
|
| - def __init__(self, callback_functions=None, enumerations=None, interfaces=None, typedefs=None):
|
| - self.callback_functions = callback_functions or {}
|
| - self.enumerations = enumerations or {}
|
| - self.interfaces = interfaces or {}
|
| - # Typedefs are not exposed by bindings; resolve typedefs with the
|
| - # actual types and then discard the Typedefs.
|
| + def __init__(self, node):
|
| + """Args: node: AST root node, class == 'File'"""
|
| + self.callback_functions = {}
|
| + self.enumerations = {}
|
| + self.interfaces = {}
|
| +
|
| + node_class = node.GetClass()
|
| + if node_class != 'File':
|
| + raise ValueError('Unrecognized node class: %s' % node_class)
|
| +
|
| + typedefs = STANDARD_TYPEDEFS
|
| +
|
| + children = node.GetChildren()
|
| + for child in children:
|
| + child_class = child.GetClass()
|
| + if child_class == 'Interface':
|
| + interface = IdlInterface(child)
|
| + self.interfaces[interface.name] = interface
|
| + elif child_class == 'Exception':
|
| + exception = IdlException(child)
|
| + # For simplicity, treat exceptions as interfaces
|
| + self.interfaces[exception.name] = exception
|
| + elif child_class == 'Typedef':
|
| + type_name = child.GetName()
|
| + typedefs[type_name] = typedef_node_to_type(child)
|
| + elif child_class == 'Enum':
|
| + enumeration = IdlEnum(child)
|
| + self.enumerations[enumeration.name] = enumeration
|
| + elif child_class == 'Callback':
|
| + callback_function = IdlCallbackFunction(child)
|
| + self.callback_functions[callback_function.name] = callback_function
|
| + elif child_class == 'Implements':
|
| + # Implements is handled at the interface merging step
|
| + pass
|
| + else:
|
| + raise ValueError('Unrecognized node class: %s' % child_class)
|
| +
|
| + # Typedefs are not stored in IR:
|
| + # Resolve typedefs with the actual types and then discard the Typedefs.
|
| # http://www.w3.org/TR/WebIDL/#idl-typedefs
|
| - if typedefs:
|
| - self.resolve_typedefs(typedefs)
|
| + self.resolve_typedefs(typedefs)
|
|
|
| def resolve_typedefs(self, typedefs):
|
| for callback_function in self.callback_functions.itervalues():
|
| @@ -153,11 +228,24 @@ class IdlDefinitions(object):
|
| interface.resolve_typedefs(typedefs)
|
|
|
|
|
| +################################################################################
|
| +# Callback Functions
|
| +################################################################################
|
| +
|
| class IdlCallbackFunction(TypedObject):
|
| - def __init__(self, name=None, idl_type=None, arguments=None):
|
| - self.idl_type = idl_type
|
| - self.name = name
|
| - self.arguments = arguments or []
|
| + def __init__(self, node):
|
| + children = node.GetChildren()
|
| + num_children = len(children)
|
| + if num_children != 2:
|
| + raise ValueError('Expected 2 children, got %s' % num_children)
|
| + type_node, arguments_node = children
|
| + arguments_node_class = arguments_node.GetClass()
|
| + if arguments_node_class != 'Arguments':
|
| + raise ValueError('Expected Arguments node, got %s' % arguments_node_class)
|
| +
|
| + self.name = node.GetName()
|
| + self.idl_type = type_node_to_type(type_node)
|
| + self.arguments = arguments_node_to_arguments(arguments_node)
|
|
|
| def resolve_typedefs(self, typedefs):
|
| TypedObject.resolve_typedefs(self, typedefs)
|
| @@ -165,26 +253,60 @@ class IdlCallbackFunction(TypedObject):
|
| argument.resolve_typedefs(typedefs)
|
|
|
|
|
| +################################################################################
|
| +# Enumerations
|
| +################################################################################
|
| +
|
| class IdlEnum(object):
|
| # FIXME: remove, just treat enums as a dictionary
|
| - def __init__(self, name=None, values=None):
|
| - self.name = name
|
| - self.values = values or [] # FIXME: unnecessary, can't be empty
|
| + def __init__(self, node):
|
| + self.name = node.GetName()
|
| + self.values = []
|
| + for child in node.GetChildren():
|
| + self.values.append(child.GetName())
|
| +
|
|
|
| +################################################################################
|
| +# Interfaces and Exceptions
|
| +################################################################################
|
|
|
| class IdlInterface(object):
|
| - def __init__(self, attributes=None, constants=None, constructors=None, custom_constructors=None, extended_attributes=None, operations=None, is_callback=False, is_partial=False, name=None, parent=None):
|
| - self.attributes = attributes or []
|
| - self.constants = constants or []
|
| - self.constructors = constructors or []
|
| - self.custom_constructors = custom_constructors or []
|
| - self.extended_attributes = extended_attributes or {}
|
| - self.operations = operations or []
|
| - self.is_callback = is_callback
|
| - self.is_partial = is_partial
|
| + def __init__(self, node=None):
|
| + self.attributes = []
|
| + self.constants = []
|
| + self.constructors = []
|
| + self.custom_constructors = []
|
| + self.extended_attributes = {}
|
| + self.operations = []
|
| + self.parent = None
|
| + if not node: # Early exit for IdlException.__init__
|
| + return
|
| +
|
| + self.is_callback = node.GetProperty('CALLBACK') or False
|
| self.is_exception = False
|
| - self.name = name
|
| - self.parent = parent
|
| + # FIXME: uppercase 'Partial' => 'PARTIAL' in base IDL parser
|
| + self.is_partial = node.GetProperty('Partial') or False
|
| + self.name = node.GetName()
|
| +
|
| + children = node.GetChildren()
|
| + for child in children:
|
| + child_class = child.GetClass()
|
| + if child_class == 'Attribute':
|
| + self.attributes.append(IdlAttribute(child))
|
| + elif child_class == 'Const':
|
| + self.constants.append(IdlConstant(child))
|
| + elif child_class == 'ExtAttributes':
|
| + extended_attributes = ext_attributes_node_to_extended_attributes(child)
|
| + self.constructors, self.custom_constructors = (
|
| + extended_attributes_to_constructors(extended_attributes))
|
| + clear_constructor_attributes(extended_attributes)
|
| + self.extended_attributes = extended_attributes
|
| + elif child_class == 'Operation':
|
| + self.operations.append(IdlOperation(child))
|
| + elif child_class == 'Inherit':
|
| + self.parent = child.GetName()
|
| + else:
|
| + raise ValueError('Unrecognized node class: %s' % child_class)
|
|
|
| def resolve_typedefs(self, typedefs):
|
| for attribute in self.attributes:
|
| @@ -206,39 +328,149 @@ class IdlException(IdlInterface):
|
| # are not expected. Thus it is easier to implement exceptions as a
|
| # restricted subclass of interfaces.
|
| # http://www.w3.org/TR/WebIDL/#idl-exceptions
|
| - def __init__(self, name=None, constants=None, operations=None, attributes=None, extended_attributes=None):
|
| - IdlInterface.__init__(self, name=name, constants=constants, operations=operations, attributes=attributes, extended_attributes=extended_attributes)
|
| + def __init__(self, node):
|
| + # Exceptions are similar to Interfaces, but simpler
|
| + IdlInterface.__init__(self)
|
| + self.is_callback = False
|
| self.is_exception = True
|
| -
|
| + self.is_partial = False
|
| + self.name = node.GetName()
|
| +
|
| + children = node.GetChildren()
|
| + for child in children:
|
| + child_class = child.GetClass()
|
| + if child_class == 'Attribute':
|
| + attribute = IdlAttribute(child)
|
| + self.attributes.append(attribute)
|
| + elif child_class == 'Const':
|
| + self.constants.append(IdlConstant(child))
|
| + elif child_class == 'ExtAttributes':
|
| + self.extended_attributes = ext_attributes_node_to_extended_attributes(child)
|
| + elif child_class == 'ExceptionOperation':
|
| + self.operations.append(IdlOperation.from_exception_operation_node(child))
|
| + else:
|
| + raise ValueError('Unrecognized node class: %s' % child_class)
|
| +
|
| +
|
| +################################################################################
|
| +# Attributes
|
| +################################################################################
|
|
|
| class IdlAttribute(TypedObject):
|
| - def __init__(self, idl_type=None, extended_attributes=None, getter_exceptions=None, is_nullable=False, is_static=False, is_read_only=False, name=None, setter_exceptions=None):
|
| - self.idl_type = idl_type
|
| - self.extended_attributes = extended_attributes or {}
|
| - self.getter_exceptions = getter_exceptions or []
|
| - self.is_nullable = is_nullable
|
| - self.is_static = is_static
|
| - self.is_read_only = is_read_only
|
| - self.name = name
|
| - self.setter_exceptions = setter_exceptions or []
|
| -
|
| + def __init__(self, node):
|
| + self.is_read_only = node.GetProperty('READONLY') or False
|
| + self.is_static = node.GetProperty('STATIC') or False
|
| + self.name = node.GetName()
|
| + # Defaults, overridden below
|
| + self.idl_type = None
|
| + self.is_nullable = False
|
| + self.extended_attributes = {}
|
| +
|
| + children = node.GetChildren()
|
| + for child in children:
|
| + child_class = child.GetClass()
|
| + if child_class == 'Type':
|
| + self.idl_type = type_node_to_type(child)
|
| + self.is_nullable = child.GetProperty('NULLABLE') or False
|
| + elif child_class == 'ExtAttributes':
|
| + self.extended_attributes = ext_attributes_node_to_extended_attributes(child)
|
| + else:
|
| + raise ValueError('Unrecognized node class: %s' % child_class)
|
| +
|
| +
|
| +################################################################################
|
| +# Constants
|
| +################################################################################
|
|
|
| class IdlConstant(TypedObject):
|
| - def __init__(self, name=None, idl_type=None, value=None, extended_attributes=None):
|
| - self.idl_type = idl_type
|
| - self.extended_attributes = extended_attributes or {}
|
| - self.name = name
|
| - self.value = value
|
| -
|
| + def __init__(self, node):
|
| + children = node.GetChildren()
|
| + num_children = len(children)
|
| + if num_children < 2 or num_children > 3:
|
| + raise ValueError('Expected 2 or 3 children, got %s' % num_children)
|
| + type_node = children[0]
|
| + value_node = children[1]
|
| + value_node_class = value_node.GetClass()
|
| + if value_node_class != 'Value':
|
| + raise ValueError('Expected Value node, got %s' % value_node_class)
|
| +
|
| + self.name = node.GetName()
|
| + # ConstType is more limited than Type, so subtree is smaller and
|
| + # we don't use the full type_node_to_type function.
|
| + self.idl_type = type_node_inner_to_type(type_node)
|
| + self.value = value_node.GetName()
|
| +
|
| + if num_children == 3:
|
| + ext_attributes_node = children[2]
|
| + self.extended_attributes = ext_attributes_node_to_extended_attributes(ext_attributes_node)
|
| + else:
|
| + self.extended_attributes = {}
|
| +
|
| +
|
| +################################################################################
|
| +# Operations
|
| +################################################################################
|
|
|
| class IdlOperation(TypedObject):
|
| - def __init__(self, is_static=False, name=None, idl_type=None, extended_attributes=None, specials=None, arguments=None, overloaded_index=None):
|
| - self.is_static = is_static
|
| - self.name = name or ''
|
| - self.idl_type = idl_type
|
| - self.extended_attributes = extended_attributes or {}
|
| - self.specials = specials or []
|
| - self.arguments = arguments or []
|
| + def __init__(self, node=None):
|
| + self.arguments = []
|
| + self.extended_attributes = {}
|
| + self.specials = []
|
| +
|
| + if not node:
|
| + self.is_static = False
|
| + return
|
| + self.name = node.GetName() # FIXME: should just be: or ''
|
| + # FIXME: AST should use None internally
|
| + if self.name == '_unnamed_':
|
| + self.name = ''
|
| +
|
| + self.is_static = node.GetProperty('STATIC') or False
|
| + property_dictionary = node.GetProperties()
|
| + for special_keyword in SPECIAL_KEYWORD_LIST:
|
| + if special_keyword in property_dictionary:
|
| + self.specials.append(special_keyword.lower())
|
| +
|
| + self.idl_type = None
|
| + children = node.GetChildren()
|
| + for child in children:
|
| + child_class = child.GetClass()
|
| + if child_class == 'Arguments':
|
| + self.arguments = arguments_node_to_arguments(child)
|
| + elif child_class == 'Type':
|
| + self.idl_type = type_node_to_type(child)
|
| + elif child_class == 'ExtAttributes':
|
| + self.extended_attributes = ext_attributes_node_to_extended_attributes(child)
|
| + else:
|
| + raise ValueError('Unrecognized node class: %s' % child_class)
|
| +
|
| + @classmethod
|
| + def from_exception_operation_node(cls, node):
|
| + # Needed to handle one case in DOMException.idl:
|
| + # // Override in a Mozilla compatible format
|
| + # [NotEnumerable] DOMString toString();
|
| + # FIXME: can we remove this? replace with a stringifier?
|
| + operation = cls()
|
| + operation.name = node.GetName()
|
| + children = node.GetChildren()
|
| + if len(children) < 1 or len(children) > 2:
|
| + raise ValueError('ExceptionOperation node with %s children, expected 1 or 2' % len(children))
|
| +
|
| + type_node = children[0]
|
| + operation.idl_type = type_node_to_type(type_node)
|
| +
|
| + if len(children) > 1:
|
| + ext_attributes_node = children[1]
|
| + operation.extended_attributes = ext_attributes_node_to_extended_attributes(ext_attributes_node)
|
| +
|
| + return operation
|
| +
|
| + @classmethod
|
| + def constructor_from_arguments_node(cls, name, arguments_node):
|
| + constructor = cls()
|
| + constructor.name = name
|
| + constructor.arguments = arguments_node_to_arguments(arguments_node)
|
| + return constructor
|
|
|
| def resolve_typedefs(self, typedefs):
|
| TypedObject.resolve_typedefs(self, typedefs)
|
| @@ -246,11 +478,222 @@ class IdlOperation(TypedObject):
|
| argument.resolve_typedefs(typedefs)
|
|
|
|
|
| +################################################################################
|
| +# Arguments
|
| +################################################################################
|
| +
|
| class IdlArgument(TypedObject):
|
| - def __init__(self, name=None, idl_type=None, extended_attributes=None, is_optional=False, is_nullable=False, is_variadic=False):
|
| - self.idl_type = idl_type
|
| - self.extended_attributes = extended_attributes or {}
|
| - self.is_nullable = is_nullable # (T?)
|
| - self.is_optional = is_optional # (optional T)
|
| - self.is_variadic = is_variadic # (T...)
|
| - self.name = name
|
| + def __init__(self, node):
|
| + self.extended_attributes = {}
|
| + self.idl_type = None
|
| + self.is_nullable = False # (T?)
|
| + self.is_optional = node.GetProperty('OPTIONAL') # (optional T)
|
| + self.is_variadic = False # (T...)
|
| + self.name = node.GetName()
|
| +
|
| + children = node.GetChildren()
|
| + for child in children:
|
| + child_class = child.GetClass()
|
| + if child_class == 'Type':
|
| + self.idl_type = type_node_to_type(child)
|
| + # FIXME: Doesn't handle nullable arrays (Foo[]?), and arrays of
|
| + # nullable (Foo?[]) are treated as nullable arrays. No actual use.
|
| + self.is_nullable = child.GetProperty('NULLABLE')
|
| + elif child_class == 'ExtAttributes':
|
| + self.extended_attributes = ext_attributes_node_to_extended_attributes(child)
|
| + elif child_class == 'Argument':
|
| + child_name = child.GetName()
|
| + if child_name != '...':
|
| + raise ValueError('Unrecognized Argument node; expected "...", got "%s"' % child_name)
|
| + self.is_variadic = child.GetProperty('ELLIPSIS') or False
|
| + else:
|
| + raise ValueError('Unrecognized node class: %s' % child_class)
|
| +
|
| +
|
| +def arguments_node_to_arguments(node):
|
| + # [Constructor] and [CustomConstructor] without arguments (the bare form)
|
| + # have None instead of an arguments node, but have the same meaning as using
|
| + # an empty argument list, [Constructor()], so special-case this.
|
| + # http://www.w3.org/TR/WebIDL/#Constructor
|
| + if node is None:
|
| + return []
|
| + return [IdlArgument(argument_node)
|
| + for argument_node in node.GetChildren()]
|
| +
|
| +
|
| +################################################################################
|
| +# Extended attributes
|
| +################################################################################
|
| +
|
| +def ext_attributes_node_to_extended_attributes(node):
|
| + """
|
| + Returns:
|
| + Dictionary of {ExtAttributeName: ExtAttributeValue}.
|
| + Value is usually a string, with three exceptions:
|
| + Constructors: value is a list of Arguments nodes, corresponding to
|
| + possible signatures of the constructor.
|
| + CustomConstructors: value is a list of Arguments nodes, corresponding to
|
| + possible signatures of the custom constructor.
|
| + NamedConstructor: value is a Call node, corresponding to the single
|
| + signature of the named constructor.
|
| + """
|
| + # Primarily just make a dictionary from the children.
|
| + # The only complexity is handling various types of constructors:
|
| + # Constructors and Custom Constructors can have duplicate entries due to
|
| + # overloading, and thus are stored in temporary lists.
|
| + # However, Named Constructors cannot be overloaded, and thus do not have
|
| + # a list.
|
| + # FIXME: move Constructor logic into separate function, instead of modifying
|
| + # extended attributes in-place.
|
| + constructors = []
|
| + custom_constructors = []
|
| + extended_attributes = {}
|
| +
|
| + def child_node(extended_attribute_node):
|
| + children = extended_attribute_node.GetChildren()
|
| + if not children:
|
| + return None
|
| + if len(children) > 1:
|
| + raise ValueError('ExtAttributes node with %s children, expected at most 1' % len(children))
|
| + return children[0]
|
| +
|
| + extended_attribute_node_list = node.GetChildren()
|
| + for extended_attribute_node in extended_attribute_node_list:
|
| + name = extended_attribute_node.GetName()
|
| + child = child_node(extended_attribute_node)
|
| + child_class = child and child.GetClass()
|
| + if name == 'Constructor':
|
| + if child_class and child_class != 'Arguments':
|
| + raise ValueError('Constructor only supports Arguments as child, but has child of class: %s' % child_class)
|
| + constructors.append(child)
|
| + elif name == 'CustomConstructor':
|
| + if child_class and child_class != 'Arguments':
|
| + raise ValueError('[CustomConstructor] only supports Arguments as child, but has child of class: %s' % child_class)
|
| + custom_constructors.append(child)
|
| + elif name == 'NamedConstructor':
|
| + if child_class and child_class != 'Call':
|
| + raise ValueError('[NamedConstructor] only supports Call as child, but has child of class: %s' % child_class)
|
| + extended_attributes[name] = child
|
| + elif name == 'SetWrapperReferenceTo':
|
| + if not child:
|
| + raise ValueError('[SetWrapperReferenceTo] requires a child, but has none.')
|
| + if child_class != 'Arguments':
|
| + raise ValueError('[SetWrapperReferenceTo] only supports Arguments as child, but has child of class: %s' % child_class)
|
| + extended_attributes[name] = arguments_node_to_arguments(child)
|
| + elif child:
|
| + raise ValueError('ExtAttributes node with unexpected children: %s' % name)
|
| + else:
|
| + value = extended_attribute_node.GetProperty('VALUE')
|
| + extended_attributes[name] = value
|
| +
|
| + # Store constructors and custom constructors in special list attributes,
|
| + # which are deleted later. Note plural in key.
|
| + if constructors:
|
| + extended_attributes['Constructors'] = constructors
|
| + if custom_constructors:
|
| + extended_attributes['CustomConstructors'] = custom_constructors
|
| +
|
| + return extended_attributes
|
| +
|
| +
|
| +def extended_attributes_to_constructors(extended_attributes):
|
| + """Returns constructors and custom_constructors (lists of IdlOperations).
|
| +
|
| + Auxiliary function for IdlInterface.__init__.
|
| + """
|
| +
|
| + constructor_list = extended_attributes.get('Constructors', [])
|
| + constructors = [
|
| + IdlOperation.constructor_from_arguments_node('Constructor', arguments_node)
|
| + for arguments_node in constructor_list]
|
| +
|
| + custom_constructor_list = extended_attributes.get('CustomConstructors', [])
|
| + custom_constructors = [
|
| + IdlOperation.constructor_from_arguments_node('CustomConstructor', arguments_node)
|
| + for arguments_node in custom_constructor_list]
|
| +
|
| + if 'NamedConstructor' in extended_attributes:
|
| + # FIXME: support overloaded named constructors, and make homogeneous
|
| + name = 'NamedConstructor'
|
| + call_node = extended_attributes['NamedConstructor']
|
| + extended_attributes['NamedConstructor'] = call_node.GetName()
|
| + children = call_node.GetChildren()
|
| + if len(children) != 1:
|
| + raise ValueError('NamedConstructor node expects 1 child, got %s.' % len(children))
|
| + arguments_node = children[0]
|
| + named_constructor = IdlOperation.constructor_from_arguments_node('NamedConstructor', arguments_node)
|
| + # FIXME: should return named_constructor separately; appended for Perl
|
| + constructors.append(named_constructor)
|
| +
|
| + return constructors, custom_constructors
|
| +
|
| +
|
| +def clear_constructor_attributes(extended_attributes):
|
| + # Deletes Constructor*s* (plural), sets Constructor (singular)
|
| + if 'Constructors' in extended_attributes:
|
| + del extended_attributes['Constructors']
|
| + extended_attributes['Constructor'] = None
|
| + if 'CustomConstructors' in extended_attributes:
|
| + del extended_attributes['CustomConstructors']
|
| + extended_attributes['CustomConstructor'] = None
|
| +
|
| +
|
| +################################################################################
|
| +# Types
|
| +################################################################################
|
| +
|
| +def type_node_to_type(node):
|
| + children = node.GetChildren()
|
| + if len(children) < 1 or len(children) > 2:
|
| + raise ValueError('Type node expects 1 or 2 children (type + optional array []), got %s (multi-dimensional arrays are not supported).' % len(children))
|
| +
|
| + type_node_child = children[0]
|
| + idl_type = type_node_inner_to_type(type_node_child)
|
| +
|
| + if len(children) == 2:
|
| + array_node = children[1]
|
| + array_node_class = array_node.GetClass()
|
| + if array_node_class != 'Array':
|
| + raise ValueError('Expected Array node as TypeSuffix, got %s node.' % array_node_class)
|
| + idl_type += '[]'
|
| +
|
| + return idl_type
|
| +
|
| +
|
| +def type_node_inner_to_type(node):
|
| + node_class = node.GetClass()
|
| + # Note Type*r*ef, not Typedef, meaning the type is an identifier, thus
|
| + # either a typedef shorthand (but not a Typedef declaration itself) or an
|
| + # interface type. We do not distinguish these, and just use the type name.
|
| + if node_class in ['PrimitiveType', 'Typeref']:
|
| + return node.GetName()
|
| + elif node_class == 'Any':
|
| + return 'any'
|
| + elif node_class == 'Sequence':
|
| + return sequence_node_to_type(node)
|
| + elif node_class == 'UnionType':
|
| + return IdlUnionType(node)
|
| + raise ValueError('Unrecognized node class: %s' % node_class)
|
| +
|
| +
|
| +def sequence_node_to_type(node):
|
| + children = node.GetChildren()
|
| + if len(children) != 1:
|
| + raise ValueError('Sequence node expects exactly 1 child, got %s' % len(children))
|
| + sequence_child = children[0]
|
| + sequence_child_class = sequence_child.GetClass()
|
| + if sequence_child_class != 'Type':
|
| + raise ValueError('Unrecognized node class: %s' % sequence_child_class)
|
| + sequence_type = type_node_to_type(sequence_child)
|
| + return 'sequence<%s>' % sequence_type
|
| +
|
| +
|
| +def typedef_node_to_type(node):
|
| + children = node.GetChildren()
|
| + if len(children) != 1:
|
| + raise ValueError('Typedef node with %s children, expected 1' % len(children))
|
| + child = children[0]
|
| + child_class = child.GetClass()
|
| + if child_class != 'Type':
|
| + raise ValueError('Unrecognized node class: %s' % child_class)
|
| + return type_node_to_type(child)
|
|
|