oppc/ast: hash node by id
[openpower-isa.git] / src / openpower / oppc / pc_ast.py
1 import copy
2 import dataclasses
3
4
5 class NodeMeta(type):
6 pass
7
8
9 class Node(metaclass=NodeMeta):
10 def __repr__(self):
11 return f"{hex(id(self))}@{self.__class__.__name__}()"
12
13 def __hash__(self):
14 return id(self)
15
16 def __eq__(self, other):
17 if not isinstance(other, self.__class__):
18 return NotImplemented
19 return (hex(id(self)) == id(other))
20
21 def clone(self):
22 return copy.deepcopy(self)
23
24
25 class TokenMeta(NodeMeta):
26 pass
27
28
29 class Token(Node, str, metaclass=TokenMeta):
30 def __new__(cls, value):
31 if isinstance(value, cls):
32 value = str(value)
33 if not isinstance(value, str):
34 raise ValueError(value)
35
36 return super().__new__(cls, value)
37
38 def __str__(self):
39 return super(Node, self).__str__()
40
41 def __hash__(self):
42 return super(Node, self).__hash__()
43
44 def __repr__(self):
45 return f"{hex(id(self))}@{self.__class__.__name__}({str(self)})"
46
47
48 class SequenceMeta(NodeMeta):
49 __typeid__ = Node
50
51 def __new__(metacls, clsname, bases, ns, *, typeid=Node):
52 ns.setdefault("__typeid__", typeid)
53
54 return super().__new__(metacls, clsname, bases, ns)
55
56
57 class Sequence(Node, tuple, metaclass=SequenceMeta):
58 def __new__(cls, iterable=tuple()):
59 def validate(item):
60 if not isinstance(item, cls.__typeid__):
61 raise ValueError(cls, item)
62 return item
63
64 return super().__new__(cls, map(validate, iterable))
65
66 def __hash__(self):
67 return super(Node, self).__hash__()
68
69 def __repr__(self):
70 return f"{hex(id(self))}@{self.__class__.__name__}({repr(list(self))})"
71
72
73 class Scope(Sequence):
74 pass
75
76
77 class Module(Sequence):
78 pass
79
80
81 class DataclassMeta(NodeMeta):
82 def __new__(metacls, clsname, bases, ns):
83 cls = super().__new__(metacls, clsname, bases, ns)
84 wrap = dataclasses.dataclass(init=True, eq=False, unsafe_hash=True, frozen=False)
85 datacls = wrap(cls)
86 origin = datacls.__repr__
87 datacls.__repr__ = lambda self: f"{hex(id(self))}@{origin(self)}"
88
89 return datacls
90
91
92 class Dataclass(Node, metaclass=DataclassMeta):
93 def __post_init__(self):
94 for field in dataclasses.fields(self):
95 key = field.name
96 value = getattr(self, key)
97 if not isinstance(value, field.type):
98 raise ValueError(f"{self.__class__.__name__}.{key}: {value!r}")
99
100 def clone(self, **kwargs):
101 return copy.deepcopy(dataclasses.replace(self, **kwargs))
102
103
104 class LiteralMeta(TokenMeta):
105 def __new__(metacls, clsname, bases, ns, *, choices=()):
106 ns.setdefault("__choices__", choices)
107
108 return super().__new__(metacls, clsname, bases, ns)
109
110 def __iter__(cls):
111 yield from cls.__choices__
112
113
114 class Literal(Token, metaclass=LiteralMeta):
115 __choices__ = ()
116
117 def __new__(cls, value):
118 choices = cls.__choices__
119 if isinstance(value, Token):
120 value = str(value)
121 if choices and value not in choices:
122 raise ValueError(value)
123
124 return super().__new__(cls, value)
125
126
127 class GPR(Literal, choices=("RA", "RB", "RC", "RS", "RSp", "RT", "RTp")):
128 pass
129
130
131 class GPRZero(GPR, choices=("RA", "RB", "RC")):
132 pass
133
134
135 class FPR(Literal, choices=("FPR", "FRA", "FRAp", "FRB", "FRBp", "FRC", "FRS", "FRSp", "FRT", "FRTp")):
136 pass
137
138
139 class CR3(Literal, choices=("BF", "BFA")):
140 pass
141
142
143 class CR5(Literal, choices=("BA", "BB", "BC", "BI", "BT")):
144 pass
145
146
147 class XER(Literal, choices=("OV", "OV32", "CA", "CA32", "SO")):
148 pass
149
150
151 class Reserve(Literal, choices=("RESERVE", "RESERVE_LENGTH", "RESERVE_ADDR")):
152 pass
153
154
155 class Overflow(Literal, choices=("overflow",)):
156 pass
157
158
159 class Special(Literal, choices=(
160 "CR", "LR", "CTR", "TAR", "FPSCR", "MSR",
161 "SVSTATE", "SVREMAP", "SRR0", "SRR1",
162 "SVSHAPE0", "SVSHAPE1", "SVSHAPE2", "SVSHAPE3",
163 )):
164 pass
165
166
167 class XLEN(Literal, choices=("XLEN",)):
168 pass
169
170
171 class IntLiteral(Literal):
172 pass
173
174
175 class BinLiteral(IntLiteral):
176 r"""0b[01_]+"""
177 pass
178
179
180 class HexLiteral(IntLiteral):
181 r"""0x[0-9A-Fa-f_]+"""
182 pass
183
184
185 class DecLiteral(IntLiteral):
186 r"""(\d+(\.\d*)?|\.\d+)([eE][-+]? \d+)?"""
187 pass
188
189
190 class Symbol(Token):
191 r"""[A-Za-z_]+[A-Za-z0-9_]*"""
192 pass
193
194
195 class Attribute(Dataclass):
196 name: Symbol
197 subject: Node = Node()
198
199
200 class StringLiteral(Literal):
201 __STRING_ESCAPE = r"""(\\[0-9a-zA-Z._~!=&\^\-\\?'"])"""
202 __STRING_CHAR = (r"""([^"\\\n]|""" + __STRING_ESCAPE + ")")
203 __STRING = ("[\"']" + __STRING_CHAR + "*" + "[\"']")
204
205 __doc__ = __STRING
206
207 def __repr__(self):
208 return f"{hex(id(self))}@{self.__class__.__name__}({self.__str__()!r})"
209
210
211 class Whitespace(Token):
212 r"""[^\S\r\n]+"""
213
214
215 class Linebreak(Token):
216 r"""[\r\n]+"""
217
218
219 class Comment(Token):
220 r"""[ ]*(?:\043|<!--)[^\n]*"""
221 pass
222
223
224 class Indent(Node):
225 pass
226
227
228 class Dedent(Node):
229 pass
230
231
232 class LBracket(Token):
233 r"""\["""
234 pass
235
236
237 class RBracket(Token):
238 r"""\]"""
239 pass
240
241
242 class LParenthesis(Token):
243 r"""\("""
244 pass
245
246
247 class RParenthesis(Token):
248 r"""\)"""
249 pass
250
251
252 class Call(Dataclass):
253 class Name(Symbol):
254 pass
255
256 class Arguments(Sequence):
257 pass
258
259 name: Name
260 args: Arguments
261
262
263 class AssignOp(Token):
264 r"""<-"""
265 pass
266
267
268 class AssignIEAOp(Token):
269 r"""<-iea"""
270 pass
271
272
273 class AssignExpr(Dataclass):
274 lvalue: Node
275 rvalue: Node
276
277
278 class AssignIEAExpr(AssignExpr):
279 lvalue: Node
280 rvalue: Node
281
282
283 class Not(Token):
284 r"""(?:¬|~)"""
285 pass
286
287
288 class Add(Token):
289 r"""\+"""
290 pass
291
292
293 class Sub(Token):
294 r"""\-"""
295 pass
296
297
298 class Plus(Node):
299 pass
300
301
302 class Minus(Node):
303 pass
304
305
306 class Mul(Token):
307 r"""(?:×|\*)"""
308 pass
309
310
311 class MulS(Token):
312 r"""(?:×si|×s|\*si|\*s)"""
313 pass
314
315
316 class MulU(Token):
317 r"""(?:×ui|×u|\*ui|\*u)"""
318 pass
319
320
321 class Div(Token):
322 r"""/"""
323 pass
324
325
326 class DivT(Token):
327 r"""÷"""
328 pass
329
330
331 class Mod(Token):
332 r"""%"""
333 pass
334
335
336 class Sqrt(Token):
337 r"""√"""
338 pass
339
340
341 class Eq(Token):
342 r"""="""
343 pass
344
345
346 class NotEq(Token):
347 r"""(?:≠|!=)"""
348 pass
349
350
351 class Lt(Token):
352 r"""<"""
353 pass
354
355
356 class Le(Token):
357 r"""<="""
358 pass
359
360
361 class Ge(Token):
362 r""">="""
363 pass
364
365
366 class Gt(Token):
367 r""">"""
368 pass
369
370
371 class LtU(Token):
372 r"""<u"""
373 pass
374
375
376 class GtU(Token):
377 r""">u"""
378 pass
379
380
381 class BitAnd(Token):
382 r"""&"""
383 pass
384
385
386 class BitOr(Token):
387 r"""\|"""
388 pass
389
390
391 class BitXor(Token):
392 r"""(?:⊕|≡|\^)"""
393 pass
394
395
396 class UnaryExpr(Dataclass):
397 op: Node
398 value: Node
399
400
401 class BinaryExpr(Dataclass):
402 left: Node
403 op: Node
404 right: Node
405
406
407 class Keyword(Token):
408 pass
409
410
411 class FunctionKeyword(Token):
412 f"""def"""
413 pass
414
415
416 class IfKeyword(Keyword):
417 r"""if"""
418 pass
419
420
421 class ThenKeyword(Keyword):
422 r"""then"""
423 pass
424
425
426 class ElseKeyword(Keyword):
427 r"""else"""
428 pass
429
430
431 class LeaveKeyword(Keyword):
432 r"""leave"""
433 pass
434
435
436 class ForKeyword(Keyword):
437 r"""for"""
438 pass
439
440
441 class ToKeyword(Keyword):
442 r"""to"""
443 pass
444
445
446 class WhileKeyword(Keyword):
447 r"""while"""
448 pass
449
450
451 class DoKeyword(Keyword):
452 r"""while"""
453 pass
454
455
456 class ReturnKeyword(Keyword):
457 r"""return"""
458 pass
459
460
461 class SwitchKeyword(Keyword):
462 r"""switch"""
463 pass
464
465
466 class CaseKeyword(Keyword):
467 r"""case"""
468 pass
469
470
471 class DefaultKeyword(Keyword):
472 r"""while"""
473 pass
474
475
476 class Colon(Token):
477 r""":"""
478 pass
479
480
481 class LShift(Token):
482 r"""<<"""
483 pass
484
485
486 class RShift(Token):
487 r""">>"""
488 pass
489
490
491 class Comma(Token):
492 r""","""
493 pass
494
495
496 class Period(Token):
497 r"""\."""
498 pass
499
500
501 class Semicolon(Token):
502 r""";"""
503 pass
504
505
506 class BitConcat(Token):
507 r"""\|\|"""
508 pass
509
510
511 class Question(Token):
512 r"""\?"""
513 pass
514
515
516 class Endmarker(Node):
517 pass
518
519
520 class IfExpr(Dataclass):
521 test: Node
522 body: Scope
523 orelse: Scope
524
525
526 class ForExpr(Dataclass):
527 subject: Node
528 start: Node
529 end: Node
530 body: Scope
531
532
533 class WhileExpr(Dataclass):
534 test: Node
535 body: Scope
536 orelse: Scope
537
538
539 class RepeatExpr(Dataclass):
540 subject: Node
541 times: Node
542
543
544 class SubscriptExpr(Dataclass):
545 index: Node
546 subject: Node = Node()
547
548
549 class RangeSubscriptExpr(Dataclass):
550 start: Node
551 end: Node = Node()
552 subject: Node = Node()
553
554
555 class Label(Literal):
556 pass
557
558
559 class DefaultLabel(Label):
560 def __new__(cls):
561 return super().__new__(cls, "default")
562
563
564 class Labels(Sequence, typeid=Label):
565 pass
566
567
568 class Case(Dataclass):
569 labels: Labels
570 body: Scope
571
572
573 class Cases(Sequence, typeid=Case):
574 pass
575
576
577 class SwitchExpr(Dataclass):
578 subject: Node
579 cases: Cases