dune/src/arg_spec.ml

76 lines
2.1 KiB
OCaml

open Import
module Pset = Path.Set
type 'a t =
| A of string
| As of string list
| S of 'a t list
| Dep of Path.t
| Deps of Path.t list
| Dep_rel of Path.t * string
| Deps_rel of Path.t * string list
| Target of Path.t
| Path of Path.t
| Paths of Path.t list
| Dyn of ('a -> nothing t)
let rec add_deps ts set =
List.fold_left ts ~init:set ~f:(fun set t ->
match t with
| Dep fn -> Pset.add fn set
| Deps fns -> Pset.union set (Pset.of_list fns)
| Dep_rel (dir, fn) -> Pset.add (Path.relative dir fn) set
| Deps_rel (dir, fns) ->
List.fold_left fns ~init:set ~f:(fun set fn ->
Pset.add (Path.relative dir fn) set)
| S ts -> add_deps ts set
| _ -> set)
let rec add_targets ts acc =
List.fold_left ts ~init:acc ~f:(fun acc t ->
match t with
| Target fn -> fn :: acc
| S ts -> add_targets ts acc
| _ -> acc)
let expand ~dir ts x =
let dyn_deps = ref Path.Set.empty in
let add_dep path = dyn_deps := Path.Set.add path !dyn_deps in
let rec loop_dyn : nothing t -> string list = function
| A s -> [s]
| As l -> l
| Dep_rel (dir, fn) ->
add_dep (Path.relative dir fn);
[fn]
| Deps_rel (dir, fns) ->
List.iter fns ~f:(fun fn -> add_dep (Path.relative dir fn));
fns
| Dep fn ->
add_dep fn;
[Path.reach fn ~from:dir]
| Path fn -> [Path.reach fn ~from:dir]
| Deps fns ->
List.map fns ~f:(fun fn ->
add_dep fn;
Path.reach ~from:dir fn)
| Paths fns ->
List.map fns ~f:(Path.reach ~from:dir)
| S ts -> List.concat_map ts ~f:loop_dyn
| Target _ -> die "Target not allowed under Dyn"
| Dyn _ -> assert false
in
let rec loop = function
| A s -> [s]
| As l -> l
| Dep_rel (_, fn) -> [fn]
| Deps_rel (_, fns) -> fns
| (Dep fn | Path fn) -> [Path.reach fn ~from:dir]
| (Deps fns | Paths fns) -> List.map fns ~f:(Path.reach ~from:dir)
| S ts -> List.concat_map ts ~f:loop
| Target fn -> [Path.reach fn ~from:dir]
| Dyn f -> loop_dyn (f x)
in
let l = List.concat_map ts ~f:loop in
(l, !dyn_deps)