power_fields: support traversal
authorDmitry Selyutin <ghostmansd@gmail.com>
Sun, 28 Aug 2022 10:45:05 +0000 (13:45 +0300)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Mon, 29 Aug 2022 19:38:52 +0000 (20:38 +0100)
src/openpower/decoder/power_fields.py

index a500059f3af9c80304325d8c390cb396ffaef2a0..f41b89e3db5feafdd9f6db1448f9ffa547b3d7e5 100644 (file)
@@ -46,7 +46,7 @@ class Reference:
         _ = (args, kwargs)
 
     def __binary_operator(self, op, other):
-        span = self.__class__.span
+        span = dict.fromkeys(self.__class__.span).keys()
         lhs = _selectconcat(*(self.storage[bit] for bit in span))
 
         if isinstance(other, Field):
@@ -133,10 +133,6 @@ class FieldMeta(type):
     def __len__(cls):
         return len(cls.__members__)
 
-    @property
-    def span(cls):
-        return cls.__members__
-
     def remap(cls, scheme):
         if isinstance(scheme, type) and issubclass(scheme, Mapping):
             scheme = range(len(scheme))
@@ -153,6 +149,13 @@ class FieldMeta(type):
 
         return cls.__class__(cls.__name__, (cls,), {}, items=items)
 
+    @property
+    def span(cls):
+        return cls.__members__
+
+    def traverse(cls, path):
+        yield (path, cls.__members__)
+
 
 class Field(Reference, metaclass=FieldMeta):
     def __len__(self):
@@ -244,6 +247,10 @@ class ArrayMeta(type):
         for field in cls.__members__:
             yield from field.span
 
+    def traverse(cls, path=""):
+        for (idx, field) in cls:
+            yield from field.traverse(path=f"{path}[{idx}]")
+
 
 class Array(Reference, metaclass=ArrayMeta):
     def __init__(self, storage):
@@ -326,6 +333,15 @@ class MappingMeta(type):
         for field in cls.__members__.values():
             yield from field.span
 
+    def traverse(cls, path=""):
+        for (name, field) in cls:
+            if name == "_":
+                yield from field.traverse(path=path)
+            elif path == "":
+                yield from field.traverse(path=name)
+            else:
+                yield from field.traverse(path=f"{path}.{name}")
+
 
 class Mapping(Reference, metaclass=MappingMeta):
     def __init__(self, storage, **kwargs):