| 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 |