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 object_bi(self):
        attrs = {}
        self.change_current_function()
        self.arguments.append(cil.CILArgNode(VariableInfo('self', vmholder=1)))
        # self.register_instruction(cil.CILSetAttribNode(self.arguments[0].vinfo, 'value', self.void))
        # self.register_instruction(cil.CILSetAttribNode(self.arguments[0].vinfo, 'type', self.void))
        self.register_instruction(cil.CILReturnNode())

        ctor_func = cil.CILFunctionNode(
            MethodInfo(self.build_funcname('ctor'), vmholder=2),
            self.arguments, self.localvars, self.instructions)
        self.register_function(ctor_func)

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

        var1 = self.define_internal_local()
        self.register_instruction(
            cil.CILLoadNode(var1, self.dotdata['exception_6']))

        self.register_instruction(cil.CILPrintStrNode(var1))
        self.register_instruction(cil.CILErrorNode())
        self.register_instruction(cil.CILReturnNode())
        abort_func = cil.CILFunctionNode(
            MethodInfo(self.build_funcname('abort'),
                       vmholder=3,
                       returnType='Object'), self.arguments, self.localvars,
            self.instructions)
        self.register_function(abort_func)

        self.change_current_function()
        self.arguments.append(cil.CILArgNode(VariableInfo('self', vmholder=1)))
        vlocal = self.define_internal_local()
        # self.register_instruction(cil.CILGetAttribNode(vlocal, self.arguments[0].vinfo, 'type'))
        self.register_instruction(
            cil.CILTypeOfNode(vlocal, self.arguments[0].vinfo))
        self.register_instruction(cil.CILTypeName(vlocal, vlocal))
        self.register_instruction(cil.CILReturnNode(vlocal))

        typename_func = cil.CILFunctionNode(
            MethodInfo(self.build_funcname('type_name'),
                       vmholder=4,
                       returnType='String'), self.arguments, self.localvars,
            self.instructions)
        self.register_function(typename_func)

        methods = {
            'ctor': ctor_func,
            'abort': abort_func,
            'type_name': typename_func
        }
        # methods = {'ctor': ctor_func, 'type_name': typename_func}
        cinfo = ClassInfo('Object', 4 * len(attrs.keys()),
                          4 * len(methods.keys()))
        return cil.CILTypeNode(cinfo, attrs, methods)
    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.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)
        label_end = self.build_label()
        for _, label_expr, expr, vinternalocal in expr_list:
            self.register_instruction(label_expr)
            self.register_instruction(cil.CILAssignNode(vinternalocal, vexpr))
            resp = self.define_internal_local()
            self.visit(expr, resp)
            self.register_instruction(cil.CILAssignNode(dest, resp))
            self.register_instruction(cil.CILGotoNode(label_end))

        self.register_instruction(label_error)
        # self.register_instruction(cil.CILPrintStrNode(var1))
        var2 = self.define_internal_local()
        self.register_instruction(
            cil.CILLoadNode(var2, self.dotdata['exception_3']))
        self.register_instruction(cil.CILPrintStrNode(var2))
        self.register_instruction(cil.CILErrorNode())
        self.register_instruction(label_end)

        self.register_instruction(cil.CILGotoNode(labelend))

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

        self.register_instruction(labelend)

    @visitor.when(ast.CaseExpr)
    def io_bi(self, object_type):
        attrs = {}
        methods = copy(object_type.methods)

        # Print string
        self.change_current_function()
        self.arguments = [
            cil.CILArgNode(VariableInfo('self', vmholder=1)),
            cil.CILArgNode(VariableInfo('x', vmholder=2))
        ]

        self.register_instruction(cil.CILPrintStrNode(self.arguments[1].vinfo))

        # v_local1 = self.define_internal_local()
        self.register_instruction(cil.CILReturnNode(self.arguments[0].vinfo))
        out_string = cil.CILFunctionNode(
            MethodInfo(self.build_funcname('out_string'),
                       paramsType=['String'],
                       returnType='IO'), self.arguments, self.localvars,
            self.instructions)
        self.register_function(out_string)

        # Print int
        self.change_current_function()
        self.arguments = [
            cil.CILArgNode(VariableInfo('self', vmholder=1)),
            cil.CILArgNode(VariableInfo('x', vmholder=2))
        ]

        self.register_instruction(cil.CILPrintIntNode(self.arguments[1].vinfo))

        # v_local1 = self.define_internal_local()
        self.register_instruction(cil.CILReturnNode(self.arguments[0].vinfo))
        out_int = cil.CILFunctionNode(
            MethodInfo(self.build_funcname('out_int'),
                       paramsType=['Int'],
                       returnType='IO'), self.arguments, self.localvars,
            self.instructions)
        self.register_function(out_int)

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

        v_local = self.define_internal_local()
        self.register_instruction(cil.CILReadStrNode(v_local))
        self.register_instruction(cil.CILReturnNode(v_local))

        in_string = cil.CILFunctionNode(
            MethodInfo(self.build_funcname('in_string'), returnType='String'),
            self.arguments, self.localvars, self.instructions)
        self.register_function(in_string)

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

        v_local = self.define_internal_local()
        self.register_instruction(cil.CILReadIntNode(v_local))
        self.register_instruction(cil.CILReturnNode(v_local))

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

        out_string.finfo.vmholder = len(methods.keys()) + 2
        methods['out_string'] = out_string
        out_int.finfo.vmholder = len(methods.keys()) + 2
        methods['out_int'] = out_int
        in_string.finfo.vmholder = len(methods.keys()) + 2
        methods['in_string'] = in_string
        in_int.finfo.vmholder = len(methods.keys()) + 2
        methods['in_int'] = in_int

        cinfo = ClassInfo('IO', 4 * len(attrs.keys()), 4 * len(methods.keys()),
                          object_type)
        return cil.CILTypeNode(cinfo, attrs, methods)
    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)