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 | |
5 """Node classes for the AST for a Mojo IDL file.""" | |
6 | |
7 # Note: For convenience of testing, you probably want to define __eq__() methods | |
8 # for all node types; it's okay to be slightly lax (e.g., not compare filename | |
9 # and lineno). You may also define __repr__() to help with analyzing test | |
10 # failures, especially for more complex types. | |
11 | |
12 | |
13 class NodeBase(object): | |
14 """Base class for nodes in the AST.""" | |
15 | |
16 def __init__(self, filename=None, lineno=None): | |
17 self.filename = filename | |
18 self.lineno = lineno | |
19 | |
20 def __eq__(self, other): | |
21 return type(self) == type(other) | |
22 | |
23 # Make != the inverse of ==. (Subclasses shouldn't have to override this.) | |
24 def __ne__(self, other): | |
25 return not self == other | |
26 | |
27 | |
28 # TODO(vtl): Some of this is complicated enough that it should be tested. | |
29 class NodeListBase(NodeBase): | |
30 """Represents a list of other nodes, all having the same type. (This is meant | |
31 to be subclassed, with subclasses defining _list_item_type to be the class (or | |
32 classes, in a tuple) of the members of the list.)""" | |
33 | |
34 def __init__(self, item_or_items=None, **kwargs): | |
35 super(NodeListBase, self).__init__(**kwargs) | |
36 self.items = [] | |
37 if item_or_items is None: | |
38 pass | |
39 elif isinstance(item_or_items, list): | |
40 for item in item_or_items: | |
41 assert isinstance(item, self._list_item_type) | |
42 self.Append(item) | |
43 else: | |
44 assert isinstance(item_or_items, self._list_item_type) | |
45 self.Append(item_or_items) | |
46 | |
47 # Support iteration. For everything else, users should just access |items| | |
48 # directly. (We intentionally do NOT supply |__len__()| or |__nonzero__()|, so | |
49 # |bool(NodeListBase())| is true.) | |
50 def __iter__(self): | |
51 return self.items.__iter__() | |
52 | |
53 def __eq__(self, other): | |
54 return super(NodeListBase, self).__eq__(other) and \ | |
55 self.items == other.items | |
56 | |
57 # Implement this so that on failure, we get slightly more sensible output. | |
58 def __repr__(self): | |
59 return self.__class__.__name__ + "([" + \ | |
60 ", ".join([repr(elem) for elem in self.items]) + "])" | |
61 | |
62 def Insert(self, item): | |
63 """Inserts item at the front of the list.""" | |
64 | |
65 assert isinstance(item, self._list_item_type) | |
66 self.items.insert(0, item) | |
67 self._UpdateFilenameAndLineno() | |
68 | |
69 def Append(self, item): | |
70 """Appends item to the end of the list.""" | |
71 | |
72 assert isinstance(item, self._list_item_type) | |
73 self.items.append(item) | |
74 self._UpdateFilenameAndLineno() | |
75 | |
76 def _UpdateFilenameAndLineno(self): | |
77 if self.items: | |
78 self.filename = self.items[0].filename | |
79 self.lineno = self.items[0].lineno | |
80 | |
81 | |
82 class Definition(NodeBase): | |
83 """Represents a definition of anything that has a global name (e.g., enums, | |
84 enum values, consts, structs, struct fields, interfaces). (This does not | |
85 include parameter definitions.) This class is meant to be subclassed.""" | |
86 | |
87 def __init__(self, name, **kwargs): | |
88 assert isinstance(name, str) | |
89 NodeBase.__init__(self, **kwargs) | |
90 self.name = name | |
91 | |
92 | |
93 ################################################################################ | |
94 | |
95 | |
96 class Attribute(NodeBase): | |
97 """Represents an attribute.""" | |
98 | |
99 def __init__(self, key, value, **kwargs): | |
100 assert isinstance(key, str) | |
101 super(Attribute, self).__init__(**kwargs) | |
102 self.key = key | |
103 self.value = value | |
104 | |
105 def __eq__(self, other): | |
106 return super(Attribute, self).__eq__(other) and \ | |
107 self.key == other.key and \ | |
108 self.value == other.value | |
109 | |
110 | |
111 class AttributeList(NodeListBase): | |
112 """Represents a list attributes.""" | |
113 | |
114 _list_item_type = Attribute | |
115 | |
116 | |
117 class Const(Definition): | |
118 """Represents a const definition.""" | |
119 | |
120 def __init__(self, name, typename, value, **kwargs): | |
121 # The typename is currently passed through as a string. | |
122 assert isinstance(typename, str) | |
123 # The value is either a literal (currently passed through as a string) or a | |
124 # "wrapped identifier". | |
125 assert isinstance(value, str) or isinstance(value, tuple) | |
126 super(Const, self).__init__(name, **kwargs) | |
127 self.typename = typename | |
128 self.value = value | |
129 | |
130 def __eq__(self, other): | |
131 return super(Const, self).__eq__(other) and \ | |
132 self.typename == other.typename and \ | |
133 self.value == other.value | |
134 | |
135 | |
136 class Enum(Definition): | |
137 """Represents an enum definition.""" | |
138 | |
139 def __init__(self, name, enum_value_list, **kwargs): | |
140 assert isinstance(enum_value_list, EnumValueList) | |
141 super(Enum, self).__init__(name, **kwargs) | |
142 self.enum_value_list = enum_value_list | |
143 | |
144 def __eq__(self, other): | |
145 return super(Enum, self).__eq__(other) and \ | |
146 self.enum_value_list == other.enum_value_list | |
147 | |
148 | |
149 class EnumValue(Definition): | |
150 """Represents a definition of an enum value.""" | |
151 | |
152 def __init__(self, name, value, **kwargs): | |
153 # The optional value is either an int (which is current a string) or a | |
154 # "wrapped identifier". | |
155 assert value is None or isinstance(value, (str, tuple)) | |
156 super(EnumValue, self).__init__(name, **kwargs) | |
157 self.value = value | |
158 | |
159 def __eq__(self, other): | |
160 return super(EnumValue, self).__eq__(other) and \ | |
161 self.value == other.value | |
162 | |
163 | |
164 class EnumValueList(NodeListBase): | |
165 """Represents a list of enum value definitions (i.e., the "body" of an enum | |
166 definition).""" | |
167 | |
168 _list_item_type = EnumValue | |
169 | |
170 | |
171 class Import(NodeBase): | |
172 """Represents an import statement.""" | |
173 | |
174 def __init__(self, import_filename, **kwargs): | |
175 assert isinstance(import_filename, str) | |
176 super(Import, self).__init__(**kwargs) | |
177 self.import_filename = import_filename | |
178 | |
179 def __eq__(self, other): | |
180 return super(Import, self).__eq__(other) and \ | |
181 self.import_filename == other.import_filename | |
182 | |
183 | |
184 class ImportList(NodeListBase): | |
185 """Represents a list (i.e., sequence) of import statements.""" | |
186 | |
187 _list_item_type = Import | |
188 | |
189 | |
190 class Interface(Definition): | |
191 """Represents an interface definition.""" | |
192 | |
193 def __init__(self, name, attribute_list, body, **kwargs): | |
194 assert attribute_list is None or isinstance(attribute_list, AttributeList) | |
195 assert isinstance(body, InterfaceBody) | |
196 super(Interface, self).__init__(name, **kwargs) | |
197 self.attribute_list = attribute_list | |
198 self.body = body | |
199 | |
200 def __eq__(self, other): | |
201 return super(Interface, self).__eq__(other) and \ | |
202 self.attribute_list == other.attribute_list and \ | |
203 self.body == other.body | |
204 | |
205 | |
206 class Method(Definition): | |
207 """Represents a method definition.""" | |
208 | |
209 def __init__(self, name, ordinal, parameter_list, response_parameter_list, | |
210 **kwargs): | |
211 assert ordinal is None or isinstance(ordinal, Ordinal) | |
212 assert isinstance(parameter_list, ParameterList) | |
213 assert response_parameter_list is None or \ | |
214 isinstance(response_parameter_list, ParameterList) | |
215 super(Method, self).__init__(name, **kwargs) | |
216 self.ordinal = ordinal | |
217 self.parameter_list = parameter_list | |
218 self.response_parameter_list = response_parameter_list | |
219 | |
220 def __eq__(self, other): | |
221 return super(Method, self).__eq__(other) and \ | |
222 self.ordinal == other.ordinal and \ | |
223 self.parameter_list == other.parameter_list and \ | |
224 self.response_parameter_list == other.response_parameter_list | |
225 | |
226 | |
227 # This needs to be declared after |Method|. | |
228 class InterfaceBody(NodeListBase): | |
229 """Represents the body of (i.e., list of definitions inside) an interface.""" | |
230 | |
231 _list_item_type = (Const, Enum, Method) | |
232 | |
233 | |
234 class Module(NodeBase): | |
235 """Represents a module statement.""" | |
236 | |
237 def __init__(self, name, attribute_list, **kwargs): | |
238 # |name| is either none or a "wrapped identifier". | |
239 assert name is None or isinstance(name, tuple) | |
240 assert attribute_list is None or isinstance(attribute_list, AttributeList) | |
241 super(Module, self).__init__(**kwargs) | |
242 self.name = name | |
243 self.attribute_list = attribute_list | |
244 | |
245 def __eq__(self, other): | |
246 return super(Module, self).__eq__(other) and \ | |
247 self.name == other.name and \ | |
248 self.attribute_list == other.attribute_list | |
249 | |
250 | |
251 class Mojom(NodeBase): | |
252 """Represents an entire .mojom file. (This is the root node.)""" | |
253 | |
254 def __init__(self, module, import_list, definition_list, **kwargs): | |
255 assert module is None or isinstance(module, Module) | |
256 assert isinstance(import_list, ImportList) | |
257 assert isinstance(definition_list, list) | |
258 super(Mojom, self).__init__(**kwargs) | |
259 self.module = module | |
260 self.import_list = import_list | |
261 self.definition_list = definition_list | |
262 | |
263 def __eq__(self, other): | |
264 return super(Mojom, self).__eq__(other) and \ | |
265 self.module == other.module and \ | |
266 self.import_list == other.import_list and \ | |
267 self.definition_list == other.definition_list | |
268 | |
269 def __repr__(self): | |
270 return "%s(%r, %r, %r)" % (self.__class__.__name__, self.module, | |
271 self.import_list, self.definition_list) | |
272 | |
273 | |
274 class Ordinal(NodeBase): | |
275 """Represents an ordinal value labeling, e.g., a struct field.""" | |
276 | |
277 def __init__(self, value, **kwargs): | |
278 assert isinstance(value, int) | |
279 super(Ordinal, self).__init__(**kwargs) | |
280 self.value = value | |
281 | |
282 def __eq__(self, other): | |
283 return super(Ordinal, self).__eq__(other) and \ | |
284 self.value == other.value | |
285 | |
286 | |
287 class Parameter(NodeBase): | |
288 """Represents a method request or response parameter.""" | |
289 | |
290 def __init__(self, name, ordinal, typename, **kwargs): | |
291 assert isinstance(name, str) | |
292 assert ordinal is None or isinstance(ordinal, Ordinal) | |
293 assert isinstance(typename, str) | |
294 super(Parameter, self).__init__(**kwargs) | |
295 self.name = name | |
296 self.ordinal = ordinal | |
297 self.typename = typename | |
298 | |
299 def __eq__(self, other): | |
300 return super(Parameter, self).__eq__(other) and \ | |
301 self.name == other.name and \ | |
302 self.ordinal == other.ordinal and \ | |
303 self.typename == other.typename | |
304 | |
305 | |
306 class ParameterList(NodeListBase): | |
307 """Represents a list of (method request or response) parameters.""" | |
308 | |
309 _list_item_type = Parameter | |
310 | |
311 | |
312 class Struct(Definition): | |
313 """Represents a struct definition.""" | |
314 | |
315 def __init__(self, name, attribute_list, body, **kwargs): | |
316 assert attribute_list is None or isinstance(attribute_list, AttributeList) | |
317 assert isinstance(body, StructBody) | |
318 super(Struct, self).__init__(name, **kwargs) | |
319 self.attribute_list = attribute_list | |
320 self.body = body | |
321 | |
322 def __eq__(self, other): | |
323 return super(Struct, self).__eq__(other) and \ | |
324 self.attribute_list == other.attribute_list and \ | |
325 self.body == other.body | |
326 | |
327 | |
328 class StructField(Definition): | |
329 """Represents a struct field definition.""" | |
330 | |
331 def __init__(self, name, ordinal, typename, default_value, **kwargs): | |
332 assert isinstance(name, str) | |
333 assert ordinal is None or isinstance(ordinal, Ordinal) | |
334 assert isinstance(typename, str) | |
335 # The optional default value is currently either a value as a string or a | |
336 # "wrapped identifier". | |
337 assert default_value is None or isinstance(default_value, (str, tuple)) | |
338 super(StructField, self).__init__(name, **kwargs) | |
339 self.ordinal = ordinal | |
340 self.typename = typename | |
341 self.default_value = default_value | |
342 | |
343 def __eq__(self, other): | |
344 return super(StructField, self).__eq__(other) and \ | |
345 self.ordinal == other.ordinal and \ | |
346 self.typename == other.typename and \ | |
347 self.default_value == other.default_value | |
348 | |
349 | |
350 # This needs to be declared after |StructField|. | |
351 class StructBody(NodeListBase): | |
352 """Represents the body of (i.e., list of definitions inside) a struct.""" | |
353 | |
354 _list_item_type = (Const, Enum, StructField) | |
355 | |
356 | |
357 class Union(Definition): | |
358 """Represents a union definition.""" | |
359 | |
360 def __init__(self, name, body, **kwargs): | |
361 assert isinstance(body, UnionBody) | |
362 super(Union, self).__init__(name, **kwargs) | |
363 self.body = body | |
364 | |
365 def __eq__(self, other): | |
366 return super(Union, self).__eq__(other) and \ | |
367 self.body == other.body | |
368 | |
369 | |
370 class UnionField(Definition): | |
371 | |
372 def __init__(self, name, ordinal, typename, **kwargs): | |
373 assert isinstance(name, str) | |
374 assert ordinal is None or isinstance(ordinal, Ordinal) | |
375 assert isinstance(typename, str) | |
376 super(UnionField, self).__init__(name, **kwargs) | |
377 self.ordinal = ordinal | |
378 self.typename = typename | |
379 | |
380 def __eq__(self, other): | |
381 return super(UnionField, self).__eq__(other) and \ | |
382 self.ordinal == other.ordinal and \ | |
383 self.typename == other.typename | |
384 | |
385 | |
386 class UnionBody(NodeListBase): | |
387 | |
388 _list_item_type = UnionField | |
OLD | NEW |