11320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci# Copyright 2014 The Chromium Authors. All rights reserved.
21320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci# Use of this source code is governed by a BSD-style license that can be
31320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci# found in the LICENSE file.
41320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci"""Generates Python source files from a mojom.Module."""
61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport re
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccifrom itertools import ifilter
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport mojom.generate.generator as generator
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport mojom.generate.module as mojom
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccifrom mojom.generate.template_expander import UseJinja
131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci_kind_to_type = {
151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.BOOL:                  '_descriptor.TYPE_BOOL',
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.INT8:                  '_descriptor.TYPE_INT8',
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.UINT8:                 '_descriptor.TYPE_UINT8',
181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.INT16:                 '_descriptor.TYPE_INT16',
191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.UINT16:                '_descriptor.TYPE_UINT16',
201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.INT32:                 '_descriptor.TYPE_INT32',
211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.UINT32:                '_descriptor.TYPE_UINT32',
221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.INT64:                 '_descriptor.TYPE_INT64',
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.UINT64:                '_descriptor.TYPE_UINT64',
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.FLOAT:                 '_descriptor.TYPE_FLOAT',
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.DOUBLE:                '_descriptor.TYPE_DOUBLE',
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.STRING:                '_descriptor.TYPE_STRING',
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.NULLABLE_STRING:       '_descriptor.TYPE_NULLABLE_STRING',
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.HANDLE:                '_descriptor.TYPE_HANDLE',
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.DCPIPE:                '_descriptor.TYPE_HANDLE',
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.DPPIPE:                '_descriptor.TYPE_HANDLE',
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.MSGPIPE:               '_descriptor.TYPE_HANDLE',
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.SHAREDBUFFER:          '_descriptor.TYPE_HANDLE',
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.NULLABLE_HANDLE:       '_descriptor.TYPE_NULLABLE_HANDLE',
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.NULLABLE_DCPIPE:       '_descriptor.TYPE_NULLABLE_HANDLE',
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.NULLABLE_DPPIPE:       '_descriptor.TYPE_NULLABLE_HANDLE',
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.NULLABLE_MSGPIPE:      '_descriptor.TYPE_NULLABLE_HANDLE',
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.NULLABLE_SHAREDBUFFER: '_descriptor.TYPE_NULLABLE_HANDLE',
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci# int64 integers are not handled by array.array. int64/uint64 array are
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci# supported but storage is not optimized (ie. they are plain python list, not
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci# array.array)
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci_kind_to_typecode_for_native_array = {
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.INT8:   'b',
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.UINT8:  'B',
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.INT16:  'h',
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.UINT16: 'H',
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.INT32:  'i',
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.UINT32: 'I',
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.FLOAT:  'f',
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.DOUBLE: 'd',
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci_kind_to_typecode = dict(_kind_to_typecode_for_native_array)
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci_kind_to_typecode.update({
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.INT64:                 'q',
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.UINT64:                'Q',
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.HANDLE:                'i',
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.DCPIPE:                'i',
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.DPPIPE:                'i',
611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.MSGPIPE:               'i',
621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.SHAREDBUFFER:          'i',
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.NULLABLE_HANDLE:       'i',
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.NULLABLE_DCPIPE:       'i',
651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.NULLABLE_DPPIPE:       'i',
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.NULLABLE_MSGPIPE:      'i',
671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  mojom.NULLABLE_SHAREDBUFFER: 'i',
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci})
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccidef NameToComponent(name):
721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  # insert '_' between anything and a Title name (e.g, HTTPEntry2FooBar ->
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  # HTTP_Entry2_FooBar)
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  name = re.sub('([^_])([A-Z][^A-Z_]+)', r'\1_\2', name)
751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  # insert '_' between non upper and start of upper blocks (e.g.,
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  # HTTP_Entry2_FooBar -> HTTP_Entry2_Foo_Bar)
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  name = re.sub('([^A-Z_])([A-Z])', r'\1_\2', name)
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return [x.lower() for x in name.split('_')]
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccidef UpperCamelCase(name):
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return ''.join([x.capitalize() for x in NameToComponent(name)])
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccidef CamelCase(name):
841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  uccc = UpperCamelCase(name)
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return uccc[0].lower() + uccc[1:]
861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccidef ConstantStyle(name):
881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  components = NameToComponent(name)
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if components[0] == 'k':
901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    components = components[1:]
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return '_'.join([x.upper() for x in components])
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccidef GetNameForElement(element):
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (mojom.IsEnumKind(element) or mojom.IsInterfaceKind(element) or
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      mojom.IsStructKind(element)):
961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return UpperCamelCase(element.name)
971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if isinstance(element, mojom.EnumValue):
981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return (GetNameForElement(element.enum) + '.' +
991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            ConstantStyle(element.name))
1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if isinstance(element, (mojom.NamedValue,
1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                          mojom.Constant)):
1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return ConstantStyle(element.name)
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  raise Exception('Unexpected element: ' % element)
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccidef ExpressionToText(token):
1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if isinstance(token, (mojom.EnumValue, mojom.NamedValue)):
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return str(token.computed_value)
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if isinstance(token, mojom.BuiltinValue):
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if token.value == 'double.INFINITY' or token.value == 'float.INFINITY':
1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return 'float(\'inf\')';
1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (token.value == 'double.NEGATIVE_INFINITY' or
1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        token.value == 'float.NEGATIVE_INFINITY'):
1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return 'float(\'-inf\')'
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if token.value == 'double.NAN' or token.value == 'float.NAN':
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return 'float(\'nan\')';
1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if token in ['true', 'false']:
1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return str(token == 'true')
1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return token
1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccidef GetStructClass(kind):
1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  name = []
1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if kind.imported_from:
1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    name.append(kind.imported_from['python_module'])
1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  name.append(GetNameForElement(kind))
1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return '.'.join(name)
1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccidef GetFieldType(kind, field=None):
1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if mojom.IsAnyArrayKind(kind):
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    arguments = []
1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if kind.kind in _kind_to_typecode_for_native_array:
1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      arguments.append('%r' %_kind_to_typecode_for_native_array[kind.kind])
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    elif kind.kind != mojom.BOOL:
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      arguments.append(GetFieldType(kind.kind))
1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if mojom.IsNullableKind(kind):
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      arguments.append('nullable=True')
1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if mojom.IsFixedArrayKind(kind):
1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      arguments.append('length=%d' % kind.length)
1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    array_type = 'GenericArrayType'
1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if kind.kind == mojom.BOOL:
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      array_type = 'BooleanArrayType'
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    elif kind.kind in _kind_to_typecode_for_native_array:
1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      array_type = 'NativeArrayType'
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return '_descriptor.%s(%s)' % (array_type, ', '.join(arguments))
1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if mojom.IsStructKind(kind):
1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    arguments = [ GetStructClass(kind) ]
1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if mojom.IsNullableKind(kind):
1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      arguments.append('nullable=True')
1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return '_descriptor.StructType(%s)' % ', '.join(arguments)
1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if mojom.IsEnumKind(kind):
1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return GetFieldType(mojom.INT32)
1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return _kind_to_type.get(kind, '_descriptor.TYPE_NONE')
1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccidef GetFieldDescriptor(packed_field):
1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  field = packed_field.field
1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  class_name = 'SingleFieldGroup'
1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if field.kind == mojom.BOOL:
1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    class_name = 'FieldDescriptor'
1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  arguments = [ '%r' % field.name ]
1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  arguments.append(GetFieldType(field.kind, field))
1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  arguments.append(str(packed_field.field.ordinal))
1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if field.default:
1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if mojom.IsStructKind(field.kind):
1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      arguments.append('default_value=True')
1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    else:
1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      arguments.append('default_value=%s' % ExpressionToText(field.default))
1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return '_descriptor.%s(%s)' % (class_name, ', '.join(arguments))
1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccidef GetFieldGroup(byte):
1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if len(byte.packed_fields) > 1:
1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    descriptors = map(GetFieldDescriptor, byte.packed_fields)
1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return '_descriptor.BooleanGroup([%s])' % ', '.join(descriptors)
1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  assert len(byte.packed_fields) == 1
1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return GetFieldDescriptor(byte.packed_fields[0])
1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccidef ComputeStaticValues(module):
1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  in_progress = set()
1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  computed = set()
1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  def GetComputedValue(named_value):
1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if isinstance(named_value, mojom.EnumValue):
1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      field = next(ifilter(lambda field: field.name == named_value.name,
1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                           named_value.enum.fields), None)
1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if not field:
1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        raise RuntimeError(
1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            'Unable to get computed value for field %s of enum %s' %
1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            (named_value.name, named_value.enum.name))
1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if field not in computed:
1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        ResolveEnum(named_value.enum)
1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return field.computed_value
1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    elif isinstance(named_value, mojom.ConstantValue):
1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ResolveConstant(named_value.constant)
1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      named_value.computed_value = named_value.constant.computed_value
1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return named_value.computed_value
2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    else:
2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      print named_value
2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  def ResolveConstant(constant):
2041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if constant in computed:
2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return
2061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if constant in in_progress:
2071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      raise RuntimeError('Circular dependency for constant: %s' % constant.name)
2081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    in_progress.add(constant)
2091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if isinstance(constant.value, (mojom.EnumValue, mojom.ConstantValue)):
2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      computed_value = GetComputedValue(constant.value)
2111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    else:
2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      computed_value = ExpressionToText(constant.value)
2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    constant.computed_value = computed_value
2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    in_progress.remove(constant)
2151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    computed.add(constant)
2161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  def ResolveEnum(enum):
2181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    def ResolveEnumField(enum, field, default_value):
2191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if field in computed:
2201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        return
2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if field in in_progress:
2221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        raise RuntimeError('Circular dependency for enum: %s' % enum.name)
2231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      in_progress.add(field)
2241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if field.value:
2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if isinstance(field.value, mojom.EnumValue):
2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          computed_value = GetComputedValue(field.value)
2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        elif isinstance(field.value, str):
2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          computed_value = int(field.value, 0)
2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        else:
2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          raise RuntimeError('Unexpected value: %s' % field.value)
2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      else:
2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        computed_value = default_value
2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      field.computed_value = computed_value
2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      in_progress.remove(field)
2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      computed.add(field)
2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    current_value = 0
2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    for field in enum.fields:
2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ResolveEnumField(enum, field, current_value)
2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      current_value = field.computed_value + 1
2411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for constant in module.constants:
2431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ResolveConstant(constant)
2441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for enum in module.enums:
2461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ResolveEnum(enum)
2471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for struct in module.structs:
2491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    for constant in struct.constants:
2501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ResolveConstant(constant)
2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    for enum in struct.enums:
2521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ResolveEnum(enum)
2531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    for field in struct.fields:
2541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if isinstance(field.default, (mojom.ConstantValue, mojom.EnumValue)):
2551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        field.default.computed_value = GetComputedValue(field.default)
2561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return module
2581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass Generator(generator.Generator):
2611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  python_filters = {
2631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    'expression_to_text': ExpressionToText,
2641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    'field_group': GetFieldGroup,
2651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    'name': GetNameForElement,
2661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
2671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  @UseJinja('python_templates/module.py.tmpl', filters=python_filters)
2691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  def GeneratePythonModule(self):
2701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return {
2711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      'imports': self.GetImports(),
2721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      'enums': self.module.enums,
2731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      'module': ComputeStaticValues(self.module),
2741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      'structs': self.GetStructs(),
2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  def GenerateFiles(self, args):
2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    self.Write(self.GeneratePythonModule(),
2791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci               '%s.py' % self.module.name.replace('.mojom', '_mojom'))
2801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  def GetImports(self):
2821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    for each in self.module.imports:
2831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      each['python_module'] = each['module_name'].replace('.mojom', '_mojom')
2841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return self.module.imports
2851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  def GetJinjaParameters(self):
2871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return {
2881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      'lstrip_blocks': True,
2891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      'trim_blocks': True,
2901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
291