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 """Generates Python source files from a mojom.Module.""" | 5 """Generates Python source files from a mojom.Module.""" |
6 | 6 |
7 import re | 7 import re |
8 from itertools import ifilter | 8 from itertools import ifilter |
9 | 9 |
10 import mojom.generate.generator as generator | 10 import mojom.generate.generator as generator |
11 import mojom.generate.module as mojom | 11 import mojom.generate.module as mojom |
12 from mojom.generate.template_expander import UseJinja | 12 from mojom.generate.template_expander import UseJinja |
13 | 13 |
14 _kind_to_type = { | 14 _kind_to_type = { |
15 mojom.BOOL: '_descriptor.TYPE_BOOL', | 15 mojom.BOOL: "_descriptor.TYPE_BOOL", |
16 mojom.INT8: '_descriptor.TYPE_INT8', | 16 mojom.INT8: "_descriptor.TYPE_INT8", |
17 mojom.UINT8: '_descriptor.TYPE_UINT8', | 17 mojom.UINT8: "_descriptor.TYPE_UINT8", |
18 mojom.INT16: '_descriptor.TYPE_INT16', | 18 mojom.INT16: "_descriptor.TYPE_INT16", |
19 mojom.UINT16: '_descriptor.TYPE_UINT16', | 19 mojom.UINT16: "_descriptor.TYPE_UINT16", |
20 mojom.INT32: '_descriptor.TYPE_INT32', | 20 mojom.INT32: "_descriptor.TYPE_INT32", |
21 mojom.UINT32: '_descriptor.TYPE_UINT32', | 21 mojom.UINT32: "_descriptor.TYPE_UINT32", |
22 mojom.INT64: '_descriptor.TYPE_INT64', | 22 mojom.INT64: "_descriptor.TYPE_INT64", |
23 mojom.UINT64: '_descriptor.TYPE_UINT64', | 23 mojom.UINT64: "_descriptor.TYPE_UINT64", |
24 mojom.FLOAT: '_descriptor.TYPE_FLOAT', | 24 mojom.FLOAT: "_descriptor.TYPE_FLOAT", |
25 mojom.DOUBLE: '_descriptor.TYPE_DOUBLE', | 25 mojom.DOUBLE: "_descriptor.TYPE_DOUBLE", |
26 mojom.STRING: '_descriptor.TYPE_STRING', | 26 mojom.STRING: "_descriptor.TYPE_STRING", |
27 mojom.NULLABLE_STRING: '_descriptor.TYPE_NULLABLE_STRING', | 27 mojom.NULLABLE_STRING: "_descriptor.TYPE_NULLABLE_STRING", |
28 mojom.HANDLE: '_descriptor.TYPE_HANDLE', | 28 mojom.HANDLE: "_descriptor.TYPE_HANDLE", |
29 mojom.DCPIPE: '_descriptor.TYPE_HANDLE', | 29 mojom.DCPIPE: "_descriptor.TYPE_HANDLE", |
30 mojom.DPPIPE: '_descriptor.TYPE_HANDLE', | 30 mojom.DPPIPE: "_descriptor.TYPE_HANDLE", |
31 mojom.MSGPIPE: '_descriptor.TYPE_HANDLE', | 31 mojom.MSGPIPE: "_descriptor.TYPE_HANDLE", |
32 mojom.SHAREDBUFFER: '_descriptor.TYPE_HANDLE', | 32 mojom.SHAREDBUFFER: "_descriptor.TYPE_HANDLE", |
33 mojom.NULLABLE_HANDLE: '_descriptor.TYPE_NULLABLE_HANDLE', | 33 mojom.NULLABLE_HANDLE: "_descriptor.TYPE_NULLABLE_HANDLE", |
34 mojom.NULLABLE_DCPIPE: '_descriptor.TYPE_NULLABLE_HANDLE', | 34 mojom.NULLABLE_DCPIPE: "_descriptor.TYPE_NULLABLE_HANDLE", |
35 mojom.NULLABLE_DPPIPE: '_descriptor.TYPE_NULLABLE_HANDLE', | 35 mojom.NULLABLE_DPPIPE: "_descriptor.TYPE_NULLABLE_HANDLE", |
36 mojom.NULLABLE_MSGPIPE: '_descriptor.TYPE_NULLABLE_HANDLE', | 36 mojom.NULLABLE_MSGPIPE: "_descriptor.TYPE_NULLABLE_HANDLE", |
37 mojom.NULLABLE_SHAREDBUFFER: '_descriptor.TYPE_NULLABLE_HANDLE', | 37 mojom.NULLABLE_SHAREDBUFFER: "_descriptor.TYPE_NULLABLE_HANDLE", |
38 } | 38 } |
39 | 39 |
40 # int64 integers are not handled by array.array. int64/uint64 array are | 40 # int64 integers are not handled by array.array. int64/uint64 array are |
41 # supported but storage is not optimized (ie. they are plain python list, not | 41 # supported but storage is not optimized (ie. they are plain python list, not |
42 # array.array) | 42 # array.array) |
43 _kind_to_typecode_for_native_array = { | 43 _kind_to_typecode = { |
44 mojom.INT8: 'b', | 44 mojom.INT8: "'b'", |
45 mojom.UINT8: 'B', | 45 mojom.UINT8: "'B'", |
46 mojom.INT16: 'h', | 46 mojom.INT16: "'h'", |
47 mojom.UINT16: 'H', | 47 mojom.UINT16: "'H'", |
48 mojom.INT32: 'i', | 48 mojom.INT32: "'i'", |
49 mojom.UINT32: 'I', | 49 mojom.UINT32: "'I'", |
50 mojom.FLOAT: 'f', | 50 mojom.FLOAT: "'f'", |
51 mojom.DOUBLE: 'd', | 51 mojom.DOUBLE: "'d'", |
52 } | 52 } |
53 | 53 |
54 _kind_to_typecode = dict(_kind_to_typecode_for_native_array) | |
55 _kind_to_typecode.update({ | |
56 mojom.INT64: 'q', | |
57 mojom.UINT64: 'Q', | |
58 mojom.HANDLE: 'i', | |
59 mojom.DCPIPE: 'i', | |
60 mojom.DPPIPE: 'i', | |
61 mojom.MSGPIPE: 'i', | |
62 mojom.SHAREDBUFFER: 'i', | |
63 mojom.NULLABLE_HANDLE: 'i', | |
64 mojom.NULLABLE_DCPIPE: 'i', | |
65 mojom.NULLABLE_DPPIPE: 'i', | |
66 mojom.NULLABLE_MSGPIPE: 'i', | |
67 mojom.NULLABLE_SHAREDBUFFER: 'i', | |
68 }) | |
69 | |
70 | 54 |
71 def NameToComponent(name): | 55 def NameToComponent(name): |
72 # insert '_' between anything and a Title name (e.g, HTTPEntry2FooBar -> | 56 # insert '_' between anything and a Title name (e.g, HTTPEntry2FooBar -> |
73 # HTTP_Entry2_FooBar) | 57 # HTTP_Entry2_FooBar) |
74 name = re.sub('([^_])([A-Z][^A-Z_]+)', r'\1_\2', name) | 58 name = re.sub('([^_])([A-Z][^A-Z_]+)', r'\1_\2', name) |
75 # insert '_' between non upper and start of upper blocks (e.g., | 59 # insert '_' between non upper and start of upper blocks (e.g., |
76 # HTTP_Entry2_FooBar -> HTTP_Entry2_Foo_Bar) | 60 # HTTP_Entry2_FooBar -> HTTP_Entry2_Foo_Bar) |
77 name = re.sub('([^A-Z_])([A-Z])', r'\1_\2', name) | 61 name = re.sub('([^A-Z_])([A-Z])', r'\1_\2', name) |
78 return [x.lower() for x in name.split('_')] | 62 return [x.lower() for x in name.split('_')] |
79 | 63 |
(...skipping 28 matching lines...) Expand all Loading... |
108 | 92 |
109 if isinstance(token, mojom.BuiltinValue): | 93 if isinstance(token, mojom.BuiltinValue): |
110 if token.value == 'double.INFINITY' or token.value == 'float.INFINITY': | 94 if token.value == 'double.INFINITY' or token.value == 'float.INFINITY': |
111 return 'float(\'inf\')'; | 95 return 'float(\'inf\')'; |
112 if (token.value == 'double.NEGATIVE_INFINITY' or | 96 if (token.value == 'double.NEGATIVE_INFINITY' or |
113 token.value == 'float.NEGATIVE_INFINITY'): | 97 token.value == 'float.NEGATIVE_INFINITY'): |
114 return 'float(\'-inf\')' | 98 return 'float(\'-inf\')' |
115 if token.value == 'double.NAN' or token.value == 'float.NAN': | 99 if token.value == 'double.NAN' or token.value == 'float.NAN': |
116 return 'float(\'nan\')'; | 100 return 'float(\'nan\')'; |
117 | 101 |
118 if token in ['true', 'false']: | 102 if token in ["true", "false"]: |
119 return str(token == 'true') | 103 return str(token == "true") |
120 | 104 |
121 return token | 105 return token |
122 | 106 |
123 def GetStructClass(kind): | 107 def GetStructClass(kind): |
124 name = [] | 108 name = [] |
125 if kind.imported_from: | 109 if kind.imported_from: |
126 name.append(kind.imported_from['python_module']) | 110 name.append(kind.imported_from['python_module']) |
127 name.append(GetNameForElement(kind)) | 111 name.append(GetNameForElement(kind)) |
128 return '.'.join(name) | 112 return '.'.join(name) |
129 | 113 |
130 def GetFieldType(kind, field=None): | 114 def GetFieldType(kind, field=None): |
131 if mojom.IsAnyArrayKind(kind): | 115 if mojom.IsAnyArrayKind(kind): |
132 arguments = [] | 116 if kind.kind in _kind_to_typecode: |
133 if kind.kind in _kind_to_typecode_for_native_array: | 117 arguments = [ _kind_to_typecode[kind.kind] ] |
134 arguments.append('%r' %_kind_to_typecode_for_native_array[kind.kind]) | 118 else: |
135 elif kind.kind != mojom.BOOL: | 119 arguments = [ GetFieldType(kind.kind) ] |
136 arguments.append(GetFieldType(kind.kind)) | |
137 if mojom.IsNullableKind(kind): | 120 if mojom.IsNullableKind(kind): |
138 arguments.append('nullable=True') | 121 arguments.append("nullable=True") |
139 if mojom.IsFixedArrayKind(kind): | 122 if mojom.IsFixedArrayKind(kind): |
140 arguments.append('length=%d' % kind.length) | 123 arguments.append("length=%d" % kind.length) |
141 array_type = 'GenericArrayType' | 124 if kind.kind in _kind_to_typecode: |
142 if kind.kind == mojom.BOOL: | 125 return "_descriptor.NativeArrayType(%s)" % ", ".join(arguments) |
143 array_type = 'BooleanArrayType' | 126 else: |
144 elif kind.kind in _kind_to_typecode_for_native_array: | 127 return "_descriptor.PointerArrayType(%s)" % ", ".join(arguments) |
145 array_type = 'NativeArrayType' | |
146 return '_descriptor.%s(%s)' % (array_type, ', '.join(arguments)) | |
147 | 128 |
148 if mojom.IsStructKind(kind): | 129 if mojom.IsStructKind(kind): |
149 arguments = [ GetStructClass(kind) ] | 130 arguments = [ GetStructClass(kind) ] |
150 if mojom.IsNullableKind(kind): | 131 if mojom.IsNullableKind(kind): |
151 arguments.append('nullable=True') | 132 arguments.append("nullable=True") |
152 return '_descriptor.StructType(%s)' % ', '.join(arguments) | 133 return "_descriptor.StructType(%s)" % ", ".join(arguments) |
153 | 134 |
154 if mojom.IsEnumKind(kind): | 135 if mojom.IsEnumKind(kind): |
155 return GetFieldType(mojom.INT32) | 136 return GetFieldType(mojom.INT32) |
156 | 137 |
157 return _kind_to_type.get(kind, '_descriptor.TYPE_NONE') | 138 return _kind_to_type.get(kind, "_descriptor.TYPE_NONE") |
158 | 139 |
159 def GetFieldDescriptor(packed_field): | 140 def GetFieldDescriptor(packed_field): |
160 field = packed_field.field | 141 field = packed_field.field |
161 class_name = 'SingleFieldGroup' | 142 arguments = [ '\'%s\'' % field.name ] |
| 143 arguments.append(GetFieldType(field.kind, field)) |
| 144 arguments.append(str(packed_field.offset)) |
162 if field.kind == mojom.BOOL: | 145 if field.kind == mojom.BOOL: |
163 class_name = 'FieldDescriptor' | 146 arguments.append('bit_offset=%d' % packed_field.bit) |
164 arguments = [ '%r' % field.name ] | |
165 arguments.append(GetFieldType(field.kind, field)) | |
166 arguments.append(str(packed_field.field.ordinal)) | |
167 if field.default: | 147 if field.default: |
168 if mojom.IsStructKind(field.kind): | 148 if mojom.IsStructKind(field.kind): |
169 arguments.append('default_value=True') | 149 arguments.append('default_value=True') |
170 else: | 150 else: |
171 arguments.append('default_value=%s' % ExpressionToText(field.default)) | 151 arguments.append('default_value=%s' % ExpressionToText(field.default)) |
172 return '_descriptor.%s(%s)' % (class_name, ', '.join(arguments)) | 152 return '_descriptor.FieldDescriptor(%s)' % ', '.join(arguments) |
173 | |
174 def GetFieldGroup(byte): | |
175 if len(byte.packed_fields) > 1: | |
176 descriptors = map(GetFieldDescriptor, byte.packed_fields) | |
177 return '_descriptor.BooleanGroup([%s])' % ', '.join(descriptors) | |
178 assert len(byte.packed_fields) == 1 | |
179 return GetFieldDescriptor(byte.packed_fields[0]) | |
180 | 153 |
181 def ComputeStaticValues(module): | 154 def ComputeStaticValues(module): |
182 in_progress = set() | 155 in_progress = set() |
183 computed = set() | 156 computed = set() |
184 | 157 |
185 def GetComputedValue(named_value): | 158 def GetComputedValue(named_value): |
186 if isinstance(named_value, mojom.EnumValue): | 159 if isinstance(named_value, mojom.EnumValue): |
187 field = next(ifilter(lambda field: field.name == named_value.name, | 160 field = next(ifilter(lambda field: field.name == named_value.name, |
188 named_value.enum.fields), None) | 161 named_value.enum.fields), None) |
189 if not field: | 162 if not field: |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 for constant in struct.constants: | 222 for constant in struct.constants: |
250 ResolveConstant(constant) | 223 ResolveConstant(constant) |
251 for enum in struct.enums: | 224 for enum in struct.enums: |
252 ResolveEnum(enum) | 225 ResolveEnum(enum) |
253 for field in struct.fields: | 226 for field in struct.fields: |
254 if isinstance(field.default, (mojom.ConstantValue, mojom.EnumValue)): | 227 if isinstance(field.default, (mojom.ConstantValue, mojom.EnumValue)): |
255 field.default.computed_value = GetComputedValue(field.default) | 228 field.default.computed_value = GetComputedValue(field.default) |
256 | 229 |
257 return module | 230 return module |
258 | 231 |
259 | |
260 class Generator(generator.Generator): | 232 class Generator(generator.Generator): |
261 | 233 |
262 python_filters = { | 234 python_filters = { |
263 'expression_to_text': ExpressionToText, | 235 'expression_to_text': ExpressionToText, |
264 'field_group': GetFieldGroup, | 236 'field_descriptor': GetFieldDescriptor, |
265 'name': GetNameForElement, | 237 'name': GetNameForElement, |
266 } | 238 } |
267 | 239 |
268 @UseJinja('python_templates/module.py.tmpl', filters=python_filters) | 240 @UseJinja('python_templates/module.py.tmpl', filters=python_filters) |
269 def GeneratePythonModule(self): | 241 def GeneratePythonModule(self): |
270 return { | 242 return { |
271 'imports': self.GetImports(), | 243 'imports': self.GetImports(), |
272 'enums': self.module.enums, | 244 'enums': self.module.enums, |
273 'module': ComputeStaticValues(self.module), | 245 'module': ComputeStaticValues(self.module), |
274 'structs': self.GetStructs(), | 246 'structs': self.GetStructs(), |
275 } | 247 } |
276 | 248 |
277 def GenerateFiles(self, args): | 249 def GenerateFiles(self, args): |
278 self.Write(self.GeneratePythonModule(), | 250 self.Write(self.GeneratePythonModule(), |
279 '%s.py' % self.module.name.replace('.mojom', '_mojom')) | 251 '%s.py' % self.module.name.replace('.mojom', '_mojom')) |
280 | 252 |
281 def GetImports(self): | 253 def GetImports(self): |
282 for each in self.module.imports: | 254 for each in self.module.imports: |
283 each['python_module'] = each['module_name'].replace('.mojom', '_mojom') | 255 each['python_module'] = each['module_name'].replace('.mojom', '_mojom') |
284 return self.module.imports | 256 return self.module.imports |
285 | 257 |
286 def GetJinjaParameters(self): | 258 def GetJinjaParameters(self): |
287 return { | 259 return { |
288 'lstrip_blocks': True, | 260 'lstrip_blocks': True, |
289 'trim_blocks': True, | 261 'trim_blocks': True, |
290 } | 262 } |
OLD | NEW |