oppc/pseudocode: always use keywords for emit calls
[openpower-isa.git] / src / openpower / oppc / pc_util.py
index e3e184edc7284dba6fa64fc3069e4ddbcc11f446..63ea9b1ce4b3a75b5b78d577f636097bd9012947 100644 (file)
@@ -1,12 +1,10 @@
-import collections
 import contextlib
 import functools
 
-import mdis.dispatcher
+
 import mdis.visitor
 import mdis.walker
-
-import openpower.oppc.pc_ast as pc_ast
+import mdis.dispatcher
 
 
 class Hook(mdis.dispatcher.Hook):
@@ -45,362 +43,20 @@ class Code(list):
 
         return "\n".join(lines)
 
-    def emit(self, stmt, level=0):
+    def emit(self, stmt="", level=0):
         item = ((level + self.__level), stmt)
         self.append(item)
 
 
-class PseudocodeVisitor(mdis.visitor.ContextVisitor):
+class Visitor(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.Assign, pc_ast.AssignIEA)
-    def Assign(self, node):
-        mapping = {
-            pc_ast.Assign: "<-",
-            pc_ast.AssignIEA: "<-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)
+        self.__walker = mdis.walker.Walker()
 
-    @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: "<u",
-            pc_ast.Gt: ">",
-            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)
+        self.traverse(root=root)
 
+        return super().__init__()
 
-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)
+    def traverse(self, root):
+        with self(root):
+            for node in self.__walker(root):
+                self.traverse(root=node)