summaryrefslogblamecommitdiffstats
path: root/src/front/ast.py
blob: f2214401062e80122c52d45972234cd0e98d5a53 (plain) (tree)
1
2
3
4
                      
          
 
                   

















                                                 

                    
                                               


                                  

                                                                         
                                       
                               
 


                                               
                     
                                                             

                            
                                  

                            








                                                                                                                            
 

                                                                                                                    



                      




















                                                                                                                      
                             
                                                                                 
                                    

                                              

                            



















                                                                                                                                                                                         
                       

                                                       
                                
                                                           
                                    
                                  

                            








                                                                                                                                                          
                       



                                                          

                                 
                                                


                                    



                                                                                                                           
                       

                                                           
                                 
                                                       



                                    



                                                                                                                                                   
                       

                                                                                
                              
                                                           



                                  









                                                                                                        
                       

                                                                             



                                        
 

                       
 

                     
 

                           

                       
                                                      
 


                                                   
 





                                                   
 

                                                     
 




                                                         
 


                                                                                             
 

                                                        
 



                                                                                          

                                                     
                                                          
                        
                          
 


                                                                                                                    
 

                                                                           
 

                                                                                                          


                                          
                                                    

                       
                                                                  


                                           






                                                     

                       










                                                                  
from back.tac import *
import sys

class Node(object):
    labels = 0

    def newlabel(self):
        Node.labels += 1
        return Node.labels

    def emitlabel(self, i):
        sys.stdout.write("L" + str(i) + ":")
        sys.stdout.flush()

    def emit(self, s):
        sys.stdout.write("\t" + s + "\n")
        sys.stdout.flush()

    def debug(self, msg):
        #sys.stdout.write("DEBUG: " + msg + "\n")
        #sys.stdout.flush()
        return

class Program(Node):
    def __init__(self, functions, lineno = -1):
        self.functions = functions
        self.lineno = lineno

    def generate(self):
        self.debug("Program.generate(): functions = %s" % self.functions)
        for function in self.functions:
            function.generate()

    def __repr__(self):
        return "<Program: %s>" % self.functions

class Function(Node):
    def __init__(self, name, params, statement, lineno = -1):
        self.name = name
        self.params = params
        self.statement = statement
        self.lineno = lineno

    def generate(self):
        self.debug("Function.generate(): name = %s, params = %s, statement = %s" % (self.name, self.params, self.statement))
        print "%s:" % self.name
        begin = self.newlabel()
        after = self.newlabel()
        self.emitlabel(begin)
        self.statement.generate(begin, after)
        self.emitlabel(after)
        print

    def __repr__(self):
        return "<Function: %s(%s) at line %d: %s>" % (self.name, str(self.params), self.lineno, str(self.statement))

class Statement(Node):
    pass

class Sequence(Statement):
    def __init__(self, s1, s2, lineno = -1):
        self.s1 = s1
        self.s2 = s2
        self.lineno = lineno

    def generate(self, before, after):
        self.debug("Sequence.generate(before = %d, after = %d): s1 = %s, s2 = %s" % (before, after, self.s1, self.s2))
        if not self.s1:
            self.s2.generate(before, after)
        elif not self.s2:
            self.s1.generate(before, after)
        else:
            label = self.newlabel()
            self.s1.generate(before, label)
            self.emitlabel(label)
            self.s2.generate(label, after)

    def __repr__(self):
        return "<Sequence at line %d: %s, %s>" % (self.lineno, self.s1, self.s2)

class IfStatement(Statement):
    def __init__(self, expression, true_statement, false_statement, lineno = -1):
        self.expression = expression
        self.true_statement = true_statement
        self.false_statement = false_statement
        self.lineno = lineno

    def generate(self, before, after):
        self.debug("IfStatement.generate(before = %d, after = %d): expression = %s, true = %s, false = %s" % (before, after, self.expression, self.true_statement, self.false_statement))

        x = self.expression.reduce()

        if self.false_statement:
            true_label = self.newlabel()
            false_label = self.newlabel()
            self.emit("iffalse %s goto L%d" % (x, false_label))
            self.emitlabel(true_label)
            self.true_statement.generate(true_label, after)
            self.emit("goto L%d" % after)
            self.emitlabel(false_label)
            self.false_statement.generate(false_label, after)
        else:
            true_label = self.newlabel()
            self.emit("iffalse %s goto L%d" % (x, after))
            self.emitlabel(true_label)
            self.true_statement.generate(true_label, after)

    def __repr__(self):
        return "<IfStatement at line %d>" % self.lineno

