Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / mojo / public / tools / bindings / pylib / mojom / parse / translate.py
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 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}
113
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)
121         return rv
122
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,
129                                          ast.Method),
130               'enums': _MapTreeForType(_EnumToDict, interface.body, ast.Enum),
131               'constants': _MapTreeForType(_ConstToDict, interface.body,
132                                            ast.Const)}
133
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)
149     return self.mojom
150
151
152 def Translate(tree, name):
153   return _MojomBuilder().Build(tree, name)