open Ocamlbuild_plugin

let split s ~on =
  let rec loop i =
    match String.index_from s i on with
    | exception Not_found -> [String.sub s i (String.length s - i)]
    | j -> String.sub s i (j - i) :: loop (j + 1)
  in
  loop 0

let exe_ext ~native = if native then "native" else "byte"

let parse_tag_arg s =
  let set, args =
    match String.index s ' ' with
    | exception Not_found -> (s, "")
    | i -> (String.before s i, String.after s i)
  in
  let libs = split set ~on:'+' in
  (List.sort String.compare libs, args)

let prog_of_libs ~native libs =
  "omp-driver-" ^ String.concat "+" libs -.- exe_ext ~native

let pp_command_of_string ~native s =
  let libs, args = parse_tag_arg s in
  S [ A "-pp"
    ; A (Printf.sprintf "./%s --dump-ast%s" (prog_of_libs ~native libs) args)
    ]

let deps_of_string ~native s =
  let libs, _ = parse_tag_arg s in
  [ prog_of_libs ~native libs ]

let dispatch = function
  | After_rules -> begin
      (* If we are using a native plugin, we might as well use a native preprocessor. *)
      let native = !Options.native_plugin in

      pflag [ "ocaml"; "compile"  ] "omp-driver" (pp_command_of_string ~native);
      pflag [ "ocaml"; "ocamldep" ] "omp-driver" (pp_command_of_string ~native);
      pflag [ "ocaml"; "doc"      ] "omp-driver" (pp_command_of_string ~native);

      pdep [ "ocaml"; "compile"  ] "omp-driver" (deps_of_string ~native);
      pdep [ "ocaml"; "ocamldep" ] "omp-driver" (deps_of_string ~native);
      pdep [ "ocaml"; "doc"      ] "omp-driver" (deps_of_string ~native);

      let target = "omp-driver-%" -.- exe_ext ~native in
      rule "autogenerated ocaml-migrate-parsetree driver"
        ~prod:target
        (fun env _ ->
           let pkgs = split (env "%") ~on:'+' @ ["ocaml-migrate-parsetree.driver-main"] in
           Cmd (S [ if native then !Options.ocamlopt else !Options.ocamlc
                  ; A "-predicates"; A "ppx_driver"
                  ; A "-linkpkg"
                  ; A "-o"; A (env target)
                  ; A "-package"; A (String.concat "," pkgs)
                  ]))
    end
  | _ -> ()
