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 """Translates parse tree to Mojom IR.""" | 5 """Translates parse tree to Mojom IR.""" |
6 | 6 |
7 | 7 |
8 import re | 8 import re |
9 | 9 |
10 from . import ast | 10 from . import ast |
11 | 11 |
12 | 12 |
13 def _MapTreeForType(func, tree, type_to_map): | 13 def _MapTreeForType(func, tree, type_to_map): |
14 assert isinstance(type_to_map, type) | 14 assert isinstance(type_to_map, type) |
15 if not tree: | 15 if not tree: |
16 return [] | 16 return [] |
17 return [func(subtree) for subtree in tree if isinstance(subtree, type_to_map)] | 17 return [func(subtree) for subtree in tree if isinstance(subtree, type_to_map)] |
18 | 18 |
19 _FIXED_ARRAY_REGEXP = re.compile(r'\[[0-9]+\]') | 19 _FIXED_ARRAY_REGEXP = re.compile(r'\[[0-9]+\]') |
20 | 20 |
21 def _MapKind(kind): | 21 def MapKind(kind): |
viettrungluu
2014/10/08 16:21:56
Is there a reason you're making this non-private?
Elliot Glaysher
2014/10/08 18:20:51
Because pylint won't let me upload the patch if I
viettrungluu
2014/10/08 18:22:51
Probably you should just suppress that pylint warn
Elliot Glaysher
2014/10/08 19:24:46
Done.
| |
22 map_to_kind = {'bool': 'b', | 22 map_to_kind = {'bool': 'b', |
23 'int8': 'i8', | 23 'int8': 'i8', |
24 'int16': 'i16', | 24 'int16': 'i16', |
25 'int32': 'i32', | 25 'int32': 'i32', |
26 'int64': 'i64', | 26 'int64': 'i64', |
27 'uint8': 'u8', | 27 'uint8': 'u8', |
28 'uint16': 'u16', | 28 'uint16': 'u16', |
29 'uint32': 'u32', | 29 'uint32': 'u32', |
30 'uint64': 'u64', | 30 'uint64': 'u64', |
31 'float': 'f', | 31 'float': 'f', |
32 'double': 'd', | 32 'double': 'd', |
33 'string': 's', | 33 'string': 's', |
34 'handle': 'h', | 34 'handle': 'h', |
35 'handle<data_pipe_consumer>': 'h:d:c', | 35 'handle<data_pipe_consumer>': 'h:d:c', |
36 'handle<data_pipe_producer>': 'h:d:p', | 36 'handle<data_pipe_producer>': 'h:d:p', |
37 'handle<message_pipe>': 'h:m', | 37 'handle<message_pipe>': 'h:m', |
38 'handle<shared_buffer>': 'h:s'} | 38 'handle<shared_buffer>': 'h:s'} |
39 if kind.endswith('?'): | 39 if kind.endswith('?'): |
40 base_kind = _MapKind(kind[0:-1]) | 40 base_kind = MapKind(kind[0:-1]) |
41 # NOTE: This doesn't rule out enum types. Those will be detected later, when | 41 # NOTE: This doesn't rule out enum types. Those will be detected later, when |
42 # cross-reference is established. | 42 # cross-reference is established. |
43 reference_kinds = ('s', 'h', 'a', 'r', 'x') | 43 reference_kinds = ('m', 's', 'h', 'a', 'r', 'x') |
44 if base_kind[0] not in reference_kinds: | 44 if base_kind[0] not in reference_kinds: |
45 raise Exception( | 45 raise Exception( |
46 'A type (spec "%s") cannot be made nullable' % base_kind) | 46 'A type (spec "%s") cannot be made nullable' % base_kind) |
47 return '?' + base_kind | 47 return '?' + base_kind |
48 if kind.endswith('}'): | |
49 lbracket = kind.rfind('{') | |
50 value = kind[0:lbracket] | |
51 return 'm[' + MapKind(kind[lbracket+1:-1]) + '][' + MapKind(value) + ']' | |
48 if kind.endswith('[]'): | 52 if kind.endswith('[]'): |
49 typename = kind[0:-2] | 53 typename = kind[0:-2] |
50 if _FIXED_ARRAY_REGEXP.search(typename): | 54 if _FIXED_ARRAY_REGEXP.search(typename): |
51 raise Exception('Arrays of fixed sized arrays not supported') | 55 raise Exception('Arrays of fixed sized arrays not supported') |
52 return 'a:' + _MapKind(typename) | 56 return 'a:' + MapKind(typename) |
53 if kind.endswith(']'): | 57 if kind.endswith(']'): |
54 lbracket = kind.rfind('[') | 58 lbracket = kind.rfind('[') |
55 typename = kind[0:lbracket] | 59 typename = kind[0:lbracket] |
56 if typename.find('[') != -1: | 60 if typename.find('[') != -1: |
57 raise Exception('Fixed sized arrays of arrays not supported') | 61 raise Exception('Fixed sized arrays of arrays not supported') |
58 return 'a' + kind[lbracket+1:-1] + ':' + _MapKind(typename) | 62 return 'a' + kind[lbracket+1:-1] + ':' + MapKind(typename) |
59 if kind.endswith('&'): | 63 if kind.endswith('&'): |
60 return 'r:' + _MapKind(kind[0:-1]) | 64 return 'r:' + MapKind(kind[0:-1]) |
61 if kind in map_to_kind: | 65 if kind in map_to_kind: |
62 return map_to_kind[kind] | 66 return map_to_kind[kind] |
63 return 'x:' + kind | 67 return 'x:' + kind |
64 | 68 |
65 def _AttributeListToDict(attribute_list): | 69 def _AttributeListToDict(attribute_list): |
66 if attribute_list is None: | 70 if attribute_list is None: |
67 return {} | 71 return {} |
68 assert isinstance(attribute_list, ast.AttributeList) | 72 assert isinstance(attribute_list, ast.AttributeList) |
69 # TODO(vtl): Check for duplicate keys here. | 73 # TODO(vtl): Check for duplicate keys here. |
70 return dict([(attribute.key, attribute.value) | 74 return dict([(attribute.key, attribute.value) |
71 for attribute in attribute_list]) | 75 for attribute in attribute_list]) |
72 | 76 |
73 def _EnumToDict(enum): | 77 def _EnumToDict(enum): |
74 def EnumValueToDict(enum_value): | 78 def EnumValueToDict(enum_value): |
75 assert isinstance(enum_value, ast.EnumValue) | 79 assert isinstance(enum_value, ast.EnumValue) |
76 return {'name': enum_value.name, | 80 return {'name': enum_value.name, |
77 'value': enum_value.value} | 81 'value': enum_value.value} |
78 | 82 |
79 assert isinstance(enum, ast.Enum) | 83 assert isinstance(enum, ast.Enum) |
80 return {'name': enum.name, | 84 return {'name': enum.name, |
81 'fields': map(EnumValueToDict, enum.enum_value_list)} | 85 'fields': map(EnumValueToDict, enum.enum_value_list)} |
82 | 86 |
83 def _ConstToDict(const): | 87 def _ConstToDict(const): |
84 assert isinstance(const, ast.Const) | 88 assert isinstance(const, ast.Const) |
85 return {'name': const.name, | 89 return {'name': const.name, |
86 'kind': _MapKind(const.typename), | 90 'kind': MapKind(const.typename), |
87 'value': const.value} | 91 'value': const.value} |
88 | 92 |
89 | 93 |
90 class _MojomBuilder(object): | 94 class _MojomBuilder(object): |
91 def __init__(self): | 95 def __init__(self): |
92 self.mojom = {} | 96 self.mojom = {} |
93 | 97 |
94 def Build(self, tree, name): | 98 def Build(self, tree, name): |
95 def StructToDict(struct): | 99 def StructToDict(struct): |
96 def StructFieldToDict(struct_field): | 100 def StructFieldToDict(struct_field): |
97 assert isinstance(struct_field, ast.StructField) | 101 assert isinstance(struct_field, ast.StructField) |
98 return {'name': struct_field.name, | 102 return {'name': struct_field.name, |
99 'kind': _MapKind(struct_field.typename), | 103 'kind': MapKind(struct_field.typename), |
100 'ordinal': struct_field.ordinal.value \ | 104 'ordinal': struct_field.ordinal.value \ |
101 if struct_field.ordinal else None, | 105 if struct_field.ordinal else None, |
102 'default': struct_field.default_value} | 106 'default': struct_field.default_value} |
103 | 107 |
104 assert isinstance(struct, ast.Struct) | 108 assert isinstance(struct, ast.Struct) |
105 return {'name': struct.name, | 109 return {'name': struct.name, |
106 'attributes': _AttributeListToDict(struct.attribute_list), | 110 'attributes': _AttributeListToDict(struct.attribute_list), |
107 'fields': _MapTreeForType(StructFieldToDict, struct.body, | 111 'fields': _MapTreeForType(StructFieldToDict, struct.body, |
108 ast.StructField), | 112 ast.StructField), |
109 'enums': _MapTreeForType(_EnumToDict, struct.body, ast.Enum), | 113 'enums': _MapTreeForType(_EnumToDict, struct.body, ast.Enum), |
110 'constants': _MapTreeForType(_ConstToDict, struct.body, | 114 'constants': _MapTreeForType(_ConstToDict, struct.body, |
111 ast.Const)} | 115 ast.Const)} |
112 | 116 |
113 def InterfaceToDict(interface): | 117 def InterfaceToDict(interface): |
114 def MethodToDict(method): | 118 def MethodToDict(method): |
115 def ParameterToDict(param): | 119 def ParameterToDict(param): |
116 assert isinstance(param, ast.Parameter) | 120 assert isinstance(param, ast.Parameter) |
117 return {'name': param.name, | 121 return {'name': param.name, |
118 'kind': _MapKind(param.typename), | 122 'kind': MapKind(param.typename), |
119 'ordinal': param.ordinal.value if param.ordinal else None} | 123 'ordinal': param.ordinal.value if param.ordinal else None} |
120 | 124 |
121 assert isinstance(method, ast.Method) | 125 assert isinstance(method, ast.Method) |
122 rv = {'name': method.name, | 126 rv = {'name': method.name, |
123 'parameters': map(ParameterToDict, method.parameter_list), | 127 'parameters': map(ParameterToDict, method.parameter_list), |
124 'ordinal': method.ordinal.value if method.ordinal else None} | 128 'ordinal': method.ordinal.value if method.ordinal else None} |
125 if method.response_parameter_list is not None: | 129 if method.response_parameter_list is not None: |
126 rv['response_parameters'] = map(ParameterToDict, | 130 rv['response_parameters'] = map(ParameterToDict, |
127 method.response_parameter_list) | 131 method.response_parameter_list) |
128 return rv | 132 return rv |
(...skipping 22 matching lines...) Expand all Loading... | |
151 _MapTreeForType(InterfaceToDict, tree.definition_list, ast.Interface) | 155 _MapTreeForType(InterfaceToDict, tree.definition_list, ast.Interface) |
152 self.mojom['enums'] = \ | 156 self.mojom['enums'] = \ |
153 _MapTreeForType(_EnumToDict, tree.definition_list, ast.Enum) | 157 _MapTreeForType(_EnumToDict, tree.definition_list, ast.Enum) |
154 self.mojom['constants'] = \ | 158 self.mojom['constants'] = \ |
155 _MapTreeForType(_ConstToDict, tree.definition_list, ast.Const) | 159 _MapTreeForType(_ConstToDict, tree.definition_list, ast.Const) |
156 return self.mojom | 160 return self.mojom |
157 | 161 |
158 | 162 |
159 def Translate(tree, name): | 163 def Translate(tree, name): |
160 return _MojomBuilder().Build(tree, name) | 164 return _MojomBuilder().Build(tree, name) |
OLD | NEW |