def _try_whole_slice(x: Var, indices: List[Var], values: Var, accumulate: bool) -> bool:
        """
        Usually indices is a list of non-None tensors, so we stack them and feed to mb.scatter_nd
        However, when there exists a whole slice (i.e. :), that index is represented as None
        """
        if all(map(lambda index: index is not None, indices)):
            return False

        # We have 2 ways to translate such torch.index_put, both have pros and cons
        # 1. mb.scatter_nd
        #    * pro: can handle accumulate or update
        #    * cons: (1) falls off ANE; (2) can only have whole slice at last dimensions
        # 2. mb.torch_tensor_assign
        #    * pros: (1) may reside on ANE; (2) can have whole slice at arbitrary dimension
        #    * con: can only handle update
        # Here we use mb.torch_tensor_assign
        # TODO: explore how can we cover as many torch.index_put cases as possible
        if accumulate:
            raise NotImplementedError(
                "If there existed any whole slice (e.g. : in x[:, 0]), "
                "only torch.index_put(..., accumulate=False) handled yet"
            )

        begin = [0] * x.rank
        end = list(x.shape)
        stride = [1] * x.rank
        begin_mask = [True] * x.rank
        end_mask = [True] * x.rank
        # note: in torch slice, an indexed dim becomes size 1, rather than squeezed, e.g.
        #     x = torch.zeros((2, 3))
        #     y = x[:, 1]
        # we will get y.shape as (2, 1)
        is_dim_unity = [False] * x.rank
        for dim, index in enumerate(indices):
            if index is not None:
                if len(index.shape) > 0:
                    index = mb.squeeze(x=index)
                begin[dim] = index
                end[dim] = mb.add(x=index, y=1)
                begin_mask[dim] = False
                end_mask[dim] = False
                is_dim_unity[dim] = True
        begin = mb.concat(values=begin, axis=0)
        end = mb.concat(values=end, axis=0)

        expected_values_shape = []
        for dim in range(x.rank):
            expected_values_shape.append(1 if is_dim_unity[dim] else x.shape[dim])
        expected_values_shape = tuple(expected_values_shape)

        if values.shape != expected_values_shape:
            values_name = values.name + "_broadcasted"
            values = _utils.pymil_broadcast_to(values, expected_values_shape, values_name)

        updated_x = _translate_torch_tensor_assign(
            x=x,
            updates=values,
            begin=begin,
            end=end,
            stride=stride,
            begin_mask=begin_mask,
            end_mask=end_mask,
            squeeze_mask=[False] * x.rank,
            name=node.name,
        )
        context.add(updated_x)
        return True

        Usually indices is a list of non-None tensors, so we stack them and feed to mb.scatter_nd
        However, when there exists a whole slice (i.e. :), that index is represented as None
        
coremltools/converters/mil/frontend/torch/ops.py