def sanitize_name(self, name: str, allow_prefix_underscore: Optional[bool] = True) -> str:
        """
        Sanitize the input string and return it back.
        Input string should be of the format: [a-zA-Z_][a-zA-Z0-9_]*

        If it is not, then it is sanitized in the following manner:
        - first, any character that is not [a-zA-Z0-9_] is replaced with "_"
        - if the starting character is not [a-zA-Z_], it is prefixed with self.prefix
        - the resulting string must be unique. If it has been encountered before,
          it is appended by "_0" or "_1" and so on, until it becomes unique.

        :name: str
            current name

        :return: str
            updated name. Returns the same string, if sanitization not required.
        """

        # replace any character that is not [a-zA-Z0-9_] with an underscore
        new_name = self._replace_invalid_char_with_underscore(name)

        # now check if the name starts with anything but [A-Za-z_]
        # if so, then add the prefix
        if re.match("[^a-zA-Z_]", new_name):
            new_name = self.prefix + new_name

        reserved_names = [
            "any",
            "bool",
            "program",
            "func",
            "tensor",
            "list",
            "dict",
            "tuple",
            "true",
            "false",
            "string",
            "bf16",
            "fp16",
            "fp32",
            "fp64",
            "int8",
            "int16",
            "int32",
            "int64",
            "uint8",
            "uint16",
            "uint32",
            "uint64",
            "state",
        ]
        if new_name in reserved_names:
            new_name += "_workaround"

        # if the name start with _, we append "var" in front of it
        if not allow_prefix_underscore:
            if new_name.startswith("_"):
                new_name = "var" + new_name

        if new_name == name:
            # return if nothing has changed
            self.all_names.add(name)
            return name
        else:
            # name has changed
            # make sure it is unique, then return
            if new_name in self.all_names:
                idx = 0
                new_name += "_" + str(idx)
                while new_name in self.all_names:
                    idx += 1
                    new_name += "_" + str(idx)
            # now we have a unique name
            self.all_names.add(new_name)
            return new_name

        Sanitize the input string and return it back.
        Input string should be of the format: [a-zA-Z_][a-zA-Z0-9_]*

        If it is not, then it is sanitized in the following manner:
        - first, any character that is not [a-zA-Z0-9_] is replaced with "_"
        - if the starting character is not [a-zA-Z_], it is prefixed with self.prefix
        - the resulting string must be unique. If it has been encountered before,
          it is appended by "_0" or "_1" and so on, until it becomes unique.

        :name: str
            current name

        :return: str
            updated name. Returns the same string, if sanitization not required.
        
coremltools/converters/mil/mil/passes/defs/preprocess.py