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 objects for the AST for a Mojo IDL file.""" | 5 """Node objects 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). | 9 # and lineno). |
10 | 10 |
11 | 11 |
12 class BaseNode(object): | 12 class NodeBase(object): |
13 """Base class for nodes in the AST.""" | 13 """Base class for nodes in the AST.""" |
14 | 14 |
15 def __init__(self, filename=None, lineno=None): | 15 def __init__(self, filename=None, lineno=None): |
16 self.filename = filename | 16 self.filename = filename |
17 self.lineno = lineno | 17 self.lineno = lineno |
18 | 18 |
19 | 19 |
20 class Ordinal(BaseNode): | 20 class Ordinal(NodeBase): |
21 """Represents an ordinal value labeling, e.g., a struct field.""" | 21 """Represents an ordinal value labeling, e.g., a struct field.""" |
22 | 22 |
23 def __init__(self, value, **kwargs): | 23 def __init__(self, value, **kwargs): |
24 BaseNode.__init__(self, **kwargs) | 24 NodeBase.__init__(self, **kwargs) |
25 self.value = value | 25 self.value = value |
26 | 26 |
27 def __eq__(self, other): | 27 def __eq__(self, other): |
28 return self.value == other.value | 28 return self.value == other.value |
29 | 29 |
30 | 30 |
31 class Parameter(BaseNode): | 31 class Parameter(NodeBase): |
32 """Represents a method request or response parameter.""" | 32 """Represents a method request or response parameter.""" |
33 | 33 |
34 def __init__(self, typename, name, ordinal, **kwargs): | 34 def __init__(self, typename, name, ordinal, **kwargs): |
35 assert isinstance(ordinal, Ordinal) | 35 assert isinstance(ordinal, Ordinal) |
36 BaseNode.__init__(self, **kwargs) | 36 NodeBase.__init__(self, **kwargs) |
37 self.typename = typename | 37 self.typename = typename |
38 self.name = name | 38 self.name = name |
39 self.ordinal = ordinal | 39 self.ordinal = ordinal |
40 | 40 |
41 def __eq__(self, other): | 41 def __eq__(self, other): |
42 return self.typename == other.typename and \ | 42 return self.typename == other.typename and \ |
43 self.name == other.name and \ | 43 self.name == other.name and \ |
44 self.ordinal == other.ordinal | 44 self.ordinal == other.ordinal |
| 45 |
| 46 |
| 47 class NodeListBase(NodeBase): |
| 48 """Represents a list of other nodes, all having the same type. (This is meant |
| 49 to be subclassed, with subclasses defining _list_item_type to be the class of |
| 50 the members of the list; _list_item_type should also be a NodeBase.)""" |
| 51 |
| 52 def __init__(self, item_or_items=None, **kwargs): |
| 53 assert issubclass(self._list_item_type, NodeBase) |
| 54 NodeBase.__init__(self, **kwargs) |
| 55 if item_or_items is None: |
| 56 self.elements = [] |
| 57 elif isinstance(item_or_items, list): |
| 58 # TODO(vtl): Possibly we should assert that each element of the list is a |
| 59 # |_list_item_type|. |
| 60 self.elements = list(item_or_items) |
| 61 else: |
| 62 assert isinstance(item_or_items, self._list_item_type) |
| 63 self.elements = [item_or_items] |
| 64 self._UpdateFilenameAndLineno() |
| 65 |
| 66 # Support iteration. For everything else, users should just access |elements| |
| 67 # directly. (We intentionally do NOT supply |__len__()| or |__nonzero__()|, so |
| 68 # |bool(NodeListBase())| is true.) |
| 69 def __iter__(self): |
| 70 return self.elements.__iter__() |
| 71 |
| 72 def __eq__(self, other): |
| 73 if type(self) != type(other): |
| 74 return False |
| 75 for element in self.elements: |
| 76 if self.elements != other.elements: |
| 77 return False |
| 78 return True |
| 79 |
| 80 def Append(self, item): |
| 81 assert isinstance(item, self._list_item_type) |
| 82 self.elements.append(item) |
| 83 self._UpdateFilenameAndLineno() |
| 84 |
| 85 def _UpdateFilenameAndLineno(self): |
| 86 if self.elements: |
| 87 self.filename = self.elements[0].filename |
| 88 self.lineno = self.elements[0].lineno |
| 89 |
| 90 |
| 91 class ParameterList(NodeListBase): |
| 92 """Represents a list of (method request or response) parameters.""" |
| 93 |
| 94 _list_item_type = Parameter |
OLD | NEW |