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 = []
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