Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(339)

Side by Side Diff: Source/bindings/scripts/idl_definitions.py

Issue 185303013: Remove Perl cruft from IDL compiler front end (mostly JSON export) (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | Source/bindings/scripts/idl_definitions_builder.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (C) 2013 Google Inc. All rights reserved. 1 # Copyright (C) 2013 Google Inc. All rights reserved.
2 # 2 #
3 # Redistribution and use in source and binary forms, with or without 3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions are 4 # modification, are permitted provided that the following conditions are
5 # met: 5 # met:
6 # 6 #
7 # * Redistributions of source code must retain the above copyright 7 # * Redistributions of source code must retain the above copyright
8 # notice, this list of conditions and the following disclaimer. 8 # notice, this list of conditions and the following disclaimer.
9 # * Redistributions in binary form must reproduce the above 9 # * Redistributions in binary form must reproduce the above
10 # copyright notice, this list of conditions and the following disclaimer 10 # copyright notice, this list of conditions and the following disclaimer
11 # in the documentation and/or other materials provided with the 11 # in the documentation and/or other materials provided with the
12 # distribution. 12 # distribution.
13 # * Neither the name of Google Inc. nor the names of its 13 # * Neither the name of Google Inc. nor the names of its
14 # contributors may be used to endorse or promote products derived from 14 # contributors may be used to endorse or promote products derived from
15 # this software without specific prior written permission. 15 # this software without specific prior written permission.
16 # 16 #
17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 28
29 """Blink IDL Intermediate Representation (IR) classes. 29 """Blink IDL Intermediate Representation (IR) classes."""
30 30
31 Also JSON export, using legacy Perl terms and format, to ensure that both
32 parsers produce the same output.
33 FIXME: remove BaseIdl, JSON export (json_serializable and to_json), and Perl
34 compatibility functions and hacks once Perl compiler gone.
35 """
36
37 # Disable attribute hiding check (else JSONEncoder default raises an error)
38 # pylint: disable=E0202
39 # pylint doesn't understand ABCs. 31 # pylint doesn't understand ABCs.
40 # pylint: disable=W0232, E0203, W0201 32 # pylint: disable=W0232, E0203, W0201
41 33
42 import abc 34 import abc
43 import json
44 import re 35 import re
45 36
46 37
47 # Base classes 38 # Type classes
39
40 class IdlType(object):
41 # FIXME: replace type strings with these objects,
42 # so don't need to parse everywhere types are used.
43 # Types are stored internally as strings, not objects,
44 # e.g., as 'sequence<Foo>' or 'Foo[]',
45 # hence need to parse the string whenever a type is used.
46 # FIXME: incorporate Nullable, Variadic, etc.
47 # FIXME: properly should nest types
48 # Formally types are nested, e.g., short?[] vs. short[]?,
49 # but in practice these complex types aren't used and can treat
50 # as orthogonal properties.
51 def __init__(self, base_type, is_array=False, is_sequence=False):
52 if is_array and is_sequence:
53 raise ValueError('Array of Sequences are not allowed.')
54 self.base_type = base_type
55 self.is_array = is_array
56 self.is_sequence = is_sequence
57
58 def __str__(self):
59 type_string = self.base_type
60 if self.is_array:
61 return type_string + '[]'
62 if self.is_sequence:
63 return 'sequence<%s>' % type_string
64 return type_string
65
66 @classmethod
67 def from_string(cls, type_string):
68 sequence_re = r'^sequence<([^>]*)>$'
69 if type_string.endswith('[]'):
70 type_string = type_string[:-2]
71 sequence_match = re.match(sequence_re, type_string)
72 if sequence_match:
73 raise ValueError('Array of Sequences are not allowed.')
74 return cls(type_string, is_array=True)
75 sequence_match = re.match(sequence_re, type_string)
76 if sequence_match:
77 base_type = sequence_match.group(1)
78 return cls(base_type, is_sequence=True)
79 return cls(type_string)
80
81 def resolve_typedefs(self, typedefs):
82 if self.base_type in typedefs:
83 self.base_type = typedefs[self.base_type]
84 return self # Fluent interface
48 85
49 86
50 class BaseIdl(object): 87 class IdlUnionType(object):
51 """Abstract base class, used for JSON serialization.""" 88 # FIXME: remove class, just treat as tuple
52 __metaclass__ = abc.ABCMeta 89 def __init__(self, union_member_types=None):
90 self.union_member_types = union_member_types or []
53 91
54 @abc.abstractmethod 92 def resolve_typedefs(self, typedefs):
55 def json_serializable(self): 93 self.union_member_types = [
56 """Returns a JSON serializable form of the object. 94 typedefs.get(union_member_type, union_member_type)
57 95 for union_member_type in self.union_member_types]
58 This should be a dictionary, with keys scoped names of the form
59 Class::key, where the scope is the class name.
60 This is so we produce identical output to the Perl code, which uses
61 the Perl module JSON.pm, which uses this format.
62 """
63 pass
64 96
65 97
66 class TypedObject(object): 98 class TypedObject(object):
67 """Object with a type, such as an Attribute or Operation (return value). 99 """Object with a type, such as an Attribute or Operation (return value).
68 100
69 The type can be an actual type, or can be a typedef, which must be resolved 101 The type can be an actual type, or can be a typedef, which must be resolved
70 before passing data to the code generator. 102 before passing data to the code generator.
71 """ 103 """
72 __metaclass__ = abc.ABCMeta 104 __metaclass__ = abc.ABCMeta
73 idl_type = None 105 idl_type = None
74 extended_attributes = None 106 extended_attributes = None
75 107
76 def resolve_typedefs(self, typedefs): 108 def resolve_typedefs(self, typedefs):
77 """Resolve typedefs to actual types in the object.""" 109 """Resolve typedefs to actual types in the object."""
78 # Constructors don't have their own return type, because it's the 110 # Constructors don't have their own return type, because it's the
79 # interface itself. 111 # interface itself.
80 if not self.idl_type: 112 if not self.idl_type:
81 return 113 return
82 # (Types are represented either as strings or as IdlUnionType objects.) 114 # (Types are represented either as strings or as IdlUnionType objects.)
83 # Union types are objects, which have a member function for this 115 # Union types are objects, which have a member function for this
84 if isinstance(self.idl_type, IdlUnionType): 116 if isinstance(self.idl_type, IdlUnionType):
85 # Method 'resolve_typedefs' call is ok, but pylint can't infer this 117 # Method 'resolve_typedefs' call is ok, but pylint can't infer this
86 # pylint: disable=E1101 118 # pylint: disable=E1101
87 self.idl_type.resolve_typedefs(typedefs) 119 self.idl_type.resolve_typedefs(typedefs)
88 return 120 return
89 # Otherwise, IDL type is represented as string, so use a function 121 # Otherwise, IDL type is represented as string, so use a function
90 self.idl_type = resolve_typedefs(self.idl_type, typedefs) 122 self.idl_type = resolve_typedefs(self.idl_type, typedefs)
91 123
92 124
125 def resolve_typedefs(idl_type, typedefs):
126 """Return an IDL type (as string) with typedefs resolved."""
127 # FIXME: merge into above, as only one use
128 # Converts a string representation to and from an IdlType object to handle
129 # parsing of composite types (arrays and sequences) and encapsulate typedef
130 # resolution, e.g., GLint[] -> unsigned long[] requires parsing the '[]'.
131 # Use fluent interface to avoid auxiliary variable.
132 return str(IdlType.from_string(idl_type).resolve_typedefs(typedefs))
133
134
93 # IDL classes 135 # IDL classes
94 136
95 137
96 class IdlDefinitions(BaseIdl): 138 class IdlDefinitions(object):
97 def __init__(self, callback_functions=None, enumerations=None, file_name=Non e, interfaces=None, typedefs=None): 139 def __init__(self, callback_functions=None, enumerations=None, interfaces=No ne, typedefs=None):
98 self.callback_functions = callback_functions or {} 140 self.callback_functions = callback_functions or {}
99 self.enumerations = enumerations or {} 141 self.enumerations = enumerations or {}
100 self.file_name = file_name or None
101 self.interfaces = interfaces or {} 142 self.interfaces = interfaces or {}
102 # Typedefs are not exposed by bindings; resolve typedefs with the 143 # Typedefs are not exposed by bindings; resolve typedefs with the
103 # actual types and then discard the Typedefs. 144 # actual types and then discard the Typedefs.
104 # http://www.w3.org/TR/WebIDL/#idl-typedefs 145 # http://www.w3.org/TR/WebIDL/#idl-typedefs
105 if typedefs: 146 if typedefs:
106 self.resolve_typedefs(typedefs) 147 self.resolve_typedefs(typedefs)
107 148
108 def resolve_typedefs(self, typedefs): 149 def resolve_typedefs(self, typedefs):
109 for callback_function in self.callback_functions.itervalues(): 150 for callback_function in self.callback_functions.itervalues():
110 callback_function.resolve_typedefs(typedefs) 151 callback_function.resolve_typedefs(typedefs)
111 for interface in self.interfaces.itervalues(): 152 for interface in self.interfaces.itervalues():
112 interface.resolve_typedefs(typedefs) 153 interface.resolve_typedefs(typedefs)
113 154
114 def json_serializable(self):
115 return {
116 'idlDocument::callbackFunctions': self.callback_functions.values (),
117 'idlDocument::enumerations': self.enumerations.values(),
118 'idlDocument::fileName': self.file_name,
119 'idlDocument::interfaces': sorted(self.interfaces.values()),
120 }
121 155
122 def to_json(self, debug=False): 156 class IdlCallbackFunction(TypedObject):
123 """Returns a JSON string representing the Definitions.
124
125 The JSON output should be identical with the output of the Perl parser,
126 specifically the function serializeJSON in idl_serializer.pm,
127 which takes a Perl object created by idl_parser.pm.
128 """
129 # Sort so order consistent, allowing comparison of output
130 if debug:
131 # indent turns on pretty-printing for legibility
132 return json.dumps(self, cls=IdlEncoder, sort_keys=True, indent=4)
133 # Use compact separators so output identical to Perl
134 return json.dumps(self, cls=IdlEncoder, sort_keys=True, separators=(',', ':'))
135
136
137 class IdlCallbackFunction(BaseIdl, TypedObject):
138 def __init__(self, name=None, idl_type=None, arguments=None): 157 def __init__(self, name=None, idl_type=None, arguments=None):
139 self.idl_type = idl_type 158 self.idl_type = idl_type
140 self.name = name 159 self.name = name
141 self.arguments = arguments or [] 160 self.arguments = arguments or []
142 161
143 def resolve_typedefs(self, typedefs): 162 def resolve_typedefs(self, typedefs):
144 TypedObject.resolve_typedefs(self, typedefs) 163 TypedObject.resolve_typedefs(self, typedefs)
145 for argument in self.arguments: 164 for argument in self.arguments:
146 argument.resolve_typedefs(typedefs) 165 argument.resolve_typedefs(typedefs)
147 166
148 def json_serializable(self): 167
149 return { 168 class IdlEnum(object):
150 'callbackFunction::name': self.name, 169 # FIXME: remove, just treat enums as a dictionary
151 'callbackFunction::type': self.idl_type, 170 def __init__(self, name=None, values=None):
152 'callbackFunction::parameters': self.arguments, 171 self.name = name
153 } 172 self.values = values or [] # FIXME: unnecessary, can't be empty
154 173
155 174
156 class IdlEnum(BaseIdl): 175 class IdlInterface(object):
157 def __init__(self, name=None, values=None):
158 self.name = name
159 self.values = values or []
160
161 def json_serializable(self):
162 return {
163 'domEnum::name': self.name,
164 'domEnum::values': self.values,
165 }
166
167
168 class IdlInterface(BaseIdl):
169 def __init__(self, attributes=None, constants=None, constructors=None, custo m_constructors=None, extended_attributes=None, operations=None, is_callback=Fals e, is_partial=False, name=None, parent=None): 176 def __init__(self, attributes=None, constants=None, constructors=None, custo m_constructors=None, extended_attributes=None, operations=None, is_callback=Fals e, is_partial=False, name=None, parent=None):
170 self.attributes = attributes or [] 177 self.attributes = attributes or []
171 self.constants = constants or [] 178 self.constants = constants or []
172 self.constructors = constructors or [] 179 self.constructors = constructors or []
173 self.custom_constructors = custom_constructors or [] 180 self.custom_constructors = custom_constructors or []
174 self.extended_attributes = extended_attributes or {} 181 self.extended_attributes = extended_attributes or {}
175 self.operations = operations or [] 182 self.operations = operations or []
176 self.is_callback = is_callback 183 self.is_callback = is_callback
177 self.is_partial = is_partial 184 self.is_partial = is_partial
178 self.is_exception = False 185 self.is_exception = False
179 self.name = name 186 self.name = name
180 self.parent = parent 187 self.parent = parent
181 188
182 def resolve_typedefs(self, typedefs): 189 def resolve_typedefs(self, typedefs):
183 for attribute in self.attributes: 190 for attribute in self.attributes:
184 attribute.resolve_typedefs(typedefs) 191 attribute.resolve_typedefs(typedefs)
185 for constant in self.constants: 192 for constant in self.constants:
186 constant.resolve_typedefs(typedefs) 193 constant.resolve_typedefs(typedefs)
187 for constructor in self.constructors: 194 for constructor in self.constructors:
188 constructor.resolve_typedefs(typedefs) 195 constructor.resolve_typedefs(typedefs)
189 for custom_constructor in self.custom_constructors: 196 for custom_constructor in self.custom_constructors:
190 custom_constructor.resolve_typedefs(typedefs) 197 custom_constructor.resolve_typedefs(typedefs)
191 for operation in self.operations: 198 for operation in self.operations:
192 operation.resolve_typedefs(typedefs) 199 operation.resolve_typedefs(typedefs)
193 200
194 def json_serializable(self):
195 return {
196 'domInterface::attributes': self.attributes,
197 'domInterface::constants': self.constants,
198 'domInterface::constructors': self.constructors,
199 'domInterface::customConstructors': self.custom_constructors,
200 'domInterface::extendedAttributes': none_to_value_is_missing(self.ex tended_attributes),
201 'domInterface::functions': self.operations,
202 'domInterface::isException': false_to_none(self.is_exception),
203 'domInterface::isCallback': boolean_to_perl(false_to_none(self.is_ca llback)),
204 'domInterface::isPartial': false_to_none(self.is_partial),
205 'domInterface::name': self.name,
206 'domInterface::parent': self.parent,
207 }
208
209 201
210 class IdlException(IdlInterface): 202 class IdlException(IdlInterface):
211 # Properly exceptions and interfaces are distinct, and thus should inherit a 203 # Properly exceptions and interfaces are distinct, and thus should inherit a
212 # common base class (say, "IdlExceptionOrInterface"). 204 # common base class (say, "IdlExceptionOrInterface").
213 # However, there is only one exception (DOMException), and new exceptions 205 # However, there is only one exception (DOMException), and new exceptions
214 # are not expected. Thus it is easier to implement exceptions as a 206 # are not expected. Thus it is easier to implement exceptions as a
215 # restricted subclass of interfaces. 207 # restricted subclass of interfaces.
216 # http://www.w3.org/TR/WebIDL/#idl-exceptions 208 # http://www.w3.org/TR/WebIDL/#idl-exceptions
217 def __init__(self, name=None, constants=None, operations=None, attributes=No ne, extended_attributes=None): 209 def __init__(self, name=None, constants=None, operations=None, attributes=No ne, extended_attributes=None):
218 IdlInterface.__init__(self, name=name, constants=constants, operations=o perations, attributes=attributes, extended_attributes=extended_attributes) 210 IdlInterface.__init__(self, name=name, constants=constants, operations=o perations, attributes=attributes, extended_attributes=extended_attributes)
219 self.is_exception = True 211 self.is_exception = True
220 212
221 213
222 class IdlAttribute(BaseIdl, TypedObject): 214 class IdlAttribute(TypedObject):
223 def __init__(self, idl_type=None, extended_attributes=None, getter_exception s=None, is_nullable=False, is_static=False, is_read_only=False, name=None, sette r_exceptions=None): 215 def __init__(self, idl_type=None, extended_attributes=None, getter_exception s=None, is_nullable=False, is_static=False, is_read_only=False, name=None, sette r_exceptions=None):
224 self.idl_type = idl_type 216 self.idl_type = idl_type
225 self.extended_attributes = extended_attributes or {} 217 self.extended_attributes = extended_attributes or {}
226 self.getter_exceptions = getter_exceptions or [] 218 self.getter_exceptions = getter_exceptions or []
227 self.is_nullable = is_nullable 219 self.is_nullable = is_nullable
228 self.is_static = is_static 220 self.is_static = is_static
229 self.is_read_only = is_read_only 221 self.is_read_only = is_read_only
230 self.name = name 222 self.name = name
231 self.setter_exceptions = setter_exceptions or [] 223 self.setter_exceptions = setter_exceptions or []
232 224
233 def json_serializable(self):
234 return {
235 'domAttribute::extendedAttributes': none_to_value_is_missing(self.ex tended_attributes),
236 'domAttribute::getterExceptions': self.getter_exceptions,
237 'domAttribute::isNullable': boolean_to_perl_quoted(false_to_none(sel f.is_nullable)),
238 'domAttribute::isReadOnly': boolean_to_perl(false_to_none(self.is_re ad_only)),
239 'domAttribute::isStatic': boolean_to_perl(false_to_none(self.is_stat ic)),
240 'domAttribute::name': self.name,
241 'domAttribute::setterExceptions': self.setter_exceptions,
242 'domAttribute::type': self.idl_type,
243 }
244 225
245 226 class IdlConstant(TypedObject):
246 class IdlConstant(BaseIdl, TypedObject):
247 def __init__(self, name=None, idl_type=None, value=None, extended_attributes =None): 227 def __init__(self, name=None, idl_type=None, value=None, extended_attributes =None):
248 self.idl_type = idl_type 228 self.idl_type = idl_type
249 self.extended_attributes = extended_attributes or {} 229 self.extended_attributes = extended_attributes or {}
250 self.name = name 230 self.name = name
251 self.value = value 231 self.value = value
252 232
253 def json_serializable(self):
254 return {
255 'domConstant::extendedAttributes': none_to_value_is_missing(self.ext ended_attributes),
256 'domConstant::name': self.name,
257 'domConstant::type': self.idl_type,
258 'domConstant::value': self.value,
259 }
260 233
261 234 class IdlOperation(TypedObject):
262 class IdlOperation(BaseIdl, TypedObject):
263 def __init__(self, is_static=False, name=None, idl_type=None, extended_attri butes=None, specials=None, arguments=None, overloaded_index=None): 235 def __init__(self, is_static=False, name=None, idl_type=None, extended_attri butes=None, specials=None, arguments=None, overloaded_index=None):
264 self.is_static = is_static 236 self.is_static = is_static
265 self.name = name or '' 237 self.name = name or ''
266 self.idl_type = idl_type 238 self.idl_type = idl_type
267 self.extended_attributes = extended_attributes or {} 239 self.extended_attributes = extended_attributes or {}
268 self.specials = specials or [] 240 self.specials = specials or []
269 self.arguments = arguments or [] 241 self.arguments = arguments or []
270 # FIXME: remove overloaded_index (only here for Perl compatibility),
271 # as overloading is handled in code generator (v8_interface.py).
272 self.overloaded_index = overloaded_index
273 242
274 def resolve_typedefs(self, typedefs): 243 def resolve_typedefs(self, typedefs):
275 TypedObject.resolve_typedefs(self, typedefs) 244 TypedObject.resolve_typedefs(self, typedefs)
276 for argument in self.arguments: 245 for argument in self.arguments:
277 argument.resolve_typedefs(typedefs) 246 argument.resolve_typedefs(typedefs)
278 247
279 def json_serializable(self):
280 return {
281 'domFunction::extendedAttributes': none_to_value_is_missing(self.ext ended_attributes),
282 'domFunction::isStatic': boolean_to_perl(false_to_none(self.is_stati c)),
283 'domFunction::name': self.name,
284 'domFunction::overloadedIndex': self.overloaded_index,
285 'domFunction::parameters': self.arguments,
286 'domFunction::specials': self.specials,
287 'domFunction::type': self.idl_type,
288 }
289 248
290 249 class IdlArgument(TypedObject):
291 class IdlArgument(BaseIdl, TypedObject): 250 def __init__(self, name=None, idl_type=None, extended_attributes=None, is_op tional=False, is_nullable=False, is_variadic=False):
292 def __init__(self, name=None, idl_type=None, extended_attributes=None, is_op tional=False, is_nullable=None, is_variadic=False):
293 self.idl_type = idl_type 251 self.idl_type = idl_type
294 self.extended_attributes = extended_attributes or {} 252 self.extended_attributes = extended_attributes or {}
295 # FIXME: boolean values are inconsistent.
296 # The below hack is so that generated JSON is identical to
297 # Perl-generated JSON, where the exact values depend on the code path.
298 # False and None (Perl: 0 and undef) are semantically interchangeable,
299 # but yield different JSON.
300 # Once Perl removed, have all default to False.
301 if is_optional is None:
302 is_optional = False
303 if is_variadic is None:
304 is_variadic = False
305 self.is_nullable = is_nullable # (T?) 253 self.is_nullable = is_nullable # (T?)
306 self.is_optional = is_optional # (optional T) 254 self.is_optional = is_optional # (optional T)
307 self.is_variadic = is_variadic # (T...) 255 self.is_variadic = is_variadic # (T...)
308 self.name = name 256 self.name = name
309
310 def json_serializable(self):
311 return {
312 'domParameter::extendedAttributes': none_to_value_is_missing(self.ex tended_attributes),
313 'domParameter::isNullable': boolean_to_perl_quoted(self.is_nullable) ,
314 'domParameter::isOptional': boolean_to_perl(self.is_optional),
315 'domParameter::isVariadic': boolean_to_perl(self.is_variadic),
316 'domParameter::name': self.name,
317 'domParameter::type': self.idl_type,
318 }
319
320 # Type classes
321
322
323 def resolve_typedefs(idl_type, typedefs):
324 """Return an IDL type (as string) with typedefs resolved."""
325 # Converts a string representation to and from an IdlType object to handle
326 # parsing of composite types (arrays and sequences) and encapsulate typedef
327 # resolution, e.g., GLint[] -> unsigned long[] requires parsing the '[]'.
328 # Use fluent interface to avoid auxiliary variable.
329 return str(IdlType.from_string(idl_type).resolve_typedefs(typedefs))
330
331
332 class IdlType(object):
333 # FIXME: replace type strings with these objects,
334 # so don't need to parse everywhere types are used.
335 # Types are stored internally as strings, not objects,
336 # e.g., as 'sequence<Foo>' or 'Foo[]',
337 # hence need to parse the string whenever a type is used.
338 # FIXME: incorporate Nullable, Variadic, etc.
339 # FIXME: properly should nest types
340 # Formally types are nested, e.g., short?[] vs. short[]?,
341 # but in practice these complex types aren't used and can treat
342 # as orthogonal properties.
343 def __init__(self, base_type, is_array=False, is_sequence=False):
344 if is_array and is_sequence:
345 raise ValueError('Array of Sequences are not allowed.')
346 self.base_type = base_type
347 self.is_array = is_array
348 self.is_sequence = is_sequence
349
350 def __str__(self):
351 type_string = self.base_type
352 if self.is_array:
353 return type_string + '[]'
354 if self.is_sequence:
355 return 'sequence<%s>' % type_string
356 return type_string
357
358 @classmethod
359 def from_string(cls, type_string):
360 sequence_re = r'^sequence<([^>]*)>$'
361 if type_string.endswith('[]'):
362 type_string = type_string[:-2]
363 sequence_match = re.match(sequence_re, type_string)
364 if sequence_match:
365 raise ValueError('Array of Sequences are not allowed.')
366 return cls(type_string, is_array=True)
367 sequence_match = re.match(sequence_re, type_string)
368 if sequence_match:
369 base_type = sequence_match.group(1)
370 return cls(base_type, is_sequence=True)
371 return cls(type_string)
372
373 def resolve_typedefs(self, typedefs):
374 if self.base_type in typedefs:
375 self.base_type = typedefs[self.base_type]
376 return self # Fluent interface
377
378
379 class IdlUnionType(BaseIdl):
380 def __init__(self, union_member_types=None):
381 self.union_member_types = union_member_types or []
382
383 def resolve_typedefs(self, typedefs):
384 self.union_member_types = [
385 typedefs.get(union_member_type, union_member_type)
386 for union_member_type in self.union_member_types]
387
388 def json_serializable(self):
389 return {
390 'UnionType::unionMemberTypes': self.union_member_types,
391 }
392
393
394 # Perl JSON compatibility functions
395
396 def none_to_value_is_missing(extended_attributes):
397 # Perl IDL Parser uses 'VALUE_IS_MISSING' for null values in
398 # extended attributes, so add this as a filter when exporting to JSON.
399 new_extended_attributes = {}
400 for key, value in extended_attributes.iteritems():
401 if value is None:
402 new_extended_attributes[key] = 'VALUE_IS_MISSING'
403 else:
404 new_extended_attributes[key] = value
405 return new_extended_attributes
406
407
408 def boolean_to_perl(value):
409 # Perl stores booleans as 1, 0, or undefined (JSON null);
410 # convert to this format.
411 if value is None:
412 return None
413 return int(value)
414
415
416 def boolean_to_perl_quoted(value):
417 # Bug-for-bug compatibility with Perl.
418 # The value of isNullable is quoted ('1', '0', or undefined), rather than
419 # an integer, so add quotes.
420 if value is None:
421 return None
422 return str(int(value))
423
424
425 def false_to_none(value):
426 # The Perl parser generally uses undefined (Python None) rather than False
427 # for boolean flags, because the value is simply left undefined, rather than
428 # explicitly set to False.
429 if value is False:
430 return None
431 return value
432
433
434 # JSON export
435
436
437 class IdlEncoder(json.JSONEncoder):
438 def default(self, obj):
439 if isinstance(obj, BaseIdl):
440 return obj.json_serializable()
441 return json.JSONEncoder.default(self, obj)
OLDNEW
« no previous file with comments | « no previous file | Source/bindings/scripts/idl_definitions_builder.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698