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.
5 """Translates parse tree to Mojom IR."""
11 def _MapTreeForType(func, tree, type_to_map):
12 assert isinstance(type_to_map, type)
15 return [func(subtree) for subtree in tree if isinstance(subtree, type_to_map)]
18 map_to_kind = {'bool': 'b',
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:
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]
58 def _AttributeListToDict(attribute_list):
59 if attribute_list is None:
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])
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}
72 assert isinstance(enum, ast.Enum)
73 return {'name': enum.name,
74 'fields': map(EnumValueToDict, enum.enum_value_list)}
76 def _ConstToDict(const):
77 assert isinstance(const, ast.Const)
78 return {'name': const.name,
79 'kind': _MapKind(const.typename),
83 class _MojomBuilder(object):
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}
97 assert isinstance(struct, ast.Struct)
98 return {'name': struct.name,
99 'attributes': _AttributeListToDict(struct.attribute_list),
100 'fields': _MapTreeForType(StructFieldToDict, struct.body,
102 'enums': _MapTreeForType(_EnumToDict, struct.body, ast.Enum),
103 'constants': _MapTreeForType(_ConstToDict, struct.body,
106 def InterfaceToDict(interface):
107 def MethodToDict(method):
108 def ParameterToDict(param):
109 assert isinstance(param, ast.Parameter)
110 return {'name': param.name,
111 'kind': _MapKind(param.typename),
112 'ordinal': param.ordinal.value if param.ordinal else None}
114 assert isinstance(method, ast.Method)
115 rv = {'name': method.name,
116 'parameters': map(ParameterToDict, method.parameter_list),
117 'ordinal': method.ordinal.value if method.ordinal else None}
118 if method.response_parameter_list is not None:
119 rv['response_parameters'] = map(ParameterToDict,
120 method.response_parameter_list)
123 assert isinstance(interface, ast.Interface)
124 attributes = _AttributeListToDict(interface.attribute_list)
125 return {'name': interface.name,
126 'attributes': attributes,
127 'client': attributes.get('Client'),
128 'methods': _MapTreeForType(MethodToDict, interface.body,
130 'enums': _MapTreeForType(_EnumToDict, interface.body, ast.Enum),
131 'constants': _MapTreeForType(_ConstToDict, interface.body,
134 assert isinstance(tree, ast.Mojom)
135 self.mojom['name'] = name
136 self.mojom['namespace'] = tree.module.name[1] if tree.module else ''
137 self.mojom['imports'] = \
138 [{'filename': imp.import_filename} for imp in tree.import_list]
139 self.mojom['attributes'] = \
140 _AttributeListToDict(tree.module.attribute_list) if tree.module else {}
141 self.mojom['structs'] = \
142 _MapTreeForType(StructToDict, tree.definition_list, ast.Struct)
143 self.mojom['interfaces'] = \
144 _MapTreeForType(InterfaceToDict, tree.definition_list, ast.Interface)
145 self.mojom['enums'] = \
146 _MapTreeForType(_EnumToDict, tree.definition_list, ast.Enum)
147 self.mojom['constants'] = \
148 _MapTreeForType(_ConstToDict, tree.definition_list, ast.Const)
152 def Translate(tree, name):
153 return _MojomBuilder().Build(tree, name)