let rec compile_bam_pair ~compiler (pipeline : bam_pair pipeline) :
      [ `Normal of KEDSL.bam_file KEDSL.workflow_node ] *
      [ `Tumor of KEDSL.bam_file KEDSL.workflow_node ] *
      [ `Pipeline of bam_pair pipeline ]
    =
    let {reference_build; work_dir; machine; _} = compiler in
    begin match pipeline with
    | Bam_pair (
        (Gatk_bqsr (n_bqsr_config, Gatk_indel_realigner (n_gir_conf, n_bam)))
        ,
        (Gatk_bqsr (t_bqsr_config, Gatk_indel_realigner (t_gir_conf, t_bam)))
      )
      when
        has_option compiler
          (function `Multi_sample_indel_realignment _ -> true | _ -> false)
        && n_gir_conf = t_gir_conf ->
      let normal = compile_aligner_step ~compiler n_bam in
      let tumor = compile_aligner_step ~compiler t_bam in
      let bam_list_node =
        if has_option compiler ((=) (`Map_reduce `Gatk_indel_realigner))
        then (
          Gatk.indel_realigner_map_reduce ~run_with:machine ~compress:false
            ~configuration:n_gir_conf (KEDSL.Bam_workflow_list [normal; tumor])
        ) else
          Gatk.indel_realigner ~run_with:machine ~compress:false
            ~configuration:n_gir_conf (KEDSL.Bam_workflow_list [normal; tumor])
      in
      begin match KEDSL.explode_bam_list_node bam_list_node with
      | [realigned_normal; realigned_tumor] ->
        let new_pipeline =
          Bam_pair (
            Gatk_bqsr (n_bqsr_config,
                       Bam_sample (Filename.chop_extension realigned_normal#product#path,
                                   realigned_normal)),
            Gatk_bqsr (t_bqsr_config,
                       Bam_sample (Filename.chop_extension realigned_tumor#product#path,
                                   realigned_tumor)))
        in
        compile_bam_pair ~compiler new_pipeline
      | other ->
        failwithf "Gatk.indel_realigner did not return the correct list of length 2 (tumor, normal): it gave %d bams"
          (List.length other)
      end
    | Bam_pair ( Gatk_bqsr (_, Gatk_indel_realigner (_, _)),
                 Gatk_bqsr (_, Gatk_indel_realigner (_, _))) as bam_pair
      when
        has_option compiler
          ((=) (`Multi_sample_indel_realignment `Fail_if_not_happening)) ->
      failwithf "Option (`Multi_sample_indel_realignment `Fail_if_not_happening) is set and this pipeline does not qualify:\n%s"
        (to_json bam_pair |> Yojson.Basic.pretty_to_string)
    | Bam_pair (normal_t, tumor_t) as final_pipeline ->
      let normal = compile_aligner_step ~compiler normal_t in
      let tumor = compile_aligner_step ~compiler tumor_t in
      (`Normal normal, `Tumor tumor, `Pipeline final_pipeline)
    | With_metadata (metadata_spec, p) ->
      let `Normal normal, `Tumor tumor, `Pipeline p =
        compile_bam_pair ~compiler p in

      (`Normal (apply_with_metadata ~metadata_spec normal),
       `Tumor (apply_with_metadata ~metadata_spec tumor),
       `Pipeline p)
    end