Mercurial > lcfOS
diff 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 |
line wrap: on
line diff
--- a/python/c3/codegenerator.py Sat Mar 23 18:34:41 2013 +0100 +++ b/python/c3/codegenerator.py Fri Mar 29 17:33:17 2013 +0100 @@ -1,103 +1,95 @@ import ir from . import astnodes -def genModule(pkg): - m = ir.Module(pkg.name) - for s in pkg.scope: - if type(s) is astnodes.Variable: - genGlobal(m, s) - elif type(s) is astnodes.Function: - genFunction(m, s) - else: - print(s) - return m - -def genGlobal(m, var): - v = ir.Value() - v.name = var.name - m.Globals.append(v) - -def genFunction(m, fnc): - ft = genType(fnc.typ) - f = ir.Function(fnc.name, ft) - m.Functions.append(f) - bb = ir.BasicBlock() - f.BasicBlocks.append(bb) - genCode(bb, fnc.body) - bb.Instructions.append(ir.RetInstruction()) - -def genCode(bb, code): - if type(code) is astnodes.CompoundStatement: - for s in code.statements: - genCode(bb, s) - elif type(code) is astnodes.Assignment: - genExprCode(bb, code.rval) - # TODO: store - elif type(code) is astnodes.IfStatement: - genExprCode(bb, code.condition) - # TODO: implement IF. - t1, t2 = 1, 2 - b = ir.BranchInstruction(t1, t2) - bb.Instructions.append(b) - genCode(bb, code.truestatement) - genCode(bb, code.falsestatement) - elif type(code) is astnodes.FunctionCall: - ins = ir.CallInstruction('f', []) - bb.Instructions.append(ins) - elif type(code) is astnodes.EmptyStatement: - pass - elif type(code) is astnodes.ReturnStatement: - bb.Instructions.append(ir.RetInstruction()) - else: - print('Unknown stmt:', code) - def NumGen(): a = 0 while True: yield a a = a + 1 -nums = NumGen() -def unique(): - return 'tmp{0}'.format(nums.__next__()) +class NameGenerator: + def __init__(self, prefix): + self.prefix = prefix + self.nums = NumGen() + def gen(self): + return '{0}{1}'.format(self.prefix, self.nums.__next__()) + +class CodeGenerator: + """ Generates intermediate code from a package """ + def gencode(self, pkg): + assert type(pkg) is astnodes.Package + self.m = ir.Module(pkg.name) + self.newTmp = NameGenerator('t').gen + self.newLab = NameGenerator('lab').gen + self.genModule(pkg) + return self.m + + # Helpers: + def addIns(self, i): + self.m.Instructions.append(i) + # inner helpers: + def genModule(self, pkg): + for s in pkg.scope: + if type(s) is astnodes.Variable: + # TODO + pass + elif type(s) is astnodes.Function: + # TODO: handle arguments + # TODO handle return? + self.addIns(ir.LabelInstruction(s.name)) + self.genCode(s.body) + self.addIns(ir.RetInstruction()) + else: + print(s) -def genExprCode(bb, code): - if type(code) is astnodes.Binop: - a = genExprCode(bb, code.a) - b = genExprCode(bb, code.b) - ops = {'+': 'fadd', '-': 'fsub', '*':'fmul', '/':'fdiv'} - if code.op in ops: - op = ops[code.op] + def genCode(self, code): + if type(code) is astnodes.CompoundStatement: + for s in code.statements: + self.genCode(s) + elif type(code) is astnodes.Assignment: + re = self.genExprCode(code.rval) + self.addIns(ir.StoreInstruction(code.lval, re)) + elif type(code) is astnodes.IfStatement: + cr = self.genExprCode(code.condition) + t1, t2, te = self.newLab(), self.newLab(), self.newLab() + self.addIns(ir.IfInstruction(cr, t1, t2)) + self.addIns(ir.LabelInstruction(t1)) + self.genCode(code.truestatement) + self.addIns(ir.BranchInstruction(te)) + self.addIns(ir.LabelInstruction(t2)) + self.genCode(code.falsestatement) + self.addIns(ir.LabelInstruction(te)) + elif type(code) is astnodes.FunctionCall: + pass + elif type(code) is astnodes.EmptyStatement: + pass + elif type(code) is astnodes.ReturnStatement: + pass + else: + print('Unknown stmt:', code) + + def genExprCode(self, expr): + if type(expr) is astnodes.Binop: + ra = self.genExprCode(expr.a) + rb = self.genExprCode(expr.b) + ops = ['+', '-', '*', '/', 'and', 'or'] + if expr.op in ops: + op = expr.op + tmp = self.newTmp() + ins = ir.BinaryOperator(tmp, op, ra, rb) + self.addIns(ins) + return tmp + else: + print('Unknown binop {0}'.format(expr)) + elif type(expr) is astnodes.Constant: tmp = unique() - ins = ir.BinaryOperator(tmp, op, a, b) - bb.Instructions.append(ins) + elif type(expr) is astnodes.VariableUse: + tmp = self.newTmp() + elif type(expr) is astnodes.Literal: + tmp = self.newTmp() + ins = ir.MoveInstruction(tmp, expr.val) + self.addIns(ins) return tmp else: - print('Unknown binop {0}'.format(code)) - bb.Instructions.append(ir.BinaryOperator('unk2', code.op, a, b)) - return 'unk2' - elif type(code) is astnodes.Constant: - tmp = unique() - bb.Instructions.append(ir.LoadInstruction(tmp, code.value)) - return tmp - elif type(code) is astnodes.VariableUse: - tmp = unique() - ins = ir.LoadInstruction(tmp, code.target.name) - return tmp - elif type(code) is astnodes.Literal: - tmp = unique() - ins = ir.LoadInstruction(tmp, code.val) - return tmp - else: - print('Unknown expr:', code) - return 'unk' + print('Unknown expr:', code) -def genType(t): - return ir.Type() - -class CodeGenerator: - """ Generates intermediate code """ - def gencode(self, ast): - assert type(ast) is astnodes.Package - return genModule(ast) -