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): |
| 21 return type(self) == type(other) |
| 22 |
20 | 23 |
21 # 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. |
22 class NodeListBase(NodeBase): | 25 class NodeListBase(NodeBase): |
23 """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 |
24 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 of |
25 the members of the list; _list_item_type should also be a NodeBase.)""" | 28 the members of the list; _list_item_type should also be a NodeBase.)""" |
26 | 29 |
27 def __init__(self, item_or_items=None, **kwargs): | 30 def __init__(self, item_or_items=None, **kwargs): |
28 assert issubclass(self._list_item_type, NodeBase) | 31 assert issubclass(self._list_item_type, NodeBase) |
29 NodeBase.__init__(self, **kwargs) | 32 super(NodeListBase, self).__init__(**kwargs) |
30 if item_or_items is None: | 33 if item_or_items is None: |
31 self.elements = [] | 34 self.elements = [] |
32 elif isinstance(item_or_items, list): | 35 elif isinstance(item_or_items, list): |
33 # TODO(vtl): Possibly we should assert that each element of the list is a | 36 # TODO(vtl): Possibly we should assert that each element of the list is a |
34 # |_list_item_type|. | 37 # |_list_item_type|. |
35 self.elements = list(item_or_items) | 38 self.elements = list(item_or_items) |
36 else: | 39 else: |
37 assert isinstance(item_or_items, self._list_item_type) | 40 assert isinstance(item_or_items, self._list_item_type) |
38 self.elements = [item_or_items] | 41 self.elements = [item_or_items] |
39 self._UpdateFilenameAndLineno() | 42 self._UpdateFilenameAndLineno() |
40 | 43 |
41 # Support iteration. For everything else, users should just access |elements| | 44 # Support iteration. For everything else, users should just access |elements| |
42 # directly. (We intentionally do NOT supply |__len__()| or |__nonzero__()|, so | 45 # directly. (We intentionally do NOT supply |__len__()| or |__nonzero__()|, so |
43 # |bool(NodeListBase())| is true.) | 46 # |bool(NodeListBase())| is true.) |
44 def __iter__(self): | 47 def __iter__(self): |
45 return self.elements.__iter__() | 48 return self.elements.__iter__() |
46 | 49 |
47 def __eq__(self, other): | 50 def __eq__(self, other): |
48 return type(self) == type(other) and \ | 51 return super(NodeListBase, self).__eq__(other) and \ |
49 len(self.elements) == len(other.elements) and \ | 52 len(self.elements) == len(other.elements) and \ |
50 all(self.elements[i] == other.elements[i] \ | 53 all(self.elements[i] == other.elements[i] \ |
51 for i in xrange(len(self.elements))) | 54 for i in xrange(len(self.elements))) |
52 | 55 |
53 # Implement this so that on failure, we get slightly more sensible output. | 56 # Implement this so that on failure, we get slightly more sensible output. |
54 def __repr__(self): | 57 def __repr__(self): |
55 return self.__class__.__name__ + "([" + \ | 58 return self.__class__.__name__ + "([" + \ |
56 ", ".join([repr(elem) for elem in self.elements]) + "])" | 59 ", ".join([repr(elem) for elem in self.elements]) + "])" |
57 | 60 |
58 def Append(self, item): | 61 def Append(self, item): |
59 assert isinstance(item, self._list_item_type) | 62 assert isinstance(item, self._list_item_type) |
60 self.elements.append(item) | 63 self.elements.append(item) |
61 self._UpdateFilenameAndLineno() | 64 self._UpdateFilenameAndLineno() |
62 | 65 |
63 def _UpdateFilenameAndLineno(self): | 66 def _UpdateFilenameAndLineno(self): |
64 if self.elements: | 67 if self.elements: |
65 self.filename = self.elements[0].filename | 68 self.filename = self.elements[0].filename |
66 self.lineno = self.elements[0].lineno | 69 self.lineno = self.elements[0].lineno |
67 | 70 |
68 | 71 |
69 ################################################################################ | 72 ################################################################################ |
70 | 73 |
71 | 74 |
72 class Attribute(NodeBase): | 75 class Attribute(NodeBase): |
73 """Represents an attribute.""" | 76 """Represents an attribute.""" |
74 | 77 |
75 def __init__(self, key, value, **kwargs): | 78 def __init__(self, key, value, **kwargs): |
76 assert isinstance(key, str) | 79 assert isinstance(key, str) |
77 NodeBase.__init__(self, **kwargs) | 80 super(Attribute, self).__init__(**kwargs) |
78 self.key = key | 81 self.key = key |
79 self.value = value | 82 self.value = value |
80 | 83 |
81 def __eq__(self, other): | 84 def __eq__(self, other): |
82 return type(self) == type(other) and \ | 85 return super(Attribute, self).__eq__(other) and \ |
83 self.key == other.key and \ | 86 self.key == other.key and \ |
84 self.value == other.value | 87 self.value == other.value |
85 | 88 |
86 | 89 |
87 class AttributeList(NodeListBase): | 90 class AttributeList(NodeListBase): |
88 """Represents a list attributes.""" | 91 """Represents a list attributes.""" |
89 | 92 |
90 _list_item_type = Attribute | 93 _list_item_type = Attribute |
91 | 94 |
92 | 95 |
93 class EnumValue(NodeBase): | 96 class EnumValue(NodeBase): |
94 """Represents a definition of an enum value.""" | 97 """Represents a definition of an enum value.""" |
95 | 98 |
96 def __init__(self, name, value, **kwargs): | 99 def __init__(self, name, value, **kwargs): |
97 assert isinstance(name, str) | 100 assert isinstance(name, str) |
98 # The optional value is either an int (which is current a string) or a | 101 # The optional value is either an int (which is current a string) or a |
99 # "wrapped identifier". | 102 # "wrapped identifier". |
100 assert value is None or isinstance(value, str) or isinstance(value, tuple) | 103 assert value is None or isinstance(value, str) or isinstance(value, tuple) |
101 NodeBase.__init__(self, **kwargs) | 104 super(EnumValue, self).__init__(**kwargs) |
102 self.name = name | 105 self.name = name |
103 self.value = value | 106 self.value = value |
104 | 107 |
105 def __eq__(self, other): | 108 def __eq__(self, other): |
106 return type(self) == type(other) and \ | 109 return super(EnumValue, self).__eq__(other) and \ |
107 self.name == other.name and \ | 110 self.name == other.name and \ |
108 self.value == other.value | 111 self.value == other.value |
109 | 112 |
110 | 113 |
111 class EnumValueList(NodeListBase): | 114 class EnumValueList(NodeListBase): |
112 """Represents a list of enum value definitions (i.e., the "body" of an enum | 115 """Represents a list of enum value definitions (i.e., the "body" of an enum |
113 definition).""" | 116 definition).""" |
114 | 117 |
115 _list_item_type = EnumValue | 118 _list_item_type = EnumValue |
116 | 119 |
117 | 120 |
118 class Import(NodeBase): | 121 class Import(NodeBase): |
119 """Represents an import statement.""" | 122 """Represents an import statement.""" |
120 | 123 |
121 def __init__(self, import_filename, **kwargs): | 124 def __init__(self, import_filename, **kwargs): |
122 assert isinstance(import_filename, str) | 125 assert isinstance(import_filename, str) |
123 NodeBase.__init__(self, **kwargs) | 126 super(Import, self).__init__(**kwargs) |
124 self.import_filename = import_filename | 127 self.import_filename = import_filename |
125 | 128 |
126 def __eq__(self, other): | 129 def __eq__(self, other): |
127 return type(self) == type(other) and \ | 130 return super(Import, self).__eq__(other) and \ |
128 self.import_filename == other.import_filename | 131 self.import_filename == other.import_filename |
129 | 132 |
130 | 133 |
131 class ImportList(NodeListBase): | 134 class ImportList(NodeListBase): |
132 """Represents a list (i.e., sequence) of import statements.""" | 135 """Represents a list (i.e., sequence) of import statements.""" |
133 | 136 |
134 _list_item_type = Import | 137 _list_item_type = Import |
135 | 138 |
136 | 139 |
137 class Module(NodeBase): | 140 class Module(NodeBase): |
138 """Represents a module statement.""" | 141 """Represents a module statement.""" |
139 | 142 |
140 def __init__(self, name, attribute_list, **kwargs): | 143 def __init__(self, name, attribute_list, **kwargs): |
141 # |name| is either none or a "wrapped identifier". | 144 # |name| is either none or a "wrapped identifier". |
142 assert name is None or isinstance(name, tuple) | 145 assert name is None or isinstance(name, tuple) |
143 assert attribute_list is None or isinstance(attribute_list, AttributeList) | 146 assert attribute_list is None or isinstance(attribute_list, AttributeList) |
144 NodeBase.__init__(self, **kwargs) | 147 super(Module, self).__init__(**kwargs) |
145 self.name = name | 148 self.name = name |
146 self.attribute_list = attribute_list | 149 self.attribute_list = attribute_list |
147 | 150 |
148 def __eq__(self, other): | 151 def __eq__(self, other): |
149 return type(self) == type(other) and \ | 152 return super(Module, self).__eq__(other) and \ |
150 self.name == other.name and \ | 153 self.name == other.name and \ |
151 self.attribute_list == other.attribute_list | 154 self.attribute_list == other.attribute_list |
152 | 155 |
153 | 156 |
154 class Mojom(NodeBase): | 157 class Mojom(NodeBase): |
155 """Represents an entire .mojom file. (This is the root node.""" | 158 """Represents an entire .mojom file. (This is the root node.""" |
156 | 159 |
157 def __init__(self, module, import_list, definition_list, **kwargs): | 160 def __init__(self, module, import_list, definition_list, **kwargs): |
158 assert module is None or isinstance(module, Module) | 161 assert module is None or isinstance(module, Module) |
159 assert isinstance(import_list, ImportList) | 162 assert isinstance(import_list, ImportList) |
160 assert isinstance(definition_list, list) | 163 assert isinstance(definition_list, list) |
161 NodeBase.__init__(self, **kwargs) | 164 super(Mojom, self).__init__(**kwargs) |
162 self.module = module | 165 self.module = module |
163 self.import_list = import_list | 166 self.import_list = import_list |
164 self.definition_list = definition_list | 167 self.definition_list = definition_list |
165 | 168 |
166 def __eq__(self, other): | 169 def __eq__(self, other): |
167 return type(self) == type(other) and \ | 170 return super(Mojom, self).__eq__(other) and \ |
168 self.module == other.module and \ | 171 self.module == other.module and \ |
169 self.import_list == other.import_list and \ | 172 self.import_list == other.import_list and \ |
170 self.definition_list == other.definition_list | 173 self.definition_list == other.definition_list |
171 | 174 |
172 def __repr__(self): | 175 def __repr__(self): |
173 return "%s(%r, %r, %r)" % (self.__class__.__name__, self.module, | 176 return "%s(%r, %r, %r)" % (self.__class__.__name__, self.module, |
174 self.import_list, self.definition_list) | 177 self.import_list, self.definition_list) |
175 | 178 |
176 | 179 |
177 class Ordinal(NodeBase): | 180 class Ordinal(NodeBase): |
178 """Represents an ordinal value labeling, e.g., a struct field.""" | 181 """Represents an ordinal value labeling, e.g., a struct field.""" |
179 | 182 |
180 def __init__(self, value, **kwargs): | 183 def __init__(self, value, **kwargs): |
181 assert value is None or isinstance(value, int) | 184 assert value is None or isinstance(value, int) |
182 NodeBase.__init__(self, **kwargs) | 185 super(Ordinal, self).__init__(**kwargs) |
183 self.value = value | 186 self.value = value |
184 | 187 |
185 def __eq__(self, other): | 188 def __eq__(self, other): |
186 return type(self) == type(other) and self.value == other.value | 189 return super(Ordinal, self).__eq__(other) and \ |
| 190 self.value == other.value |
187 | 191 |
188 | 192 |
189 class Parameter(NodeBase): | 193 class Parameter(NodeBase): |
190 """Represents a method request or response parameter.""" | 194 """Represents a method request or response parameter.""" |
191 | 195 |
192 def __init__(self, typename, name, ordinal, **kwargs): | 196 def __init__(self, typename, name, ordinal, **kwargs): |
193 assert isinstance(ordinal, Ordinal) | 197 assert isinstance(ordinal, Ordinal) |
194 NodeBase.__init__(self, **kwargs) | 198 super(Parameter, self).__init__(**kwargs) |
195 self.typename = typename | 199 self.typename = typename |
196 self.name = name | 200 self.name = name |
197 self.ordinal = ordinal | 201 self.ordinal = ordinal |
198 | 202 |
199 def __eq__(self, other): | 203 def __eq__(self, other): |
200 return type(self) == type(other) and \ | 204 return super(Parameter, self).__eq__(other) and \ |
201 self.typename == other.typename and \ | 205 self.typename == other.typename and \ |
202 self.name == other.name and \ | 206 self.name == other.name and \ |
203 self.ordinal == other.ordinal | 207 self.ordinal == other.ordinal |
204 | 208 |
205 | 209 |
206 class ParameterList(NodeListBase): | 210 class ParameterList(NodeListBase): |
207 """Represents a list of (method request or response) parameters.""" | 211 """Represents a list of (method request or response) parameters.""" |
208 | 212 |
209 _list_item_type = Parameter | 213 _list_item_type = Parameter |
OLD | NEW |