Index: bindings/scripts/idl_types.py |
diff --git a/bindings/scripts/idl_types.py b/bindings/scripts/idl_types.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e488e33264830157b37294bf42dd24c86ce5ac9d |
--- /dev/null |
+++ b/bindings/scripts/idl_types.py |
@@ -0,0 +1,321 @@ |
+# Copyright 2014 The Chromium Authors. All rights reserved. |
+# Use of this source code is governed by a BSD-style license that can be |
+# found in the LICENSE file. |
+"""IDL type handling. |
+ |
+Classes: |
+IdlType |
+IdlUnionType |
+""" |
+ |
+from collections import defaultdict |
+ |
+ |
+################################################################################ |
+# IDL types |
+################################################################################ |
+ |
+INTEGER_TYPES = frozenset([ |
+ # http://www.w3.org/TR/WebIDL/#dfn-integer-type |
+ 'byte', |
+ 'octet', |
+ 'short', |
+ 'unsigned short', |
+ # int and unsigned are not IDL types |
+ 'long', |
+ 'unsigned long', |
+ 'long long', |
+ 'unsigned long long', |
+]) |
+NUMERIC_TYPES = (INTEGER_TYPES | frozenset([ |
+ # http://www.w3.org/TR/WebIDL/#dfn-numeric-type |
+ 'float', |
+ 'unrestricted float', |
+ 'double', |
+ 'unrestricted double', |
+])) |
+# http://www.w3.org/TR/WebIDL/#dfn-primitive-type |
+PRIMITIVE_TYPES = (frozenset(['boolean']) | NUMERIC_TYPES) |
+BASIC_TYPES = (PRIMITIVE_TYPES | frozenset([ |
+ # Built-in, non-composite, non-object data types |
+ # http://heycam.github.io/webidl/#idl-types |
+ 'DOMString', |
+ 'ByteString', |
+ 'Date', |
+ # http://heycam.github.io/webidl/#es-type-mapping |
+ 'void', |
+ # http://encoding.spec.whatwg.org/#type-scalarvaluestring |
+ 'ScalarValueString', |
+])) |
+TYPE_NAMES = { |
+ # http://heycam.github.io/webidl/#dfn-type-name |
+ 'any': 'Any', |
+ 'boolean': 'Boolean', |
+ 'byte': 'Byte', |
+ 'octet': 'Octet', |
+ 'short': 'Short', |
+ 'unsigned short': 'UnsignedShort', |
+ 'long': 'Long', |
+ 'unsigned long': 'UnsignedLong', |
+ 'long long': 'LongLong', |
+ 'unsigned long long': 'UnsignedLongLong', |
+ 'float': 'Float', |
+ 'unrestricted float': 'UnrestrictedFloat', |
+ 'double': 'Double', |
+ 'unrestricted double': 'UnrestrictedDouble', |
+ 'DOMString': 'String', |
+ 'ByteString': 'ByteString', |
+ 'ScalarValueString': 'ScalarValueString', |
+ 'object': 'Object', |
+ 'Date': 'Date', |
+} |
+ |
+ |
+################################################################################ |
+# Inheritance |
+################################################################################ |
+ |
+ancestors = defaultdict(list) # interface_name -> ancestors |
+ |
+def inherits_interface(interface_name, ancestor_name): |
+ return (interface_name == ancestor_name or |
+ ancestor_name in ancestors[interface_name]) |
+ |
+ |
+def set_ancestors(new_ancestors): |
+ ancestors.update(new_ancestors) |
+ |
+ |
+################################################################################ |
+# IdlType |
+################################################################################ |
+ |
+class IdlType(object): |
+ # FIXME: incorporate Nullable, etc. |
+ # FIXME: use nested types: IdlArrayType, IdlNullableType, IdlSequenceType |
+ # to support types like short?[] vs. short[]?, instead of treating these |
+ # as orthogonal properties (via flags). |
+ callback_functions = set() |
+ callback_interfaces = set() |
+ enums = {} # name -> values |
+ |
+ def __init__(self, base_type, is_array=False, is_sequence=False, is_nullable=False, is_unrestricted=False): |
+ if is_array and is_sequence: |
+ raise ValueError('Array of Sequences are not allowed.') |
+ if is_unrestricted: |
+ self.base_type = 'unrestricted %s' % base_type |
+ else: |
+ self.base_type = base_type |
+ self.is_array = is_array |
+ self.is_sequence = is_sequence |
+ self.is_nullable = is_nullable |
+ |
+ def __str__(self): |
+ type_string = self.base_type |
+ if self.is_array: |
+ return type_string + '[]' |
+ if self.is_sequence: |
+ return 'sequence<%s>' % type_string |
+ if self.is_nullable: |
+ # FIXME: Dictionary::ConversionContext::setConversionType can't |
+ # handle the '?' in nullable types (passes nullability separately). |
+ # Update that function to handle nullability from the type name, |
+ # simplifying its signature. |
+ # return type_string + '?' |
+ return type_string |
+ return type_string |
+ |
+ # FIXME: rename to native_array_element_type and move to v8_types.py |
+ @property |
+ def array_or_sequence_type(self): |
+ return self.array_type or self.sequence_type |
+ |
+ # FIXME: rename to array_element_type |
+ @property |
+ def array_type(self): |
+ return self.is_array and IdlType(self.base_type) |
+ |
+ # FIXME: rename to sequence_element_type |
+ @property |
+ def sequence_type(self): |
+ return self.is_sequence and IdlType(self.base_type) |
+ |
+ @property |
+ def is_basic_type(self): |
+ return self.base_type in BASIC_TYPES and not self.array_or_sequence_type |
+ |
+ @property |
+ def is_callback_function(self): |
+ return self.base_type in IdlType.callback_functions |
+ |
+ @property |
+ def is_callback_interface(self): |
+ return self.base_type in IdlType.callback_interfaces |
+ |
+ @property |
+ def is_composite_type(self): |
+ return (self.name == 'Any' or |
+ self.array_type or |
+ self.sequence_type or |
+ self.is_union_type) |
+ |
+ @property |
+ def is_enum(self): |
+ # FIXME: add an IdlEnumType class and a resolve_enums step at end of |
+ # IdlDefinitions constructor |
+ return self.name in IdlType.enums |
+ |
+ @property |
+ def enum_values(self): |
+ return IdlType.enums[self.name] |
+ |
+ @property |
+ def is_integer_type(self): |
+ return self.base_type in INTEGER_TYPES and not self.array_or_sequence_type |
+ |
+ @property |
+ def is_numeric_type(self): |
+ return self.base_type in NUMERIC_TYPES and not self.array_or_sequence_type |
+ |
+ @property |
+ def is_primitive_type(self): |
+ return self.base_type in PRIMITIVE_TYPES and not self.array_or_sequence_type |
+ |
+ @property |
+ def is_interface_type(self): |
+ # Anything that is not another type is an interface type. |
+ # http://www.w3.org/TR/WebIDL/#idl-types |
+ # http://www.w3.org/TR/WebIDL/#idl-interface |
+ # In C++ these are RefPtr or PassRefPtr types. |
+ return not(self.is_basic_type or |
+ self.is_composite_type or |
+ self.is_callback_function or |
+ self.is_enum or |
+ self.name == 'Object' or |
+ self.name == 'Promise') # Promise will be basic in future |
+ |
+ @property |
+ def is_union_type(self): |
+ return isinstance(self, IdlUnionType) |
+ |
+ @property |
+ def name(self): |
+ """Return type name. |
+ |
+ http://heycam.github.io/webidl/#dfn-type-name |
+ """ |
+ base_type = self.base_type |
+ base_type_name = TYPE_NAMES.get(base_type, base_type) |
+ if self.is_array: |
+ return base_type_name + 'Array' |
+ if self.is_sequence: |
+ return base_type_name + 'Sequence' |
+ if self.is_nullable: |
+ return base_type_name + 'OrNull' |
+ return base_type_name |
+ |
+ @classmethod |
+ def set_callback_functions(cls, new_callback_functions): |
+ cls.callback_functions.update(new_callback_functions) |
+ |
+ @classmethod |
+ def set_callback_interfaces(cls, new_callback_interfaces): |
+ cls.callback_interfaces.update(new_callback_interfaces) |
+ |
+ @classmethod |
+ def set_enums(cls, new_enums): |
+ cls.enums.update(new_enums) |
+ |
+ def resolve_typedefs(self, typedefs): |
+ if self.base_type not in typedefs: |
+ return self |
+ new_type = typedefs[self.base_type] |
+ if type(new_type) != type(self): |
+ # If type changes, need to return a different object, |
+ # since can't change type(self) |
+ return new_type |
+ # If type doesn't change, just mutate self to avoid a new object |
+ # FIXME: a bit ugly; use __init__ instead of setting flags |
+ self.base_type = new_type.base_type |
+ # handle array both in use and in typedef itself: |
+ # typedef Type TypeDef; |
+ # TypeDef[] ... |
+ # and: |
+ # typedef Type[] TypeArray |
+ # TypeArray ... |
+ self.is_array |= new_type.is_array |
+ self.is_sequence |= new_type.is_sequence |
+ return self |
+ |
+ |
+################################################################################ |
+# IdlUnionType |
+################################################################################ |
+ |
+class IdlUnionType(object): |
+ # http://heycam.github.io/webidl/#idl-union |
+ # FIXME: derive from IdlType, instead of stand-alone class, to reduce |
+ # duplication. |
+ def __init__(self, member_types, is_nullable=False): |
+ self.member_types = member_types |
+ self.is_nullable = is_nullable |
+ |
+ @property |
+ def array_or_sequence_type(self): |
+ return False |
+ |
+ @property |
+ def array_type(self): |
+ return False |
+ |
+ @property |
+ def is_array(self): |
+ # We do not support arrays of union types |
+ return False |
+ |
+ @property |
+ def base_type(self): |
+ return None |
+ |
+ @property |
+ def is_basic_type(self): |
+ return False |
+ |
+ @property |
+ def is_callback_function(self): |
+ return False |
+ |
+ @property |
+ def is_enum(self): |
+ return False |
+ |
+ @property |
+ def is_integer_type(self): |
+ return False |
+ |
+ @property |
+ def is_numeric_type(self): |
+ return False |
+ |
+ @property |
+ def is_primitivee_type(self): |
+ return False |
+ |
+ @property |
+ def is_sequence(self): |
+ # We do not support sequences of union types |
+ return False |
+ |
+ @property |
+ def is_union_type(self): |
+ return True |
+ |
+ @property |
+ def name(self): |
+ return 'Or'.join(member_type.name for member_type in self.member_types) |
+ |
+ def resolve_typedefs(self, typedefs): |
+ self.member_types = [ |
+ typedefs.get(member_type, member_type) |
+ for member_type in self.member_types] |
+ return self |