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