155
|
1 import ir
|
|
2 from . import astnodes
|
151
|
3
|
155
|
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)
|
156
|
9 elif type(s) is astnodes.Function:
|
|
10 genFunction(m, s)
|
|
11 else:
|
|
12 print(s)
|
155
|
13 return m
|
|
14
|
|
15 def genGlobal(m, var):
|
|
16 v = ir.Value()
|
|
17 v.name = var.name
|
|
18 m.Globals.append(v)
|
151
|
19
|
156
|
20 def genFunction(m, fnc):
|
157
|
21 ft = genType(fnc.typ)
|
|
22 f = ir.Function(fnc.name, ft)
|
158
|
23 m.Functions.append(f)
|
157
|
24 bb = ir.BasicBlock()
|
|
25 f.BasicBlocks.append(bb)
|
|
26 genCode(bb, fnc.body)
|
158
|
27 bb.Instructions.append(ir.RetInstruction())
|
157
|
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:
|
158
|
34 genExprCode(bb, code.rval)
|
|
35 # TODO: store
|
157
|
36 elif type(code) is astnodes.IfStatement:
|
158
|
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)
|
157
|
42 genCode(bb, code.truestatement)
|
158
|
43 genCode(bb, code.falsestatement)
|
|
44 elif type(code) is astnodes.ProcedureCall:
|
|
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
|
|
54 def NumGen():
|
|
55 a = 0
|
|
56 while True:
|
|
57 yield a
|
|
58 a = a + 1
|
|
59
|
|
60 nums = NumGen()
|
|
61 def unique():
|
|
62 return 'tmp{0}'.format(nums.__next__())
|
|
63
|
|
64 def genExprCode(bb, code):
|
|
65 if type(code) is astnodes.Binop:
|
|
66 a = genExprCode(bb, code.a)
|
|
67 b = genExprCode(bb, code.b)
|
|
68 ops = {'+': 'fadd', '-': 'fsub', '*':'fmul', '/':'fdiv'}
|
|
69 if code.op in ops:
|
|
70 op = ops[code.op]
|
|
71 tmp = unique()
|
|
72 ins = ir.BinaryOperator(tmp, op, a, b)
|
|
73 bb.Instructions.append(ins)
|
|
74 return tmp
|
157
|
75 else:
|
158
|
76 print('Unknown binop')
|
|
77 bb.Instructions.append(ir.BinaryOperator('unk2', code.op, a, b))
|
|
78 return 'unk2'
|
157
|
79 elif type(code) is astnodes.Constant:
|
158
|
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
|
157
|
87 else:
|
158
|
88 print('Unknown expr:', code)
|
|
89 return 'unk'
|
157
|
90
|
|
91 def genType(t):
|
|
92 return ir.Type()
|
156
|
93
|
151
|
94 class CodeGenerator:
|
|
95 """ Generates intermediate code """
|
|
96 def gencode(self, ast):
|
155
|
97 assert type(ast) is astnodes.Package
|
|
98 return genModule(ast)
|
151
|
99
|