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