Mercurial > lcfOS
comparison python/ppci/irutils.py @ 309:68b01c8abf8a
Added start of ir read and write
author | Windel Bouwman |
---|---|
date | Fri, 13 Dec 2013 13:51:02 +0100 |
parents | e609d5296ee9 |
children | 2c9768114877 |
comparison
equal
deleted
inserted
replaced
308:2e7f55319858 | 309:68b01c8abf8a |
---|---|
1 | 1 |
2 """ | 2 """ |
3 Some utilities for ir-code. | 3 Some utilities for ir-code. |
4 """ | 4 """ |
5 import re | |
5 from .ir import Temp, Block, Function, Statement | 6 from .ir import Temp, Block, Function, Statement |
7 from . import ir | |
6 | 8 |
7 def dumpgv(m, outf): | 9 def dumpgv(m, outf): |
8 print('digraph G ', file=outf) | 10 print('digraph G ', file=outf) |
9 print('{', file=outf) | 11 print('{', file=outf) |
10 for f in m.Functions: | 12 for f in m.Functions: |
20 print('"{}" -> "{}" [label="entry"]' | 22 print('"{}" -> "{}" [label="entry"]' |
21 .format(id(f), id(f.entry)), file=outf) | 23 .format(id(f), id(f.entry)), file=outf) |
22 print('}', file=outf) | 24 print('}', file=outf) |
23 | 25 |
24 | 26 |
27 class Writer: | |
28 def write(self, ir, f): | |
29 """ Write ir-code to file f """ | |
30 print(ir, file=f) | |
31 for v in ir.Variables: | |
32 print(str(v), file=f) | |
33 for fn in ir.Functions: | |
34 args = ','.join('i32 ' + str(a) for a in fn.arguments) | |
35 print('function i32 {}({})'.format(fn.name, args), file=f) | |
36 for bb in fn.Blocks: | |
37 print(' ' + str(bb), file=f) | |
38 for ins in bb.Instructions: | |
39 print(' ' + str(ins), file=f) | |
40 | |
41 | |
42 class IrParseException(Exception): | |
43 pass | |
44 | |
45 | |
46 class Reader: | |
47 def read(self, f): | |
48 """ Read ir code from file f """ | |
49 # Read lines from the file: | |
50 lines = [line.rstrip() for line in f] | |
51 | |
52 # Create a regular expression for the lexing part: | |
53 tok_spec = [ | |
54 ('NUMBER', r'\d+'), | |
55 ('ID', r'[A-Za-z][A-Za-z\d_]*'), | |
56 ('SKIP2', r' '), | |
57 ('SKIP1', r' '), | |
58 ('OTHER', r'[\.,=:;\-+*\[\]/\(\)]|>|<|{|}|&|\^|\|') | |
59 ] | |
60 tok_re = '|'.join('(?P<%s>%s)' % pair for pair in tok_spec) | |
61 gettok = re.compile(tok_re).match | |
62 | |
63 def tokenize(): | |
64 for line in lines: | |
65 if not line: | |
66 continue # Skip empty lines | |
67 mo = gettok(line) | |
68 first = True | |
69 while mo: | |
70 typ = mo.lastgroup | |
71 val = mo.group(typ) | |
72 if typ == 'ID': | |
73 if val in ['function', 'module']: | |
74 typ = val | |
75 yield (typ, val) | |
76 elif typ == 'OTHER': | |
77 typ = val | |
78 yield (typ, val) | |
79 elif typ in ['SKIP1', 'SKIP2']: | |
80 if first: | |
81 yield (typ, val) | |
82 elif typ == 'NUMBER': | |
83 yield (typ, int(val)) | |
84 else: | |
85 raise NotImplementedError(str(typ)) | |
86 first = False | |
87 pos = mo.end() | |
88 mo = gettok(line, pos) | |
89 if len(line) != pos: | |
90 raise IrParseException('Lex fault') | |
91 yield ('eol', 'eol') | |
92 yield ('eof', 'eof') | |
93 self.tokens = tokenize() | |
94 self.token = self.tokens.__next__() | |
95 | |
96 try: | |
97 module = self.parse_module() | |
98 return module | |
99 except IrParseException as e: | |
100 print(e) | |
101 | |
102 def next_token(self): | |
103 t = self.token | |
104 if t[0] != 'eof': | |
105 self.token = self.tokens.__next__() | |
106 return t | |
107 | |
108 @property | |
109 def Peak(self): | |
110 return self.token[0] | |
111 | |
112 def Consume(self, typ): | |
113 if self.Peak == typ: | |
114 return self.next_token() | |
115 else: | |
116 raise IrParseException('Expected "{}" got "{}"'.format(typ, self.Peak)) | |
117 | |
118 def parse_module(self): | |
119 """ Entry for recursive descent parser """ | |
120 self.Consume('module') | |
121 name = self.Consume('ID')[1] | |
122 module = ir.Module(name) | |
123 self.Consume('eol') | |
124 while self.Peak != 'eof': | |
125 if self.Peak == 'function': | |
126 module.add_function(self.parse_function()) | |
127 else: | |
128 raise IrParseException('Expected function got {}'.format(self.Peak)) | |
129 return module | |
130 | |
131 def parse_function(self): | |
132 self.Consume('function') | |
133 self.parse_type() | |
134 name = self.Consume('ID')[1] | |
135 function = ir.Function(name) | |
136 self.Consume('(') | |
137 while self.Peak != ')': | |
138 self.parse_type() | |
139 self.Consume('ID') | |
140 if self.Peak != ',': | |
141 break | |
142 else: | |
143 self.Consume(',') | |
144 self.Consume(')') | |
145 self.Consume('eol') | |
146 while self.Peak == 'SKIP1': | |
147 function.add_block(self.parse_block()) | |
148 return function | |
149 | |
150 def parse_type(self): | |
151 self.Consume('ID') | |
152 | |
153 def parse_block(self): | |
154 self.Consume('SKIP1') | |
155 name = self.Consume('ID')[1] | |
156 block = ir.Block(name) | |
157 self.Consume(':') | |
158 self.Consume('eol') | |
159 while self.Peak == 'SKIP2': | |
160 self.parse_statement() | |
161 return block | |
162 | |
163 def parse_statement(self): | |
164 self.Consume('SKIP2') | |
165 while self.Peak != 'eol': | |
166 # raise NotImplementedError() | |
167 self.next_token() | |
168 self.Consume('eol') | |
169 | |
170 | |
25 # Constructing IR: | 171 # Constructing IR: |
26 | 172 |
27 class NamedClassGenerator: | 173 class NamedClassGenerator: |
28 def __init__(self, prefix, cls): | 174 def __init__(self, prefix, cls): |
29 self.prefix = prefix | 175 self.prefix = prefix |
59 def setModule(self, m): | 205 def setModule(self, m): |
60 self.m = m | 206 self.m = m |
61 | 207 |
62 def newFunction(self, name): | 208 def newFunction(self, name): |
63 f = Function(name) | 209 f = Function(name) |
64 self.m.addFunc(f) | 210 self.m.add_function(f) |
65 return f | 211 return f |
66 | 212 |
67 def newBlock(self): | 213 def newBlock(self): |
68 assert self.fn | 214 assert self.fn |
69 b = self.newBlock2() | 215 b = self.newBlock2() |