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