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 """Translates parse tree to Mojom IR.""" | |
6 | |
7 | |
8 from . import ast | |
9 | |
10 | |
11 def _MapTreeForType(func, tree, type_to_map): | |
12 assert isinstance(type_to_map, type) | |
13 if not tree: | |
14 return [] | |
15 return [func(subtree) for subtree in tree if isinstance(subtree, type_to_map)] | |
16 | |
17 def _MapKind(kind): | |
18 map_to_kind = {'bool': 'b', | |
19 'int8': 'i8', | |
20 'int16': 'i16', | |
21 'int32': 'i32', | |
22 'int64': 'i64', | |
23 'uint8': 'u8', | |
24 'uint16': 'u16', | |
25 'uint32': 'u32', | |
26 'uint64': 'u64', | |
27 'float': 'f', | |
28 'double': 'd', | |
29 'string': 's', | |
30 'handle': 'h', | |
31 'handle<data_pipe_consumer>': 'h:d:c', | |
32 'handle<data_pipe_producer>': 'h:d:p', | |
33 'handle<message_pipe>': 'h:m', | |
34 'handle<shared_buffer>': 'h:s'} | |
35 if kind.endswith('?'): | |
36 base_kind = _MapKind(kind[0:-1]) | |
37 # NOTE: This doesn't rule out enum types. Those will be detected later, when | |
38 # cross-reference is established. | |
39 reference_kinds = ('m', 's', 'h', 'a', 'r', 'x') | |
40 if base_kind[0] not in reference_kinds: | |
41 raise Exception( | |
42 'A type (spec "%s") cannot be made nullable' % base_kind) | |
43 return '?' + base_kind | |
44 if kind.endswith('}'): | |
45 lbracket = kind.rfind('{') | |
46 value = kind[0:lbracket] | |
47 return 'm[' + _MapKind(kind[lbracket+1:-1]) + '][' + _MapKind(value) + ']' | |
48 if kind.endswith(']'): | |
49 lbracket = kind.rfind('[') | |
50 typename = kind[0:lbracket] | |
51 return 'a' + kind[lbracket+1:-1] + ':' + _MapKind(typename) | |
52 if kind.endswith('&'): | |
53 return 'r:' + _MapKind(kind[0:-1]) | |
54 if kind in map_to_kind: | |
55 return map_to_kind[kind] | |
56 return 'x:' + kind | |
57 | |
58 def _AttributeListToDict(attribute_list): | |
59 if attribute_list is None: | |
60 return {} | |
61 assert isinstance(attribute_list, ast.AttributeList) | |
62 # TODO(vtl): Check for duplicate keys here. | |
63 return dict([(attribute.key, attribute.value) | |
64 for attribute in attribute_list]) | |
65 | |
66 def _EnumToDict(enum): | |
67 def EnumValueToDict(enum_value): | |
68 assert isinstance(enum_value, ast.EnumValue) | |
69 return {'name': enum_value.name, | |
70 'value': enum_value.value} | |
71 | |
72 assert isinstance(enum, ast.Enum) | |
73 return {'name': enum.name, | |
74 'fields': map(EnumValueToDict, enum.enum_value_list)} | |
75 | |
76 def _ConstToDict(const): | |
77 assert isinstance(const, ast.Const) | |
78 return {'name': const.name, | |
79 'kind': _MapKind(const.typename), | |
80 'value': const.value} | |
81 | |
82 | |
83 class _MojomBuilder(object): | |
84 def __init__(self): | |
85 self.mojom = {} | |
86 | |
87 def Build(self, tree, name): | |
88 def StructToDict(struct): | |
89 def StructFieldToDict(struct_field): | |
90 assert isinstance(struct_field, ast.StructField) | |
91 return {'name': struct_field.name, | |
92 'kind': _MapKind(struct_field.typename), | |
93 'ordinal': struct_field.ordinal.value \ | |
94 if struct_field.ordinal else None, | |
95 'default': struct_field.default_value} | |
96 | |
97 assert isinstance(struct, ast.Struct) | |
98 return {'name': struct.name, | |
99 'attributes': _AttributeListToDict(struct.attribute_list), | |
100 'fields': _MapTreeForType(StructFieldToDict, struct.body, | |
101 ast.StructField), | |
102 'enums': _MapTreeForType(_EnumToDict, struct.body, ast.Enum), | |
103 'constants': _MapTreeForType(_ConstToDict, struct.body, | |
104 ast.Const)} | |
105 | |
106 def UnionToDict(union): | |
107 def UnionFieldToDict(union_field): | |
108 assert isinstance(union_field, ast.UnionField) | |
109 return {'name': union_field.name, | |
110 'kind': _MapKind(union_field.typename), | |
111 'ordinal': union_field.ordinal.value \ | |
112 if union_field.ordinal else None} | |
113 assert isinstance(union, ast.Union) | |
114 return {'name': union.name, | |
115 'fields': _MapTreeForType(UnionFieldToDict, union.body, | |
116 ast.UnionField)} | |
117 | |
118 def InterfaceToDict(interface): | |
119 def MethodToDict(method): | |
120 def ParameterToDict(param): | |
121 assert isinstance(param, ast.Parameter) | |
122 return {'name': param.name, | |
123 'kind': _MapKind(param.typename), | |
124 'ordinal': param.ordinal.value if param.ordinal else None} | |
125 | |
126 assert isinstance(method, ast.Method) | |
127 rv = {'name': method.name, | |
128 'parameters': map(ParameterToDict, method.parameter_list), | |
129 'ordinal': method.ordinal.value if method.ordinal else None} | |
130 if method.response_parameter_list is not None: | |
131 rv['response_parameters'] = map(ParameterToDict, | |
132 method.response_parameter_list) | |
133 return rv | |
134 | |
135 assert isinstance(interface, ast.Interface) | |
136 attributes = _AttributeListToDict(interface.attribute_list) | |
137 return {'name': interface.name, | |
138 'attributes': attributes, | |
139 'client': attributes.get('Client'), | |
140 'methods': _MapTreeForType(MethodToDict, interface.body, | |
141 ast.Method), | |
142 'enums': _MapTreeForType(_EnumToDict, interface.body, ast.Enum), | |
143 'constants': _MapTreeForType(_ConstToDict, interface.body, | |
144 ast.Const)} | |
145 | |
146 assert isinstance(tree, ast.Mojom) | |
147 self.mojom['name'] = name | |
148 self.mojom['namespace'] = tree.module.name[1] if tree.module else '' | |
149 self.mojom['imports'] = \ | |
150 [{'filename': imp.import_filename} for imp in tree.import_list] | |
151 self.mojom['attributes'] = \ | |
152 _AttributeListToDict(tree.module.attribute_list) if tree.module else {} | |
153 self.mojom['structs'] = \ | |
154 _MapTreeForType(StructToDict, tree.definition_list, ast.Struct) | |
155 self.mojom['union'] = \ | |
156 _MapTreeForType(UnionToDict, tree.definition_list, ast.Union) | |
157 self.mojom['interfaces'] = \ | |
158 _MapTreeForType(InterfaceToDict, tree.definition_list, ast.Interface) | |
159 self.mojom['enums'] = \ | |
160 _MapTreeForType(_EnumToDict, tree.definition_list, ast.Enum) | |
161 self.mojom['constants'] = \ | |
162 _MapTreeForType(_ConstToDict, tree.definition_list, ast.Const) | |
163 return self.mojom | |
164 | |
165 | |
166 def Translate(tree, name): | |
167 return _MojomBuilder().Build(tree, name) | |
OLD | NEW |