def get_stack_frame_infos(node: TorchNode) -> Optional[List[FrameInfo]]:
    """
    Extracts frame infos from the node's source range.

    This method parses the stack trace of the node, attempts to extract the filename and line number
    using a regular expression.
    """

    source_range = None
    pattern = None
    if isinstance(node, TorchScriptNodeInfo):
        source_range = node.source_range if len(node.source_range) > 0 else None
        pattern = r"([^ ]+\.py)\((\d+)\)"
    elif isinstance(node, torch.fx.Node):
        source_range = node.meta.get("stack_trace", None)
        pattern = r'File "(.*?)", line (\d+), in (.*?)\n'
    else:
        raise ValueError(
            f"Expected node of type 'TorchScriptNodeInfo' or 'torch.fx.Node' but got {type(node).__name__}"
        )

    if source_range is None:
        return None

    matches = re.findall(pattern=pattern, string=source_range)
    frame_infos = [FrameInfo(filename=match[0], lineno=int(match[1])) for match in matches]
    return frame_infos

    Extracts frame infos from the node's source range.

    This method parses the stack trace of the node, attempts to extract the filename and line number
    using a regular expression.
    
coremltools/models/ml_program/experimental/torch/debugging_utils.py