struct
    type t = {
      name: string;
      use_dbsnp: bool;
      use_cosmic: bool;
      additional_arguments: string list;
    }
    let create
        ?(use_dbsnp = true) ?(use_cosmic = true) name additional_arguments =
      {name; use_dbsnp; use_cosmic; additional_arguments}

    let to_json {name; use_dbsnp; use_cosmic; additional_arguments}
      : Yojson.Basic.json =
    `Assoc [
      "name"`String name;
      "use-cosmic"`Bool use_cosmic;
      "use-dbsnp"`Bool use_dbsnp;
      "additional-arguments",
      `List (List.map additional_arguments ~f:(fun s -> `String s));
    ]

    let default = create "default" []

    let compile ~reference {name; use_dbsnp; use_cosmic; additional_arguments} =
      let with_db use opt_name get_exn =
        if not use then None
        else
          let node = get_exn reference in
          Some ( [opt_name; node#product#path], [KEDSL.depends_on node])
      in
      let args, edges =
        List.filter_opt [
          with_db use_dbsnp  "--dbsnp" Reference_genome.dbsnp_exn;
          with_db use_cosmic  "--cosmic" Reference_genome.cosmic_exn;
        ]
        |> List.split
      in
      (`Arguments (List.concat args @ additional_arguments),
       `Edges (List.concat edges))

    let name t = t.name
  end