• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2015 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"""Resolves the values used for constants and enums."""
6
7from itertools import ifilter
8import mojom.generate.module as mojom
9
10def ResolveConstants(module, expression_to_text):
11  in_progress = set()
12  computed = set()
13
14  def GetResolvedValue(named_value):
15    assert isinstance(named_value, (mojom.EnumValue, mojom.ConstantValue))
16    if isinstance(named_value, mojom.EnumValue):
17      field = next(ifilter(lambda field: field.name == named_value.name,
18                           named_value.enum.fields), None)
19      if not field:
20        raise RuntimeError(
21            'Unable to get computed value for field %s of enum %s' %
22            (named_value.name, named_value.enum.name))
23      if field not in computed:
24        ResolveEnum(named_value.enum)
25      return field.resolved_value
26    else:
27      ResolveConstant(named_value.constant)
28      named_value.resolved_value = named_value.constant.resolved_value
29      return named_value.resolved_value
30
31  def ResolveConstant(constant):
32    if constant in computed:
33      return
34    if constant in in_progress:
35      raise RuntimeError('Circular dependency for constant: %s' % constant.name)
36    in_progress.add(constant)
37    if isinstance(constant.value, (mojom.EnumValue, mojom.ConstantValue)):
38      resolved_value = GetResolvedValue(constant.value)
39    else:
40      resolved_value = expression_to_text(constant.value)
41    constant.resolved_value = resolved_value
42    in_progress.remove(constant)
43    computed.add(constant)
44
45  def ResolveEnum(enum):
46    def ResolveEnumField(enum, field, default_value):
47      if field in computed:
48        return
49      if field in in_progress:
50        raise RuntimeError('Circular dependency for enum: %s' % enum.name)
51      in_progress.add(field)
52      if field.value:
53        if isinstance(field.value, mojom.EnumValue):
54          resolved_value = GetResolvedValue(field.value)
55        elif isinstance(field.value, str):
56          resolved_value = int(field.value, 0)
57        else:
58          raise RuntimeError('Unexpected value: %s' % field.value)
59      else:
60        resolved_value = default_value
61      field.resolved_value = resolved_value
62      in_progress.remove(field)
63      computed.add(field)
64
65    current_value = 0
66    for field in enum.fields:
67      ResolveEnumField(enum, field, current_value)
68      current_value = field.resolved_value + 1
69
70  for constant in module.constants:
71    ResolveConstant(constant)
72
73  for enum in module.enums:
74    ResolveEnum(enum)
75
76  for struct in module.structs:
77    for constant in struct.constants:
78      ResolveConstant(constant)
79    for enum in struct.enums:
80      ResolveEnum(enum)
81    for field in struct.fields:
82      if isinstance(field.default, (mojom.ConstantValue, mojom.EnumValue)):
83        field.default.resolved_value = GetResolvedValue(field.default)
84
85  for interface in module.interfaces:
86    for constant in interface.constants:
87      ResolveConstant(constant)
88    for enum in interface.enums:
89      ResolveEnum(enum)
90
91  return module
92