76 lines
2.1 KiB
OCaml
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)
|