oppc/code: support simple constant unary exprs
[openpower-isa.git] / src / openpower / oppc / pc_pseudocode.py
1 import collections
2
3 import openpower.oppc.pc_ast as pc_ast
4 import openpower.oppc.pc_util as pc_util
5
6
7 class PseudocodeVisitor(pc_util.Visitor):
8 def __init__(self, root):
9 self.__code = collections.defaultdict(lambda: pc_util.Code())
10 self.__root = root
11
12 return super().__init__(root=root)
13
14 def __iter__(self):
15 yield from self.__code[self.__root]
16
17 def __getitem__(self, node):
18 return self.__code[node]
19
20 @pc_util.Hook(pc_ast.Scope)
21 def Scope(self, node):
22 yield node
23 if node is not self.__root:
24 with self[node]:
25 for subnode in node:
26 for (level, stmt) in self[subnode]:
27 self[node].emit(stmt=stmt, level=level)
28 else:
29 for subnode in node:
30 for (level, stmt) in self[subnode]:
31 self[node].emit(stmt=stmt, level=level)
32
33 @pc_util.Hook(pc_ast.Call)
34 def Call(self, node):
35 yield node
36 args = []
37 for subnode in node.args:
38 for (level, stmt) in self[subnode]:
39 assert level == 0
40 args.append(stmt)
41 args = ", ".join(args)
42 stmt = f"{node.name}({args})"
43 self[node].emit(stmt=stmt)
44
45 @pc_util.Hook(pc_ast.AssignExpr, pc_ast.AssignIEAExpr)
46 def AssignExpr(self, node):
47 mapping = {
48 pc_ast.AssignExpr: "<-",
49 pc_ast.AssignIEAExpr: "<-iea",
50 }
51 yield node
52 lvalue = str(self[node.lvalue])
53 if (isinstance(node.lvalue, (pc_ast.GPR, pc_ast.FPR)) or
54 (isinstance(node.lvalue, (pc_ast.Subscript, pc_ast.RangeSubscript)) and
55 isinstance(node.lvalue.subject, (pc_ast.GPR, pc_ast.FPR)))):
56 lvalue = lvalue.replace("(", "").replace(")", "")
57 rvalue = str(self[node.rvalue])
58
59 if isinstance(node.rvalue, pc_ast.IfExpr):
60 stmt = " ".join([
61 lvalue,
62 mapping[node.__class__],
63 str(self[node.rvalue.test]),
64 "?",
65 str(self[node.rvalue.body[0]]),
66 ":",
67 str(self[node.rvalue.orelse[0]]),
68 ])
69 else:
70 stmt = " ".join([
71 lvalue,
72 mapping[node.__class__],
73 rvalue,
74 ])
75 self[node].emit(stmt=stmt)
76
77 @pc_util.Hook(pc_ast.BinaryExpr)
78 def BinaryExpr(self, node):
79 yield node
80 stmt = " ".join([
81 str(self[node.left]),
82 str(self[node.op]),
83 str(self[node.right]),
84 ])
85 self[node].emit(stmt=f"({stmt})")
86
87 @pc_util.Hook(pc_ast.IfExpr)
88 def IfExpr(self, node):
89 yield node
90 stmt = " ".join([
91 "if",
92 str(self[node.test]),
93 "then",
94 ])
95 self[node].emit(stmt=stmt)
96 for (level, stmt) in self[node.body]:
97 self[node].emit(stmt=stmt, level=level)
98 if node.orelse:
99 self[node].emit("else")
100 for (level, stmt) in self[node.orelse]:
101 self[node].emit(stmt=stmt, level=level)
102
103 @pc_util.Hook(pc_ast.ForExpr)
104 def ForExpr(self, node):
105 yield node
106 stmt = " ".join([
107 "for",
108 str(self[node.subject]),
109 "=",
110 str(self[node.start]),
111 "to",
112 str(self[node.end]),
113 ])
114 self[node].emit(stmt=stmt)
115 for (level, stmt) in self[node.body]:
116 self[node].emit(stmt=stmt, level=level)
117
118 @pc_util.Hook(pc_ast.WhileExpr)
119 def WhileExpr(self, node):
120 yield node
121 stmt = " ".join([
122 "do",
123 "while",
124 str(self[node.test]),
125 ])
126 self[node].emit(stmt=stmt)
127 for (level, stmt) in self[node.body]:
128 self[node].emit(stmt=stmt, level=level)
129 if node.orelse:
130 self[node].emit("else")
131 for (level, stmt) in self[node.orelse]:
132 self[node].emit(stmt=stmt, level=level)
133
134 @pc_util.Hook(pc_ast.RepeatExpr)
135 def RepeatExpr(self, node):
136 yield node
137 stmt = " ".join([
138 f"[{str(self[node.subject])}]",
139 "*",
140 str(self[node.times]),
141 ])
142 self[node].emit(stmt=f"({stmt})")
143
144 @pc_util.Hook(pc_ast.SwitchExpr)
145 def SwitchExpr(self, node):
146 yield node
147 self[node].emit(f"switch({str(self[node.subject])})")
148 with self[node]:
149 for (level, stmt) in self[node.cases]:
150 self[node].emit(stmt=stmt, level=level)
151
152 @pc_util.Hook(pc_ast.Cases)
153 def Cases(self, node):
154 yield node
155 for subnode in node:
156 for (level, stmt) in self[subnode]:
157 self[node].emit(stmt=stmt, level=level)
158
159 @pc_util.Hook(pc_ast.Case)
160 def Case(self, node):
161 yield node
162 for (level, stmt) in self[node.labels]:
163 self[node].emit(stmt=stmt, level=level)
164 for (level, stmt) in self[node.body]:
165 self[node].emit(stmt=stmt, level=level)
166
167 @pc_util.Hook(pc_ast.Labels)
168 def Labels(self, node):
169 yield node
170 if ((len(node) == 1) and isinstance(node[-1], pc_ast.DefaultLabel)):
171 stmt = "default:"
172 else:
173 labels = ", ".join(map(lambda label: str(self[label]), node))
174 stmt = f"case ({labels}):"
175 self[node].emit(stmt=stmt)
176
177 @pc_util.Hook(pc_ast.Label)
178 def Label(self, node):
179 yield node
180 self[node].emit(stmt=str(node))
181
182 @pc_util.Hook(pc_ast.DefaultLabel)
183 def DefaultLabel(self, node):
184 yield node
185 self[node].emit(stmt="default:")
186
187 @pc_util.Hook(pc_ast.UnaryExpr)
188 def UnaryExpr(self, node):
189 yield node
190 stmt = "".join([
191 str(self[node.op]),
192 f"({str(self[node.value])})",
193 ])
194 self[node].emit(stmt=stmt)
195
196 @pc_util.Hook(pc_ast.BinLiteral, pc_ast.DecLiteral, pc_ast.HexLiteral)
197 def Integer(self, node):
198 yield node
199 self[node].emit(stmt=str(node))
200
201 @pc_util.Hook(pc_ast.StringLiteral)
202 def StringLiteral(self, node):
203 yield node
204 self[node].emit(stmt=f"'{str(node)}'")
205
206 @pc_util.Hook(pc_ast.Symbol)
207 def Symbol(self, node):
208 yield node
209 self[node].emit(stmt=str(node))
210
211 @pc_util.Hook(pc_ast.Attribute)
212 def Attribute(self, node):
213 yield node
214 stmt = ".".join([
215 str(self[node.subject]),
216 str(self[node.name]),
217 ])
218 self[node].emit(stmt=stmt)
219
220 @pc_util.Hook(pc_ast.Not, pc_ast.Add, pc_ast.Sub,
221 pc_ast.Mul, pc_ast.MulS, pc_ast.MulU,
222 pc_ast.Div, pc_ast.DivT, pc_ast.Mod,
223 pc_ast.Sqrt,
224 pc_ast.Eq, pc_ast.NotEq,
225 pc_ast.Lt, pc_ast.Le, pc_ast.LtU,
226 pc_ast.Gt, pc_ast.Ge, pc_ast.GtU,
227 pc_ast.LShift, pc_ast.RShift,
228 pc_ast.AssignOp, pc_ast.AssignIEAOp,
229 pc_ast.BitAnd, pc_ast.BitOr, pc_ast.BitXor,
230 pc_ast.BitConcat)
231 def Op(self, node):
232 yield node
233 mapping = {
234 pc_ast.Not: "¬",
235 pc_ast.Add: "+",
236 pc_ast.Sub: "-",
237 pc_ast.Mul: "*",
238 pc_ast.MulS: "*si",
239 pc_ast.MulU: "*ui",
240 pc_ast.Div: "/",
241 pc_ast.DivT: "÷",
242 pc_ast.Mod: "%",
243 pc_ast.Sqrt: "√",
244 pc_ast.Eq: "=",
245 pc_ast.NotEq: "!=",
246 pc_ast.Lt: "<",
247 pc_ast.Le: "<=",
248 pc_ast.LtU: "<u",
249 pc_ast.Gt: ">",
250 pc_ast.Ge: ">=",
251 pc_ast.GtU: ">u",
252 pc_ast.LShift: "<<",
253 pc_ast.RShift: ">>",
254 pc_ast.AssignOp: "<-",
255 pc_ast.AssignIEAOp: "<-iea",
256 pc_ast.BitAnd: "&",
257 pc_ast.BitOr: "|",
258 pc_ast.BitXor: "^",
259 pc_ast.BitConcat: "||",
260 }
261 stmt = mapping[node.__class__]
262 self[node].emit(stmt=stmt)
263
264 @pc_util.Hook(pc_ast.LParenthesis, pc_ast.RParenthesis,
265 pc_ast.LBracket, pc_ast.RBracket)
266 def BracketOrParenthesis(self, node):
267 yield node
268 mapping = {
269 pc_ast.LParenthesis: "(",
270 pc_ast.RParenthesis: ")",
271 pc_ast.LBracket: "[",
272 pc_ast.RBracket: "]",
273 }
274 stmt = mapping[node.__class__]
275 self[node].emit(stmt=stmt)
276
277 @pc_util.Hook(pc_ast.Subscript)
278 def Subscript(self, node):
279 yield node
280 stmt = "".join([
281 str(self[node.subject]),
282 "[",
283 str(self[node.index]),
284 "]",
285 ])
286 self[node].emit(stmt=stmt)
287
288 @pc_util.Hook(pc_ast.RangeSubscript)
289 def RangeSubscript(self, node):
290 yield node
291 stmt = "".join([
292 str(self[node.subject]),
293 "[",
294 str(self[node.start]),
295 ":",
296 str(self[node.end]),
297 "]",
298 ])
299 self[node].emit(stmt=stmt)
300
301 @pc_util.Hook(pc_ast.Colon)
302 def Colon(self, node):
303 yield node
304 self[node].emit(stmt=":")
305
306 @pc_util.Hook(pc_ast.Linebreak, pc_ast.Endmarker)
307 def Ignore(self, node):
308 yield node
309
310 @pc_util.Hook(pc_ast.Keyword)
311 def Keyword(self, node):
312 yield node
313 self[node].emit(stmt=node.__doc__)
314
315 @pc_util.Hook(pc_ast.Sequence)
316 def Sequence(self, node):
317 yield node
318 stmt = ",".join(map(lambda subnode: str(self[subnode]), node))
319 self[node].emit(stmt=f"({stmt})")
320
321 @pc_util.Hook(pc_ast.Literal)
322 def Literal(self, node):
323 yield node
324 self[node].emit(stmt=str(node))
325
326 @pc_util.Hook(pc_ast.GPR, pc_ast.FPR, pc_ast.GPRZero)
327 def Reg(self, node):
328 yield node
329 if isinstance(node, pc_ast.GPRZero):
330 self[node].emit(stmt=f"({str(node)}|0)")
331 else:
332 self[node].emit(stmt=f"({str(node)})")
333
334 @pc_util.Hook(pc_ast.Node)
335 def Node(self, node):
336 raise NotImplementedError(type(node))
337
338
339 def pseudocode(root):
340 yield from PseudocodeVisitor(root=root)