def visit(self, node: ast.DivNode, dest):
        # print("------------visit node: DivNode")
        left = self.define_internal_local()
        self.visit(node.left, left)

        right = self.define_internal_local()
        self.visit(node.right, right)

        label1 = self.build_label()
        labelerror = self.build_label()
        labelend = self.build_label()

        vhalt = self.define_internal_local()
        self.register_instruction(cil.CILMinusNode(vhalt, right, 0))
        self.register_instruction(cil.CILGotoIfNode(vhalt, label1))
        self.register_instruction(cil.CILGotoNode(labelerror))

        self.register_instruction(label1)

        self.register_instruction(cil.CILDivNode(dest, left, right))
        self.register_instruction(cil.CILGotoNode(labelend))

        self.register_instruction(labelerror)
        var1 = self.define_internal_local()
        self.register_instruction(
            cil.CILLoadNode(var1, self.dotdata['exception_4']))
        self.register_instruction(cil.CILPrintStrNode(var1))
        self.register_instruction(cil.CILErrorNode())

        self.register_instruction(labelend)
    def visit(self, node: ast.DispatchDot, dest):
        # print("------------visit node: DispatchDot")

        params = []
        ctype_ = node.expr0.computedType
        method_ = self.dottypes[ctype_].methods[node.methodName].finfo

        for i, expr in enumerate(node.paramsList):
            vlocal = self.define_internal_local()
            self.visit(expr, vlocal)
            p = method_.paramsType[i]

            v_box = self._ifobjectboxing(vlocal, expr.computedType, p)
            params.append(v_box)

        v_eval = self.define_internal_local()
        self.visit(node.expr0, v_eval)

        v_box_eval = self._ifboxing(v_eval, node.expr0.computedType)

        vhalt = self.define_internal_local()
        self.register_instruction(
            cil.CILMinusNode(vhalt, self.void, v_box_eval))

        label1 = self.build_label()
        labelerror = self.build_label()
        labelend = self.build_label()

        self.register_instruction(cil.CILGotoIfNode(vhalt, label1))
        self.register_instruction(cil.CILGotoNode(labelerror))

        self.register_instruction(label1)

        v_type = self.define_internal_local()
        self.register_instruction(cil.CILTypeOfNode(v_type, v_box_eval))

        self.register_instruction(cil.CILSaveState())
        self.register_instruction(cil.CILParamNode(v_box_eval))
        for p in params:
            self.register_instruction(cil.CILParamNode(p))

        self.register_instruction(
            cil.CILDynamicCallNode(dest, v_type, method_.vmholder))
        self.register_instruction(cil.CILGotoNode(labelend))

        self.register_instruction(labelerror)
        var1 = self.define_internal_local()
        self.register_instruction(
            cil.CILLoadNode(var1, self.dotdata['exception_1']))
        self.register_instruction(cil.CILPrintStrNode(var1))
        self.register_instruction(cil.CILErrorNode())

        self.register_instruction(labelend)
    def visit(self, node: ast.Conditional, dest):
        # print("------------visit node: Conditional")
        if_eval = self.define_internal_local()
        self.visit(node.ifexpr, if_eval)

        label_then = self.build_label()
        label_end = self.build_label()

        self.register_instruction(cil.CILGotoIfNode(if_eval, label_then))
        self.visit(node.elseexpr, dest)
        self.register_instruction(cil.CILGotoNode(label_end))
        self.register_instruction(label_then)
        self.visit(node.thenexpr, dest)
        self.register_instruction(label_end)
    def visit(self, node: ast.IsVoid, dest):
        # print("------------visit node: IsVoid")
        vlocal = self.define_internal_local()
        self.visit(node.expr, vlocal)
        v_box = self._ifboxing(vlocal, node.expr.computedType)
        # self.register_instruction(cil.CILMinusNode(dest, self.void, v_box))

        rest = self.define_internal_local()
        self.register_instruction(cil.CILMinusNode(rest, self.void, v_box))
        label_1 = self.build_label()
        label_2 = self.build_label()
        self.register_instruction(cil.CILGotoIfNode(rest, label_1))
        self.register_instruction(cil.CILAssignNode(dest, 1))
        self.register_instruction(cil.CILGotoNode(label_2))
        self.register_instruction(label_1)
        self.register_instruction(cil.CILAssignNode(dest, 0))
        self.register_instruction(label_2)
    def visit(self, node: ast.DispatchSelf, dest):
        # print("------------visit node: DispatchSelf")
        params = []
        method_ = self.dottypes[self.current_class.cinfo.name].methods[
            node.methodName].finfo
        vself = self._find('self')

        vhalt = self.define_internal_local()
        self.register_instruction(cil.CILMinusNode(vhalt, self.void, vself))

        label1 = self.build_label()
        labelerror = self.build_label()
        labelend = self.build_label()

        self.register_instruction(cil.CILGotoIfNode(vhalt, label1))
        self.register_instruction(cil.CILGotoNode(labelerror))

        self.register_instruction(label1)

        for i, expr in enumerate(node.paramsList):
            vlocal = self.define_internal_local()
            self.visit(expr, vlocal)
            p = method_.paramsType[i]

            v_box = self._ifobjectboxing(vlocal, expr.computedType, p)
            params.append(v_box)

        self.register_instruction(cil.CILSaveState())

        self.register_instruction(cil.CILParamNode(vself))

        for p in params:
            self.register_instruction(cil.CILParamNode(p))

        self.register_instruction(cil.CILStaticCallNode(dest, method_.name))
        self.register_instruction(cil.CILGotoNode(labelend))

        self.register_instruction(labelerror)
        var1 = self.define_internal_local()
        self.register_instruction(
            cil.CILLoadNode(var1, self.dotdata['exception_1']))
        self.register_instruction(cil.CILPrintStrNode(var1))
        self.register_instruction(cil.CILErrorNode())

        self.register_instruction(labelend)
    def visit(self, node: ast.Case, dest):
        # print("------------visit node: Case")
        vexpr = self.define_internal_local()
        self.visit(node.case0, vexpr)

        vbox = self._ifboxing(vexpr, node.case0.computedType)

        vhalt = self.define_internal_local()
        self.register_instruction(cil.CILMinusNode(vhalt, self.void, vbox))

        label1 = self.build_label()
        labelerror = self.build_label()
        labelend = self.build_label()

        self.register_instruction(cil.CILGotoIfNode(vhalt, label1))
        self.register_instruction(cil.CILGotoNode(labelerror))

        self.register_instruction(label1)

        texpr = self.define_internal_local()
        self.register_instruction(cil.CILTypeOfNode(texpr, vbox))

        expr_list = [self.visit(case) for case in node.exprList]
    def visit(self, node: ast.Loop, dest):
        # print("------------visit node: Loop")

        cond_eval = self.define_internal_local()

        label_entry = self.build_label()
        self.register_instruction(label_entry)

        self.visit(node.whileexpr, cond_eval)

        label_end = self.build_label()
        label_loop = self.build_label()
        self.register_instruction(cil.CILGotoIfNode(cond_eval, label_loop))
        self.register_instruction(cil.CILGotoNode(label_end))

        self.register_instruction(label_loop)

        vbody = self.define_internal_local()
        self.visit(node.loopexpr, vbody)

        self.register_instruction(cil.CILGotoNode(label_entry))
        self.register_instruction(label_end)

        self.register_instruction(cil.CILAssignNode(dest, self.void))
    def visit(self, node: ast.Equal, dest):
        # print("------------visit node: Equal")
        vleft = self.define_internal_local()
        vright = self.define_internal_local()
        self.visit(node.left, vleft)
        self.visit(node.right, vright)

        if node.left.computedType == 'String':

            vlength_r = self.define_internal_local()
            self.register_instruction(cil.CILLengthNode(vlength_r, vright))
            vlength_l = self.define_internal_local()
            self.register_instruction(cil.CILLengthNode(vlength_l, vleft))

            self.register_instruction(
                cil.CILMinusNode(dest, vlength_l, vlength_r))

            label_loop = self.build_label()
            label_loopbody = self.build_label()
            label_equal = self.build_label()
            label_notequal = self.build_label()
            label_end = self.build_label()

            self.register_instruction(cil.CILGotoIfNode(dest, label_notequal))

            pos = self.define_internal_local()
            self.register_instruction(cil.CILAssignNode(pos, 0))

            self.register_instruction(label_loop)
            self.register_instruction(
                cil.CILGotoIfNode(vlength_r, label_loopbody))

            self.register_instruction(cil.CILGotoNode(label_equal))

            self.register_instruction(label_loopbody)
            cleft = self.define_internal_local()
            cright = self.define_internal_local()
            self.register_instruction(cil.CILGetIndexNode(cleft, vleft, pos))
            self.register_instruction(cil.CILGetIndexNode(cright, vright, pos))
            self.register_instruction(cil.CILMinusNode(vlength_r, vlength_r,
                                                       1))
            self.register_instruction(cil.CILPlusNode(pos, pos, 1))

            vrest = self.define_internal_local()
            self.register_instruction(cil.CILMinusNode(vrest, cleft, cright))
            self.register_instruction(cil.CILGotoIfNode(vrest, label_notequal))

            self.register_instruction(cil.CILGotoNode(label_loop))

            self.register_instruction(label_equal)
            self.register_instruction(cil.CILAssignNode(dest, 1))
            self.register_instruction(cil.CILGotoNode(label_end))

            self.register_instruction(label_notequal)
            self.register_instruction(cil.CILAssignNode(dest, 0))
            self.register_instruction(label_end)

        else:
            rest = self.define_internal_local()
            self.register_instruction(cil.CILMinusNode(rest, vleft, vright))
            label_1 = self.build_label()
            label_2 = self.build_label()
            self.register_instruction(cil.CILGotoIfNode(rest, label_1))
            self.register_instruction(cil.CILAssignNode(dest, 1))
            self.register_instruction(cil.CILGotoNode(label_2))
            self.register_instruction(label_1)
            self.register_instruction(cil.CILAssignNode(dest, 0))
            self.register_instruction(label_2)
        expr_list = [self.visit(case) for case in node.exprList]

        label_init = self.build_label()
        self.register_instruction(label_init)

        label_error = self.build_label()

        for tlocal, label_expr, _, _ in expr_list:
            vinternal = self.define_internal_local()
            # self.register_instruction(cil.CILMinusNode(vinternal, tlocal, texpr))

            rest = self.define_internal_local()
            self.register_instruction(cil.CILMinusNode(rest, tlocal, texpr))
            label_1 = self.build_label()
            label_2 = self.build_label()
            self.register_instruction(cil.CILGotoIfNode(rest, label_1))
            self.register_instruction(cil.CILAssignNode(vinternal, 1))
            self.register_instruction(cil.CILGotoNode(label_2))
            self.register_instruction(label_1)
            self.register_instruction(cil.CILAssignNode(vinternal, 0))
            self.register_instruction(label_2)

            # self.register_instruction(cil.CILMinusNode(vinternal, 1, vinternal))
            self.register_instruction(cil.CILGotoIfNode(vinternal, label_expr))

        vobject = self.define_internal_local()
        self.register_instruction(
            cil.CILAllocateNode(vobject, self.dottypes['Object'].cinfo))
        self.register_instruction(cil.CILTypeOfNode(vobject, vobject))
        vo_comp = self.define_internal_local()
        # self.register_instruction(cil.CILMinusNode(vo_comp, vobject, texpr))
    def string_bi(self, object_type):
        attrs = {'value': VariableInfo('value', vmholder=1)}
        methods = copy(object_type.methods)

        self.change_current_function()
        self.arguments = [
            cil.CILArgNode(VariableInfo('self', vmholder=1)),
            cil.CILArgNode(VariableInfo('string2', vmholder=2))
        ]

        vlocal1 = self.define_internal_local()
        self.register_instruction(
            cil.CILGetAttribNode(vlocal1, self.arguments[0].vinfo,
                                 attrs['value'].vmholder))

        vlocal2 = self.define_internal_local()
        self.register_instruction(
            cil.CILConcatNode(vlocal2, vlocal1, self.arguments[1].vinfo))

        # self.register_instruction(cil.CILSetAttribNode(self.arguments[0].vinfo, 'value', vlocal2))
        self.register_instruction(cil.CILReturnNode(vlocal2))

        concat_func = cil.CILFunctionNode(
            MethodInfo(self.build_funcname('concat'),
                       paramsType=['String'],
                       returnType='String'), self.arguments, self.localvars,
            self.instructions)
        self.register_function(concat_func)

        self.change_current_function()
        self.arguments = [cil.CILArgNode(VariableInfo('self', vmholder=1))]

        v_local3 = self.define_internal_local()
        self.register_instruction(
            cil.CILGetAttribNode(v_local3, self.arguments[0].vinfo,
                                 attrs['value'].vmholder))

        v_local4 = self.define_internal_local()
        self.register_instruction(cil.CILLengthNode(v_local4, v_local3))

        self.register_instruction(cil.CILReturnNode(v_local4))

        length_func = cil.CILFunctionNode(
            MethodInfo(self.build_funcname('length'), returnType='Int'),
            self.arguments, self.localvars, self.instructions)
        self.register_function(length_func)

        # Substring
        self.change_current_function()
        self.arguments = [
            cil.CILArgNode(VariableInfo('self', vmholder=1)),
            cil.CILArgNode(VariableInfo('i', vmholder=2)),
            cil.CILArgNode(VariableInfo('l', vmholder=3))
        ]

        label_val = self.build_label()
        label_nval = self.build_label()
        label_fin = self.build_label()

        label_nval1 = self.build_label()
        label_fin1 = self.build_label()

        label_nval2 = self.build_label()
        label_fin2 = self.build_label()

        vvar2 = self.define_internal_local()
        self.register_instruction(cil.CILAssignNode(vvar2, 0))

        vvar1 = self.define_internal_local()
        self.register_instruction(
            cil.CILLessThan(vvar1, self.arguments[1].vinfo, vvar2))
        self.register_instruction(cil.CILGotoIfNode(vvar1, label_nval1))

        self.register_instruction(
            cil.CILLessThan(vvar1, self.arguments[2].vinfo, vvar2))
        self.register_instruction(cil.CILGotoIfNode(vvar1, label_nval2))

        self.register_instruction(
            cil.CILGotoIfNode(self.arguments[2].vinfo, label_val))

        self.register_instruction(cil.CILGotoNode(label_nval))

        self.register_instruction(label_val)
        v_local5 = self.define_internal_local()
        self.register_instruction(
            cil.CILGetAttribNode(v_local5, self.arguments[0].vinfo,
                                 attrs['value'].vmholder))

        vhalt = self.define_internal_local()
        vlength = self.define_internal_local()
        self.register_instruction(cil.CILLengthNode(vlength, v_local5))

        vsum = self.define_internal_local()
        self.register_instruction(
            cil.CILPlusNode(vsum, self.arguments[1].vinfo,
                            self.arguments[2].vinfo))
        self.register_instruction(cil.CILMinusNode(vsum, vsum, 1))
        self.register_instruction(cil.CILLessThan(vhalt, vsum, vlength))

        label1 = self.build_label()
        labelerror = self.build_label()
        labelend = self.build_label()

        self.register_instruction(cil.CILGotoIfNode(vhalt, label1))
        self.register_instruction(cil.CILGotoNode(labelerror))

        self.register_instruction(label1)

        v_local6 = self.define_internal_local()
        self.register_instruction(
            cil.CILSubstringNode(v_local6, v_local5, self.arguments[1].vinfo,
                                 self.arguments[2].vinfo))
        self.register_instruction(cil.CILReturnNode(v_local6))

        self.register_instruction(cil.CILGotoNode(labelend))

        self.register_instruction(labelerror)
        var1 = self.define_internal_local()
        self.register_instruction(
            cil.CILLoadNode(var1, self.dotdata['exception_5']))
        self.register_instruction(cil.CILPrintStrNode(var1))
        self.register_instruction(cil.CILErrorNode())

        self.register_instruction(labelend)
        self.register_instruction(cil.CILGotoNode(label_fin))

        self.register_instruction(label_nval)
        msg = self.register_data("")
        var = self.define_internal_local()
        self.register_instruction(cil.CILLoadNode(var, msg))
        self.register_instruction(cil.CILReturnNode(var))

        self.register_instruction(label_fin)
        self.register_instruction(cil.CILGotoNode(label_fin2))

        self.register_instruction(label_nval2)
        var1 = self.define_internal_local()
        self.register_instruction(
            cil.CILLoadNode(var1, self.dotdata['exception_5']))
        self.register_instruction(cil.CILPrintStrNode(var1))
        self.register_instruction(cil.CILErrorNode())

        self.register_instruction(label_fin2)
        self.register_instruction(cil.CILGotoNode(label_fin1))

        self.register_instruction(label_nval1)
        var1 = self.define_internal_local()
        self.register_instruction(
            cil.CILLoadNode(var1, self.dotdata['exception_5']))
        self.register_instruction(cil.CILPrintStrNode(var1))
        self.register_instruction(cil.CILErrorNode())

        self.register_instruction(label_fin1)

        substr_func = cil.CILFunctionNode(
            MethodInfo(self.build_funcname('substr'),
                       paramsType=['Int', 'Int'],
                       returnType='String'), self.arguments, self.localvars,
            self.instructions)
        self.register_function(substr_func)

        length_func.finfo.vmholder = len(methods.keys()) + 2
        methods['length'] = length_func
        concat_func.finfo.vmholder = len(methods.keys()) + 2
        methods['concat'] = concat_func
        substr_func.finfo.vmholder = len(methods.keys()) + 2
        methods['substr'] = substr_func

        cinfo = ClassInfo('String', 4 * len(attrs.keys()),
                          4 * len(methods.keys()), object_type)
        return cil.CILTypeNode(cinfo, attrs, methods)