summaryrefslogtreecommitdiff
path: root/utils/ipc/mojo/public/tools/mojom/mojom/generate/constant_resolver.py
diff options
context:
space:
mode:
Diffstat (limited to 'utils/ipc/mojo/public/tools/mojom/mojom/generate/constant_resolver.py')
-rw-r--r--utils/ipc/mojo/public/tools/mojom/mojom/generate/constant_resolver.py93
1 files changed, 93 insertions, 0 deletions
diff --git a/utils/ipc/mojo/public/tools/mojom/mojom/generate/constant_resolver.py b/utils/ipc/mojo/public/tools/mojom/mojom/generate/constant_resolver.py
new file mode 100644
index 00000000..0dfd996e
--- /dev/null
+++ b/utils/ipc/mojo/public/tools/mojom/mojom/generate/constant_resolver.py
@@ -0,0 +1,93 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Resolves the values used for constants and enums."""
+
+from itertools import ifilter
+
+from mojom.generate import module as mojom
+
+
+def ResolveConstants(module, expression_to_text):
+ in_progress = set()
+ computed = set()
+
+ def GetResolvedValue(named_value):
+ assert isinstance(named_value, (mojom.EnumValue, mojom.ConstantValue))
+ if isinstance(named_value, mojom.EnumValue):
+ field = next(
+ ifilter(lambda field: field.name == named_value.name,
+ named_value.enum.fields), None)
+ if not field:
+ raise RuntimeError(
+ 'Unable to get computed value for field %s of enum %s' %
+ (named_value.name, named_value.enum.name))
+ if field not in computed:
+ ResolveEnum(named_value.enum)
+ return field.resolved_value
+ else:
+ ResolveConstant(named_value.constant)
+ named_value.resolved_value = named_value.constant.resolved_value
+ return named_value.resolved_value
+
+ def ResolveConstant(constant):
+ if constant in computed:
+ return
+ if constant in in_progress:
+ raise RuntimeError('Circular dependency for constant: %s' % constant.name)
+ in_progress.add(constant)
+ if isinstance(constant.value, (mojom.EnumValue, mojom.ConstantValue)):
+ resolved_value = GetResolvedValue(constant.value)
+ else:
+ resolved_value = expression_to_text(constant.value)
+ constant.resolved_value = resolved_value
+ in_progress.remove(constant)
+ computed.add(constant)
+
+ def ResolveEnum(enum):
+ def ResolveEnumField(enum, field, default_value):
+ if field in computed:
+ return
+ if field in in_progress:
+ raise RuntimeError('Circular dependency for enum: %s' % enum.name)
+ in_progress.add(field)
+ if field.value:
+ if isinstance(field.value, mojom.EnumValue):
+ resolved_value = GetResolvedValue(field.value)
+ elif isinstance(field.value, str):
+ resolved_value = int(field.value, 0)
+ else:
+ raise RuntimeError('Unexpected value: %s' % field.value)
+ else:
+ resolved_value = default_value
+ field.resolved_value = resolved_value
+ in_progress.remove(field)
+ computed.add(field)
+
+ current_value = 0
+ for field in enum.fields:
+ ResolveEnumField(enum, field, current_value)
+ current_value = field.resolved_value + 1
+
+ for constant in module.constants:
+ ResolveConstant(constant)
+
+ for enum in module.enums:
+ ResolveEnum(enum)
+
+ for struct in module.structs:
+ for constant in struct.constants:
+ ResolveConstant(constant)
+ for enum in struct.enums:
+ ResolveEnum(enum)
+ for field in struct.fields:
+ if isinstance(field.default, (mojom.ConstantValue, mojom.EnumValue)):
+ field.default.resolved_value = GetResolvedValue(field.default)
+
+ for interface in module.interfaces:
+ for constant in interface.constants:
+ ResolveConstant(constant)
+ for enum in interface.enums:
+ ResolveEnum(enum)
+
+ return module