summaryrefslogtreecommitdiff
path: root/contrib/extraction/extract_env.ml
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/extraction/extract_env.ml')
-rw-r--r--contrib/extraction/extract_env.ml287
1 files changed, 156 insertions, 131 deletions
diff --git a/contrib/extraction/extract_env.ml b/contrib/extraction/extract_env.ml
index 311b42c0..49a86200 100644
--- a/contrib/extraction/extract_env.ml
+++ b/contrib/extraction/extract_env.ml
@@ -6,7 +6,7 @@
(* * GNU Lesser General Public License Version 2.1 *)
(************************************************************************)
-(*i $Id: extract_env.ml 10794 2008-04-15 00:12:06Z letouzey $ i*)
+(*i $Id: extract_env.ml 11846 2009-01-22 18:55:10Z letouzey $ i*)
open Term
open Declarations
@@ -83,8 +83,8 @@ module type VISIT = sig
end
module Visit : VISIT = struct
- (* Thanks to C.S.C, what used to be in a single KNset should now be split
- into a KNset (for inductives and modules names) and a Cset for constants
+ (* What used to be in a single KNset should now be split into a KNset
+ (for inductives and modules names) and a Cset for constants
(and still the remaining MPset) *)
type must_visit =
{ mutable kn : KNset.t; mutable con : Cset.t; mutable mp : MPset.t }
@@ -140,6 +140,30 @@ let factor_fix env l cb msb =
labels, recd, msb''
end
+let build_mb expr typ_opt =
+ { mod_expr = Some expr;
+ mod_type = typ_opt;
+ mod_constraints = Univ.Constraint.empty;
+ mod_alias = Mod_subst.empty_subst;
+ mod_retroknowledge = [] }
+
+let my_type_of_mb env mb =
+ match mb.mod_type with
+ | Some mtb -> mtb
+ | None -> Modops.eval_struct env (Option.get mb.mod_expr)
+
+(** Ad-hoc update of environment, inspired by [Mod_type.check_with_aux_def].
+ To check with Elie. *)
+
+let env_for_mtb_with env mtb idl =
+ let msid,sig_b = match Modops.eval_struct env mtb with
+ | SEBstruct(msid,sig_b) -> msid,sig_b
+ | _ -> assert false
+ in
+ let l = label_of_id (List.hd idl) in
+ let before = fst (list_split_at (fun (l',_) -> l=l') sig_b) in
+ Modops.add_signature (MPself msid) before env
+
(* From a [structure_body] (i.e. a list of [structure_field_body])
to specifications. *)
@@ -151,7 +175,7 @@ let rec extract_sfb_spec env mp = function
let specs = extract_sfb_spec env mp msig in
if logical_spec s then specs
else begin Visit.add_spec_deps s; (l,Spec s) :: specs end
- | (l,SFBmind cb) :: msig ->
+ | (l,SFBmind _) :: msig ->
let kn = make_kn mp empty_dirpath l in
let s = Sind (kn, extract_inductive env kn) in
let specs = extract_sfb_spec env mp msig in
@@ -159,45 +183,52 @@ let rec extract_sfb_spec env mp = function
else begin Visit.add_spec_deps s; (l,Spec s) :: specs end
| (l,SFBmodule mb) :: msig ->
let specs = extract_sfb_spec env mp msig in
- let mtb = Modops.type_of_mb env mb in
- let spec = extract_seb_spec env (mb.mod_type<>None) mtb in
+ let spec = extract_seb_spec env (my_type_of_mb env mb) in
(l,Smodule spec) :: specs
| (l,SFBmodtype mtb) :: msig ->
let specs = extract_sfb_spec env mp msig in
- (l,Smodtype (extract_seb_spec env true(*?*) mtb.typ_expr)) :: specs
- | (l,SFBalias(mp1,_))::msig ->
- extract_sfb_spec env mp
- ((l,SFBmodule {mod_expr = Some (SEBident mp1);
- mod_type = None;
- mod_constraints = Univ.Constraint.empty;
- mod_alias = Mod_subst.empty_subst;
- mod_retroknowledge = []})::msig)
+ (l,Smodtype (extract_seb_spec env mtb.typ_expr)) :: specs
+ | (l,SFBalias(mp1,typ_opt,_))::msig ->
+ let mb = build_mb (SEBident mp1) typ_opt in
+ extract_sfb_spec env mp ((l,SFBmodule mb) :: msig)
(* From [struct_expr_body] to specifications *)
+(* Invariant: the [seb] given to [extract_seb_spec] should either come:
+ - from a [mod_type] or [type_expr] field
+ - from the output of [Modops.eval_struct].
+ This way, any encountered [SEBident] should be a true module type.
+ For instance, [my_type_of_mb] ensures this invariant.
+*)
-and extract_seb_spec env truetype = function
- | SEBident kn when truetype -> Visit.add_mp kn; MTident kn
+and extract_seb_spec env = function
+ | SEBident mp -> Visit.add_mp mp; MTident mp
| SEBwith(mtb',With_definition_body(idl,cb))->
- let mtb''= extract_seb_spec env truetype mtb' in
- (match extract_with_type env cb with (* cb peut contenir des kn *)
+ let env' = env_for_mtb_with env mtb' idl in
+ let mtb''= extract_seb_spec env mtb' in
+ (match extract_with_type env' cb with (* cb peut contenir des kn *)
| None -> mtb''
| Some (vl,typ) -> MTwith(mtb'',ML_With_type(idl,vl,typ)))
- | SEBwith(mtb',With_module_body(idl,mp,_))->
+ | SEBwith(mtb',With_module_body(idl,mp,_,_))->
Visit.add_mp mp;
- MTwith(extract_seb_spec env truetype mtb',
+ MTwith(extract_seb_spec env mtb',
ML_With_module(idl,mp))
+(* TODO: On pourrait peut-etre oter certaines eta-expansion, du genre:
+ | SEBfunctor(mbid,_,SEBapply(m,SEBident (MPbound mbid2),_))
+ when mbid = mbid2 -> extract_seb_spec env m
+ (* faudrait alors ajouter un test de non-apparition de mbid dans mb *)
+*)
| SEBfunctor (mbid, mtb, mtb') ->
let mp = MPbound mbid in
let env' = Modops.add_module mp (Modops.module_body_of_type mtb) env in
- MTfunsig (mbid, extract_seb_spec env true mtb.typ_expr,
- extract_seb_spec env' truetype mtb')
+ MTfunsig (mbid, extract_seb_spec env mtb.typ_expr,
+ extract_seb_spec env' mtb')
| SEBstruct (msid, msig) ->
let mp = MPself msid in
let env' = Modops.add_signature mp msig env in
MTsig (msid, extract_sfb_spec env' mp msig)
- | (SEBapply _|SEBident _ (*when not truetype*)) as mtb ->
- extract_seb_spec env truetype (Modops.eval_struct env mtb)
+ | SEBapply _ as mtb ->
+ extract_seb_spec env (Modops.eval_struct env mtb)
(* From a [structure_body] (i.e. a list of [structure_field_body])
@@ -248,19 +279,11 @@ let rec extract_sfb env mp all = function
let ms = extract_sfb env mp all msb in
let mp = MPdot (mp,l) in
if all || Visit.needed_mp mp then
- (l,SEmodtype (extract_seb_spec env true(*?*) mtb.typ_expr)) :: ms
- else ms
- | (l,SFBalias (mp1,cst)) :: msb ->
- let ms = extract_sfb env mp all msb in
- let mp = MPdot (mp,l) in
- if all || Visit.needed_mp mp then
- (l,SEmodule (extract_module env mp true
- {mod_expr = Some (SEBident mp1);
- mod_type = None;
- mod_constraints= Univ.Constraint.empty;
- mod_alias = empty_subst;
- mod_retroknowledge = []})) :: ms
+ (l,SEmodtype (extract_seb_spec env mtb.typ_expr)) :: ms
else ms
+ | (l,SFBalias (mp1,typ_opt,_)) :: msb ->
+ let mb = build_mb (SEBident mp1) typ_opt in
+ extract_sfb env mp all ((l,SFBmodule mb) :: msb)
(* From [struct_expr_body] to implementations *)
@@ -274,7 +297,7 @@ and extract_seb env mpo all = function
| SEBfunctor (mbid, mtb, meb) ->
let mp = MPbound mbid in
let env' = Modops.add_module mp (Modops.module_body_of_type mtb) env in
- MEfunctor (mbid, extract_seb_spec env true mtb.typ_expr,
+ MEfunctor (mbid, extract_seb_spec env mtb.typ_expr,
extract_seb env' None true meb)
| SEBstruct (msid, msb) ->
let mp,msb = match mpo with
@@ -288,17 +311,8 @@ and extract_seb env mpo all = function
and extract_module env mp all mb =
(* [mb.mod_expr <> None ], since we look at modules from outside. *)
(* Example of module with empty [mod_expr] is X inside a Module F [X:SIG]. *)
- let meb = Option.get mb.mod_expr in
- let mtb = match mb.mod_type with
- | None -> Modops.eval_struct env meb
- | Some mt -> mt
- in
- (* Because of the "with" construct, the module type can be [MTBsig] with *)
- (* a msid different from the one of the module. Here is the patch. *)
- (* PL 26/02/2008: is this still relevant ?
- let mtb = replicate_msid meb mtb in *)
- { ml_mod_expr = extract_seb env (Some mp) all meb;
- ml_mod_type = extract_seb_spec env (mb.mod_type<>None) mtb }
+ { ml_mod_expr = extract_seb env (Some mp) all (Option.get mb.mod_expr);
+ ml_mod_type = extract_seb_spec env (my_type_of_mb env mb) }
let unpack = function MEstruct (_,sel) -> sel | _ -> assert false
@@ -345,28 +359,38 @@ let mono_filename f =
(* Builds a suitable filename from a module id *)
-let module_filename m =
- let d = descr () in
- let f = if d.capital_file then String.capitalize else String.uncapitalize in
- let fn = f (string_of_id m) in
- Some (fn^d.file_suffix), Option.map ((^) fn) d.sig_suffix, m
+let module_filename fc =
+ let d = descr () in
+ let fn = if d.capital_file then fc else String.uncapitalize fc
+ in
+ Some (fn^d.file_suffix), Option.map ((^) fn) d.sig_suffix, id_of_string fc
(*s Extraction of one decl to stdout. *)
let print_one_decl struc mp decl =
- let d = descr () in
- reset_renaming_tables AllButExternal;
- ignore (create_renamings struc);
- push_visible mp;
- msgnl (d.pp_decl decl);
+ let d = descr () in
+ reset_renaming_tables AllButExternal;
+ set_phase Pre;
+ ignore (d.pp_struct struc);
+ set_phase Impl;
+ push_visible mp None;
+ msgnl (d.pp_decl decl);
pop_visible ()
(*s Extraction of a ml struct to a file. *)
-let print_structure_to_file (fn,si,mo) struc =
- let d = descr () in
- reset_renaming_tables AllButExternal;
- let used_modules = create_renamings struc in
+let formatter dry file =
+ if dry then Format.make_formatter (fun _ _ _ -> ()) (fun _ -> ())
+ else match file with
+ | None -> !Pp_control.std_ft
+ | Some cout ->
+ let ft = Pp_control.with_output_to cout in
+ Option.iter (Format.pp_set_margin ft) (Pp_control.get_margin ());
+ ft
+
+let print_structure_to_file (fn,si,mo) dry struc =
+ let d = descr () in
+ reset_renaming_tables AllButExternal;
let unsafe_needs = {
mldummy = struct_ast_search ((=) MLdummy) struc;
tdummy = struct_type_search Mlutil.isDummy struc;
@@ -375,40 +399,39 @@ let print_structure_to_file (fn,si,mo) struc =
if lang () <> Haskell then false
else struct_ast_search (function MLmagic _ -> true | _ -> false) struc }
in
- (* print the implementation *)
- let cout = Option.map open_out fn in
- let ft = match cout with
- | None -> !Pp_control.std_ft
- | Some cout -> Pp_control.with_output_to cout in
- begin try
- msg_with ft (d.preamble mo used_modules unsafe_needs);
- if lang () = Ocaml then begin
- (* for computing objects to duplicate *)
- let devnull = Format.make_formatter (fun _ _ _ -> ()) (fun _ -> ()) in
- msg_with devnull (d.pp_struct struc);
- reset_renaming_tables OnlyLocal;
- end;
+ (* First, a dry run, for computing objects to rename or duplicate *)
+ set_phase Pre;
+ let devnull = formatter true None in
+ msg_with devnull (d.pp_struct struc);
+ let opened = opened_libraries () in
+ (* Print the implementation *)
+ let cout = if dry then None else Option.map open_out fn in
+ let ft = formatter dry cout in
+ begin try
+ (* The real printing of the implementation *)
+ set_phase Impl;
+ msg_with ft (d.preamble mo opened unsafe_needs);
msg_with ft (d.pp_struct struc);
Option.iter close_out cout;
with e ->
Option.iter close_out cout; raise e
end;
- Option.iter info_file fn;
- (* print the signature *)
- Option.iter
- (fun si ->
+ if not dry then Option.iter info_file fn;
+ (* Now, let's print the signature *)
+ Option.iter
+ (fun si ->
let cout = open_out si in
- let ft = Pp_control.with_output_to cout in
- begin try
- msg_with ft (d.sig_preamble mo used_modules unsafe_needs);
- reset_renaming_tables OnlyLocal;
+ let ft = formatter false (Some cout) in
+ begin try
+ set_phase Intf;
+ msg_with ft (d.sig_preamble mo opened unsafe_needs);
msg_with ft (d.pp_sig (signature_of_structure struc));
close_out cout;
with e ->
close_out cout; raise e
end;
info_file si)
- si
+ (if dry then None else si)
(*********************************************)
@@ -426,51 +449,56 @@ let init modular =
reset ();
if modular && lang () = Scheme then error_scheme ()
+(* From a list of [reference], let's retrieve whether they correspond
+ to modules or [global_reference]. Warn the user if both is possible. *)
+
+let rec locate_ref = function
+ | [] -> [],[]
+ | r::l ->
+ let q = snd (qualid_of_reference r) in
+ let mpo = try Some (Nametab.locate_module q) with Not_found -> None
+ and ro = try Some (Nametab.locate q) with Not_found -> None in
+ match mpo, ro with
+ | None, None -> Nametab.error_global_not_found q
+ | None, Some r -> let refs,mps = locate_ref l in r::refs,mps
+ | Some mp, None -> let refs,mps = locate_ref l in refs,mp::mps
+ | Some mp, Some r ->
+ warning_both_mod_and_cst q mp r;
+ let refs,mps = locate_ref l in refs,mp::mps
(*s Recursive extraction in the Coq toplevel. The vernacular command is
\verb!Recursive Extraction! [qualid1] ... [qualidn]. Also used when
extracting to a file with the command:
\verb!Extraction "file"! [qualid1] ... [qualidn]. *)
-let full_extraction f qualids =
- init false;
- let rec find = function
- | [] -> [],[]
- | q::l ->
- let refs,mps = find l in
- try
- let mp = Nametab.locate_module (snd (qualid_of_reference q)) in
- if is_modfile mp then error_MPfile_as_mod mp true;
- refs,(mp::mps)
- with Not_found -> (Nametab.global q)::refs, mps
- in
- let refs,mps = find qualids in
- let struc = optimize_struct refs (mono_environment refs mps) in
- warning_axioms ();
- print_structure_to_file (mono_filename f) struc;
+let full_extr f (refs,mps) =
+ init false;
+ List.iter (fun mp -> if is_modfile mp then error_MPfile_as_mod mp true) mps;
+ let struc = optimize_struct refs (mono_environment refs mps) in
+ warning_axioms ();
+ print_structure_to_file (mono_filename f) false struc;
reset ()
+let full_extraction f lr = full_extr f (locate_ref lr)
+
(*s Simple extraction in the Coq toplevel. The vernacular command
is \verb!Extraction! [qualid]. *)
-let simple_extraction qid =
- init false;
- try
- let mp = Nametab.locate_module (snd (qualid_of_reference qid)) in
- if is_modfile mp then error_MPfile_as_mod mp true;
- full_extraction None [qid]
- with Not_found ->
- let r = Nametab.global qid in
- if is_custom r then
- msgnl (str "User defined extraction:" ++ spc () ++
- str (find_custom r) ++ fnl ())
- else
- let struc = optimize_struct [r] (mono_environment [r] []) in
- let d = get_decl_in_structure r struc in
- warning_axioms ();
- print_one_decl struc (modpath_of_r r) d;
- reset ()
+let simple_extraction r = match locate_ref [r] with
+ | ([], [mp]) as p -> full_extr None p
+ | [r],[] ->
+ init false;
+ if is_custom r then
+ msgnl (str "User defined extraction:" ++ spc () ++
+ str (find_custom r) ++ fnl ())
+ else
+ let struc = optimize_struct [r] (mono_environment [r] []) in
+ let d = get_decl_in_structure r struc in
+ warning_axioms ();
+ print_one_decl struc (modpath_of_r r) d;
+ reset ()
+ | _ -> assert false
(*s (Recursive) Extraction of a library. The vernacular command is
@@ -489,19 +517,16 @@ let extraction_library is_rec m =
if Visit.needed_mp mp
then (mp, unpack (extract_seb env (Some mp) true meb)) :: l
else l
- in
- let struc = List.fold_left select [] l in
- let struc = optimize_struct [] struc in
- warning_axioms ();
- record_contents_fstlev struc;
- let rec print = function
- | [] -> ()
- | (MPfile dir, _) :: l when not is_rec && dir <> dir_m -> print l
- | (MPfile dir, sel) as e :: l ->
- let short_m = snd (split_dirpath dir) in
- print_structure_to_file (module_filename short_m) [e];
- print l
+ in
+ let struc = List.fold_left select [] l in
+ let struc = optimize_struct [] struc in
+ warning_axioms ();
+ let print = function
+ | (MPfile dir as mp, sel) as e ->
+ let dry = not is_rec && dir <> dir_m in
+ let s = string_of_modfile mp in
+ print_structure_to_file (module_filename s) dry [e]
| _ -> assert false
- in
- print struc;
+ in
+ List.iter print struc;
reset ()