From: Dmitry Selyutin Date: Tue, 9 Jan 2024 18:08:41 +0000 (+0300) Subject: oppc: decouple pseudocode module X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=64483a5f85b1a81e4eb4aa903c6bb0f71124d235;p=openpower-isa.git oppc: decouple pseudocode module --- diff --git a/src/openpower/oppc/__main__.py b/src/openpower/oppc/__main__.py index 420b4d84..deb165a2 100644 --- a/src/openpower/oppc/__main__.py +++ b/src/openpower/oppc/__main__.py @@ -8,7 +8,7 @@ from openpower.decoder.power_enums import ( import openpower.oppc.pc_lexer as pc_lexer import openpower.oppc.pc_parser as pc_parser -import openpower.oppc.pc_util as pc_util +import openpower.oppc.pc_pseudocode as pc_pseudocode def dedent(line): @@ -21,7 +21,7 @@ def parse(parser, origin): origin = tuple(origin) tree = parser.parse(code="\n".join(origin)) stream = io.StringIO() - for (level, line) in pc_util.pseudocode(tree): + for (level, line) in pc_pseudocode.pseudocode(tree): print(f"{' ' * 4 * level}{line}", file=stream) stream.seek(0) target = tuple(stream) @@ -64,5 +64,5 @@ RA <- result[64-XLEN:63] """ tree = parser.parse(code=code) print(tree) -for (level, line) in pc_util.pseudocode(tree): +for (level, line) in pc_pseudocode.pseudocode(tree): print(f"{' ' * 4 * level}{line}") diff --git a/src/openpower/oppc/pc_pseudocode.py b/src/openpower/oppc/pc_pseudocode.py new file mode 100644 index 00000000..76058ecb --- /dev/null +++ b/src/openpower/oppc/pc_pseudocode.py @@ -0,0 +1,406 @@ +import collections +import contextlib +import functools + +import mdis.dispatcher +import mdis.visitor +import mdis.walker + +import openpower.oppc.pc_ast as pc_ast + + +class Hook(mdis.dispatcher.Hook): + def __call__(self, call): + hook = super().__call__(call) + + class ConcreteHook(hook.__class__): + @functools.wraps(hook.__call__) + @contextlib.contextmanager + def __call__(self, dispatcher, node, *args, **kwargs): + return hook(dispatcher, node, *args, **kwargs) + + return ConcreteHook(*tuple(self)) + + +class Code(list): + def __init__(self): + self.__level = 0 + return super().__init__() + + def __enter__(self): + self.__level += 1 + return self + + def __exit__(self, exc_type, exc_value, exc_traceback): + self.__level -= 1 + + def __str__(self): + if len(self) == 0: + raise ValueError("empty code") + + lines = [] + for (level, stmt) in self: + line = ((" " * level * 4) + stmt) + lines.append(line) + + return "\n".join(lines) + + def emit(self, stmt, level=0): + item = ((level + self.__level), stmt) + self.append(item) + + +class PseudocodeVisitor(mdis.visitor.ContextVisitor): + def __init__(self, root): + self.__root = root + self.__code = collections.defaultdict(lambda: Code()) + + return super().__init__() + + def __iter__(self): + yield from self.__code.items() + + def __getitem__(self, node): + return self.__code[node] + + @Hook(pc_ast.Scope) + def Scope(self, node): + yield node + if node is not self.__root: + with self[node]: + for subnode in node: + for (level, stmt) in self[subnode]: + self[node].emit(stmt=stmt, level=level) + else: + for subnode in node: + for (level, stmt) in self[subnode]: + self[node].emit(stmt=stmt, level=level) + + @Hook(pc_ast.Call) + def Call(self, node): + yield node + args = [] + for subnode in node.args: + for (level, stmt) in self[subnode]: + assert level == 0 + args.append(stmt) + args = ", ".join(args) + stmt = f"{node.name}({args})" + self[node].emit(stmt=stmt) + + @Hook(pc_ast.AssignExpr, pc_ast.AssignIEAExpr) + def AssignExpr(self, node): + mapping = { + pc_ast.AssignExpr: "<-", + pc_ast.AssignIEAExpr: "<-iea", + } + yield node + lvalue = str(self[node.lvalue]) + if (isinstance(node.lvalue, (pc_ast.GPR, pc_ast.FPR)) or + (isinstance(node.lvalue, (pc_ast.Subscript, pc_ast.RangeSubscript)) and + isinstance(node.lvalue.subject, (pc_ast.GPR, pc_ast.FPR)))): + lvalue = lvalue.replace("(", "").replace(")", "") + rvalue = str(self[node.rvalue]) + + if isinstance(node.rvalue, pc_ast.IfExpr): + # All right, this deserves an explanation. + # We basically convert T <- C ? A : B into this code: + # + # if C then + # T <- A + # else + # T <- B + # + # To make things work, we must ensure that objects are unique. + # Otherwise we'll reuse the bogus code already produced before. + (body, orelse) = map(lambda node: node.clone(), + (node.rvalue.body[0], node.rvalue.orelse[0])) + body = pc_ast.Scope([node.__class__(lvalue=node.lvalue.clone(), rvalue=body)]) + orelse = pc_ast.Scope([node.__class__(lvalue=node.lvalue.clone(), rvalue=orelse)]) + tmpnode = node.rvalue.clone(body=body, orelse=orelse) + walker = mdis.walker.Walker() + traverse(root=tmpnode, visitor=self, walker=walker) + for (level, stmt) in self[tmpnode]: + self[node].emit(stmt=stmt, level=level) + else: + stmt = " ".join([ + lvalue, + mapping[node.__class__], + rvalue, + ]) + self[node].emit(stmt=stmt) + + @Hook(pc_ast.BinaryExpr) + def BinaryExpr(self, node): + yield node + stmt = " ".join([ + str(self[node.left]), + str(self[node.op]), + str(self[node.right]), + ]) + self[node].emit(stmt=f"({stmt})") + + @Hook(pc_ast.IfExpr) + def IfExpr(self, node): + yield node + stmt = " ".join([ + "if", + str(self[node.test]), + "then", + ]) + self[node].emit(stmt=stmt) + for (level, stmt) in self[node.body]: + self[node].emit(stmt=stmt, level=level) + if node.orelse: + self[node].emit("else") + for (level, stmt) in self[node.orelse]: + self[node].emit(stmt=stmt, level=level) + + @Hook(pc_ast.ForExpr) + def ForExpr(self, node): + yield node + stmt = " ".join([ + "for", + str(self[node.subject]), + "=", + str(self[node.start]), + "to", + str(self[node.end]), + ]) + self[node].emit(stmt=stmt) + for (level, stmt) in self[node.body]: + self[node].emit(stmt=stmt, level=level) + + @Hook(pc_ast.WhileExpr) + def WhileExpr(self, node): + yield node + stmt = " ".join([ + "do", + "while", + str(self[node.test]), + ]) + self[node].emit(stmt=stmt) + for (level, stmt) in self[node.body]: + self[node].emit(stmt=stmt, level=level) + if node.orelse: + self[node].emit("else") + for (level, stmt) in self[node.orelse]: + self[node].emit(stmt=stmt, level=level) + + @Hook(pc_ast.RepeatExpr) + def RepeatExpr(self, node): + yield node + stmt = " ".join([ + f"[{str(self[node.subject])}]", + "*", + str(self[node.times]), + ]) + self[node].emit(stmt=f"({stmt})") + + @Hook(pc_ast.SwitchExpr) + def SwitchExpr(self, node): + yield node + self[node].emit(f"switch({str(self[node.subject])})") + with self[node]: + for (level, stmt) in self[node.cases]: + self[node].emit(stmt=stmt, level=level) + + @Hook(pc_ast.Cases) + def Cases(self, node): + yield node + for subnode in node: + for (level, stmt) in self[subnode]: + self[node].emit(stmt=stmt, level=level) + + @Hook(pc_ast.Case) + def Case(self, node): + yield node + for (level, stmt) in self[node.labels]: + self[node].emit(stmt=stmt, level=level) + for (level, stmt) in self[node.body]: + self[node].emit(stmt=stmt, level=level) + + @Hook(pc_ast.Labels) + def Labels(self, node): + yield node + if ((len(node) == 1) and isinstance(node[-1], pc_ast.DefaultLabel)): + stmt = "default:" + else: + labels = ", ".join(map(lambda label: str(self[label]), node)) + stmt = f"case ({labels}):" + self[node].emit(stmt=stmt) + + @Hook(pc_ast.Label) + def Label(self, node): + yield node + self[node].emit(stmt=str(node)) + + @Hook(pc_ast.DefaultLabel) + def DefaultLabel(self, node): + yield node + self[node].emit(stmt="default:") + + @Hook(pc_ast.UnaryExpr) + def UnaryExpr(self, node): + yield node + stmt = "".join([ + str(self[node.op]), + f"({str(self[node.value])})", + ]) + self[node].emit(stmt=stmt) + + @Hook(pc_ast.BinLiteral, pc_ast.DecLiteral, pc_ast.HexLiteral) + def Integer(self, node): + yield node + self[node].emit(stmt=str(node)) + + @Hook(pc_ast.StringLiteral) + def StringLiteral(self, node): + yield node + self[node].emit(stmt=f"'{str(node)}'") + + @Hook(pc_ast.Symbol) + def Symbol(self, node): + yield node + self[node].emit(stmt=str(node)) + + @Hook(pc_ast.Attribute) + def Attribute(self, node): + yield node + stmt = ".".join([ + str(self[node.subject]), + str(self[node.name]), + ]) + self[node].emit(stmt=stmt) + + @Hook(pc_ast.Not, pc_ast.Add, pc_ast.Sub, + pc_ast.Mul, pc_ast.MulS, pc_ast.MulU, + pc_ast.Div, pc_ast.DivT, pc_ast.Mod, + pc_ast.Sqrt, + pc_ast.Eq, pc_ast.NotEq, + pc_ast.Lt, pc_ast.Le, pc_ast.LtU, + pc_ast.Gt, pc_ast.Ge, pc_ast.GtU, + pc_ast.LShift, pc_ast.RShift, + pc_ast.AssignOp, pc_ast.AssignIEAOp, + pc_ast.BitAnd, pc_ast.BitOr, pc_ast.BitXor, + pc_ast.BitConcat) + def Op(self, node): + yield node + mapping = { + pc_ast.Not: "¬", + pc_ast.Add: "+", + pc_ast.Sub: "-", + pc_ast.Mul: "*", + pc_ast.MulS: "*si", + pc_ast.MulU: "*ui", + pc_ast.Div: "/", + pc_ast.DivT: "÷", + pc_ast.Mod: "%", + pc_ast.Sqrt: "√", + pc_ast.Eq: "=", + pc_ast.NotEq: "!=", + pc_ast.Lt: "<", + pc_ast.Le: "<=", + pc_ast.LtU: "", + pc_ast.Ge: ">=", + pc_ast.GtU: ">u", + pc_ast.LShift: "<<", + pc_ast.RShift: ">>", + pc_ast.AssignOp: "<-", + pc_ast.AssignIEAOp: "<-iea", + pc_ast.BitAnd: "&", + pc_ast.BitOr: "|", + pc_ast.BitXor: "^", + pc_ast.BitConcat: "||", + } + stmt = mapping[node.__class__] + self[node].emit(stmt=stmt) + + @Hook(pc_ast.LParenthesis, pc_ast.RParenthesis, + pc_ast.LBracket, pc_ast.RBracket) + def BracketOrParenthesis(self, node): + yield node + mapping = { + pc_ast.LParenthesis: "(", + pc_ast.RParenthesis: ")", + pc_ast.LBracket: "[", + pc_ast.RBracket: "]", + } + stmt = mapping[node.__class__] + self[node].emit(stmt=stmt) + + @Hook(pc_ast.Subscript) + def Subscript(self, node): + yield node + stmt = "".join([ + str(self[node.subject]), + "[", + str(self[node.index]), + "]", + ]) + self[node].emit(stmt=stmt) + + @Hook(pc_ast.RangeSubscript) + def RangeSubscript(self, node): + yield node + stmt = "".join([ + str(self[node.subject]), + "[", + str(self[node.start]), + ":", + str(self[node.end]), + "]", + ]) + self[node].emit(stmt=stmt) + + @Hook(pc_ast.Colon) + def Colon(self, node): + yield node + self[node].emit(stmt=":") + + @Hook(pc_ast.Linebreak, pc_ast.Endmarker) + def Ignore(self, node): + yield node + + @Hook(pc_ast.Keyword) + def Keyword(self, node): + yield node + self[node].emit(stmt=node.__doc__) + + @Hook(pc_ast.Sequence) + def Sequence(self, node): + yield node + stmt = ",".join(map(lambda subnode: str(self[subnode]), node)) + self[node].emit(stmt=f"({stmt})") + + @Hook(pc_ast.Literal) + def Literal(self, node): + yield node + self[node].emit(stmt=str(node)) + + @Hook(pc_ast.GPR, pc_ast.FPR, pc_ast.GPRZero) + def Reg(self, node): + yield node + if isinstance(node, pc_ast.GPRZero): + self[node].emit(stmt=f"({str(node)}|0)") + else: + self[node].emit(stmt=f"({str(node)})") + + @Hook(pc_ast.Node) + def Node(self, node): + raise NotImplementedError(type(node)) + + +def traverse(root, visitor, walker): + with visitor(root): + for node in walker(root): + traverse(root=node, visitor=visitor, walker=walker) + + +def pseudocode(root): + walker = mdis.walker.Walker() + visitor = PseudocodeVisitor(root=root) + traverse(root=root, visitor=visitor, walker=walker) + for (level, stmt) in visitor[root]: + yield (level, stmt) diff --git a/src/openpower/oppc/pc_util.py b/src/openpower/oppc/pc_util.py deleted file mode 100644 index 76058ecb..00000000 --- a/src/openpower/oppc/pc_util.py +++ /dev/null @@ -1,406 +0,0 @@ -import collections -import contextlib -import functools - -import mdis.dispatcher -import mdis.visitor -import mdis.walker - -import openpower.oppc.pc_ast as pc_ast - - -class Hook(mdis.dispatcher.Hook): - def __call__(self, call): - hook = super().__call__(call) - - class ConcreteHook(hook.__class__): - @functools.wraps(hook.__call__) - @contextlib.contextmanager - def __call__(self, dispatcher, node, *args, **kwargs): - return hook(dispatcher, node, *args, **kwargs) - - return ConcreteHook(*tuple(self)) - - -class Code(list): - def __init__(self): - self.__level = 0 - return super().__init__() - - def __enter__(self): - self.__level += 1 - return self - - def __exit__(self, exc_type, exc_value, exc_traceback): - self.__level -= 1 - - def __str__(self): - if len(self) == 0: - raise ValueError("empty code") - - lines = [] - for (level, stmt) in self: - line = ((" " * level * 4) + stmt) - lines.append(line) - - return "\n".join(lines) - - def emit(self, stmt, level=0): - item = ((level + self.__level), stmt) - self.append(item) - - -class PseudocodeVisitor(mdis.visitor.ContextVisitor): - def __init__(self, root): - self.__root = root - self.__code = collections.defaultdict(lambda: Code()) - - return super().__init__() - - def __iter__(self): - yield from self.__code.items() - - def __getitem__(self, node): - return self.__code[node] - - @Hook(pc_ast.Scope) - def Scope(self, node): - yield node - if node is not self.__root: - with self[node]: - for subnode in node: - for (level, stmt) in self[subnode]: - self[node].emit(stmt=stmt, level=level) - else: - for subnode in node: - for (level, stmt) in self[subnode]: - self[node].emit(stmt=stmt, level=level) - - @Hook(pc_ast.Call) - def Call(self, node): - yield node - args = [] - for subnode in node.args: - for (level, stmt) in self[subnode]: - assert level == 0 - args.append(stmt) - args = ", ".join(args) - stmt = f"{node.name}({args})" - self[node].emit(stmt=stmt) - - @Hook(pc_ast.AssignExpr, pc_ast.AssignIEAExpr) - def AssignExpr(self, node): - mapping = { - pc_ast.AssignExpr: "<-", - pc_ast.AssignIEAExpr: "<-iea", - } - yield node - lvalue = str(self[node.lvalue]) - if (isinstance(node.lvalue, (pc_ast.GPR, pc_ast.FPR)) or - (isinstance(node.lvalue, (pc_ast.Subscript, pc_ast.RangeSubscript)) and - isinstance(node.lvalue.subject, (pc_ast.GPR, pc_ast.FPR)))): - lvalue = lvalue.replace("(", "").replace(")", "") - rvalue = str(self[node.rvalue]) - - if isinstance(node.rvalue, pc_ast.IfExpr): - # All right, this deserves an explanation. - # We basically convert T <- C ? A : B into this code: - # - # if C then - # T <- A - # else - # T <- B - # - # To make things work, we must ensure that objects are unique. - # Otherwise we'll reuse the bogus code already produced before. - (body, orelse) = map(lambda node: node.clone(), - (node.rvalue.body[0], node.rvalue.orelse[0])) - body = pc_ast.Scope([node.__class__(lvalue=node.lvalue.clone(), rvalue=body)]) - orelse = pc_ast.Scope([node.__class__(lvalue=node.lvalue.clone(), rvalue=orelse)]) - tmpnode = node.rvalue.clone(body=body, orelse=orelse) - walker = mdis.walker.Walker() - traverse(root=tmpnode, visitor=self, walker=walker) - for (level, stmt) in self[tmpnode]: - self[node].emit(stmt=stmt, level=level) - else: - stmt = " ".join([ - lvalue, - mapping[node.__class__], - rvalue, - ]) - self[node].emit(stmt=stmt) - - @Hook(pc_ast.BinaryExpr) - def BinaryExpr(self, node): - yield node - stmt = " ".join([ - str(self[node.left]), - str(self[node.op]), - str(self[node.right]), - ]) - self[node].emit(stmt=f"({stmt})") - - @Hook(pc_ast.IfExpr) - def IfExpr(self, node): - yield node - stmt = " ".join([ - "if", - str(self[node.test]), - "then", - ]) - self[node].emit(stmt=stmt) - for (level, stmt) in self[node.body]: - self[node].emit(stmt=stmt, level=level) - if node.orelse: - self[node].emit("else") - for (level, stmt) in self[node.orelse]: - self[node].emit(stmt=stmt, level=level) - - @Hook(pc_ast.ForExpr) - def ForExpr(self, node): - yield node - stmt = " ".join([ - "for", - str(self[node.subject]), - "=", - str(self[node.start]), - "to", - str(self[node.end]), - ]) - self[node].emit(stmt=stmt) - for (level, stmt) in self[node.body]: - self[node].emit(stmt=stmt, level=level) - - @Hook(pc_ast.WhileExpr) - def WhileExpr(self, node): - yield node - stmt = " ".join([ - "do", - "while", - str(self[node.test]), - ]) - self[node].emit(stmt=stmt) - for (level, stmt) in self[node.body]: - self[node].emit(stmt=stmt, level=level) - if node.orelse: - self[node].emit("else") - for (level, stmt) in self[node.orelse]: - self[node].emit(stmt=stmt, level=level) - - @Hook(pc_ast.RepeatExpr) - def RepeatExpr(self, node): - yield node - stmt = " ".join([ - f"[{str(self[node.subject])}]", - "*", - str(self[node.times]), - ]) - self[node].emit(stmt=f"({stmt})") - - @Hook(pc_ast.SwitchExpr) - def SwitchExpr(self, node): - yield node - self[node].emit(f"switch({str(self[node.subject])})") - with self[node]: - for (level, stmt) in self[node.cases]: - self[node].emit(stmt=stmt, level=level) - - @Hook(pc_ast.Cases) - def Cases(self, node): - yield node - for subnode in node: - for (level, stmt) in self[subnode]: - self[node].emit(stmt=stmt, level=level) - - @Hook(pc_ast.Case) - def Case(self, node): - yield node - for (level, stmt) in self[node.labels]: - self[node].emit(stmt=stmt, level=level) - for (level, stmt) in self[node.body]: - self[node].emit(stmt=stmt, level=level) - - @Hook(pc_ast.Labels) - def Labels(self, node): - yield node - if ((len(node) == 1) and isinstance(node[-1], pc_ast.DefaultLabel)): - stmt = "default:" - else: - labels = ", ".join(map(lambda label: str(self[label]), node)) - stmt = f"case ({labels}):" - self[node].emit(stmt=stmt) - - @Hook(pc_ast.Label) - def Label(self, node): - yield node - self[node].emit(stmt=str(node)) - - @Hook(pc_ast.DefaultLabel) - def DefaultLabel(self, node): - yield node - self[node].emit(stmt="default:") - - @Hook(pc_ast.UnaryExpr) - def UnaryExpr(self, node): - yield node - stmt = "".join([ - str(self[node.op]), - f"({str(self[node.value])})", - ]) - self[node].emit(stmt=stmt) - - @Hook(pc_ast.BinLiteral, pc_ast.DecLiteral, pc_ast.HexLiteral) - def Integer(self, node): - yield node - self[node].emit(stmt=str(node)) - - @Hook(pc_ast.StringLiteral) - def StringLiteral(self, node): - yield node - self[node].emit(stmt=f"'{str(node)}'") - - @Hook(pc_ast.Symbol) - def Symbol(self, node): - yield node - self[node].emit(stmt=str(node)) - - @Hook(pc_ast.Attribute) - def Attribute(self, node): - yield node - stmt = ".".join([ - str(self[node.subject]), - str(self[node.name]), - ]) - self[node].emit(stmt=stmt) - - @Hook(pc_ast.Not, pc_ast.Add, pc_ast.Sub, - pc_ast.Mul, pc_ast.MulS, pc_ast.MulU, - pc_ast.Div, pc_ast.DivT, pc_ast.Mod, - pc_ast.Sqrt, - pc_ast.Eq, pc_ast.NotEq, - pc_ast.Lt, pc_ast.Le, pc_ast.LtU, - pc_ast.Gt, pc_ast.Ge, pc_ast.GtU, - pc_ast.LShift, pc_ast.RShift, - pc_ast.AssignOp, pc_ast.AssignIEAOp, - pc_ast.BitAnd, pc_ast.BitOr, pc_ast.BitXor, - pc_ast.BitConcat) - def Op(self, node): - yield node - mapping = { - pc_ast.Not: "¬", - pc_ast.Add: "+", - pc_ast.Sub: "-", - pc_ast.Mul: "*", - pc_ast.MulS: "*si", - pc_ast.MulU: "*ui", - pc_ast.Div: "/", - pc_ast.DivT: "÷", - pc_ast.Mod: "%", - pc_ast.Sqrt: "√", - pc_ast.Eq: "=", - pc_ast.NotEq: "!=", - pc_ast.Lt: "<", - pc_ast.Le: "<=", - pc_ast.LtU: "", - pc_ast.Ge: ">=", - pc_ast.GtU: ">u", - pc_ast.LShift: "<<", - pc_ast.RShift: ">>", - pc_ast.AssignOp: "<-", - pc_ast.AssignIEAOp: "<-iea", - pc_ast.BitAnd: "&", - pc_ast.BitOr: "|", - pc_ast.BitXor: "^", - pc_ast.BitConcat: "||", - } - stmt = mapping[node.__class__] - self[node].emit(stmt=stmt) - - @Hook(pc_ast.LParenthesis, pc_ast.RParenthesis, - pc_ast.LBracket, pc_ast.RBracket) - def BracketOrParenthesis(self, node): - yield node - mapping = { - pc_ast.LParenthesis: "(", - pc_ast.RParenthesis: ")", - pc_ast.LBracket: "[", - pc_ast.RBracket: "]", - } - stmt = mapping[node.__class__] - self[node].emit(stmt=stmt) - - @Hook(pc_ast.Subscript) - def Subscript(self, node): - yield node - stmt = "".join([ - str(self[node.subject]), - "[", - str(self[node.index]), - "]", - ]) - self[node].emit(stmt=stmt) - - @Hook(pc_ast.RangeSubscript) - def RangeSubscript(self, node): - yield node - stmt = "".join([ - str(self[node.subject]), - "[", - str(self[node.start]), - ":", - str(self[node.end]), - "]", - ]) - self[node].emit(stmt=stmt) - - @Hook(pc_ast.Colon) - def Colon(self, node): - yield node - self[node].emit(stmt=":") - - @Hook(pc_ast.Linebreak, pc_ast.Endmarker) - def Ignore(self, node): - yield node - - @Hook(pc_ast.Keyword) - def Keyword(self, node): - yield node - self[node].emit(stmt=node.__doc__) - - @Hook(pc_ast.Sequence) - def Sequence(self, node): - yield node - stmt = ",".join(map(lambda subnode: str(self[subnode]), node)) - self[node].emit(stmt=f"({stmt})") - - @Hook(pc_ast.Literal) - def Literal(self, node): - yield node - self[node].emit(stmt=str(node)) - - @Hook(pc_ast.GPR, pc_ast.FPR, pc_ast.GPRZero) - def Reg(self, node): - yield node - if isinstance(node, pc_ast.GPRZero): - self[node].emit(stmt=f"({str(node)}|0)") - else: - self[node].emit(stmt=f"({str(node)})") - - @Hook(pc_ast.Node) - def Node(self, node): - raise NotImplementedError(type(node)) - - -def traverse(root, visitor, walker): - with visitor(root): - for node in walker(root): - traverse(root=node, visitor=visitor, walker=walker) - - -def pseudocode(root): - walker = mdis.walker.Walker() - visitor = PseudocodeVisitor(root=root) - traverse(root=root, visitor=visitor, walker=walker) - for (level, stmt) in visitor[root]: - yield (level, stmt)