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.CoolClass):
        self.current_class_name = node.name
        parent = self.dottypes[node.parent]

        attrs = copy(parent.attrs)
        for attr in node.attrs:
            vinfo = attr.vinfo
            vinfo.vmholder = len(attrs.keys()) + 1
            attrs[attr.attrName] = vinfo

        ctor = self.build_funcname('ctor')
        constructor = cil.CILFunctionNode(MethodInfo(ctor, vmholder=2), [], [],
                                          [])
        self.register_function(constructor)

        methods = copy(parent.methods)
        methods['ctor'] = constructor
        for func in node.methods:
            meth_ = self.type_hierachy[self.current_class_name].methodlist[
                func.name]
            finfo = MethodInfo(meth_.rename)
            ffunc = cil.CILFunctionNode(finfo, [], [], [])
            self.register_function(ffunc)

            if not methods.__contains__(func.name):
                ffunc.finfo.vmholder = len(methods.keys()) + 2
            else:
                ffunc.finfo.vmholder = methods[func.name].finfo.vmholder

            methods[func.name] = ffunc
            ffunc.finfo.paramsType = meth_.paramsType
            ffunc.finfo.returnType = meth_.returnType

        vinfo = ClassInfo(self.current_class_name, 4 * len(attrs.keys()),
                          4 * len(methods.keys()), parent)
        return cil.CILTypeNode(vinfo, attrs, methods)
    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)
 def bool_bi(self, object_type):
     attrs = {'value': VariableInfo('value', vmholder=1)}
     methods = copy(object_type.methods)
     cinfo = ClassInfo('Bool', 4 * len(attrs.keys()),
                       4 * len(methods.keys()), object_type)
     return cil.CILTypeNode(cinfo, attrs, methods)