This internal method takes the options and statements from the PROC and generates
        the code needed to submit it to SAS. It then submits the code.
        :param self:
        :param procname: str
        :param required_set: set of options
        :param legal_set: set of valid options
        :param kwargs: dict (optional)
        :return: sas result object

def _run_proc(self, procname: str, required_set: set, legal_set: set, **kwargs: dict):
        """
        This internal method takes the options and statements from the PROC and generates
        the code needed to submit it to SAS. It then submits the code.
        :param self:
        :param procname: str
        :param required_set: set of options
        :param legal_set: set of valid options
        :param kwargs: dict (optional)
        :return: sas result object
        """
        data = kwargs.pop('data', None)
        if isinstance(data, str):
            tempdata = data
            try:
                table = tempdata.split('.')[-1]
                lib = tempdata.split('.')[-2]
            except IndexError:
                lib = ''
            # check that the table exists
            assert self.sas.exist(table, lib), "The dataset does not exist. Check your spelling and/or libname assignment."
            data = self.sas.sasdata(table, lib)
        assert isinstance(data, SASdata), "Data must be a sasdata object. Wrong type or string conversion failed."

        if required_set is None:
            required_set = {}
        objtype = procname.lower()
        if {'model'}.intersection(required_set) and 'target' in kwargs.keys() and 'model' not in kwargs.keys():
            kwargs = SASProcCommons._processNominals(self, kwargs, data)
            t_str, tcls_str = SASProcCommons._target_stmt(self, kwargs['target'])
            i_str, icls_str = SASProcCommons._input_stmt(self, kwargs['input'])
            kwargs['model'] = str(t_str + ' = ' + i_str)
            if len(icls_str) > 0:
                kwargs['cls'] = str(tcls_str + " " + icls_str)
            legal_set.add('cls')
            drop_target = kwargs.pop('target', None)
            drop_input = kwargs.pop('input', None)
            self.logger.debug(drop_target)
            self.logger.debug(drop_input)

        elif {'target'}.intersection(required_set) and 'model' in kwargs.keys() and 'target' not in kwargs.keys():
            SASProcCommons._convert_model_to_target(self)

        verifiedKwargs = SASProcCommons._stmt_check(self, required_set, legal_set, kwargs)
        obj1 = []
        nosub = False
        objname = ''
        log = ''
        if len(verifiedKwargs):
            objname = procname[:3].lower() + self.sas._objcnt()  # translate to a libname so needs to be less than 8
            code = SASProcCommons._makeProcCallMacro(self, objtype, objname, data, verifiedKwargs)
            self.logger.debug(procname + " macro submission: " + str(code))
            if not self.sas.nosub:
                ll = self.sas.submit(code, "text")
                log = ll['LOG']
                error = SASProcCommons._errorLog(log)
                isinstance(error, str)
                if len(error) > 1:
                    RuntimeWarning("ERRORS found in SAS log: \n%s" % error)
                    return SASresults(obj1, self.sas, objname, nosub, log)
                try:
                    obj1 = SASProcCommons._objectmethods(self, objname)
                    self.logger.debug(obj1)
                except Exception:
                    pass
            else:
                print(code)
                nosub = True
        else:
            RuntimeWarning("Error in code submission")
        return SASresults(obj1, self.sas, objname, nosub, log)