Ejemplo n.º 1
0
    def __init__(self):
        super(GenerateCode, self).__init__()

        # version dictionary for temporaries
        self.versions = defaultdict(int)

        # The generated code (list of tuples)
        self.code = BasicBlock()
        self.start_block = self.code

        # A list of external declarations (and types)
        self.externs = []
Ejemplo n.º 2
0
class GenerateCode(exprast.NodeVisitor):
    '''
    Node visitor class that creates 3-address encoded instruction sequences.
    '''
    def __init__(self):
        super(GenerateCode, self).__init__()

        # version dictionary for temporaries
        self.versions = defaultdict(int)

        # The generated code (list of tuples)
        self.code = BasicBlock()
        self.start_block = self.code

        # A list of external declarations (and types)
        self.externs = []

    def new_temp(self,typeobj):
        '''
        Create a new temporary variable of a given type.
        '''
        name = "__%s_%d" % (typeobj.name, self.versions[typeobj.name])
        self.versions[typeobj.name] += 1
        return name

    # You must implement visit_Nodename methods for all of the other
    # AST nodes.  In your code, you will need to make instructions
    # and append them to the self.code list.
    #
    # A few sample methods follow.  You may have to adjust depending
    # on the names of the AST nodes you've defined.

    def visit_Literal(self,node):
        # Create a new temporary variable name 
        target = self.new_temp(node.type)

        # Make the SSA opcode and append to list of generated instructions
        inst = ('literal_'+node.type.name, node.value, target)
        self.code.append(inst)

        # Save the name of the temporary variable where the value was placed 
        node.gen_location = target

    def visit_BinaryOp(self,node):
        # Visit the left and right expressions
        self.visit(node.left)
        self.visit(node.right)

        # Make a new temporary for storing the result
        target = self.new_temp(node.type)

        # Create the opcode and append to list
        opcode = binary_ops[node.op] + "_"+node.left.type.name
        inst = (opcode, node.left.gen_location, node.right.gen_location, target)
        self.code.append(inst)

        # Store location of the result on the node
        node.gen_location = target

    def visit_RelationalOp(self,node):
        # Visit the left and right expressions
        self.visit(node.left)
        self.visit(node.right)

        # Make a new temporary for storing the result
        target = self.new_temp(node.type)

        # Create the opcode and append to list
        #opcode = binary_ops[node.op] + "_"+node.left.type.name
        opcode = "cmp" + "_"+node.left.type.name
        inst = (opcode, binary_ops[node.op], node.left.gen_location, node.right.gen_location, target)
        self.code.append(inst)

        # Store location of the result on the node
        node.gen_location = target

    def visit_PrintStatement(self,node):
        # Visit the printed expression
        self.visit(node.expr)

        # Create the opcode and append to list
        inst = ('print_'+node.expr.type.name, node.expr.gen_location)
        self.code.append(inst)

    def visit_Program(self,node):
        self.visit(node.program)

    #def visit_Statements(self,node):
    #    self.visit(node.expr)
    #    inst = ('print_'+node.expr.type.name, node.expr.gen_location)
    #    self.code.append(inst)

    #def visit_Statement(self,node):
    #    self.visit(node.expr)
    #    inst = ('print_'+node.expr.type.name, node.expr.gen_location)
    #    self.code.append(inst)

    def visit_ConstDeclaration(self,node):
        # allocate in memory
        inst = ('alloc_'+node.type.name, 
                    node.id)
        self.code.append(inst)
        # store init val
        self.visit(node.value)
        inst = ('store_'+node.type.name,
                node.value.gen_location,
                node.id)
        self.code.append(inst)

    def visit_VarDeclaration(self,node):
        # allocate in memory
        inst = ('alloc_'+node.type.name, 
                    node.id)
        self.code.append(inst)
        # store pot. init val
        if node.value:
            self.visit(node.value)
            inst = ('store_'+node.type.name,
                    node.value.gen_location,
                    node.id)
            self.code.append(inst)

    def visit_LoadLocation(self,node):
        target = self.new_temp(node.type)
        inst = ('load_'+node.type.name,
                node.name,
                target)
        self.code.append(inst)
        node.gen_location = target

    #def visit_Extern(self,node):
    #    self.visit(node.expr)
    #    inst = ('print_'+node.expr.type.name, node.expr.gen_location)
    #    self.code.append(inst)

    #def visit_FuncPrototype(self,node):
    #    self.visit(node.expr)
    #    inst = ('print_'+node.expr.type.name, node.expr.gen_location)
    #    self.code.append(inst)

    #def visit_Parameters(self,node):
    #    self.visit(node.expr)
    #    inst = ('print_'+node.expr.type.name, node.expr.gen_location)
    #    self.code.append(inst)
    #    node.gen_location = target

    #def visit_ParamDecl(self,node):
    #    self.visit(node.expr)
    #    inst = ('print_'+node.expr.type.name, node.expr.gen_location)
    #    self.code.append(inst)

    def visit_AssignmentStatement(self,node):
        self.visit(node.value)
        
        inst = ('store_'+node.value.type.name, 
                node.value.gen_location, 
                node.location)
        self.code.append(inst)

    def visit_UnaryOp(self,node):
        self.visit(node.left)
        target = self.new_temp(node.type)
        opcode = unary_ops[node.op] + "_" + node.left.type.name
        inst = (opcode, node.left.gen_location)
        self.code.append(inst)
        node.gen_location = target

    def visit_IfStatement(self,node):
        if_block = IfBlock()
        self.code.next_block = if_block
        # condition
        self.switch_block(if_block)
        self.visit(node.condition)
        if_block.test = node.condition.gen_location
        # then branch
        if_block.if_branch = BasicBlock()
        self.switch_block(if_block.if_branch)
        self.visit(node.then_b)
        # else branch
        if node.else_b:
            if_block.else_branch = BasicBlock()
            self.switch_block(if_block.else_branch)
            self.visit(node.else_b)
        # set up next block
        if_block.next_block = BasicBlock()
        self.switch_block(if_block.next_block)

    def visit_WhileStatement(self, node):
        while_block = WhileBlock()
        self.code.next_block = while_block
        # condition
        self.switch_block(while_block)
        self.visit(node.condition)
        while_block.test = node.condition.gen_location
        # body
        while_block.body = BasicBlock()
        self.switch_block(while_block.body)
        self.visit(node.body)
        while_block.next_block = BasicBlock()
        self.switch_block(while_block.next_block)

    def switch_block(self, next_block):
        self.code = next_block

    def visit_Group(self,node):
        self.visit(node.expression)
        node.gen_location = node.expression.gen_location