Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(196)

Side by Side Diff: mojo/public/tools/bindings/pylib/mojom/generate/mojom_translator.py

Issue 2250183003: Make the fuchsia mojo/public repo the source of truth. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 # Copyright 2015 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5 #
6 # This module is responsible for translating a MojomFileGraph (see
7 # mojom_files.mojom) to one or more module.Module.
8 #
9 # This module takes the output of the mojom parser, a MojomFileGraph and
10 # translates it to the input of the code generators, a module.Module object.
11 # This is part of version 2 of the code generation pipeline. In version 1, the
12 # analogous functionality (translating from parser output to code generators
13 # input) is performed by the data module.
14 #
15 # The code generators remain from version 1 of the pipeline and so this module
16 # serves as an adapter between the v1 backends and the v2 frontend.
17 #
18 # The current version of this script does not validate the input data at all
19 # and instead trusts that it will be invoked with valid data produced by the
20 # frontend parser.
21 #
22 # NOTE: This module assumes that the python path contains the generated modules
23 # for mojom_files.mojom and mojom_types.mojom as well as their dependencies.
24 # It is the responsibility of the module's loader to handle this.
25
26 import os
27
28 from generated import mojom_files_mojom
29 from generated import mojom_types_mojom
30 import module
31 import operator
32 import pack
33
34
35 class FileTranslator(object):
36 """FileTranslator translates a MojomFile to a module.Module."""
37 def __init__(self, graph, file_name):
38 """Initializes a FileTranslator.
39
40 Args:
41 graph: {mojom_files_mojom.MojomFileGraph} containing the file to be
42 translated.
43 file_name: {str} key to the file to be translated in graph.files.
44 """
45 assert isinstance(graph, mojom_files_mojom.MojomFileGraph)
46 self._type_cache = {}
47 self._value_cache = {}
48 self._constant_cache = {}
49 self._graph = graph
50 self._file_name = file_name
51 self._types = {}
52 self._module = module.Module()
53 self._transitive_imports = {}
54
55 def Translate(self):
56 """Translates the file specified in the constructor.
57
58 Returns:
59 {module.Module} representing the translated file.
60 """
61 mojom_file = self._graph.files[self._file_name]
62
63 mod = self._module
64 self.PopulateModuleMetadata(mod, mojom_file)
65
66 mod.imports = []
67 self._transitive_imports = self.GetTransitiveImports(mojom_file)
68 mod.transitive_imports = self._transitive_imports.values()
69 if mojom_file.imports:
70 mod.imports = [
71 self._transitive_imports[imp] for imp in mojom_file.imports]
72
73 if mojom_file.declared_mojom_objects:
74 if mojom_file.declared_mojom_objects.top_level_constants:
75 mod.constants = [
76 self.ConstantFromKey(key)
77 for key in mojom_file.declared_mojom_objects.top_level_constants]
78
79 user_defined_types = ['interfaces', 'structs', 'unions']
80 for user_defined_type in user_defined_types:
81 if getattr(mojom_file.declared_mojom_objects, user_defined_type):
82 setattr(mod, user_defined_type, [self.UserDefinedFromTypeKey(key)
83 for key in getattr(
84 mojom_file.declared_mojom_objects, user_defined_type)])
85 if mojom_file.declared_mojom_objects.top_level_enums:
86 mod.enums = [self.UserDefinedFromTypeKey(key)
87 for key in mojom_file.declared_mojom_objects.top_level_enums]
88
89 mod.serialized_runtime_type_info = mojom_file.serialized_runtime_type_info
90
91 return mod
92
93 def PopulateModuleMetadata(self, mod, mojom_file):
94 """Populates some fields of a module.Module based on a MojomFile.
95
96 Populates name, path, namespace and attributes of mod.
97
98 Args:
99 mod: {module.Module} the module to be populated.
100 mojom_file: {MojomFile} the file to be translated.
101 """
102 mod.name = os.path.basename(mojom_file.file_name)
103 # specified_file_name is the file name specified on the command line if one
104 # was specified. The mojom parser sets specified_file_name to the empty
105 # string if the file was parsed only because the file was imported by
106 # another file. While specified_file_name can be None, the mojom parser
107 # should not set it to None, so we check for that error here.
108 assert mojom_file.specified_file_name is not None
109 mod.specified_name = mojom_file.specified_file_name
110 mod.path = mojom_file.file_name
111 mod.namespace = mojom_file.module_namespace
112 # Note that attribute values are typed. That is why we use
113 # attr.value.data directly instead of the string representation of it.
114 if mojom_file.attributes:
115 mod.attributes = {attr.key:
116 attr.value.data for attr in mojom_file.attributes}
117
118 def GetTransitiveImports(self, mojom_file):
119 """Gets a mojom file's transitive imports.
120
121 Args:
122 mojom_file: {mojom_files.MojomFile} the mojom file whose imports have to
123 be found.
124
125 Returns:
126 {dict} The key is the file_name which is an index into self._graph.files
127 and is referenced in the SourceFileInfo.file_name of imported types.
128 The value is a dictionary as returned by ImportFromMojom.
129 """
130 if not mojom_file.imports:
131 return {}
132 to_be_processed = set(mojom_file.imports)
133 processed = set()
134 transitive_imports = {}
135
136 while to_be_processed:
137 import_name = to_be_processed.pop()
138 processed.add(import_name)
139
140 import_dict = self.ImportFromMojom(import_name)
141
142 transitive_imports[import_dict['module'].path] = import_dict
143
144 import_file = self._graph.files[import_name]
145 if import_file.imports:
146 to_be_processed.update(set(import_file.imports) - processed)
147
148 return transitive_imports
149
150 def ImportFromMojom(self, import_name):
151 """Builds a dict representing an import.
152
153 Args:
154 import_name: {str} key to the imported file in graph.files.
155
156 Returns:
157 {dict} representing the imported file.
158 """
159 import_file = self._graph.files[import_name]
160 import_module = module.Module()
161 self.PopulateModuleMetadata(import_module, import_file)
162
163 import_item = {
164 'module_name': import_module.name,
165 'namespace': import_module.namespace,
166 'module': import_module,
167 }
168 return import_item
169
170 def UnionFromMojom(self, union, mojom_type):
171 """Populates a module.Union based on a MojomUnion.
172
173 Args:
174 union: {module.Union} to be populated.
175 mojom_type: {UserDefinedType} referring to the MojomUnion to be
176 translated.
177 """
178 assert mojom_type.tag == mojom_types_mojom.UserDefinedType.Tags.union_type
179 mojom_union = mojom_type.union_type
180 self.PopulateUserDefinedType(union, mojom_union)
181 union.fields = [self.UnionFieldFromMojom(f) for f in mojom_union.fields]
182 # mojom_union.fields is indexed by the field tags. We want
183 # to capture these tags but sort union.fields by declaration_order.
184 union.fields.sort(key=lambda field: field.declaration_order)
185
186 def StructFromMojom(self, struct, mojom_type):
187 """Populates a module.Struct based on a MojomStruct.
188
189 Args:
190 struct: {module.Struct} to be populated.
191 mojom_type: {UserDefinedType} referring to the MojomStruct to be
192 translated.
193 """
194 assert mojom_type.tag == mojom_types_mojom.UserDefinedType.Tags.struct_type
195 mojom_struct = mojom_type.struct_type
196 self.StructFromMojomStruct(struct, mojom_struct)
197
198 def StructFromMojomStruct(self, struct, mojom_struct):
199 """Populates a module.Struct based on a MojomStruct.
200
201 Args:
202 struct: {module.Struct} to be populated.
203 mojom_struct: {mojom_types.MojomStruct} to be translated.
204 """
205 self.PopulateUserDefinedType(struct, mojom_struct)
206 # mojom_struct.fields is indexed by the field ordinals.
207 struct.fields_in_ordinal_order = [self.StructFieldFromMojom(ordinal, f)
208 for (ordinal, f) in enumerate(mojom_struct.fields)]
209 # We also want a list of fields sorted in declaration_order.
210 struct.fields = [f for f in struct.fields_in_ordinal_order]
211 struct.fields.sort(key=lambda field: field.declaration_order)
212
213 assert mojom_struct.version_info
214 struct.versions = [self.VersionInfoFromMojom(version) for version in
215 mojom_struct.version_info]
216 self.PopulateContainedDeclarationsFromMojom(
217 struct, mojom_struct.decl_data.contained_declarations)
218
219 def UnionFieldFromMojom(self, mojom_field):
220 """Translates a mojom_types_mojom.UnionField to a module.UnionField.
221
222 Args:
223 mojom_field: {mojom_types_mojom.UnionField} to be translated.
224
225 Returns:
226 {module.UnionField} translated from mojom_field.
227 """
228 union_field = module.UnionField()
229 self.PopulateCommonFieldValues(union_field, mojom_field)
230 # The |ordinal| attribute of |union_field| contains the field's tag
231 # as computed by the Mojom front-end.
232 union_field.ordinal = mojom_field.tag
233 # The |declared_tag| field is populated only if the user explicitly
234 # specified a tag for the field in the .mojom file and as such is not
235 # defined for every field. If defined it is equal to the |ordinal|
236 # attribute. Currently no code generators are consuming this data.
237 union_field.declared_tag = self.OrdinalFromMojom(mojom_field)
238 # The declaration_order field preserves the index of the field in
239 # declaration order in the .mojom file.
240 union_field.declaration_order = mojom_field.decl_data.declaration_order
241 return union_field
242
243 def StructFieldFromMojom(self, ordinal, mojom_field):
244 """Translates a mojom_types_mojom.StructField to a module.StructField.
245
246 Args:
247 ordinal: {int} The 0-based ordinal position of the field within the
248 struct. Note that this is not necessarily the same as the lexical
249 order or the packing order.
250 mojom_field: {mojom_types_mojom.StructField} to be translated.
251
252 Returns:
253 {module.StructField} translated from mojom_field.
254 """
255 struct_field = module.StructField()
256 self.PopulateCommonFieldValues(struct_field, mojom_field)
257 struct_field.computed_offset = mojom_field.offset
258 struct_field.computed_bit = mojom_field.bit
259 struct_field.computed_min_version = mojom_field.min_version
260 # Note that the |ordinal| attribute of |struct_field| records only the
261 # *declared* ordinal and as such is not defined for every field whereas
262 # the |computed_ordinal| attribute is defined for every field. If
263 # |ordinal| is defined then it is equal to |computed_ordinal|.
264 struct_field.ordinal = self.OrdinalFromMojom(mojom_field)
265 struct_field.computed_ordinal = ordinal
266 struct_field.declaration_order = mojom_field.decl_data.declaration_order
267 if mojom_field.default_value:
268 if (mojom_field.default_value.tag ==
269 mojom_types_mojom.DefaultFieldValue.Tags.default_keyword):
270 struct_field.default = 'default'
271 else:
272 struct_field.default = self.ValueFromMojom(
273 mojom_field.default_value.value)
274
275 return struct_field
276
277 def VersionInfoFromMojom(self, mojom_version):
278 """Translates a mojom_types_mojom.StructVersion to a pack.VersionInfo
279 Args:
280 mojom_version: {mojom_types_mojom.StructVersion} to be translated.
281
282 Returns:
283 {pack.VersionInfo} translated from |mojom_version|.
284 """
285 return pack.VersionInfo(mojom_version.version_number,
286 mojom_version.num_fields, mojom_version.num_bytes)
287
288
289 def ParamFromMojom(self, mojom):
290 """Translates a mojom_types_mojom.StructField to a module.Parameter.
291
292 The parameters passed to and returned from a method are expressed as a
293 struct. The struct fields in the struct are the parameters.
294
295 Args:
296 mojom: {mojom_types_mojom.StructField} representing a method parameter.
297
298 Returns:
299 {module.Parameter} translated from the mojom.
300 """
301 param = module.Parameter()
302 param.ordinal = self.OrdinalFromMojom(mojom)
303 self.PopulateCommonFieldValues(param, mojom)
304 return param
305
306 def PopulateCommonFieldValues(self, field, mojom_field):
307 """Populates a number of common field values based on a mojom field.
308
309 Args:
310 field: {module.Field|module.Parameter} to be populated.
311 mojom_field: {StructField|UnionField} to be translated.
312 """
313 # TODO(rudominer) Some of the code generators check that the type
314 # of field.name is a non-unicode string. If we change this we can
315 # remove the str() below.
316 field.name = str(mojom_field.decl_data.short_name)
317 field.kind = self.KindFromMojom(mojom_field.type)
318 field.attributes = self.AttributesFromMojom(mojom_field)
319
320 def PopulateContainedDeclarationsFromMojom(
321 self, parent_kind, contained_declarations):
322 """Populates a module.Struct|module.Interface with contained declarations.
323
324 Args:
325 parent_kind: {module.Struct|module.Interface} to be populated.
326 contained_declarations: {mojom_types_mojom.ContainedDeclarations} from
327 which the contained types need to be extracted.
328 """
329 if not contained_declarations:
330 return
331
332 if contained_declarations.enums:
333 for enum_key in contained_declarations.enums:
334 enum = self.UserDefinedFromTypeKey(enum_key)
335 parent_kind.enums.append(enum)
336
337 if contained_declarations.constants:
338 for const_key in contained_declarations.constants:
339 const = self.ConstantFromKey(const_key)
340 parent_kind.constants.append(const)
341
342 def EnumFromMojom(self, enum, mojom_type):
343 """Populates a module.Enum based on a MojomEnum.
344
345 Args:
346 enum: {module.Enum} to be populated.
347 mojom_type: {mojom_types_mojom.Type} referring to the MojomEnum to be
348 translated.
349 """
350 assert mojom_type.tag == mojom_types_mojom.UserDefinedType.Tags.enum_type
351 mojom_enum = mojom_type.enum_type
352 self.PopulateUserDefinedType(enum, mojom_enum)
353 if mojom_enum.decl_data.container_type_key:
354 parent_kind = self.UserDefinedFromTypeKey(
355 mojom_enum.decl_data.container_type_key)
356 enum.parent_kind = parent_kind
357 enum.fields = [self.EnumFieldFromMojom(value)
358 for value in mojom_enum.values]
359
360 def EnumFieldFromMojom(self, mojom_enum_value):
361 """Translates an mojom_types_mojom.EnumValue to a module.EnumField.
362
363 mojom_enum_value: {mojom_types_mojom.EnumValue} to be translated.
364
365 Returns:
366 {module.EnumField} translated from mojom_enum_value.
367 """
368 field = module.EnumField()
369 field.name = mojom_enum_value.decl_data.short_name
370 field.attributes = self.AttributesFromMojom(mojom_enum_value)
371 field.numeric_value = mojom_enum_value.int_value
372 if mojom_enum_value.initializer_value is not None:
373 field.value = self.ValueFromMojom(mojom_enum_value.initializer_value)
374
375 return field
376
377 def AttributesFromMojom(self, mojom):
378 """Extracts the attributes from a Mojom object into a dict.
379
380 Args:
381 mojom: A type in mojom_types_mojom containing a decl_data field.
382
383 Returns:
384 {dict<str, str>} of the attributes.
385 """
386 if not mojom.decl_data.attributes:
387 return None
388
389 # Note that attribute values are typed. That is why we use
390 # attr.value.data directly instead of the string representation of it.
391 return {attr.key: attr.value.data for attr in mojom.decl_data.attributes}
392
393 def PopulateUserDefinedType(self, module_type, mojom):
394 """Populates fields that are common among user-defined types.
395
396 Args:
397 module_type: {module.Struct|Union|Enum} to be populated.
398 mojom: {MojomStruct|MojomUnion|MojomEnum} to be translated.
399 """
400 module_type.attributes = self.AttributesFromMojom(mojom)
401 module_type.name = mojom.decl_data.short_name
402 module_type.spec = mojom.decl_data.full_identifier
403 if module_type.spec == None:
404 module_type.spec = mojom.decl_data.short_name
405 self.PopulateModuleOrImportedFrom(module_type, mojom)
406
407 def PopulateModuleOrImportedFrom(self, module_type, mojom):
408 """Populates either the module field or the imported_from field.
409
410 All user-defined types must have either the module field populated (if
411 they are from the currently-processed module) or the imported_from (if
412 they are imported from another module).
413
414 Args:
415 module_type: {module.Struct|Union|Enum|Interface} to be populated.
416 mojom: {MojomStruct|MojomUnion|MojomEnum|MojomInterface} to be translated.
417 """
418 if mojom.decl_data.source_file_info:
419 if mojom.decl_data.source_file_info.file_name == self._file_name:
420 module_type.module = self._module
421 else:
422 imported_from = self._transitive_imports[
423 mojom.decl_data.source_file_info.file_name]
424 module_type.imported_from = imported_from
425 module_type.module = imported_from['module']
426
427
428 def OrdinalFromMojom(self, mojom):
429 """Extracts the declared ordinal from a mojom StructField or UnionField.
430
431 Args:
432 mojom: {MojomStruct|MojomUnion} from which the ordinal is to be extracted.
433
434 Returns:
435 {int} if an ordinal was present, {NoneType} otherwise.
436 """
437 ordinal = mojom.decl_data.declared_ordinal
438 if ordinal < 0:
439 return None
440 return ordinal
441
442 def InterfaceFromMojom(self, interface, mojom_type):
443 """Populates a module.Interface from a mojom_types_mojom.MojomInterface.
444
445 Args:
446 interface: {module.Interface} to be populated.
447 mojom_type: {UserDefinedType} referring to the MojomInterface to be
448 translated.
449 """
450 assert (mojom_type.tag
451 == mojom_types_mojom.UserDefinedType.Tags.interface_type)
452 mojom_interface = mojom_type.interface_type
453 interface.attributes = self.AttributesFromMojom(mojom_interface)
454 self.PopulateModuleOrImportedFrom(interface, mojom_interface)
455 interface.name = mojom_interface.decl_data.short_name
456 interface.spec = interface.name
457 interface.version = mojom_interface.current_version
458 interface.service_name = mojom_interface.service_name
459 if interface.attributes:
460 assert interface.service_name == interface.attributes.get(
461 'ServiceName', None), interface.service_name
462 else:
463 assert interface.service_name is None, interface.service_name
464
465
466 # Translate the dictionary of methods into a list of module.Methods.
467 interface.methods = [self.MethodFromMojom(mojom_method, interface)
468 for ordinal, mojom_method in mojom_interface.methods.iteritems()]
469 # We want the methods in an interface to be in some deterministic order
470 # and we choose declaration order (i.e. lexical order within the
471 # .mojom file.)
472 interface.methods.sort(key=lambda method: method.declaration_order)
473 self.PopulateContainedDeclarationsFromMojom(
474 interface, mojom_interface.decl_data.contained_declarations)
475
476 def MethodFromMojom(self, mojom_method, interface):
477 """Translates a mojom_types_mojom.MojomMethod to a module.Method.
478
479 Args:
480 mojom_method: {mojom_types_mojom.MojomMethod} to be translated.
481 interface: {module.Interface} the method is a member of.
482
483 Returns:
484 {module.Method} translated from mojom_method.
485 """
486 method = module.Method(interface, mojom_method.decl_data.short_name)
487 method.ordinal = mojom_method.ordinal
488 method.declaration_order = mojom_method.decl_data.declaration_order
489 method.param_struct = module.Struct()
490 self.StructFromMojomStruct(method.param_struct, mojom_method.parameters)
491 # The name of a synthetic request parameter struct is not guaranteed by
492 # the frontend to be anything in particular so we set the name of the
493 # translated struct to a value that the code generators are expecting.
494 method.param_struct.name = "%s_%s_Params" % (
495 method.interface.name, method.name)
496 method.parameters = [self.ParamFromMojom(param)
497 for param in mojom_method.parameters.fields]
498 if mojom_method.response_params is not None:
499 method.response_param_struct = module.Struct()
500 self.StructFromMojomStruct(method.response_param_struct,
501 mojom_method.response_params)
502 # The name of a synthetic response parameter struct is not guaranteed by
503 # the frontend to be anything in particular so we set the name of the
504 # translated struct to a value that the code generators are expecting.
505 method.response_param_struct.name = "%s_%s_ResponseParams" % (
506 method.interface.name, method.name)
507 method.response_parameters = [self.ParamFromMojom(param)
508 for param in mojom_method.response_params.fields]
509
510 method.min_version=mojom_method.min_version
511
512 return method
513
514 def ConstantFromKey(self, constant_key):
515 """Takes a key into the map graph.resolved_constants and returns the module
516 equivalent constant.
517
518 Args:
519 constant_key: {str} the key referring to the constant whose translation
520 is to be returned.
521
522 Returns:
523 {module.Constant} translated.
524 """
525 if constant_key in self._constant_cache:
526 return self._constant_cache[constant_key]
527
528 mojom_const = self._graph.resolved_constants[constant_key]
529 const = module.Constant()
530 self._constant_cache[constant_key] = const
531
532 self.ConstantFromMojom(const, mojom_const)
533 return const
534
535 def ConstantFromMojom(self, const, mojom_const):
536 """Populates a module.Constant based on a DeclaredConstant.
537
538 Args:
539 const: {module.Constant} to be populated.
540 mojom_const: {mojom_types_mojom.DeclaredConstant} to be translated.
541
542 Returns:
543 {module.Constant} translated from mojom_const.
544 """
545 const.name = mojom_const.decl_data.short_name
546 const.kind = self.KindFromMojom(mojom_const.type)
547 const.value = self.ValueFromMojom(mojom_const.value)
548 const.parent_kind = None
549 if mojom_const.decl_data.container_type_key:
550 const.parent_kind = self.UserDefinedFromTypeKey(
551 mojom_const.decl_data.container_type_key)
552
553 def ValueFromMojom(self, value):
554 """Translates a mojom_types_mojom.Value.
555
556 Args:
557 value: {mojom_types_mojom.Value} to be translated.
558
559 Returns:
560 {str|module.BuiltinValue|module.NamedValue} translated from the passed in
561 mojom_value.
562 If value is a literal value, a string is returned. If the literal value is
563 a string literal value, the returned string is enclosed in double
564 quotes. If the literal value is a boolean literal value then one of the
565 strings 'true' or 'false' is returned. Otherwise the literal value is a
566 numeric literal value and in this case the returned value is a Python
567 string representation of the numeric value.
568 If value is a built-in value, a module.BuiltinValue is returned.
569 If value is a user defined reference, a module.NamedValue is returned.
570 """
571 if value.tag == mojom_types_mojom.Value.Tags.literal_value:
572 if (value.literal_value.tag
573 == mojom_types_mojom.LiteralValue.Tags.string_value):
574 return '"%s"' % value.literal_value.data
575 if (value.literal_value.tag
576 == mojom_types_mojom.LiteralValue.Tags.bool_value):
577 # The strings 'true' and 'false' are used to represent bool literals.
578 return ('%s' % value.literal_value.data).lower()
579 elif (value.literal_value.tag
580 == mojom_types_mojom.LiteralValue.Tags.float_value or
581 value.literal_value.tag
582 == mojom_types_mojom.LiteralValue.Tags.double_value):
583 # Use the Python repr() function to get a string that accurately
584 # represents the value of the floating point number.
585 return repr(value.literal_value.data)
586 return str(value.literal_value.data)
587 elif value.tag == mojom_types_mojom.Value.Tags.builtin_value:
588 mojom_to_builtin = {
589 mojom_types_mojom.BuiltinConstantValue.DOUBLE_INFINITY:
590 'double.INFINITY',
591 mojom_types_mojom.BuiltinConstantValue.DOUBLE_NEGATIVE_INFINITY:
592 'double.NEGATIVE_INFINITY',
593 mojom_types_mojom.BuiltinConstantValue.DOUBLE_NAN:
594 'double.NAN',
595 mojom_types_mojom.BuiltinConstantValue.FLOAT_INFINITY:
596 'float.INFINITY',
597 mojom_types_mojom.BuiltinConstantValue.FLOAT_NEGATIVE_INFINITY:
598 'float.NEGATIVE_INFINITY',
599 mojom_types_mojom.BuiltinConstantValue.FLOAT_NAN: 'float.NAN',
600 }
601 return module.BuiltinValue(mojom_to_builtin[value.builtin_value])
602 return self.FromUserValueReference(value)
603
604 def FromUserValueReference(self, value):
605 """Translates a mojom_types.EnumValueReference or ConstantReference into the
606 module equivalent.
607
608 Args:
609 value: {mojom_types_mojom.Value} the value ref to be translated. It
610 must be of type EnumValueReference or ConstantReference.
611
612 Returns:
613 {module.EnumValue|module.ConstantValue} translated.
614 """
615 if value.tag == mojom_types_mojom.Value.Tags.constant_reference:
616 return self.ConstantValueFromKey(value.constant_reference.constant_key)
617 assert value.tag == mojom_types_mojom.Value.Tags.enum_value_reference
618 return self.EnumValueFromKey(value.enum_value_reference.enum_type_key,
619 value.enum_value_reference.enum_value_index)
620
621 def ConstantValueFromKey(self, constant_key):
622 """Takes a key into graph.resolved_constants referring to a
623 mojom declared_constant and returns a module.ConstantValue referring to the
624 module equivalent constant.
625
626 Args:
627 constant_key: {str} the constant key referring to a constant.
628
629 Returns:
630 {module.ConstantValue} translated.
631 """
632 if constant_key in self._value_cache:
633 return self._value_cache[constant_key]
634
635 const_value = module.ConstantValue()
636 self._value_cache[constant_key] = const_value
637
638 const = self.ConstantFromKey(constant_key)
639 const_value.constant = const
640 const_value.name = const.name
641 const_value.parent_kind = const.parent_kind
642 self.PopulateModuleOrImportedFrom(const_value,
643 self._graph.resolved_constants[constant_key])
644 const_value.namespace = const_value.module.namespace
645 return const_value
646
647 def EnumValueFromKey(self, enum_type_key, enum_value_index):
648 """Takes an enum type key and an enum value index (together these
649 form a key to a mojom_enum_value) and returns a module.EnumValue referring
650 the module equivalent enum value
651
652 Args:
653 enum_type_key: {str} the type key of a mojom_enum
654 enum_value_index: {int} the 0-based index into the |values| array of
655 the mojom_enum
656
657 Returns:
658 {module.EnumValue} translated from mojom_enum_value.
659 """
660 enum_value_key = (enum_type_key, enum_value_index)
661 if enum_value_key in self._value_cache:
662 return self._value_cache[enum_value_key]
663
664 mojom_enum = self._graph.resolved_types[enum_type_key].enum_type
665 mojom_enum_value = mojom_enum.values[enum_value_index]
666
667 # We need to create and cache the EnumValue object just in case later calls
668 # require the creation of that same EnumValue object.
669 enum_value = module.EnumValue()
670 self._value_cache[enum_value_key] = enum_value
671
672 enum = self.UserDefinedFromTypeKey(enum_type_key)
673 enum_value.enum = enum
674 self.PopulateModuleOrImportedFrom(enum_value, mojom_enum_value)
675 enum_value.namespace = enum_value.module.namespace
676 enum_value.parent_kind = enum.parent_kind
677 enum_value.name = mojom_enum_value.decl_data.short_name
678
679 return enum_value
680
681 def KindFromMojom(self, mojom_type):
682 """Translates a mojom_types_mojom.Type to its equivalent module type.
683
684 It is guaranteed that two calls to KindFromMojom with the same input yield
685 the same object.
686
687 Args:
688 mojom_type: {mojom_types_mojom.Type} to be translated.
689
690 Returns:
691 {module.Kind} translated from mojom_type.
692 """
693 mappers = {
694 mojom_types_mojom.Type.Tags.simple_type: self.SimpleKindFromMojom,
695 mojom_types_mojom.Type.Tags.string_type: self.StringFromMojom,
696 mojom_types_mojom.Type.Tags.handle_type: self.HandleFromMojom,
697 mojom_types_mojom.Type.Tags.array_type: self.ArrayFromMojom,
698 mojom_types_mojom.Type.Tags.map_type: self.MapFromMojom,
699 mojom_types_mojom.Type.Tags.type_reference: self.UserDefinedFromTypeRef,
700 }
701 return mappers[mojom_type.tag](mojom_type)
702
703 def SimpleKindFromMojom(self, mojom_type):
704 """Translates a simple type to its module equivalent.
705
706 Args:
707 mojom_type: {mojom_types_mojom.Type} with its simple_type field set to be
708 translated.
709
710 Returns:
711 {module.Kind} translated from mojom_type.
712 """
713 simple_mojom_types = {
714 mojom_types_mojom.SimpleType.BOOL: module.BOOL,
715 mojom_types_mojom.SimpleType.INT8: module.INT8,
716 mojom_types_mojom.SimpleType.INT16: module.INT16,
717 mojom_types_mojom.SimpleType.INT32: module.INT32,
718 mojom_types_mojom.SimpleType.INT64: module.INT64,
719 mojom_types_mojom.SimpleType.UINT8: module.UINT8,
720 mojom_types_mojom.SimpleType.UINT16: module.UINT16,
721 mojom_types_mojom.SimpleType.UINT32: module.UINT32,
722 mojom_types_mojom.SimpleType.UINT64: module.UINT64,
723 mojom_types_mojom.SimpleType.FLOAT: module.FLOAT,
724 mojom_types_mojom.SimpleType.DOUBLE: module.DOUBLE,
725 }
726 return simple_mojom_types[mojom_type.simple_type]
727
728 def HandleFromMojom(self, mojom_type):
729 """Translates a handle type to its module equivalent.
730
731 Args:
732 mojom_type: {mojom_types_mojom.Type} with its handle_type field set to be
733 translated.
734
735 Returns:
736 {module.ReferenceKind} translated from mojom_type.
737 """
738 handle_mojom_types = {
739 mojom_types_mojom.HandleType.Kind.UNSPECIFIED: module.HANDLE,
740 mojom_types_mojom.HandleType.Kind.MESSAGE_PIPE: module.MSGPIPE,
741 mojom_types_mojom.HandleType.Kind.DATA_PIPE_CONSUMER: module.DCPIPE,
742 mojom_types_mojom.HandleType.Kind.DATA_PIPE_PRODUCER: module.DPPIPE,
743 mojom_types_mojom.HandleType.Kind.SHARED_BUFFER: module.SHAREDBUFFER,
744 }
745
746 nullable_handle_mojom_types = {
747 mojom_types_mojom.HandleType.Kind.UNSPECIFIED: module.NULLABLE_HANDLE,
748 mojom_types_mojom.HandleType.Kind.MESSAGE_PIPE: module.NULLABLE_MSGPIPE,
749 mojom_types_mojom.HandleType.Kind.DATA_PIPE_CONSUMER:
750 module.NULLABLE_DCPIPE,
751 mojom_types_mojom.HandleType.Kind.DATA_PIPE_PRODUCER:
752 module.NULLABLE_DPPIPE,
753 mojom_types_mojom.HandleType.Kind.SHARED_BUFFER:
754 module.NULLABLE_SHAREDBUFFER,
755 }
756
757 if mojom_type.handle_type.nullable:
758 return nullable_handle_mojom_types[mojom_type.handle_type.kind]
759 return handle_mojom_types[mojom_type.handle_type.kind]
760
761 def StringFromMojom(self, mojom_type):
762 """Translates a string type to its module equivalent.
763
764 Args:
765 mojom_type: {mojom_types_mojom.Type} with its string_type field set to be
766 translated.
767
768 Returns:
769 {module.ReferenceKind} translated from mojom_type. Either module.STRING or
770 module.NULLABLE_STRING.
771 """
772 if mojom_type.string_type.nullable:
773 return module.NULLABLE_STRING
774 return module.STRING
775
776 def ArrayFromMojom(self, mojom_type):
777 """Translates an array type to its module equivalent.
778
779 Args:
780 mojom_type: {mojom_types_mojom.Type} with its array_type field set to be
781 translated.
782
783 Returns:
784 {module.Array} translated from mojom_type.
785 """
786 array = module.Array(
787 kind=self.KindFromMojom(mojom_type.array_type.element_type))
788 if mojom_type.array_type.fixed_length > 0:
789 array.length = mojom_type.array_type.fixed_length
790 if mojom_type.array_type.nullable:
791 return array.MakeNullableKind()
792 return array
793
794 def MapFromMojom(self, mojom_type):
795 """Translates a map type to its module equivalent.
796
797 Args:
798 mojom_type: {mojom_types_mojom.Type} with its map_type field set to be
799 translated.
800
801 Returns:
802 {module.Map} translated from mojom_type.
803 """
804 key_kind = self.KindFromMojom(mojom_type.map_type.key_type)
805 value_kind = self.KindFromMojom(mojom_type.map_type.value_type)
806 module_map = module.Map(key_kind=key_kind, value_kind=value_kind)
807 if mojom_type.map_type.nullable:
808 return module_map.MakeNullableKind()
809 return module_map
810
811 def UserDefinedFromTypeRef(self, mojom_type):
812 """Translates a type reference to the module equivalent of the
813 UserDefinedType that the reference refers to.
814
815 Args:
816 mojom_type: {mojom_types_mojom.Type} with its type_reference field set to
817 be translated.
818
819 Returns:
820 {module.Enum|Struct|Union|Interface} translated from mojom_type.
821 """
822 type_key = mojom_type.type_reference.type_key
823 module_type = self.UserDefinedFromTypeKey(type_key)
824 if mojom_type.type_reference.is_interface_request:
825 module_type = module.InterfaceRequest(module_type)
826 if mojom_type.type_reference.nullable:
827 return module_type.MakeNullableKind()
828 return module_type
829
830 def UserDefinedFromTypeKey(self, type_key):
831 """Takes a type key into graph.resolved_types and returns the module
832 equivalent.
833
834 Args:
835 type_key: {str} the type key referring to the type to be returned.
836
837 Returns:
838 {module.Enum|Struct|Union|Interface} translated.
839 """
840 if type_key in self._type_cache:
841 return self._type_cache[type_key]
842 else:
843 mojom_type = self._graph.resolved_types[type_key]
844 return self.UserDefinedFromMojom(type_key, mojom_type)
845
846 def UserDefinedFromMojom(self, type_key, mojom_type):
847 """Translates a user defined type to its module equivalent.
848
849 Args:
850 type_key: {str} the type key referring to the type in graph.resolved_types
851 used to cache the type object.
852 mojom_type: {mojom_types_mojom.UserDefinedType} to be translated.
853
854 Returns:
855 {module.Enum|Struct|Union|Interface} translated from mojom_type.
856 """
857 user_defined_types = {
858 mojom_types_mojom.UserDefinedType.Tags.struct_type:
859 (module.Struct, self.StructFromMojom),
860 mojom_types_mojom.UserDefinedType.Tags.enum_type:
861 (module.Enum, self.EnumFromMojom),
862 mojom_types_mojom.UserDefinedType.Tags.union_type:
863 (module.Union, self.UnionFromMojom),
864 mojom_types_mojom.UserDefinedType.Tags.interface_type:
865 (module.Interface, self.InterfaceFromMojom),
866 }
867 module_type_class, from_mojom = user_defined_types[mojom_type.tag]
868 module_type = module_type_class()
869
870 if module_type.spec == None:
871 # module.py expects the spec of user defined types to be set when
872 # constructing map, array, and interface request types, but the value
873 # appears to be only used for error messages.
874 module_type.spec = 'dummyspec'
875
876 # It is necessary to cache the type object before populating it since in
877 # the course of populating it, it may be necessary to resolve that same
878 # type (say, a struct with a field of its own type).
879 self._type_cache[type_key] = module_type
880 from_mojom(module_type, mojom_type)
881
882 module_type.type_key = type_key
883
884 return module_type
885
886
887 def TranslateFileGraph(graph):
888 """Translates a mojom_types_mojom.MojomFileGraph to module.Module(s).
889
890 The input is the output of the parser. The output is the input to the
891 various bindings generators.
892
893 Args:
894 graph: {mojom_types_mojom.MojomFileGraph} to be translated.
895
896 Return:
897 {dict<str, module.Module>} mapping the file's name to its module.Module
898 translation for all files in graph.files.
899 """
900 return {file_name: FileTranslator(graph, file_name).Translate()
901 for file_name in graph.files}
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698