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 | |
Nils Barth (inactive)
2014/08/14 16:18:55
nit:
IdlArrayOrSequenceType
IdlArrayType
Id
| |
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. | |
Nils Barth (inactive)
2014/08/14 16:18:56
Want to put a lil' FIXME here?
(Probably a short f
| |
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_sequence = True | |
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 |