Chromium Code Reviews| 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 |