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 | 4 |
5 """Node classes for the AST for a Mojo IDL file.""" | 5 """Node classes for the AST for a Mojo IDL file.""" |
6 | 6 |
7 # Note: For convenience of testing, you probably want to define __eq__() methods | 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 | 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 | 9 # and lineno). You may also define __repr__() to help with analyzing test |
10 # failures, especially for more complex types. | 10 # failures, especially for more complex types. |
11 | 11 |
12 | 12 |
13 class NodeBase(object): | 13 class NodeBase(object): |
14 """Base class for nodes in the AST.""" | 14 """Base class for nodes in the AST.""" |
15 | 15 |
16 def __init__(self, filename=None, lineno=None): | 16 def __init__(self, filename=None, lineno=None): |
17 self.filename = filename | 17 self.filename = filename |
18 self.lineno = lineno | 18 self.lineno = lineno |
19 | 19 |
20 def __eq__(self, other): | 20 def __eq__(self, other): |
21 return type(self) == type(other) | 21 return type(self) == type(other) |
22 | 22 |
23 | 23 |
24 # TODO(vtl): Some of this is complicated enough that it should be tested. | 24 # TODO(vtl): Some of this is complicated enough that it should be tested. |
25 class NodeListBase(NodeBase): | 25 class NodeListBase(NodeBase): |
26 """Represents a list of other nodes, all having the same type. (This is meant | 26 """Represents a list of other nodes, all having the same type. (This is meant |
27 to be subclassed, with subclasses defining _list_item_type to be the class of | 27 to be subclassed, with subclasses defining _list_item_type to be the class (or |
28 the members of the list; _list_item_type should also be a NodeBase.)""" | 28 classes, in a tuple) of the members of the list.)""" |
29 | 29 |
30 def __init__(self, item_or_items=None, **kwargs): | 30 def __init__(self, item_or_items=None, **kwargs): |
31 assert issubclass(self._list_item_type, NodeBase) | |
32 super(NodeListBase, self).__init__(**kwargs) | 31 super(NodeListBase, self).__init__(**kwargs) |
32 self.items = [] | |
33 if item_or_items is None: | 33 if item_or_items is None: |
34 self.elements = [] | 34 pass |
DaveMoore
2014/07/16 18:07:08
Nit: isn't this a noop?
viettrungluu
2014/07/16 18:17:59
Oops. Let me fix that separately, so that I don't
| |
35 self.items = [] | |
35 elif isinstance(item_or_items, list): | 36 elif isinstance(item_or_items, list): |
36 # TODO(vtl): Possibly we should assert that each element of the list is a | 37 for item in item_or_items: |
37 # |_list_item_type|. | 38 assert isinstance(item, self._list_item_type) |
38 self.elements = list(item_or_items) | 39 self.Append(item) |
39 else: | 40 else: |
40 assert isinstance(item_or_items, self._list_item_type) | 41 assert isinstance(item_or_items, self._list_item_type) |
41 self.elements = [item_or_items] | 42 self.Append(item_or_items) |
42 self._UpdateFilenameAndLineno() | |
43 | 43 |
44 # Support iteration. For everything else, users should just access |elements| | 44 # Support iteration. For everything else, users should just access |items| |
45 # directly. (We intentionally do NOT supply |__len__()| or |__nonzero__()|, so | 45 # directly. (We intentionally do NOT supply |__len__()| or |__nonzero__()|, so |
46 # |bool(NodeListBase())| is true.) | 46 # |bool(NodeListBase())| is true.) |
47 def __iter__(self): | 47 def __iter__(self): |
48 return self.elements.__iter__() | 48 return self.items.__iter__() |
49 | 49 |
50 def __eq__(self, other): | 50 def __eq__(self, other): |
51 return super(NodeListBase, self).__eq__(other) and \ | 51 return super(NodeListBase, self).__eq__(other) and \ |
52 len(self.elements) == len(other.elements) and \ | 52 len(self.items) == len(other.items) and \ |
53 all(self.elements[i] == other.elements[i] \ | 53 all(self.items[i] == other.items[i] for i in xrange(len(self.items))) |
54 for i in xrange(len(self.elements))) | |
55 | 54 |
56 # Implement this so that on failure, we get slightly more sensible output. | 55 # Implement this so that on failure, we get slightly more sensible output. |
57 def __repr__(self): | 56 def __repr__(self): |
58 return self.__class__.__name__ + "([" + \ | 57 return self.__class__.__name__ + "([" + \ |
59 ", ".join([repr(elem) for elem in self.elements]) + "])" | 58 ", ".join([repr(elem) for elem in self.items]) + "])" |
59 | |
60 def Insert(self, item): | |
61 """Inserts item at the front of the list.""" | |
62 | |
63 assert isinstance(item, self._list_item_type) | |
64 self.items.insert(0, item) | |
65 self._UpdateFilenameAndLineno() | |
60 | 66 |
61 def Append(self, item): | 67 def Append(self, item): |
68 """Appends item to the end of the list.""" | |
69 | |
62 assert isinstance(item, self._list_item_type) | 70 assert isinstance(item, self._list_item_type) |
63 self.elements.append(item) | 71 self.items.append(item) |
64 self._UpdateFilenameAndLineno() | 72 self._UpdateFilenameAndLineno() |
65 | 73 |
66 def _UpdateFilenameAndLineno(self): | 74 def _UpdateFilenameAndLineno(self): |
67 if self.elements: | 75 if self.items: |
68 self.filename = self.elements[0].filename | 76 self.filename = self.items[0].filename |
69 self.lineno = self.elements[0].lineno | 77 self.lineno = self.items[0].lineno |
70 | 78 |
71 | 79 |
72 class Definition(NodeBase): | 80 class Definition(NodeBase): |
73 """Represents a definition of anything that has a global name (e.g., enums, | 81 """Represents a definition of anything that has a global name (e.g., enums, |
74 enum values, consts, structs, struct fields, interfaces). (This does not | 82 enum values, consts, structs, struct fields, interfaces). (This does not |
75 include parameter definitions.) This class is meant to be subclassed.""" | 83 include parameter definitions.) This class is meant to be subclassed.""" |
76 | 84 |
77 def __init__(self, name, **kwargs): | 85 def __init__(self, name, **kwargs): |
78 assert isinstance(name, str) | 86 assert isinstance(name, str) |
79 NodeBase.__init__(self, **kwargs) | 87 NodeBase.__init__(self, **kwargs) |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
248 self.ordinal == other.ordinal and \ | 256 self.ordinal == other.ordinal and \ |
249 self.typename == other.typename | 257 self.typename == other.typename |
250 | 258 |
251 | 259 |
252 class ParameterList(NodeListBase): | 260 class ParameterList(NodeListBase): |
253 """Represents a list of (method request or response) parameters.""" | 261 """Represents a list of (method request or response) parameters.""" |
254 | 262 |
255 _list_item_type = Parameter | 263 _list_item_type = Parameter |
256 | 264 |
257 | 265 |
266 class Struct(Definition): | |
267 """Represents a struct definition.""" | |
268 | |
269 def __init__(self, name, attribute_list, body, **kwargs): | |
270 assert attribute_list is None or isinstance(attribute_list, AttributeList) | |
271 assert isinstance(body, StructBody) | |
272 super(Struct, self).__init__(name, **kwargs) | |
273 self.attribute_list = attribute_list | |
274 self.body = body | |
275 | |
276 def __eq__(self, other): | |
277 return super(Struct, self).__eq__(other) and \ | |
278 self.attribute_list == other.attribute_list and \ | |
279 self.body == other.body | |
280 | |
281 | |
258 class StructField(Definition): | 282 class StructField(Definition): |
259 """Represents a struct field definition.""" | 283 """Represents a struct field definition.""" |
260 | 284 |
261 def __init__(self, name, ordinal, typename, default_value, **kwargs): | 285 def __init__(self, name, ordinal, typename, default_value, **kwargs): |
262 assert isinstance(name, str) | 286 assert isinstance(name, str) |
263 assert ordinal is None or isinstance(ordinal, Ordinal) | 287 assert ordinal is None or isinstance(ordinal, Ordinal) |
264 assert isinstance(typename, str) | 288 assert isinstance(typename, str) |
265 # The optional default value is currently either a value as a string or a | 289 # The optional default value is currently either a value as a string or a |
266 # "wrapped identifier". | 290 # "wrapped identifier". |
267 assert default_value is None or isinstance(default_value, (str, tuple)) | 291 assert default_value is None or isinstance(default_value, (str, tuple)) |
268 super(StructField, self).__init__(name, **kwargs) | 292 super(StructField, self).__init__(name, **kwargs) |
269 self.ordinal = ordinal | 293 self.ordinal = ordinal |
270 self.typename = typename | 294 self.typename = typename |
271 self.default_value = default_value | 295 self.default_value = default_value |
272 | 296 |
273 def __eq__(self, other): | 297 def __eq__(self, other): |
274 return super(StructField, self).__eq__(other) and \ | 298 return super(StructField, self).__eq__(other) and \ |
275 self.ordinal == other.ordinal and \ | 299 self.ordinal == other.ordinal and \ |
276 self.typename == other.typename and \ | 300 self.typename == other.typename and \ |
277 self.default_value == other.default_value | 301 self.default_value == other.default_value |
302 | |
303 | |
304 # This needs to be declared after |StructField|. | |
305 class StructBody(NodeListBase): | |
306 """Represents the body of (i.e., list of definitions inside) a struct.""" | |
307 | |
308 _list_item_type = (Const, Enum, StructField) | |
OLD | NEW |