def generate_str_cmp(self):
        self.current_procedure = mips.ProcedureNode(STR_CMP)

        #comparing char by char
        self.register_instruction(mips.CommentNode, "Comparing char by char")
        self.register_instruction(mips.LoadWordNode, s0, CHARS_ATTR_OFFSET,
                                  t6)  #char array pointer offset
        self.register_instruction(mips.LoadWordNode, s1, CHARS_ATTR_OFFSET, t7)

        #char by char loop
        self.register_instruction(mips.Label, "strcmp_loop")
        self.register_instruction(mips.LoadInmediate, s2, 0)
        self.register_instruction(mips.LoadByteNode, s2, 0, s0)

        self.register_instruction(mips.LoadInmediate, s3, 0)
        self.register_instruction(mips.LoadByteNode, s3, 0, s1)

        self.register_instruction(mips.SetEq, a0, s2, s3)
        self.register_instruction(mips.BranchOnEqZero, a0, "end_loop")

        self.register_instruction(mips.BranchOnEqZero, s3, "end_loop")
        self.register_instruction(mips.BranchOnEqZero, s2, "end_loop")
        self.register_instruction(mips.AddiNode, s0, s0, 1)
        self.register_instruction(mips.AddiNode, s1, s1, 1)

        self.register_instruction(mips.Jump, "strcmp_loop")

        self.register_instruction(mips.Label, "end_loop")
        self.register_instruction(mips.JumpRegister, ra)

        self.text.append(self.current_procedure)
    def generate_input(self):
        # copies from t7 to t6 a0 bytes
        self.memo.save()
        reg4 = self.memo.get_unused_reg()
        reg5 = self.memo.get_unused_reg()

        self.current_procedure = mips.ProcedureNode("Input")

        self.register_instruction(mips.Label, "input_loop")

        self.register_instruction(mips.LoadByteNode, t8, 0, t7)
        self.register_instruction(mips.StoreByteNode, t8, 0, t6)

        self.register_instruction(mips.AddiNode, t6, t6, 1)
        self.register_instruction(mips.AddiNode, t7, t7, 1)
        self.register_instruction(mips.BranchOnGreaterZero, t8, "input_loop")
        self.register_instruction(mips.AddiNode, t6, t6, -2)

        self.register_instruction(mips.LoadInmediate, reg4, 10)
        self.register_instruction(mips.LoadByteNode, reg5, 0, t6)
        self.register_instruction(mips.BranchOnNotEqualNode, reg4, reg5,
                                  "input_end")
        self.register_instruction(mips.LoadInmediate, t8, 0)
        self.register_instruction(mips.StoreByteNode, t8, 0, t6)

        self.register_instruction(mips.Label, "input_end")
        self.register_instruction(mips.Jump, ra)

        self.text.append(self.current_procedure)
    def generate_str_length(self):
        # calculates the length of the null-terminated char array referenced by $a0 and stores it in $a0
        self.memo.save()
        reg1 = self.memo.get_unused_reg()
        reg2 = self.memo.get_unused_reg()

        self.current_procedure = mips.ProcedureNode(LENGTH)

        self.register_instruction(mips.LoadInmediate, reg1, 0)

        self.register_instruction(mips.Label, "length_loop")
        self.register_instruction(mips.LoadByteNode, reg2, 0, a0)
        self.register_instruction(mips.BranchOnEqualNode, zero, reg2,
                                  "length_end")

        self.register_instruction(mips.AddiNode, reg1, reg1, 1)
        self.register_instruction(mips.AddiNode, a0, a0, 1)
        self.register_instruction(mips.Jump, "length_loop")

        self.register_instruction(mips.Label, "length_end")
        self.register_instruction(mips.MoveNode, a0, reg1)
        self.register_instruction(mips.Jump, ra)

        self.text.append(self.current_procedure)
        self.memo.clean()
    def generate_copy(self):
        # copies from t1 to t6 a0 bytes
        self.memo.save()
        self.current_procedure = mips.ProcedureNode(COPY)

        self.register_instruction(mips.Label, "copy_loop")
        self.register_instruction(mips.BranchOnEqualNode, zero, a0, "copy_end")
        self.register_instruction(mips.LoadByteNode, t8, 0, t7)
        self.register_instruction(mips.StoreByteNode, t8, 0, t6)
        self.register_instruction(mips.AddiNode, t6, t6, 1)
        self.register_instruction(mips.AddiNode, t7, t7, 1)
        self.register_instruction(mips.AddiNode, a0, a0, -1)
        self.register_instruction(mips.Jump, "copy_loop")

        self.register_instruction(mips.Label, "copy_end")
        self.register_instruction(mips.Jump, ra)

        self.text.append(self.current_procedure)
        self.memo.clean()
    def visit(self, node):
        self.memo.save()
        locals_save = self.locals
        params_save = self.params
        self.locals, self.params = [], []
        self.current_procedure = mips.ProcedureNode(node.name)

        saved_fp = self.memo.get_unused_reg()
        self.register_instruction(mips.MoveNode, saved_fp, fp)

        self.register_instruction(mips.CommentNode, "New $fp")
        self.register_instruction(mips.MoveNode, fp, sp)

        self.register_instruction(mips.CommentNode,
                                  "Reserving space for locals")
        self.register_instruction(mips.AddiNode, sp, sp,
                                  4 * len(node.localvars))

        self.register_instruction(mips.CommentNode, "Pushing $ra")
        self.register_push(ra)

        self.register_instruction(mips.CommentNode, "Saving $fp")
        self.register_push(saved_fp)
        self.memo.clean()

        for local in node.localvars:
            self.locals.append(local.name)

        for param in node.params:
            self.params.append(param.name)

        self.register_instruction(mips.CommentNode, "Executing instructions")
        for inst in node.instructions:
            self.visit(inst)

        self.text.append(self.current_procedure)
        self.locals = locals_save
        self.params = params_save