Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 """IDL type handling. | 4 """IDL type handling. |
| 5 | 5 |
| 6 Classes: | 6 Classes: |
| 7 IdlTypeBase | 7 IdlTypeBase |
| 8 IdlType | 8 IdlType |
| 9 IdlUnionType | 9 IdlUnionType |
| 10 IdlArrayOrSequenceType | |
| 10 """ | 11 """ |
| 11 | 12 |
| 12 from collections import defaultdict | 13 from collections import defaultdict |
| 13 | 14 |
| 14 | 15 |
| 15 ################################################################################ | 16 ################################################################################ |
| 16 # IDL types | 17 # IDL types |
| 17 ################################################################################ | 18 ################################################################################ |
| 18 | 19 |
| 19 INTEGER_TYPES = frozenset([ | 20 INTEGER_TYPES = frozenset([ |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 89 def inherits_interface(interface_name, ancestor_name): | 90 def inherits_interface(interface_name, ancestor_name): |
| 90 return (interface_name == ancestor_name or | 91 return (interface_name == ancestor_name or |
| 91 ancestor_name in ancestors[interface_name]) | 92 ancestor_name in ancestors[interface_name]) |
| 92 | 93 |
| 93 | 94 |
| 94 def set_ancestors(new_ancestors): | 95 def set_ancestors(new_ancestors): |
| 95 ancestors.update(new_ancestors) | 96 ancestors.update(new_ancestors) |
| 96 | 97 |
| 97 | 98 |
| 98 class IdlTypeBase(object): | 99 class IdlTypeBase(object): |
| 99 """Base class for IdlType and IdlUnionType.""" | 100 """Base class for IdlType, IdlUnionType and IdlArrayOrSequenceType.""" |
| 100 | 101 |
| 101 def __init__(self, is_array=False, is_sequence=False, is_nullable=False): | 102 def __init__(self, is_nullable): |
| 102 self.base_type = None | 103 self.base_type = None |
| 103 self.is_array = is_array | 104 self.is_array = False |
| 104 self.is_sequence = is_sequence | |
| 105 self.is_nullable = is_nullable | 105 self.is_nullable = is_nullable |
| 106 self.is_sequence = False | |
| 107 | |
| 108 def __str__(self): | |
| 109 inner_string = self.inner_string | |
| 110 if self.is_nullable: | |
| 111 # FIXME: Dictionary::ConversionContext::setConversionType can't | |
| 112 # handle the '?' in nullable types (passes nullability separately). | |
| 113 # Update that function to handle nullability from the type name, | |
| 114 # simplifying its signature. | |
| 115 # return inner_string + '?' | |
| 116 return inner_string | |
| 117 return inner_string | |
| 106 | 118 |
| 107 @property | 119 @property |
| 108 def native_array_element_type(self): | 120 def inner_string(self): |
| 109 return None | 121 raise NotImplementedError( |
| 122 'inner_string property should be defined in subclasses') | |
| 110 | 123 |
| 111 @property | 124 @property |
| 112 def array_element_type(self): | 125 def array_element_type(self): |
| 113 return None | 126 return None |
| 114 | 127 |
| 115 @property | 128 @property |
| 116 def is_basic_type(self): | 129 def is_basic_type(self): |
| 117 return False | 130 return False |
| 118 | 131 |
| 119 @property | 132 @property |
| 120 def is_callback_function(self): | 133 def is_callback_function(self): |
| 121 return False | 134 return False |
| 122 | 135 |
| 123 @property | 136 @property |
| 137 def is_callback_interface(self): | |
| 138 return False | |
| 139 | |
| 140 @property | |
| 124 def is_dictionary(self): | 141 def is_dictionary(self): |
| 125 return False | 142 return False |
| 126 | 143 |
| 127 @property | 144 @property |
| 128 def is_enum(self): | 145 def is_enum(self): |
| 129 return False | 146 return False |
| 130 | 147 |
| 131 @property | 148 @property |
| 132 def is_integer_type(self): | 149 def is_integer_type(self): |
| 133 return False | 150 return False |
| 134 | 151 |
| 135 @property | 152 @property |
| 136 def is_numeric_type(self): | 153 def is_numeric_type(self): |
| 137 return False | 154 return False |
| 138 | 155 |
| 139 @property | 156 @property |
| 140 def is_primitivee_type(self): | 157 def is_primitive_type(self): |
| 141 return False | 158 return False |
| 142 | 159 |
| 143 @property | 160 @property |
| 161 def is_interface_type(self): | |
| 162 return False | |
| 163 | |
| 164 @property | |
| 144 def is_string_type(self): | 165 def is_string_type(self): |
| 145 return False | 166 return False |
| 146 | 167 |
| 147 @property | 168 @property |
| 148 def is_union_type(self): | 169 def is_union_type(self): |
| 149 return False | 170 return False |
| 150 | 171 |
| 151 @property | 172 @property |
| 152 def may_raise_exception_on_conversion(self): | 173 def may_raise_exception_on_conversion(self): |
| 153 return False | 174 return False |
| 154 | 175 |
| 155 @property | 176 @property |
| 156 def name(self): | 177 def name(self): |
| 178 if self.is_nullable: | |
| 179 return self.inner_name + 'OrNull' | |
| 180 return self.inner_name | |
| 181 | |
| 182 @property | |
| 183 def inner_name(self): | |
| 157 raise NotImplementedError( | 184 raise NotImplementedError( |
| 158 'name property should be defined in subclasses') | 185 'inner_name property should be defined in subclasses') |
| 159 | 186 |
| 160 def resolve_typedefs(self, typedefs): | 187 def resolve_typedefs(self, typedefs): |
| 161 raise NotImplementedError( | 188 raise NotImplementedError( |
| 162 'resolve_typedefs should be defined in subclasses') | 189 'resolve_typedefs should be defined in subclasses') |
| 163 | 190 |
| 164 | 191 |
| 165 ################################################################################ | 192 ################################################################################ |
| 166 # IdlType | 193 # IdlType |
| 167 ################################################################################ | 194 ################################################################################ |
| 168 | 195 |
| 169 class IdlType(IdlTypeBase): | 196 class IdlType(IdlTypeBase): |
| 170 # FIXME: incorporate Nullable, etc. | 197 # FIXME: incorporate Nullable, etc. |
| 171 # FIXME: use nested types: IdlArrayType, IdlNullableType, IdlSequenceType | |
| 172 # to support types like short?[] vs. short[]?, instead of treating these | 198 # to support types like short?[] vs. short[]?, instead of treating these |
| 173 # as orthogonal properties (via flags). | 199 # as orthogonal properties (via flags). |
| 174 callback_functions = set() | 200 callback_functions = set() |
| 175 callback_interfaces = set() | 201 callback_interfaces = set() |
| 176 dictionaries = set() | 202 dictionaries = set() |
| 177 enums = {} # name -> values | 203 enums = {} # name -> values |
| 178 | 204 |
| 179 def __init__(self, base_type, is_array=False, is_sequence=False, is_nullable =False, is_unrestricted=False): | 205 def __init__(self, base_type, is_nullable=False, is_unrestricted=False): |
| 180 super(IdlType, self).__init__(is_array=is_array, is_sequence=is_sequence , is_nullable=is_nullable) | 206 super(IdlType, self).__init__(is_nullable) |
| 181 if is_array and is_sequence: | |
| 182 raise ValueError('Array of Sequences are not allowed.') | |
| 183 if is_unrestricted: | 207 if is_unrestricted: |
| 184 self.base_type = 'unrestricted %s' % base_type | 208 self.base_type = 'unrestricted %s' % base_type |
| 185 else: | 209 else: |
| 186 self.base_type = base_type | 210 self.base_type = base_type |
| 187 | 211 |
| 188 def __str__(self): | |
| 189 type_string = self.base_type | |
| 190 if self.is_array: | |
| 191 return type_string + '[]' | |
| 192 if self.is_sequence: | |
| 193 return 'sequence<%s>' % type_string | |
| 194 if self.is_nullable: | |
| 195 # FIXME: Dictionary::ConversionContext::setConversionType can't | |
| 196 # handle the '?' in nullable types (passes nullability separately). | |
| 197 # Update that function to handle nullability from the type name, | |
| 198 # simplifying its signature. | |
| 199 # return type_string + '?' | |
| 200 return type_string | |
| 201 return type_string | |
| 202 | |
| 203 # FIXME: move to v8_types.py | |
| 204 @property | 212 @property |
| 205 def native_array_element_type(self): | 213 def inner_string(self): |
| 206 return self.array_element_type or self.sequence_element_type | 214 return self.base_type |
| 207 | 215 |
| 208 @property | 216 @property |
| 209 def array_element_type(self): | 217 def array_element_type(self): |
| 210 return self.is_array and IdlType(self.base_type) | 218 return self.is_array and IdlType(self.base_type) |
| 211 | 219 |
| 212 @property | 220 @property |
| 213 def sequence_element_type(self): | 221 def sequence_element_type(self): |
| 214 return self.is_sequence and IdlType(self.base_type) | 222 return self.is_sequence and IdlType(self.base_type) |
| 215 | 223 |
| 216 @property | 224 @property |
| 217 def is_basic_type(self): | 225 def is_basic_type(self): |
| 218 return self.base_type in BASIC_TYPES and not self.native_array_element_t ype | 226 return self.base_type in BASIC_TYPES |
| 219 | 227 |
| 220 @property | 228 @property |
| 221 def is_callback_function(self): | 229 def is_callback_function(self): |
| 222 return self.base_type in IdlType.callback_functions | 230 return self.base_type in IdlType.callback_functions |
| 223 | 231 |
| 224 @property | 232 @property |
| 225 def is_callback_interface(self): | 233 def is_callback_interface(self): |
| 226 return self.base_type in IdlType.callback_interfaces | 234 return self.base_type in IdlType.callback_interfaces |
| 227 | 235 |
| 228 @property | 236 @property |
| 229 def is_dictionary(self): | 237 def is_dictionary(self): |
| 230 return self.base_type in IdlType.dictionaries | 238 return self.base_type in IdlType.dictionaries |
| 231 | 239 |
| 232 @property | 240 @property |
| 233 def is_composite_type(self): | |
| 234 return (self.name == 'Any' or | |
| 235 self.array_element_type or | |
| 236 self.sequence_element_type or | |
| 237 self.is_union_type) | |
| 238 | |
| 239 @property | |
| 240 def is_enum(self): | 241 def is_enum(self): |
| 241 # FIXME: add an IdlEnumType class and a resolve_enums step at end of | 242 # FIXME: add an IdlEnumType class and a resolve_enums step at end of |
| 242 # IdlDefinitions constructor | 243 # IdlDefinitions constructor |
| 243 return self.name in IdlType.enums | 244 return self.name in IdlType.enums |
| 244 | 245 |
| 245 @property | 246 @property |
| 246 def enum_values(self): | 247 def enum_values(self): |
| 247 return IdlType.enums[self.name] | 248 return IdlType.enums[self.name] |
| 248 | 249 |
| 249 @property | 250 @property |
| 250 def is_integer_type(self): | 251 def is_integer_type(self): |
| 251 return self.base_type in INTEGER_TYPES and not self.native_array_element _type | 252 return self.base_type in INTEGER_TYPES |
| 252 | 253 |
| 253 @property | 254 @property |
| 254 def is_numeric_type(self): | 255 def is_numeric_type(self): |
| 255 return self.base_type in NUMERIC_TYPES and not self.native_array_element _type | 256 return self.base_type in NUMERIC_TYPES |
| 256 | 257 |
| 257 @property | 258 @property |
| 258 def is_primitive_type(self): | 259 def is_primitive_type(self): |
| 259 return self.base_type in PRIMITIVE_TYPES and not self.native_array_eleme nt_type | 260 return self.base_type in PRIMITIVE_TYPES |
| 260 | 261 |
| 261 @property | 262 @property |
| 262 def is_interface_type(self): | 263 def is_interface_type(self): |
| 263 # Anything that is not another type is an interface type. | 264 # Anything that is not another type is an interface type. |
| 264 # http://www.w3.org/TR/WebIDL/#idl-types | 265 # http://www.w3.org/TR/WebIDL/#idl-types |
| 265 # http://www.w3.org/TR/WebIDL/#idl-interface | 266 # http://www.w3.org/TR/WebIDL/#idl-interface |
| 266 # In C++ these are RefPtr or PassRefPtr types. | 267 # In C++ these are RefPtr or PassRefPtr types. |
| 267 return not(self.is_basic_type or | 268 return not(self.is_basic_type or |
| 268 self.is_composite_type or | |
| 269 self.is_callback_function or | 269 self.is_callback_function or |
| 270 self.is_dictionary or | 270 self.is_dictionary or |
| 271 self.is_enum or | 271 self.is_enum or |
| 272 self.name == 'Any' or | |
| 272 self.name == 'Object' or | 273 self.name == 'Object' or |
| 273 self.name == 'Promise') # Promise will be basic in future | 274 self.name == 'Promise') # Promise will be basic in future |
| 274 | 275 |
| 275 @property | 276 @property |
| 276 def is_string_type(self): | 277 def is_string_type(self): |
| 277 return self.base_type_name in STRING_TYPES | 278 return self.inner_name in STRING_TYPES |
| 278 | 279 |
| 279 @property | 280 @property |
| 280 def may_raise_exception_on_conversion(self): | 281 def may_raise_exception_on_conversion(self): |
| 281 return (self.is_integer_type or | 282 return (self.is_integer_type or |
| 282 self.name in ('ByteString', 'ScalarValueString')) | 283 self.name in ('ByteString', 'ScalarValueString')) |
| 283 | 284 |
| 284 @property | 285 @property |
| 285 def is_union_type(self): | 286 def is_union_type(self): |
| 286 return isinstance(self, IdlUnionType) | 287 return isinstance(self, IdlUnionType) |
| 287 | 288 |
| 288 @property | 289 @property |
| 289 def base_type_name(self): | 290 def inner_name(self): |
| 291 """Return type name (or inner type name if nullable) | |
| 292 | |
| 293 http://heycam.github.io/webidl/#dfn-type-name | |
| 294 """ | |
| 290 base_type = self.base_type | 295 base_type = self.base_type |
| 291 return TYPE_NAMES.get(base_type, base_type) | 296 return TYPE_NAMES.get(base_type, base_type) |
| 292 | 297 |
| 293 @property | |
| 294 def name(self): | |
| 295 """Return type name. | |
| 296 | |
| 297 http://heycam.github.io/webidl/#dfn-type-name | |
| 298 """ | |
| 299 base_type_name = self.base_type_name | |
| 300 if self.is_array: | |
| 301 return base_type_name + 'Array' | |
| 302 if self.is_sequence: | |
| 303 return base_type_name + 'Sequence' | |
| 304 if self.is_nullable: | |
| 305 return base_type_name + 'OrNull' | |
| 306 return base_type_name | |
| 307 | |
| 308 @classmethod | 298 @classmethod |
| 309 def set_callback_functions(cls, new_callback_functions): | 299 def set_callback_functions(cls, new_callback_functions): |
| 310 cls.callback_functions.update(new_callback_functions) | 300 cls.callback_functions.update(new_callback_functions) |
| 311 | 301 |
| 312 @classmethod | 302 @classmethod |
| 313 def set_callback_interfaces(cls, new_callback_interfaces): | 303 def set_callback_interfaces(cls, new_callback_interfaces): |
| 314 cls.callback_interfaces.update(new_callback_interfaces) | 304 cls.callback_interfaces.update(new_callback_interfaces) |
| 315 | 305 |
| 316 @classmethod | 306 @classmethod |
| 317 def set_dictionaries(cls, new_dictionaries): | 307 def set_dictionaries(cls, new_dictionaries): |
| 318 cls.dictionaries.update(new_dictionaries) | 308 cls.dictionaries.update(new_dictionaries) |
| 319 | 309 |
| 320 @classmethod | 310 @classmethod |
| 321 def set_enums(cls, new_enums): | 311 def set_enums(cls, new_enums): |
| 322 cls.enums.update(new_enums) | 312 cls.enums.update(new_enums) |
| 323 | 313 |
| 324 def resolve_typedefs(self, typedefs): | 314 def resolve_typedefs(self, typedefs): |
| 315 # This function either returns |self|, possibly mutated, or leaves this | |
| 316 # object unmodified and returns a different object. | |
| 325 if self.base_type not in typedefs: | 317 if self.base_type not in typedefs: |
| 326 return self | 318 return self |
| 327 new_type = typedefs[self.base_type] | 319 new_type = typedefs[self.base_type] |
| 328 if type(new_type) != type(self): | 320 if type(new_type) != type(self): |
| 329 # If type changes, need to return a different object, | 321 # If type changes, need to return a different object, |
| 330 # since can't change type(self) | 322 # since can't change type(self) |
| 331 return new_type | 323 return new_type |
| 332 # If type doesn't change, just mutate self to avoid a new object | 324 # If type doesn't change, just mutate self to avoid a new object |
| 333 # FIXME: a bit ugly; use __init__ instead of setting flags | 325 self.__init__(new_type.base_type, self.is_nullable or new_type.is_nullab le) |
| 334 self.base_type = new_type.base_type | |
| 335 # handle array both in use and in typedef itself: | |
| 336 # typedef Type TypeDef; | |
| 337 # TypeDef[] ... | |
| 338 # and: | |
| 339 # typedef Type[] TypeArray | |
| 340 # TypeArray ... | |
| 341 self.is_array |= new_type.is_array | |
| 342 self.is_sequence |= new_type.is_sequence | |
| 343 return self | 326 return self |
| 344 | 327 |
| 345 | 328 |
| 346 ################################################################################ | 329 ################################################################################ |
| 347 # IdlUnionType | 330 # IdlUnionType |
| 348 ################################################################################ | 331 ################################################################################ |
| 349 | 332 |
| 350 class IdlUnionType(IdlTypeBase): | 333 class IdlUnionType(IdlTypeBase): |
| 351 # http://heycam.github.io/webidl/#idl-union | 334 # http://heycam.github.io/webidl/#idl-union |
| 352 def __init__(self, member_types, is_nullable=False): | 335 def __init__(self, member_types, is_nullable=False): |
| 353 super(IdlUnionType, self).__init__(is_nullable=is_nullable) | 336 super(IdlUnionType, self).__init__(is_nullable=is_nullable) |
| 354 self.member_types = member_types | 337 self.member_types = member_types |
| 355 | 338 |
| 356 @property | 339 @property |
| 357 def is_union_type(self): | 340 def is_union_type(self): |
| 358 return True | 341 return True |
| 359 | 342 |
| 360 @property | 343 @property |
| 361 def name(self): | 344 def inner_name(self): |
| 345 """Return type name (or inner type name if nullable) | |
| 346 | |
| 347 http://heycam.github.io/webidl/#dfn-type-name | |
| 348 """ | |
| 362 return 'Or'.join(member_type.name for member_type in self.member_types) | 349 return 'Or'.join(member_type.name for member_type in self.member_types) |
| 363 | 350 |
| 364 def resolve_typedefs(self, typedefs): | 351 def resolve_typedefs(self, typedefs): |
| 365 self.member_types = [ | 352 self.member_types = [ |
| 366 typedefs.get(member_type, member_type) | 353 typedefs.get(member_type, member_type) |
| 367 for member_type in self.member_types] | 354 for member_type in self.member_types] |
| 368 return self | 355 return self |
| 356 | |
| 357 | |
| 358 ################################################################################ | |
| 359 # IdlArrayOrSequenceType, IdlArrayType, IdlSequenceType | |
| 360 ################################################################################ | |
| 361 | |
| 362 class IdlArrayOrSequenceType(IdlTypeBase): | |
| 363 """Base class for IdlArrayType and IdlSequenceType.""" | |
| 364 | |
| 365 def __init__(self, element_type, is_nullable=False): | |
| 366 super(IdlArrayOrSequenceType, self).__init__(is_nullable) | |
| 367 self.element_type = element_type | |
| 368 | |
| 369 def resolve_typedefs(self, typedefs): | |
| 370 self.element_type = self.element_type.resolve_typedefs(typedefs) | |
| 371 return self | |
| 372 | |
| 373 | |
| 374 class IdlArrayType(IdlArrayOrSequenceType): | |
| 375 def __init__(self, element_type, is_nullable=False): | |
| 376 super(IdlArrayType, self).__init__(element_type, is_nullable) | |
| 377 self.is_array = True | |
| 378 | |
| 379 @property | |
| 380 def inner_string(self): | |
| 381 return '%s[]' % self.element_type | |
| 382 | |
| 383 @property | |
| 384 def inner_name(self): | |
| 385 return self.element_type.name + 'Array' | |
| 386 | |
| 387 | |
| 388 class IdlSequenceType(IdlArrayOrSequenceType): | |
| 389 def __init__(self, element_type, is_nullable=False): | |
| 390 super(IdlSequenceType, self).__init__(element_type, is_nullable) | |
| 391 self.is_array = True | |
|
haraken
2014/08/14 15:51:34
This should be:
self.is_sequence = True
Jens Widell
2014/08/14 16:03:18
Oups! Fixed.
That had no effect on code generatio
Nils Barth (inactive)
2014/08/14 16:18:55
Actually, could you try removing is_array and is_s
| |
| 392 | |
| 393 @property | |
| 394 def inner_string(self): | |
| 395 return 'sequence<%s>' % self.element_type | |
| 396 | |
| 397 @property | |
| 398 def inner_name(self): | |
| 399 return self.element_type.name + 'Sequence' | |
| OLD | NEW |