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