comparison python/c3/codegenerator.py @ 170:4348da5ca307

Cleanup of ir dir
author Windel Bouwman
date Fri, 29 Mar 2013 17:33:17 +0100
parents ee0d30533dae
children 3eb9b9e2958d
comparison
equal deleted inserted replaced
169:ee0d30533dae 170:4348da5ca307
1 import ir 1 import ir
2 from . import astnodes 2 from . import astnodes
3
4 def genModule(pkg):
5 m = ir.Module(pkg.name)
6 for s in pkg.scope:
7 if type(s) is astnodes.Variable:
8 genGlobal(m, s)
9 elif type(s) is astnodes.Function:
10 genFunction(m, s)
11 else:
12 print(s)
13 return m
14
15 def genGlobal(m, var):
16 v = ir.Value()
17 v.name = var.name
18 m.Globals.append(v)
19
20 def genFunction(m, fnc):
21 ft = genType(fnc.typ)
22 f = ir.Function(fnc.name, ft)
23 m.Functions.append(f)
24 bb = ir.BasicBlock()
25 f.BasicBlocks.append(bb)
26 genCode(bb, fnc.body)
27 bb.Instructions.append(ir.RetInstruction())
28
29 def genCode(bb, code):
30 if type(code) is astnodes.CompoundStatement:
31 for s in code.statements:
32 genCode(bb, s)
33 elif type(code) is astnodes.Assignment:
34 genExprCode(bb, code.rval)
35 # TODO: store
36 elif type(code) is astnodes.IfStatement:
37 genExprCode(bb, code.condition)
38 # TODO: implement IF.
39 t1, t2 = 1, 2
40 b = ir.BranchInstruction(t1, t2)
41 bb.Instructions.append(b)
42 genCode(bb, code.truestatement)
43 genCode(bb, code.falsestatement)
44 elif type(code) is astnodes.FunctionCall:
45 ins = ir.CallInstruction('f', [])
46 bb.Instructions.append(ins)
47 elif type(code) is astnodes.EmptyStatement:
48 pass
49 elif type(code) is astnodes.ReturnStatement:
50 bb.Instructions.append(ir.RetInstruction())
51 else:
52 print('Unknown stmt:', code)
53 3
54 def NumGen(): 4 def NumGen():
55 a = 0 5 a = 0
56 while True: 6 while True:
57 yield a 7 yield a
58 a = a + 1 8 a = a + 1
59 9
60 nums = NumGen() 10 class NameGenerator:
61 def unique(): 11 def __init__(self, prefix):
62 return 'tmp{0}'.format(nums.__next__()) 12 self.prefix = prefix
13 self.nums = NumGen()
14 def gen(self):
15 return '{0}{1}'.format(self.prefix, self.nums.__next__())
63 16
64 def genExprCode(bb, code): 17 class CodeGenerator:
65 if type(code) is astnodes.Binop: 18 """ Generates intermediate code from a package """
66 a = genExprCode(bb, code.a) 19 def gencode(self, pkg):
67 b = genExprCode(bb, code.b) 20 assert type(pkg) is astnodes.Package
68 ops = {'+': 'fadd', '-': 'fsub', '*':'fmul', '/':'fdiv'} 21 self.m = ir.Module(pkg.name)
69 if code.op in ops: 22 self.newTmp = NameGenerator('t').gen
70 op = ops[code.op] 23 self.newLab = NameGenerator('lab').gen
24 self.genModule(pkg)
25 return self.m
26
27 # Helpers:
28 def addIns(self, i):
29 self.m.Instructions.append(i)
30 # inner helpers:
31 def genModule(self, pkg):
32 for s in pkg.scope:
33 if type(s) is astnodes.Variable:
34 # TODO
35 pass
36 elif type(s) is astnodes.Function:
37 # TODO: handle arguments
38 # TODO handle return?
39 self.addIns(ir.LabelInstruction(s.name))
40 self.genCode(s.body)
41 self.addIns(ir.RetInstruction())
42 else:
43 print(s)
44
45 def genCode(self, code):
46 if type(code) is astnodes.CompoundStatement:
47 for s in code.statements:
48 self.genCode(s)
49 elif type(code) is astnodes.Assignment:
50 re = self.genExprCode(code.rval)
51 self.addIns(ir.StoreInstruction(code.lval, re))
52 elif type(code) is astnodes.IfStatement:
53 cr = self.genExprCode(code.condition)
54 t1, t2, te = self.newLab(), self.newLab(), self.newLab()
55 self.addIns(ir.IfInstruction(cr, t1, t2))
56 self.addIns(ir.LabelInstruction(t1))
57 self.genCode(code.truestatement)
58 self.addIns(ir.BranchInstruction(te))
59 self.addIns(ir.LabelInstruction(t2))
60 self.genCode(code.falsestatement)
61 self.addIns(ir.LabelInstruction(te))
62 elif type(code) is astnodes.FunctionCall:
63 pass
64 elif type(code) is astnodes.EmptyStatement:
65 pass
66 elif type(code) is astnodes.ReturnStatement:
67 pass
68 else:
69 print('Unknown stmt:', code)
70
71 def genExprCode(self, expr):
72 if type(expr) is astnodes.Binop:
73 ra = self.genExprCode(expr.a)
74 rb = self.genExprCode(expr.b)
75 ops = ['+', '-', '*', '/', 'and', 'or']
76 if expr.op in ops:
77 op = expr.op
78 tmp = self.newTmp()
79 ins = ir.BinaryOperator(tmp, op, ra, rb)
80 self.addIns(ins)
81 return tmp
82 else:
83 print('Unknown binop {0}'.format(expr))
84 elif type(expr) is astnodes.Constant:
71 tmp = unique() 85 tmp = unique()
72 ins = ir.BinaryOperator(tmp, op, a, b) 86 elif type(expr) is astnodes.VariableUse:
73 bb.Instructions.append(ins) 87 tmp = self.newTmp()
88 elif type(expr) is astnodes.Literal:
89 tmp = self.newTmp()
90 ins = ir.MoveInstruction(tmp, expr.val)
91 self.addIns(ins)
74 return tmp 92 return tmp
75 else: 93 else:
76 print('Unknown binop {0}'.format(code)) 94 print('Unknown expr:', code)
77 bb.Instructions.append(ir.BinaryOperator('unk2', code.op, a, b))
78 return 'unk2'
79 elif type(code) is astnodes.Constant:
80 tmp = unique()
81 bb.Instructions.append(ir.LoadInstruction(tmp, code.value))
82 return tmp
83 elif type(code) is astnodes.VariableUse:
84 tmp = unique()
85 ins = ir.LoadInstruction(tmp, code.target.name)
86 return tmp
87 elif type(code) is astnodes.Literal:
88 tmp = unique()
89 ins = ir.LoadInstruction(tmp, code.val)
90 return tmp
91 else:
92 print('Unknown expr:', code)
93 return 'unk'
94 95
95 def genType(t):
96 return ir.Type()
97
98 class CodeGenerator:
99 """ Generates intermediate code """
100 def gencode(self, ast):
101 assert type(ast) is astnodes.Package
102 return genModule(ast)
103