def visit(self, node: cil.SubstringNode):
        self.add_inst(
            mips.CommentNode(
                f"<substr:>{node.dest}[{node.index}:{node.length}]"))

        self.visit(cil.StaticCallNode('String__init', node.dest))

        src_address = self.get_address('self')
        dest_address = self.get_address(node.dest)
        index_address = self.get_address(node.index)
        length_address = self.get_address(node.length)

        push_src = (mips.LWNode(a0,
                                (src_address, fp)), mips.LWNode(a0, (4, a0)))
        push_length = (mips.LWNode(a2, (length_address, fp)),
                       mips.LWNode(a2, (4, a2)))
        push_index = (mips.LWNode(a1, (index_address, fp)),
                      mips.LWNode(a1, (4, a1)))

        self.add_inst(
            *push_src,
            *push_length,
            *push_index,
            mips.JALNode('substr'),
        )

        self.add_inst(
            mips.LWNode(t1, (dest_address, fp)), mips.SWNode(v0, 4, t1),
            mips.CommentNode(
                f"</substr:>{node.dest}[{node.index}:{node.length}]"))
    def visit(self, node: cil.ConformsNode):
        left_offset = self.get_address(node.left)
        # right_offset = self.get_address(node.right)
        dest_offset = self.get_address(node.dest)

        self.add_inst(
            mips.CommentNode(
                f"<conforms:{node.dest}<-{node.left}-{node.right}>"), )

        self.add_inst(
            mips.LWNode(
                t0, (left_offset, fp)).with_comm("Load left pointer to self"),
            mips.LWNode(
                a0, (0, t0)).with_comm("Load left pointer to type of self"),
            mips.LANode(a1, node.right), mips.JALNode('conforms'),
            mips.MoveNode(s0, v0))

        self.visit(cil.StaticCallNode('Bool__init', node.dest))

        self.add_inst(
            mips.LWNode(t0, (dest_offset, fp)),
            mips.SWNode(s0, 4, t0),
            mips.CommentNode(
                f"</conforms:{node.dest}<-{node.left}-{node.right}>"),
        )
    def visit(self, node: cil.StaticCallNode):
        dest = self.get_address(node.dest)

        self.add_inst(
            mips.CommentNode(f"<staticcall:{node.function}-{node.dest}>"),
            mips.JALNode(node.function),
            mips.SWNode(v0, dest, fp),
            mips.CommentNode(f"</staticcall:{node.function}-{node.dest}>"),
        )
 def visit(self, node: cil.InitNode):
     dest = self.get_address(node.dest)
     self.add_inst(
         mips.LWNode(a0, node.type_name),
         mips.JALNode('malloc'),
         mips.LANode(t0, node.type_name).with_comm(
             f"Get pointer to type {node.type_name}"),
         mips.SWNode(t0, 0, v0).with_comm(f"Set type pointer as attr"),
         mips.SWNode(v0, dest, fp),
     )
    def visit(self, node: cil.ReadStringNode):
        self.add_inst(mips.CommentNode(f"<readstring:{node.dest}>"))

        address = self.get_address(node.dest)

        self.add_inst(mips.LINode(a0, 512), mips.JALNode('malloc'),
                      mips.MoveNode(t2, v0))
        self.add_inst(
            mips.MoveNode(a0, t2),
            mips.LINode(a1, 512),
            mips.LINode(v0, 8),
            mips.SysCallNode(),
        )
        self.visit(cil.StaticCallNode('String__init', node.dest))
        self.add_inst(mips.LWNode(t0, (address, fp)), mips.SWNode(t2, 4, t0))

        # Remove eol
        self.add_inst(mips.MoveNode(a0, t2), mips.JALNode('remove_eol'))

        self.add_inst(mips.CommentNode(f"</readstring:{node.dest}>"))
    def visit(self, node: cil.ConcatNode):
        self.add_inst(
            mips.CommentNode(f"<concat:{node.dest}={node.str1}+{node.str2}>"))

        self.visit(cil.StaticCallNode("String__init", node.dest))

        str1_address = self.get_address(node.str1)
        str2_address = self.get_address(node.str2)
        dest_address = self.get_address(node.dest)

        # Calc length of str1 and save it in t0
        length_of_str1 = (mips.LWNode(a0, (str1_address, fp)),
                          mips.LWNode(a0, (4, a0)), mips.JALNode('length'),
                          mips.MoveNode(t0, v0))
        # Calc length of str2 and save it in t1
        length_of_str2 = (mips.LWNode(a0, (str2_address, fp)),
                          mips.LWNode(a0, (4, a0)), mips.JALNode('length'),
                          mips.MoveNode(t1, v0))

        push_str1 = (mips.LWNode(a0,
                                 (str1_address, fp)), mips.LWNode(a0, (4, a0)))
        push_str2 = (mips.LWNode(a1,
                                 (str2_address, fp)), mips.LWNode(a1, (4, a1)))
        push_length = (mips.ADDNode(a2, t0, t1), )

        self.add_inst(
            *length_of_str1,
            *length_of_str2,
            *push_str1,
            *push_str2,
            *push_length,
            mips.JALNode('concat'),
        )

        self.add_inst(mips.LWNode(t1, (dest_address, fp)),
                      mips.SWNode(v0, 4, t1))

        self.add_inst(
            mips.CommentNode(f"</concat:{node.dest}={node.str1}+{node.str2}>"))
    def visit(self, node: cil.IsVoidNode):
        src = self.get_address(node.src)
        dest = self.get_address(node.dest)

        self.add_inst(mips.CommentNode(f"<isvoid:{node.dest}-{node.src}>"), )

        self.visit(cil.StaticCallNode('Bool__init', node.dest))

        self.add_inst(
            mips.LWNode(a0, (src, fp)).with_comm('Push instance pointer'),
            mips.JALNode('isvoid'),
            mips.LWNode(t0, (dest, fp)).with_comm('Load Bool pointer'),
            mips.SWNode(v0, 4,
                        t0).with_comm('Save isvoid result as value of Bool'),
            mips.CommentNode(f"</isvoid:{node.dest}-{node.src}>"),
        )
    def visit(self, node: cil.LengthNode):
        self.add_inst(
            mips.CommentNode(f"<length:{node.dest}=len({node.src})>"))

        self.visit(cil.StaticCallNode("Int__init", node.dest))

        src_address = self.get_address(node.src)
        dest_address = self.get_address(node.dest)

        self.add_inst(
            mips.LWNode(a0, (src_address, fp)),
            mips.LWNode(a0, (4, a0)),
            mips.JALNode('length'),
            mips.LWNode(t1, (dest_address, fp)),
            mips.SWNode(v0, 4, t1),
        )

        self.add_inst(
            mips.CommentNode(f"</length:{node.dest}=len({node.src})>"))
    def visit(self, node: cil.EqualNode):
        left = self.get_address(node.left)
        right = self.get_address(node.right)
        dest = self.get_address(node.dest)

        self.add_inst(
            mips.CommentNode(
                f"<equal: {node.dest} <- {node.left} = {node.right}>"), )

        self.visit(cil.StaticCallNode("Bool__init", node.dest))

        self.add_inst(
            mips.LWNode(a0, (left, fp)),
            mips.LWNode(a1, (right, fp)),
            mips.JALNode("equal"),
            mips.LWNode(t0, (dest, fp)),
            mips.SWNode(v0, 4, t0),
            mips.CommentNode(
                f"<equal: {node.dest} <- {node.left} = {node.right}>"),
        )