summaryrefslogtreecommitdiff
path: root/contrib/extraction/extraction.ml
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/extraction/extraction.ml')
-rw-r--r--contrib/extraction/extraction.ml98
1 files changed, 60 insertions, 38 deletions
diff --git a/contrib/extraction/extraction.ml b/contrib/extraction/extraction.ml
index 46bf06dd..6bfe861f 100644
--- a/contrib/extraction/extraction.ml
+++ b/contrib/extraction/extraction.ml
@@ -6,7 +6,7 @@
(* * GNU Lesser General Public License Version 2.1 *)
(************************************************************************)
-(*i $Id: extraction.ml,v 1.136.2.1 2004/07/16 19:30:07 herbelin Exp $ i*)
+(*i $Id: extraction.ml,v 1.136.2.4 2005/12/01 11:27:15 letouzey Exp $ i*)
(*i*)
open Util
@@ -183,15 +183,17 @@ let rec extract_type env db j c args =
| (Info, Default) ->
(* Standard case: two [extract_type] ... *)
let mld = extract_type env' (0::db) j d [] in
- if mld = Tdummy then Tdummy
+ if type_eq (mlt_env env) mld Tdummy then Tdummy
else Tarr (extract_type env db 0 t [], mld)
| (Info, TypeScheme) when j > 0 ->
(* A new type var. *)
let mld = extract_type env' (j::db) (j+1) d [] in
- if mld = Tdummy then Tdummy else Tarr (Tdummy, mld)
+ if type_eq (mlt_env env) mld Tdummy then Tdummy
+ else Tarr (Tdummy, mld)
| _ ->
let mld = extract_type env' (0::db) j d [] in
- if mld = Tdummy then Tdummy else Tarr (Tdummy, mld))
+ if type_eq (mlt_env env) mld Tdummy then Tdummy
+ else Tarr (Tdummy, mld))
| Sort _ -> Tdummy (* The two logical cases. *)
| _ when sort_of env (applist (c, args)) = InProp -> Tdummy
| Rel n ->
@@ -343,38 +345,53 @@ and extract_ind env kn = (* kn is supposed to be in long form *)
if List.length l = 1 && not (type_mem_kn kn (List.hd l))
then raise (I Singleton);
if l = [] then raise (I Standard);
+ if not mib.mind_record then raise (I Standard);
let ip = (kn, 0) in
- if is_custom (IndRef ip) then raise (I Standard);
- let projs =
- try (find_structure ip).s_PROJ
- with Not_found -> raise (I Standard);
+ let r = IndRef ip in
+ if is_custom r then raise (I Standard);
+ (* Now we're sure it's a record. *)
+ (* First, we find its field names. *)
+ let rec names_prod t = match kind_of_term t with
+ | Prod(n,_,t) -> n::(names_prod t)
+ | LetIn(_,_,_,t) -> names_prod t
+ | Cast(t,_) -> names_prod t
+ | _ -> []
in
- let n = nb_default_params env mip0.mind_nf_arity in
- let projs = try List.map out_some projs with _ -> raise (I Standard) in
- let is_true_proj kn =
- let (_,body) = Sign.decompose_lam_assum (constant_value env kn) in
- match kind_of_term body with
- | Rel _ -> false
- | Case _ -> true
- | _ -> assert false
+ let field_names =
+ list_skipn mip0.mind_nparams (names_prod mip0.mind_user_lc.(0)) in
+ assert (List.length field_names = List.length typ);
+ let projs = ref KNset.empty in
+ let mp,d,_ = repr_kn kn in
+ let rec select_fields l typs = match l,typs with
+ | [],[] -> []
+ | (Name id)::l, typ::typs ->
+ if type_eq (mlt_env env) Tdummy typ then select_fields l typs
+ else
+ let knp = make_kn mp d (label_of_id id) in
+ if not (List.mem false (type_to_sign (mlt_env env) typ)) then
+ projs := KNset.add knp !projs;
+ (ConstRef knp) :: (select_fields l typs)
+ | Anonymous::l, typ::typs ->
+ if type_eq (mlt_env env) Tdummy typ then select_fields l typs
+ else error_record r
+ | _ -> assert false
in
- let projs = List.filter is_true_proj projs in
- let rec check = function
- | [] -> [],[]
- | (typ, kn) :: l ->
- let l1,l2 = check l in
- if type_eq (mlt_env env) Tdummy typ then l1,l2
- else
- let r = ConstRef kn in
- if List.mem false (type_to_sign (mlt_env env) typ)
- then r :: l1, l2
- else r :: l1, r :: l2
- in
- add_record kn n (check (List.combine typ projs));
- raise (I Record)
+ let field_glob = select_fields field_names typ
+ in
+ (* Is this record officially declared with its projections ? *)
+ (* If so, we use this information. *)
+ begin try
+ let n = nb_default_params env mip0.mind_nf_arity in
+ List.iter
+ (option_iter
+ (fun kn -> if KNset.mem kn !projs then add_projection n kn))
+ (find_structure ip).s_PROJ
+ with Not_found -> ()
+ end;
+ Record field_glob
with (I info) -> info
in
- let i = {ind_info = ind_info; ind_nparams = npar; ind_packets = packets} in
+ let i = {ind_info = ind_info; ind_nparams = npar; ind_packets = packets} in
add_ind kn i;
internal_call := KNset.remove kn !internal_call;
i
@@ -564,7 +581,9 @@ and extract_cst_app env mle mlt kn args =
(* Different situations depending of the number of arguments: *)
if ls = 0 then put_magic_if magic2 head
else if List.mem true s then
- if la >= ls then put_magic_if (magic2 && not magic1) (MLapp (head, mla))
+ if la >= ls || not (List.mem false s)
+ then
+ put_magic_if (magic2 && not magic1) (MLapp (head, mla))
else
(* Not enough arguments. We complete via eta-expansion. *)
let ls' = ls-la in
@@ -599,7 +618,7 @@ and extract_cons_app env mle mlt (((kn,i) as ip,j) as cp) args =
let type_cons = type_recomp (types, Tglob (IndRef ip, list_tvar)) in
let type_cons = instantiation (nb_tvars, type_cons) in
(* Then, the usual variables [s], [ls], [la], ... *)
- let s = List.map ((<>) Tdummy) types in
+ let s = List.map (type_neq env Tdummy) types in
let ls = List.length s in
let la = List.length args in
assert (la <= ls + params_nb);
@@ -614,7 +633,7 @@ and extract_cons_app env mle mlt (((kn,i) as ip,j) as cp) args =
let head mla =
if mi.ind_info = Singleton then
put_magic_if magic1 (List.hd mla) (* assert (List.length mla = 1) *)
- else put_magic_if magic1 (MLcons (ConstructRef cp, mla))
+ else put_magic_if magic1 (MLcons (mi.ind_info, ConstructRef cp, mla))
in
(* Different situations depending of the number of arguments: *)
if la < params_nb then
@@ -670,10 +689,12 @@ and extract_case env mle ((kn,i) as ip,c,br) mlt =
(* The types of the arguments of the corresponding constructor. *)
let f t = type_subst_vect metas (type_expand env t) in
let l = List.map f oi.ip_types.(i) in
+ (* the corresponding signature *)
+ let s = List.map (type_neq env Tdummy) oi.ip_types.(i) in
(* Extraction of the branch (in functional form). *)
let e = extract_maybe_term env mle (type_recomp (l,mlt)) br.(i) in
(* We suppress dummy arguments according to signature. *)
- let ids,e = case_expunge (List.map ((<>) Tdummy) l) e in
+ let ids,e = case_expunge s e in
(ConstructRef (ip,i+1), List.rev ids, e)
in
if mi.ind_info = Singleton then
@@ -687,7 +708,7 @@ and extract_case env mle ((kn,i) as ip,c,br) mlt =
end
else
(* Standard case: we apply [extract_branch]. *)
- MLcase (a, Array.init br_size extract_branch)
+ MLcase (mi.ind_info, a, Array.init br_size extract_branch)
(*s Extraction of a (co)-fixpoint. *)
@@ -726,7 +747,7 @@ let extract_std_constant env kn body typ =
(* The real type [t']: without head lambdas, expanded, *)
(* and with [Tvar] translated to [Tvar'] (not instantiable). *)
let l,t' = type_decomp (type_expand env (var2var' t)) in
- let s = List.map ((<>) Tdummy) l in
+ let s = List.map (type_neq env Tdummy) l in
(* The initial ML environment. *)
let mle = List.fold_left Mlenv.push_std_type Mlenv.empty l in
(* Decomposing the top level lambdas of [body]. *)
@@ -836,7 +857,8 @@ let logical_decl = function
| Dterm (_,MLdummy,Tdummy) -> true
| Dtype (_,[],Tdummy) -> true
| Dfix (_,av,tv) ->
- (array_for_all ((=) MLdummy) av) && (array_for_all ((=) Tdummy) tv)
+ (array_for_all ((=) MLdummy) av) &&
+ (array_for_all ((=) Tdummy) tv)
| Dind (_,i) -> array_for_all (fun ip -> ip.ip_logical) i.ind_packets
| _ -> false