insndb: make walk yield paths
authorDmitry Selyutin <ghostmansd@gmail.com>
Sat, 10 Jun 2023 19:00:56 +0000 (22:00 +0300)
committerDmitry Selyutin <ghostmansd@gmail.com>
Sat, 10 Jun 2023 19:00:56 +0000 (22:00 +0300)
src/openpower/insndb/core.py
src/openpower/insndb/db.py

index 70e9c16cf62a58faf48e44c9646cae9edfd77024..23e68e393d4c53f9efa4496fbb943c8b3cd3888e 100644 (file)
@@ -72,7 +72,7 @@ class walkmethod:
 class Node:
     @walkmethod
     def walk(clsself, match=None):
-        return ()
+        yield from ()
 
 
 class DataclassMeta(type):
@@ -93,9 +93,12 @@ class Dataclass(Node, metaclass=DataclassMeta):
         def field_value(field):
             return getattr(clsself, field.name)
 
-        field = (field_type if isinstance(clsself, type) else field_value)
+        field_node = (field_type if isinstance(clsself, type) else field_value)
 
-        yield from filter(match, map(field, _dataclasses.fields(clsself)))
+        for field in _dataclasses.fields(clsself):
+            path = field.name
+            node = field_node(field)
+            yield (path, node)
 
 
 class Tuple(Node, tuple):
@@ -109,11 +112,11 @@ class Tuple(Node, tuple):
             match = lambda subnode: True
 
         if isinstance(clsself, type):
-            yield clsself.__datatype
+            yield ("[]", clsself.__datatype)
         else:
-            for item in clsself:
+            for (index, item) in enumerate(clsself):
                 if match(item):
-                    yield item
+                    yield (str(index), item)
 
 
 class VisitorMethod:
@@ -127,8 +130,8 @@ class VisitorMethod:
         return self.__nodecls
 
     @_contextlib.contextmanager
-    def __call__(self, node):
-        return self.__method(self=self, node=node)
+    def __call__(self, path, node):
+        return self.__method(self=self, path=path, node=node)
 
 
 class VisitorMeta(type):
@@ -156,11 +159,11 @@ class VisitorMeta(type):
 
 class Visitor(metaclass=VisitorMeta):
     @_contextlib.contextmanager
-    def __call__(self, node):
+    def __call__(self, path, node):
         (visitorcls, nodecls) = map(type, (self, node))
         if nodecls in visitorcls:
             handler = visitorcls[nodecls]
-            with handler(node=node) as ctx:
+            with handler(path=path, node=node) as ctx:
                 yield ctx
         else:
             yield node
@@ -180,18 +183,18 @@ class visitormethod:
 
 
 def walk(root, match=None):
-    nodes = _collections.deque([root])
-    while nodes:
-        node = nodes.popleft()
-        nodes.extend(node.walk(match=match))
-        yield node
+    pairs = _collections.deque([root])
+    while pairs:
+        (path, node) = pairs.popleft()
+        pairs.extend(node.walk(match=match))
+        yield (path, node)
 
 
-def visit(visitor, node):
-    with visitor(node=node):
+def visit(visitor, node, path="/"):
+    with visitor(path=path, node=node):
         if isinstance(node, Node):
-            for subnode in node.walk():
-                visit(visitor=visitor, node=subnode)
+            for (subpath, subnode) in node.walk():
+                visit(visitor=visitor, path=subpath, node=subnode)
 
 
 @_functools.total_ordering
@@ -3834,10 +3837,10 @@ class Database(Node):
             match = lambda subnode: True
 
         if isinstance(clsself, type):
-            yield Records
+            yield ("records", Records)
         else:
             if match(clsself.__db):
-                yield clsself.__db
+                yield ("records", clsself.__db)
 
     def __repr__(self):
         return repr(self.__db)
index fb9ee05cf45238a38a10d2e24cc56213800c496a..15b915b99bf2fa69138bc5607de1bd57e09b9570 100644 (file)
@@ -45,9 +45,9 @@ class TreeVisitor(Visitor):
         return super().__init__()
 
     @contextlib.contextmanager
-    def __call__(self, node):
-        with super().__call__(node) as node:
-            print((" " * (self.__depth * 4)), repr(node))
+    def __call__(self, path, node):
+        with super().__call__(path=path, node=node):
+            print((" " * (self.__depth * 4)), path)
             self.__depth += 1
             yield node
             self.__depth -= 1
@@ -55,7 +55,7 @@ class TreeVisitor(Visitor):
 
 class ListVisitor(Visitor):
     @visitormethod(Record)
-    def Record(self, node):
+    def Record(self, path, node):
         print(node.name)
         yield node
 
@@ -70,7 +70,7 @@ class SVP64InstructionVisitor(InstructionVisitor):
 
 class OpcodesVisitor(InstructionVisitor):
     @visitormethod(Record)
-    def Record(self, node):
+    def Record(self, path, node):
         for opcode in node.opcodes:
             print(opcode)
         yield node
@@ -78,7 +78,7 @@ class OpcodesVisitor(InstructionVisitor):
 
 class OperandsVisitor(InstructionVisitor):
     @visitormethod(Record)
-    def Record(self, node):
+    def Record(self, path, node):
         if isinstance(node, Record):
             for operand in node.dynamic_operands:
                 print(operand.name, ",".join(map(str, operand.span)))
@@ -91,7 +91,7 @@ class OperandsVisitor(InstructionVisitor):
 
 class PCodeVisitor(InstructionVisitor):
     @visitormethod(Record)
-    def Record(self, node):
+    def Record(self, path, node):
         if isinstance(node, Record):
             for line in node.pcode:
                 print(line)
@@ -100,7 +100,7 @@ class PCodeVisitor(InstructionVisitor):
 
 class ExtrasVisitor(SVP64InstructionVisitor):
     @visitormethod(Record)
-    def Record(self, node):
+    def Record(self, path, node):
         for (name, extra) in node.extras.items():
             print(name)
             print("    sel", extra["sel"])
@@ -163,7 +163,7 @@ def main():
     visitor = commands[command][0]()
 
     db = Database(find_wiki_dir())
-    records = next(db.walk(match=lambda node: isinstance(node, Records)))
+    (path, records) = next(db.walk(match=lambda node: isinstance(node, Records)))
     if not isinstance(visitor, InstructionVisitor):
         match = None
     else:
@@ -171,8 +171,8 @@ def main():
         def match(record):
             return (isinstance(record, Record) and (record.name == insn))
 
-    for node in records.walk(match=match):
-        visit(visitor=visitor, node=node)
+    for (subpath, node) in records.walk(match=match):
+        visit(visitor=visitor, node=node, path=subpath)
 
 
 if __name__ == "__main__":