def visit(self, node: ast.ProgramNode):
        object_class = self.object_bi()
        self.dottypes['Object'] = object_class
        self.dottypes['Int'] = self.int_bi(object_class)
        self.dottypes['Bool'] = self.bool_bi(object_class)
        self.dottypes['String'] = self.string_bi(object_class)
        self.dottypes['IO'] = self.io_bi(object_class)

        for child in node.classList:
            self.dottypes[child.name] = self.visit(child)

        self.change_current_function('entry')
        vlocal = self.define_internal_local()
        cclass = self.dottypes['Main']
        self.register_instruction(cil.CILAllocateNode(vlocal, cclass.cinfo))

        self.register_instruction(cil.CILSaveState())
        self.register_instruction(cil.CILParamNode(vlocal))

        vlocal2 = self.define_internal_local()
        nctor = cclass.methods['ctor'].finfo.name
        self.register_instruction(cil.CILStaticCallNode(vlocal2, nctor))

        mname = cclass.methods['main'].finfo.name
        self.register_instruction(cil.CILSaveState())
        self.register_instruction(cil.CILParamNode(vlocal))
        self.register_instruction(cil.CILStaticCallNode(vlocal2, mname))
        self.register_instruction(cil.CILReturnFinal())

        entry_m = cil.CILFunctionNode(MethodInfo(self.current_function_name),
                                      self.arguments, self.localvars,
                                      self.instructions)
        self.register_function(entry_m)

        return cil.CILProgramNode(self.dottypes, self.dotdata, self.dotcode)
    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 _boxing(self, vinfo, ctype):
     vlocal = self.define_internal_local()
     self.register_instruction(
         cil.CILAllocateNode(vlocal, self.dottypes[ctype].cinfo))
     # t_local = self.define_internal_local()
     # self.register_instruction(cil.CILTypeOfNode(t_local, vlocal))
     self.register_instruction(cil.CILSaveState())
     self.register_instruction(cil.CILParamNode(vlocal))
     useless = self.define_internal_local()
     fname = self.dottypes[ctype].methods['ctor'].finfo.name
     self.register_instruction(cil.CILStaticCallNode(useless, fname))
     num2 = self.dottypes[ctype].attrs['value'].vmholder
     self.register_instruction(cil.CILSetAttribNode(vlocal, num2, vinfo))
     return vlocal
    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.New, dest):
        # print("------------visit node: New")
        if node.newType == 'Int' or node.newType == 'Bool':
            self.register_instruction(cil.CILAssignNode(dest, 0))

        elif node.newType == 'String':
            msg = self.register_data("")
            var = self.define_internal_local()
            self.register_instruction(cil.CILLoadNode(var, msg))
            self.register_instruction(cil.CILAssignNode(dest, var))

        else:
            self.register_instruction(
                cil.CILAllocateNode(dest, self.dottypes[node.newType].cinfo))
            self.register_instruction(cil.CILSaveState())
            self.register_instruction(cil.CILParamNode(dest))
            useless = self.define_internal_local()
            # v_type = self.define_internal_local()
            # self.register_instruction(cil.CILTypeOfNode(v_type, dest))
            fname = self.dottypes[node.newType].methods['ctor'].finfo.name
            self.register_instruction(cil.CILStaticCallNode(useless, fname))
    def visit(self, node: ast.CoolClass):
        # print("------------visit node: CoolClass")
        self.current_class = self.dottypes[node.name]
        parent_class = self.current_class.cinfo.parent

        self.change_current_function(self.current_class.methods['ctor'])
        self.register_argument(VariableInfo('self'))

        useless = self.define_internal_local()
        self.register_instruction(cil.CILSaveState())
        self.register_instruction(cil.CILParamNode(self.arguments[0].vinfo))
        name = parent_class.methods['ctor'].finfo.name
        self.register_instruction(cil.CILStaticCallNode(useless, name))

        for attr in node.attrs:
            self.visit(attr)

        self.register_instruction(cil.CILReturnNode())

        for func in node.methods:
            self.visit(func)