view 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 source

import ir
from . import astnodes

def NumGen():
   a = 0
   while True:
      yield a
      a = a + 1

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 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()
      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 expr:', code)