[Libre-soc-bugs] [Bug 1094] insndb instruction database visitor-walker is needed

bugzilla-daemon at libre-soc.org bugzilla-daemon at libre-soc.org
Wed Jun 7 10:50:21 BST 2023


https://bugs.libre-soc.org/show_bug.cgi?id=1094

--- Comment #51 from Dmitry Selyutin <ghostmansd at gmail.com> ---
I've come up with the idea based on AST example you posted, and updated the
code. I think it takes best from the ideas you posted and Jacob's managers.

https://git.libre-soc.org/?p=openpower-isa.git;a=commitdiff;h=5f07a672ec7eb1cf3206f87ddc00ea10f4430a24

The idea is: all this stuff inherits from some generic Node. Each Node-derived
can specify what subnodes it has (also of class Node).

The visiting algorithm is then described as:

class Visitor:
    @_contextlib.contextmanager
    def Node(self, node, depth):
        yield node
        for subnode in node.subnodes:
            manager = subnode.__class__.__name__
            manager = getattr(self, manager, self.Node)
            with manager(node=subnode, depth=(depth + 1)):
                pass

    def __getattr__(self, attr):
        return self.Node

    def __call__(self, node, depth):
        manager = node.__class__.__name__
        manager = getattr(self, manager, self.Node)
        return manager(node=node, depth=depth)

def visit(visitor, node):
    with visitor(node=node, depth=0):
        pass

Note the way it's called: __call__ yields either overriden context manager or
default Node context manager (and the latter just goes over subnodes).

Then anyone can specify how the specific types are handled. Here's the visitor
which filters the concrete record in database and prints its opcodes. Note that
I also have __setitem__ in this _concrete_ visitor (not on top-level) which is
used to access command line arguments (I could've used just **kwargs here, or
call setattr(concrete_visitor, cmd_arg), or whatever).

class InstructionVisitor(BaseVisitor):
    @contextlib.contextmanager
    def Database(self, node, depth):
        yield node
        for subnode in node.subnodes:
            if subnode.name == self["insn"]:
                with self(node=subnode, depth=(depth + 1)):
                    pass

class OpcodesVisitor(InstructionVisitor):
    @contextlib.contextmanager
    def Record(self, node, depth):
        for opcode in node.opcodes:
            print(opcode)
        yield node

-- 
You are receiving this mail because:
You are on the CC list for the bug.


More information about the libre-soc-bugs mailing list