class Node:
@walkmethod
def walk(clsself, match=None):
- return ()
+ yield from ()
class DataclassMeta(type):
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):
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:
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):
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
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
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)
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
class ListVisitor(Visitor):
@visitormethod(Record)
- def Record(self, node):
+ def Record(self, path, node):
print(node.name)
yield node
class OpcodesVisitor(InstructionVisitor):
@visitormethod(Record)
- def Record(self, node):
+ def Record(self, path, node):
for opcode in node.opcodes:
print(opcode)
yield node
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)))
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)
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"])
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:
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__":