ocaml/tools/depend.ml

338 lines
12 KiB
OCaml
Raw Normal View History

(***********************************************************************)
(* *)
(* OCaml *)
(* *)
(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
(* *)
(* Copyright 1999 Institut National de Recherche en Informatique et *)
(* en Automatique. All rights reserved. This file is distributed *)
(* under the terms of the Q Public License version 1.0. *)
(* *)
(***********************************************************************)
open Asttypes
open Location
open Longident
open Parsetree
module StringSet = Set.Make(struct type t = string let compare = compare end)
(* Collect free module identifiers in the a.s.t. *)
let free_structure_names = ref StringSet.empty
let rec addmodule bv lid =
match lid with
Lident s ->
if not (StringSet.mem s bv)
then free_structure_names := StringSet.add s !free_structure_names
| Ldot(l, s) -> addmodule bv l
| Lapply(l1, l2) -> addmodule bv l1; addmodule bv l2
let add bv lid =
match lid.txt with
Ldot(l, s) -> addmodule bv l
| _ -> ()
let addmodule bv lid = addmodule bv lid.txt
let rec add_type bv ty =
match ty.ptyp_desc with
Ptyp_any -> ()
| Ptyp_var v -> ()
| Ptyp_arrow(_, t1, t2) -> add_type bv t1; add_type bv t2
| Ptyp_tuple tl -> List.iter (add_type bv) tl
| Ptyp_constr(c, tl) -> add bv c; List.iter (add_type bv) tl
| Ptyp_object (fl, _) -> List.iter (fun (_, t) -> add_type bv t) fl
| Ptyp_class(c, tl, _) -> add bv c; List.iter (add_type bv) tl
| Ptyp_alias(t, s) -> add_type bv t
| Ptyp_variant(fl, _, _) ->
List.iter
(function Rtag(_,_,stl) -> List.iter (add_type bv) stl
| Rinherit sty -> add_type bv sty)
fl
| Ptyp_poly(_, t) -> add_type bv t
| Ptyp_package pt -> add_package_type bv pt
| Ptyp_extension _ -> ()
and add_package_type bv (lid, l) =
add bv lid;
List.iter (add_type bv) (List.map (fun (_, e) -> e) l)
let add_opt add_fn bv = function
None -> ()
| Some x -> add_fn bv x
let add_constructor_decl bv pcd =
List.iter (add_type bv) pcd.pcd_args; Misc.may (add_type bv) pcd.pcd_res
let add_type_declaration bv td =
List.iter
(fun (ty1, ty2, _) -> add_type bv ty1; add_type bv ty2)
td.ptype_cstrs;
add_opt add_type bv td.ptype_manifest;
let add_tkind = function
Ptype_abstract -> ()
| Ptype_variant cstrs ->
List.iter (add_constructor_decl bv) cstrs
| Ptype_record lbls ->
List.iter (fun pld -> add_type bv pld.pld_type) lbls in
add_tkind td.ptype_kind
let rec add_class_type bv cty =
match cty.pcty_desc with
Pcty_constr(l, tyl) ->
add bv l; List.iter (add_type bv) tyl
| Pcty_signature { pcsig_self = ty; pcsig_fields = fieldl } ->
add_type bv ty;
List.iter (add_class_type_field bv) fieldl
| Pcty_fun(_, ty1, cty2) ->
add_type bv ty1; add_class_type bv cty2
| Pcty_extension _ -> ()
and add_class_type_field bv pctf =
match pctf.pctf_desc with
Pctf_inherit cty -> add_class_type bv cty
| Pctf_val(_, _, _, ty) -> add_type bv ty
| Pctf_method(_, _, _, ty) -> add_type bv ty
| Pctf_constraint(ty1, ty2) -> add_type bv ty1; add_type bv ty2
| Pctf_extension _ -> ()
let add_class_description bv infos =
add_class_type bv infos.pci_expr
let add_class_type_declaration = add_class_description
let pattern_bv = ref StringSet.empty
let rec add_pattern bv pat =
match pat.ppat_desc with
Ppat_any -> ()
| Ppat_var _ -> ()
| Ppat_alias(p, _) -> add_pattern bv p
| Ppat_constant _ -> ()
| Ppat_tuple pl -> List.iter (add_pattern bv) pl
| Ppat_construct(c, op, _) -> add bv c; add_opt add_pattern bv op
| Ppat_record(pl, _) ->
List.iter (fun (lbl, p) -> add bv lbl; add_pattern bv p) pl
| Ppat_array pl -> List.iter (add_pattern bv) pl
| Ppat_or(p1, p2) -> add_pattern bv p1; add_pattern bv p2
| Ppat_constraint(p, ty) -> add_pattern bv p; add_type bv ty
| Ppat_variant(_, op) -> add_opt add_pattern bv op
| Ppat_type li -> add bv li
| Ppat_lazy p -> add_pattern bv p
| Ppat_unpack id -> pattern_bv := StringSet.add id.txt !pattern_bv
| Ppat_extension _ -> ()
let add_pattern bv pat =
pattern_bv := bv;
add_pattern bv pat;
!pattern_bv
let rec add_expr bv exp =
match exp.pexp_desc with
Pexp_ident l -> add bv l
| Pexp_constant _ -> ()
| Pexp_let(rf, pel, e) ->
let bv = add_bindings rf bv pel in add_expr bv e
| Pexp_function (_, opte, pel) ->
add_opt add_expr bv opte; add_pat_expr_list bv pel
| Pexp_apply(e, el) ->
add_expr bv e; List.iter (fun (_,e) -> add_expr bv e) el
| Pexp_match(e, pel) -> add_expr bv e; add_pat_expr_list bv pel
| Pexp_try(e, pel) -> add_expr bv e; add_pat_expr_list bv pel
| Pexp_tuple el -> List.iter (add_expr bv) el
| Pexp_construct(c, opte, _) -> add bv c; add_opt add_expr bv opte
| Pexp_variant(_, opte) -> add_opt add_expr bv opte
| Pexp_record(lblel, opte) ->
List.iter (fun (lbl, e) -> add bv lbl; add_expr bv e) lblel;
add_opt add_expr bv opte
| Pexp_field(e, fld) -> add_expr bv e; add bv fld
| Pexp_setfield(e1, fld, e2) -> add_expr bv e1; add bv fld; add_expr bv e2
| Pexp_array el -> List.iter (add_expr bv) el
| Pexp_ifthenelse(e1, e2, opte3) ->
add_expr bv e1; add_expr bv e2; add_opt add_expr bv opte3
| Pexp_sequence(e1, e2) -> add_expr bv e1; add_expr bv e2
| Pexp_while(e1, e2) -> add_expr bv e1; add_expr bv e2
| Pexp_for( _, e1, e2, _, e3) ->
add_expr bv e1; add_expr bv e2; add_expr bv e3
| Pexp_constraint(e1, oty2, oty3) ->
add_expr bv e1;
add_opt add_type bv oty2;
add_opt add_type bv oty3
| Pexp_when(e1, e2) -> add_expr bv e1; add_expr bv e2
| Pexp_send(e, m) -> add_expr bv e
| Pexp_new li -> add bv li
| Pexp_setinstvar(v, e) -> add_expr bv e
| Pexp_override sel -> List.iter (fun (s, e) -> add_expr bv e) sel
| Pexp_letmodule(id, m, e) ->
add_module bv m; add_expr (StringSet.add id.txt bv) e
| Pexp_assert (e) -> add_expr bv e
| Pexp_assertfalse -> ()
| Pexp_lazy (e) -> add_expr bv e
| Pexp_poly (e, t) -> add_expr bv e; add_opt add_type bv t
| Pexp_object { pcstr_self = pat; pcstr_fields = fieldl } ->
let bv = add_pattern bv pat in List.iter (add_class_field bv) fieldl
| Pexp_newtype (_, e) -> add_expr bv e
| Pexp_pack m -> add_module bv m
| Pexp_open (m, e) -> addmodule bv m; add_expr bv e
| Pexp_extension _ -> ()
and add_pat_expr_list bv pel =
List.iter (fun (p, e) -> let bv = add_pattern bv p in add_expr bv e) pel
and add_bindings recf bv pel =
let bv' = List.fold_left (fun bv (p, _) -> add_pattern bv p) bv pel in
let bv = if recf = Recursive then bv' else bv in
List.iter (fun (_, e) -> add_expr bv e) pel;
bv'
and add_modtype bv mty =
match mty.pmty_desc with
Pmty_ident l -> add bv l
| Pmty_signature s -> add_signature bv s
| Pmty_functor(id, mty1, mty2) ->
add_modtype bv mty1; add_modtype (StringSet.add id.txt bv) mty2
| Pmty_with(mty, cstrl) ->
add_modtype bv mty;
List.iter
(function (_, Pwith_type td) -> add_type_declaration bv td
| (_, Pwith_module (lid)) -> addmodule bv lid
| (_, Pwith_typesubst td) -> add_type_declaration bv td
| (_, Pwith_modsubst (lid)) -> addmodule bv lid)
cstrl
| Pmty_typeof m -> add_module bv m
| Pmty_extension _ -> ()
and add_signature bv = function
[] -> ()
| item :: rem -> add_signature (add_sig_item bv item) rem
and add_sig_item bv item =
match item.psig_desc with
Psig_value vd ->
add_type bv vd.pval_type; bv
| Psig_type dcls ->
List.iter (add_type_declaration bv) dcls; bv
| Psig_exception pcd ->
add_constructor_decl bv pcd; bv
| Psig_module pmd ->
add_modtype bv pmd.pmd_type; StringSet.add pmd.pmd_name.txt bv
| Psig_recmodule decls ->
let bv' = List.fold_right StringSet.add (List.map (fun pmd -> pmd.pmd_name.txt) decls) bv in
List.iter (fun pmd -> add_modtype bv' pmd.pmd_type) decls;
bv'
| Psig_modtype x ->
begin match x.pmtd_type with
None -> ()
| Some mty -> add_modtype bv mty
end;
bv
| Psig_open (lid, _) ->
addmodule bv lid; bv
| Psig_include (mty, _) ->
add_modtype bv mty; bv
| Psig_class cdl ->
List.iter (add_class_description bv) cdl; bv
| Psig_class_type cdtl ->
List.iter (add_class_type_declaration bv) cdtl; bv
| Psig_attribute _ | Psig_extension _ ->
bv
and add_module bv modl =
match modl.pmod_desc with
Pmod_ident l -> addmodule bv l
| Pmod_structure s -> ignore (add_structure bv s)
| Pmod_functor(id, mty, modl) ->
add_modtype bv mty;
add_module (StringSet.add id.txt bv) modl
| Pmod_apply(mod1, mod2) ->
add_module bv mod1; add_module bv mod2
| Pmod_constraint(modl, mty) ->
add_module bv modl; add_modtype bv mty
| Pmod_unpack(e) ->
add_expr bv e
| Pmod_extension _ ->
()
and add_structure bv item_list =
List.fold_left add_struct_item bv item_list
and add_struct_item bv item =
match item.pstr_desc with
Pstr_eval (e, _attrs) ->
add_expr bv e; bv
| Pstr_value(rf, pel, _attrs) ->
let bv = add_bindings rf bv pel in bv
| Pstr_primitive vd ->
add_type bv vd.pval_type; bv
| Pstr_type dcls ->
List.iter (add_type_declaration bv) dcls; bv
| Pstr_exception pcd ->
add_constructor_decl bv pcd; bv
| Pstr_exn_rebind(id, l, _attrs) ->
add bv l; bv
| Pstr_module x ->
add_module bv x.pmb_expr; StringSet.add x.pmb_name.txt bv
| Pstr_recmodule bindings ->
let bv' =
List.fold_right StringSet.add
(List.map (fun x -> x.pmb_name.txt) bindings) bv in
List.iter
(fun x -> add_module bv' x.pmb_expr)
bindings;
bv'
| Pstr_modtype x ->
add_modtype bv x.pmtb_type; bv
| Pstr_open (l, _attrs) ->
addmodule bv l; bv
| Pstr_class cdl ->
List.iter (add_class_declaration bv) cdl; bv
| Pstr_class_type cdtl ->
List.iter (add_class_type_declaration bv) cdtl; bv
| Pstr_include (modl, _attrs) ->
add_module bv modl; bv
| Pstr_attribute _ | Pstr_extension _ ->
bv
and add_use_file bv top_phrs =
ignore (List.fold_left add_top_phrase bv top_phrs)
and add_implementation bv l =
ignore (add_structure bv l)
and add_top_phrase bv = function
| Ptop_def str -> add_structure bv str
| Ptop_dir (_, _) -> bv
and add_class_expr bv ce =
match ce.pcl_desc with
Pcl_constr(l, tyl) ->
add bv l; List.iter (add_type bv) tyl
| Pcl_structure { pcstr_self = pat; pcstr_fields = fieldl } ->
let bv = add_pattern bv pat in List.iter (add_class_field bv) fieldl
| Pcl_fun(_, opte, pat, ce) ->
add_opt add_expr bv opte;
let bv = add_pattern bv pat in add_class_expr bv ce
| Pcl_apply(ce, exprl) ->
add_class_expr bv ce; List.iter (fun (_,e) -> add_expr bv e) exprl
| Pcl_let(rf, pel, ce) ->
let bv = add_bindings rf bv pel in add_class_expr bv ce
| Pcl_constraint(ce, ct) ->
add_class_expr bv ce; add_class_type bv ct
| Pcl_extension _ -> ()
and add_class_field bv pcf =
match pcf.pcf_desc with
Pcf_inherit(_, ce, _) -> add_class_expr bv ce
| Pcf_val(_, _, Cfk_concrete (_, e))
| Pcf_method(_, _, Cfk_concrete (_, e)) -> add_expr bv e
| Pcf_val(_, _, Cfk_virtual ty)
| Pcf_method(_, _, Cfk_virtual ty) -> add_type bv ty
| Pcf_constraint(ty1, ty2) -> add_type bv ty1; add_type bv ty2
| Pcf_initializer e -> add_expr bv e
| Pcf_extension _ -> ()
and add_class_declaration bv decl =
add_class_expr bv decl.pci_expr