OLD | NEW |
(Empty) | |
| 1 # Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. |
| 4 """IDL type handling. |
| 5 |
| 6 Classes: |
| 7 IdlType |
| 8 IdlUnionType |
| 9 """ |
| 10 |
| 11 from collections import defaultdict |
| 12 |
| 13 |
| 14 ################################################################################ |
| 15 # IDL types |
| 16 ################################################################################ |
| 17 |
| 18 INTEGER_TYPES = frozenset([ |
| 19 # http://www.w3.org/TR/WebIDL/#dfn-integer-type |
| 20 'byte', |
| 21 'octet', |
| 22 'short', |
| 23 'unsigned short', |
| 24 # int and unsigned are not IDL types |
| 25 'long', |
| 26 'unsigned long', |
| 27 'long long', |
| 28 'unsigned long long', |
| 29 ]) |
| 30 NUMERIC_TYPES = (INTEGER_TYPES | frozenset([ |
| 31 # http://www.w3.org/TR/WebIDL/#dfn-numeric-type |
| 32 'float', |
| 33 'unrestricted float', |
| 34 'double', |
| 35 'unrestricted double', |
| 36 ])) |
| 37 # http://www.w3.org/TR/WebIDL/#dfn-primitive-type |
| 38 PRIMITIVE_TYPES = (frozenset(['boolean']) | NUMERIC_TYPES) |
| 39 BASIC_TYPES = (PRIMITIVE_TYPES | frozenset([ |
| 40 # Built-in, non-composite, non-object data types |
| 41 # http://heycam.github.io/webidl/#idl-types |
| 42 'DOMString', |
| 43 'ByteString', |
| 44 'Date', |
| 45 # http://heycam.github.io/webidl/#es-type-mapping |
| 46 'void', |
| 47 # http://encoding.spec.whatwg.org/#type-scalarvaluestring |
| 48 'ScalarValueString', |
| 49 ])) |
| 50 TYPE_NAMES = { |
| 51 # http://heycam.github.io/webidl/#dfn-type-name |
| 52 'any': 'Any', |
| 53 'boolean': 'Boolean', |
| 54 'byte': 'Byte', |
| 55 'octet': 'Octet', |
| 56 'short': 'Short', |
| 57 'unsigned short': 'UnsignedShort', |
| 58 'long': 'Long', |
| 59 'unsigned long': 'UnsignedLong', |
| 60 'long long': 'LongLong', |
| 61 'unsigned long long': 'UnsignedLongLong', |
| 62 'float': 'Float', |
| 63 'unrestricted float': 'UnrestrictedFloat', |
| 64 'double': 'Double', |
| 65 'unrestricted double': 'UnrestrictedDouble', |
| 66 'DOMString': 'String', |
| 67 'ByteString': 'ByteString', |
| 68 'ScalarValueString': 'ScalarValueString', |
| 69 'object': 'Object', |
| 70 'Date': 'Date', |
| 71 } |
| 72 |
| 73 |
| 74 ################################################################################ |
| 75 # Inheritance |
| 76 ################################################################################ |
| 77 |
| 78 ancestors = defaultdict(list) # interface_name -> ancestors |
| 79 |
| 80 def inherits_interface(interface_name, ancestor_name): |
| 81 return (interface_name == ancestor_name or |
| 82 ancestor_name in ancestors[interface_name]) |
| 83 |
| 84 |
| 85 def set_ancestors(new_ancestors): |
| 86 ancestors.update(new_ancestors) |
| 87 |
| 88 |
| 89 ################################################################################ |
| 90 # IdlType |
| 91 ################################################################################ |
| 92 |
| 93 class IdlType(object): |
| 94 # FIXME: incorporate Nullable, etc. |
| 95 # FIXME: use nested types: IdlArrayType, IdlNullableType, IdlSequenceType |
| 96 # to support types like short?[] vs. short[]?, instead of treating these |
| 97 # as orthogonal properties (via flags). |
| 98 callback_functions = set() |
| 99 callback_interfaces = set() |
| 100 enums = {} # name -> values |
| 101 |
| 102 def __init__(self, base_type, is_array=False, is_sequence=False, is_nullable
=False, is_unrestricted=False): |
| 103 if is_array and is_sequence: |
| 104 raise ValueError('Array of Sequences are not allowed.') |
| 105 if is_unrestricted: |
| 106 self.base_type = 'unrestricted %s' % base_type |
| 107 else: |
| 108 self.base_type = base_type |
| 109 self.is_array = is_array |
| 110 self.is_sequence = is_sequence |
| 111 self.is_nullable = is_nullable |
| 112 |
| 113 def __str__(self): |
| 114 type_string = self.base_type |
| 115 if self.is_array: |
| 116 return type_string + '[]' |
| 117 if self.is_sequence: |
| 118 return 'sequence<%s>' % type_string |
| 119 if self.is_nullable: |
| 120 # FIXME: Dictionary::ConversionContext::setConversionType can't |
| 121 # handle the '?' in nullable types (passes nullability separately). |
| 122 # Update that function to handle nullability from the type name, |
| 123 # simplifying its signature. |
| 124 # return type_string + '?' |
| 125 return type_string |
| 126 return type_string |
| 127 |
| 128 # FIXME: rename to native_array_element_type and move to v8_types.py |
| 129 @property |
| 130 def array_or_sequence_type(self): |
| 131 return self.array_type or self.sequence_type |
| 132 |
| 133 # FIXME: rename to array_element_type |
| 134 @property |
| 135 def array_type(self): |
| 136 return self.is_array and IdlType(self.base_type) |
| 137 |
| 138 # FIXME: rename to sequence_element_type |
| 139 @property |
| 140 def sequence_type(self): |
| 141 return self.is_sequence and IdlType(self.base_type) |
| 142 |
| 143 @property |
| 144 def is_basic_type(self): |
| 145 return self.base_type in BASIC_TYPES and not self.array_or_sequence_type |
| 146 |
| 147 @property |
| 148 def is_callback_function(self): |
| 149 return self.base_type in IdlType.callback_functions |
| 150 |
| 151 @property |
| 152 def is_callback_interface(self): |
| 153 return self.base_type in IdlType.callback_interfaces |
| 154 |
| 155 @property |
| 156 def is_composite_type(self): |
| 157 return (self.name == 'Any' or |
| 158 self.array_type or |
| 159 self.sequence_type or |
| 160 self.is_union_type) |
| 161 |
| 162 @property |
| 163 def is_enum(self): |
| 164 # FIXME: add an IdlEnumType class and a resolve_enums step at end of |
| 165 # IdlDefinitions constructor |
| 166 return self.name in IdlType.enums |
| 167 |
| 168 @property |
| 169 def enum_values(self): |
| 170 return IdlType.enums[self.name] |
| 171 |
| 172 @property |
| 173 def is_integer_type(self): |
| 174 return self.base_type in INTEGER_TYPES and not self.array_or_sequence_ty
pe |
| 175 |
| 176 @property |
| 177 def is_numeric_type(self): |
| 178 return self.base_type in NUMERIC_TYPES and not self.array_or_sequence_ty
pe |
| 179 |
| 180 @property |
| 181 def is_primitive_type(self): |
| 182 return self.base_type in PRIMITIVE_TYPES and not self.array_or_sequence_
type |
| 183 |
| 184 @property |
| 185 def is_interface_type(self): |
| 186 # Anything that is not another type is an interface type. |
| 187 # http://www.w3.org/TR/WebIDL/#idl-types |
| 188 # http://www.w3.org/TR/WebIDL/#idl-interface |
| 189 # In C++ these are RefPtr or PassRefPtr types. |
| 190 return not(self.is_basic_type or |
| 191 self.is_composite_type or |
| 192 self.is_callback_function or |
| 193 self.is_enum or |
| 194 self.name == 'Object' or |
| 195 self.name == 'Promise') # Promise will be basic in future |
| 196 |
| 197 @property |
| 198 def is_union_type(self): |
| 199 return isinstance(self, IdlUnionType) |
| 200 |
| 201 @property |
| 202 def name(self): |
| 203 """Return type name. |
| 204 |
| 205 http://heycam.github.io/webidl/#dfn-type-name |
| 206 """ |
| 207 base_type = self.base_type |
| 208 base_type_name = TYPE_NAMES.get(base_type, base_type) |
| 209 if self.is_array: |
| 210 return base_type_name + 'Array' |
| 211 if self.is_sequence: |
| 212 return base_type_name + 'Sequence' |
| 213 if self.is_nullable: |
| 214 return base_type_name + 'OrNull' |
| 215 return base_type_name |
| 216 |
| 217 @classmethod |
| 218 def set_callback_functions(cls, new_callback_functions): |
| 219 cls.callback_functions.update(new_callback_functions) |
| 220 |
| 221 @classmethod |
| 222 def set_callback_interfaces(cls, new_callback_interfaces): |
| 223 cls.callback_interfaces.update(new_callback_interfaces) |
| 224 |
| 225 @classmethod |
| 226 def set_enums(cls, new_enums): |
| 227 cls.enums.update(new_enums) |
| 228 |
| 229 def resolve_typedefs(self, typedefs): |
| 230 if self.base_type not in typedefs: |
| 231 return self |
| 232 new_type = typedefs[self.base_type] |
| 233 if type(new_type) != type(self): |
| 234 # If type changes, need to return a different object, |
| 235 # since can't change type(self) |
| 236 return new_type |
| 237 # If type doesn't change, just mutate self to avoid a new object |
| 238 # FIXME: a bit ugly; use __init__ instead of setting flags |
| 239 self.base_type = new_type.base_type |
| 240 # handle array both in use and in typedef itself: |
| 241 # typedef Type TypeDef; |
| 242 # TypeDef[] ... |
| 243 # and: |
| 244 # typedef Type[] TypeArray |
| 245 # TypeArray ... |
| 246 self.is_array |= new_type.is_array |
| 247 self.is_sequence |= new_type.is_sequence |
| 248 return self |
| 249 |
| 250 |
| 251 ################################################################################ |
| 252 # IdlUnionType |
| 253 ################################################################################ |
| 254 |
| 255 class IdlUnionType(object): |
| 256 # http://heycam.github.io/webidl/#idl-union |
| 257 # FIXME: derive from IdlType, instead of stand-alone class, to reduce |
| 258 # duplication. |
| 259 def __init__(self, member_types, is_nullable=False): |
| 260 self.member_types = member_types |
| 261 self.is_nullable = is_nullable |
| 262 |
| 263 @property |
| 264 def array_or_sequence_type(self): |
| 265 return False |
| 266 |
| 267 @property |
| 268 def array_type(self): |
| 269 return False |
| 270 |
| 271 @property |
| 272 def is_array(self): |
| 273 # We do not support arrays of union types |
| 274 return False |
| 275 |
| 276 @property |
| 277 def base_type(self): |
| 278 return None |
| 279 |
| 280 @property |
| 281 def is_basic_type(self): |
| 282 return False |
| 283 |
| 284 @property |
| 285 def is_callback_function(self): |
| 286 return False |
| 287 |
| 288 @property |
| 289 def is_enum(self): |
| 290 return False |
| 291 |
| 292 @property |
| 293 def is_integer_type(self): |
| 294 return False |
| 295 |
| 296 @property |
| 297 def is_numeric_type(self): |
| 298 return False |
| 299 |
| 300 @property |
| 301 def is_primitivee_type(self): |
| 302 return False |
| 303 |
| 304 @property |
| 305 def is_sequence(self): |
| 306 # We do not support sequences of union types |
| 307 return False |
| 308 |
| 309 @property |
| 310 def is_union_type(self): |
| 311 return True |
| 312 |
| 313 @property |
| 314 def name(self): |
| 315 return 'Or'.join(member_type.name for member_type in self.member_types) |
| 316 |
| 317 def resolve_typedefs(self, typedefs): |
| 318 self.member_types = [ |
| 319 typedefs.get(member_type, member_type) |
| 320 for member_type in self.member_types] |
| 321 return self |
OLD | NEW |