155
|
1 import ir
|
|
2 from . import astnodes
|
151
|
3
|
158
|
4 def NumGen():
|
|
5 a = 0
|
|
6 while True:
|
|
7 yield a
|
|
8 a = a + 1
|
|
9
|
170
|
10 class NameGenerator:
|
|
11 def __init__(self, prefix):
|
|
12 self.prefix = prefix
|
|
13 self.nums = NumGen()
|
|
14 def gen(self):
|
|
15 return '{0}{1}'.format(self.prefix, self.nums.__next__())
|
|
16
|
|
17 class CodeGenerator:
|
|
18 """ Generates intermediate code from a package """
|
|
19 def gencode(self, pkg):
|
|
20 assert type(pkg) is astnodes.Package
|
|
21 self.m = ir.Module(pkg.name)
|
|
22 self.newTmp = NameGenerator('t').gen
|
|
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)
|
158
|
44
|
170
|
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:
|
158
|
85 tmp = unique()
|
170
|
86 elif type(expr) is astnodes.VariableUse:
|
|
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)
|
158
|
92 return tmp
|
157
|
93 else:
|
170
|
94 print('Unknown expr:', code)
|
157
|
95
|