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()