class WhileStatement(Statement):
    def __init__(self, expression, statement, lineno = -1):
        self.expression = expression
        self.statement = statement
        self.lineno = lineno

    def generate(self, before, after):
        self.debug("WhileStatement.generate(before = %d, after = %d): expression = %s, statement = %s" % (before, after, self.expression, self.statement))
        x = self.expression.reduce()
        self.emit("iffalse %s goto L%d" % (x, after))
        label = self.newlabel()
        self.emitlabel(label)
        self.statement.generate(label, before)
        self.emit("goto L%d" % before)

    def __repr__(self):
        return "<WhileStatement at line %d>" % self.lineno

    def eval(self,tacarray):
        return tacarray.append(te)

class ReturnStatement(Statement):
    def __init__(self, expression, lineno = -1):
        self.expression = expression
        self.lineno = lineno

    def generate(self, before, after):
        self.debug("ReturnStatement.generate(before = %d, after = %d): expression = %s" % (before, after, self.expression))
        self.emit("return %s" % self.expression.reduce())

    def __repr__(self):
        return "<ReturnStatement at line %d>" % self.lineno

class AssignStatement(Statement):
    def __init__(self, ident, expression, lineno = -1):
        self.ident = ident
        self.expression = expression
        self.lineno = lineno

    def generate(self, before, after):
        self.debug("AssignStatement.generate(before = %d, after = %d): ident = %s, expression = %s" % (before, after, self.ident, self.expression))
        self.emit("%s = %s" % (self.ident, self.expression.reduce()))

    def __repr__(self):
        return "<AssignStatement for %s at line %d>" % (self.ident, self.lineno)

class FunctionCall(Statement):
    def __init__(self, ident, arguments = [], lineno = -1):
        self.ident = ident
        self.arguments = arguments
        self.lineno = lineno

    def generate(self):
        self.debug("FunctionCall.generate(): ident = %s, arguments = %s" % (self.ident, self.arguments))
        self.emit("call %s" % self.ident)

    def reduce(self):
        self.debug("FunctionCall.reduce(): %s" % self)
        t = Temporary()
        self.emit("%s = call %s%s" % (t, self.ident, self.arguments))
        return t

    def __repr__(self):
        return "<FunctionCall for %s at line %d>" % (self.ident, self.lineno)

class Expression(Node):
    def __init__(self, op, lineno = -1):
        self.op = op
        self.lineno = -1

    def generate(self):
        return self

    def reduce(self):
        return self

    def __str__(self):
        return str(self.op)

    def __repr__(self):
        return "<Expression at line %d>" % self.lineno

class Operation(Expression):
    def __init__(self, op, lineno = -1):
        super(Operation, self).__init__(op, lineno)

    def reduce(self):
        self.debug("Operation.reduce(): %s" % self)
        x = self.generate()
        t = Temporary()
        self.emit("%s = %s" % (t, x))
        return t

    def __repr__(self):
        return "<Operation at line %d>" % self.lineno

class UnaryExpression(Operation):
    """ Unary expressions are !x or -x ..."""
    def __init__(self, op, right, lineno = -1):
        super(UnaryExpression, self).__init__(op, lineno)
        self.right = right

    def generate(self):
        self.debug("UnaryExpression.generate(): op = %s, right = %s" % (self.op, self.right))
        return UnaryExpression(self.op, self.right.reduce())

    def __str__(self):
        return "%s %s" % (str(self.op), str(self.right))

    def __repr__(self):
        return "<UnaryExpression: %s(%s) at line %d>" % (self.op, self.right, self.lineno)

class BinaryExpression(Operation):
    """ Biary expression are x+y, x-y, ... """
    def __init__(self, left, op, right, lineno = -1):
        super(BinaryExpression, self).__init__(op, lineno)
        self.left = left
        self.right = right

    def generate(self):
        self.debug("BinaryExpression.generate(): left = %s, op = %s, right = %s" % (self.left, self.op, self.right))
        return BinaryExpression(self.left.reduce(), self.op, self.right.reduce())

    def __str__(self):
        return "%s %s %s" % (str(self.left), str(self.op), str(self.right))

    def __repr__(self):
        return "<BinaryExpression: %s(%s, %s) at line %d>" % (self.op, self.left, self.right, self.lineno)

class Variable(Expression):
    def __init__(self, name, lineno = -1):
        super(Variable, self).__init__(name, lineno)

    def __repr__(self):
        return "<Variable: %s at line %d>" %(self.op, self.lineno)

class Constant(Expression):
    def __init__(self, value, lineno = -1):
        super(Constant, self).__init__(value, lineno)

    def jumping(self, true_label, false_label):
        if self.op and true_label != 0:
            self.emit("goto L%d" % true_label)
        elif not self.op and false_label != 0:
            self.emit("goto L%d" % false_label)

    def __repr__(self):
        return "<Constant: %d at line %d>" %(self.op, self.lineno)

class Temporary(Expression):
    count = 0

    def __init__(self):
        self.number = Temporary.count
        Temporary.count += 1

    def __str__(self):
        return "t%d" % self.number