aboutsummaryrefslogtreecommitdiffhomepage
path: root/contrib/extraction/extraction.ml
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/extraction/extraction.ml')
-rw-r--r--contrib/extraction/extraction.ml337
1 files changed, 244 insertions, 93 deletions
diff --git a/contrib/extraction/extraction.ml b/contrib/extraction/extraction.ml
index 616648143..aa7fadc67 100644
--- a/contrib/extraction/extraction.ml
+++ b/contrib/extraction/extraction.ml
@@ -8,6 +8,7 @@ open Term
open Declarations
open Environ
open Reduction
+open Inductive
open Instantiate
open Miniml
open Mlimport
@@ -26,102 +27,178 @@ type extraction_result =
| Emltype of ml_type * signature * identifier list
| Emlterm of ml_ast
+(*s Utility functions. *)
+
+let array_foldi f a =
+ let n = Array.length a in
+ let rec fold i v = if i = n then v else fold (succ i) (f i a.(i) v) in
+ fold 0
+
let flexible_name = id_of_string "flex"
let id_of_name = function
| Anonymous -> id_of_string "_"
| Name id -> id
-(*s Extraction of a type. *)
+let params_of_sign =
+ List.fold_left (fun l v -> match v with Vskip,_ -> l | _,id -> id :: l) []
-let rec extract_type c =
- let genv = Global.env() in
- let rec extract_rec env sign fl c args = match kind_of_term (whd_beta c) with
- | IsProd (n, t, d) ->
- assert (args = []);
- let id = id_of_name n in (* FIXME: capture problem *)
+let signature_of_arity =
+ let rec sign_of acc env c = match kind_of_term c with
+ | IsProd (n, t, c') ->
let env' = push_rel (n,None,t) env in
- (match extract_rec env sign fl t [] with
- | Tarity ->
- extract_rec env' ((Varity,id) :: sign) fl d []
- | Tmltype (t', _, fl') ->
- (match extract_rec env' ((Vskip,id) :: sign) fl' d [] with
- | Tarity -> Tarity
- | Tmltype (d', sign', fl'') ->
- Tmltype (Tarr (t', d'), sign', fl'')))
- | IsSort (Prop Null) ->
- assert (args = []);
- Tmltype (Tprop, [], [])
- | IsSort _ ->
- assert (args = []);
- Tarity
- | IsApp (d, args') ->
- extract_rec env sign fl d (Array.to_list args' @ args)
- | IsRel n ->
- (match List.nth sign (pred n) with
- | Vskip, id -> Tmltype (Tvar id, sign, id :: fl)
- | Varity, id -> Tmltype (Tvar id, sign, fl))
- | IsConst (sp,a) ->
- let cty = constant_type genv Evd.empty (sp,a) in
- if is_arity genv Evd.empty cty then
- (match extract_constant sp with
- | Emltype (_, sc, flc) ->
- assert (List.length sc = List.length args);
- let (mlargs,fl') =
- List.fold_left
- (fun ((args,fl) as acc) (v,a) -> match v with
- | Vskip,_ -> acc
- | Varity,_ -> match extract_rec env sign fl a [] with
- | Tarity -> assert false
- | Tmltype (mla,_,fl') -> (mla :: args, fl')
- )
- ([],fl) (List.combine sc args)
- in
- let flc = List.map (fun i -> Tvar i) flc in
- Tmltype (Tapp ((Tglob (ConstRef sp)) :: mlargs @ flc),
- sign, fl')
- | Emlterm _ ->
- assert false)
- else
- failwith "todo: expanse c, reduce and apply recursively"
- | IsMutInd _ ->
- failwith "todo"
- | IsMutCase _
- | IsFix _ ->
- let id = next_ident_away flexible_name fl in
- Tmltype (Tvar id, sign, id :: fl)
- | IsCast (c, _) ->
- extract_rec env sign fl c args
- | _ ->
+ let id = id_of_name n in
+ sign_of
+ (((if is_arity env Evd.empty t then Varity else Vskip), id) :: acc)
+ env' c'
+ | IsSort _ ->
+ acc
+ | _ ->
assert false
in
- extract_rec (Global.env()) [] [] c []
+ sign_of []
+
+(* [list_of_ml_arrows] applied to the ML type [a->b->...->z->t]
+ returns the list [[a;b;...:z]]. *)
+let rec list_of_ml_arrows = function
+ | Tarr (a, b) -> a :: list_of_ml_arrows b
+ | t -> []
+
+(*s Tables to keep the extraction of inductive types and constructors. *)
+
+type inductive_extraction_result = signature * identifier list
+
+let inductive_extraction_table =
+ ref (Gmap.empty : (inductive_path, inductive_extraction_result) Gmap.t)
+
+let add_inductive_extraction i e =
+ inductive_extraction_table := Gmap.add i e !inductive_extraction_table
+
+let lookup_inductive_extraction i = Gmap.find i !inductive_extraction_table
+
+type constructor_extraction_result = ml_type list * signature
+
+let constructor_extraction_table =
+ ref (Gmap.empty : (constructor_path, constructor_extraction_result) Gmap.t)
+
+let add_constructor_extraction c e =
+ constructor_extraction_table := Gmap.add c e !constructor_extraction_table
+
+let lookup_constructor_extraction i = Gmap.find i !constructor_extraction_table
+
+(*i FIXME
+let inductive_declaration_table =
+ ref (Gmap.empty : (section_path, ml_ind list) Gmap.t)
+
+let add_inductive_declaration sp d =
+ inductive_declaration_table := Gmap.add
+i*)
+
+(*s Extraction of a type. *)
+
+let rec extract_type env c =
+ let genv = Global.env() in
+ let rec extract_rec env sign fl c args =
+ let ty = Typing.type_of env Evd.empty c in
+ if is_Prop (whd_betadeltaiota env Evd.empty ty) then
+ Tmltype (Tprop, [], fl)
+ else
+ match kind_of_term (whd_betaiota c) with
+ | IsProd (n, t, d) ->
+ assert (args = []);
+ let id = id_of_name n in (* FIXME: capture problem *)
+ let env' = push_rel (n,None,t) env in
+ (match extract_rec env sign fl t [] with
+ | Tarity ->
+ extract_rec env' ((Varity,id) :: sign) fl d []
+ | Tmltype (t', _, fl') ->
+ (match extract_rec env' ((Vskip,id) :: sign) fl' d [] with
+ | Tarity -> Tarity
+ | Tmltype (d', sign', fl'') ->
+ Tmltype (Tarr (t', d'), sign', fl'')))
+ | IsLambda (n, t, d) ->
+ assert (args = []);
+ let id = id_of_name n in (* FIXME: capture problem *)
+ let env' = push_rel (n,None,t) env in
+ (match extract_rec env sign fl t [] with
+ | Tarity ->
+ extract_rec env' ((Varity,id) :: sign) fl d []
+ | Tmltype (t', _, fl') ->
+ extract_rec env' ((Vskip,id) :: sign) fl' d [])
+ | IsSort (Prop Null) ->
+ assert (args = []);
+ Tmltype (Tprop, [], [])
+ | IsSort _ ->
+ assert (args = []);
+ Tarity
+ | IsApp (d, args') ->
+ extract_rec env sign fl d (Array.to_list args' @ args)
+ | IsRel n ->
+ (match List.nth sign (pred n) with
+ | Vskip, id -> Tmltype (Tvar id, sign, id :: fl)
+ | Varity, id -> Tmltype (Tvar id, sign, fl))
+ | IsConst (sp,a) ->
+ let cty = constant_type genv Evd.empty (sp,a) in
+ if is_arity env Evd.empty cty then
+ (match extract_constant sp with
+ | Emltype (_, sc, flc) ->
+ extract_type_app env sign fl (ConstRef sp,sc,flc) args
+ | Emlterm _ -> assert false)
+ else
+ let cvalue = constant_value env (sp,a) in
+ extract_rec env sign fl (mkApp (cvalue, Array.of_list args)) []
+ | IsMutInd (spi,_) ->
+ let (si,fli) = extract_inductive spi in
+ extract_type_app env sign fl (IndRef spi,si,fli) args
+ | IsMutCase _
+ | IsFix _ ->
+ let id = next_ident_away flexible_name fl in
+ Tmltype (Tvar id, sign, id :: fl)
+ | IsCast (c, _) ->
+ extract_rec env sign fl c args
+ | _ ->
+ assert false
+ and extract_type_app env sign fl (r,sc,flc) args =
+ let nargs = List.length args in
+ assert (List.length sc >= nargs);
+ let (mlargs,fl') =
+ List.fold_right
+ (fun (v,a) ((args,fl) as acc) -> match v with
+ | Vskip,_ -> acc
+ | Varity,_ -> match extract_rec env sign fl a [] with
+ | Tarity -> assert false
+ | Tmltype (mla,_,fl') -> (mla :: args, fl'))
+ (List.combine (list_firstn nargs (List.rev sc)) args)
+ ([],fl)
+ in
+ let flc = List.map (fun i -> Tvar i) flc in
+ Tmltype (Tapp ((Tglob r) :: mlargs @ flc), sign, fl')
+ in
+ extract_rec env [] [] c []
+
(*s Extraction of a term. *)
and extract_term c =
failwith "todo"
-(*i
- let rec extract_rec env c = match kind_of_term (whd_beta c) with
- | _ ->
- failwith "todo"
- | IsSort _ | IsXtra _ | IsVar _ | IsMeta _ ->
- assert false
- in
- extract_rec (Global.env()) c
-i*)
+ (*i
+ let rec extract_rec env c = match kind_of_term (whd_beta c) with
+ | _ ->
+ failwith "todo"
+ | IsSort _ | IsXtra _ | IsVar _ | IsMeta _ ->
+ assert false
+ in
+ extract_rec (Global.env()) c
+ i*)
(*s Extraction of a constr. *)
and extract_constr_with_type c t =
- let redt = whd_betadeltaiota (Global.env()) Evd.empty t in
- if isSort redt then begin
- if is_Prop redt then
- Emltype (Tprop, [], [])
- else
- match extract_type c with
- | Tarity -> error "not an ML type"
- | Tmltype (t, sign, fl) -> Emltype (t, sign, fl)
+ let genv = Global.env () in
+ if is_arity genv Evd.empty t then begin
+ match extract_type genv c with
+ | Tarity -> error "not an ML type"
+ | Tmltype (t, sign, fl) -> Emltype (t, sign, fl)
end else
let t = extract_term c in
Emlterm t
@@ -136,28 +213,102 @@ and extract_constant sp =
let typ = cb.const_type in
let body = match cb.const_body with Some c -> c | None -> assert false in
extract_constr_with_type body typ
-
+
(*s Extraction of an inductive. *)
-and extract_inductive sp =
- let mib = Global.lookup_mind sp in
- failwith "todo"
- (* Dtype ... *)
+and extract_inductive ((sp,_) as i) =
+ extract_mib sp;
+ lookup_inductive_extraction i
+
+and extract_constructor (((sp,_),_) as c) =
+ extract_mib sp;
+ lookup_constructor_extraction c
+
+and extract_mib sp =
+ if not (Gmap.mem (sp,0) !inductive_extraction_table) then begin
+ let mib = Global.lookup_mind sp in
+ let genv = Global.env () in
+ (* first pass: we store inductive signatures together with empty flex. *)
+ Array.iteri
+ (fun i ib -> add_inductive_extraction (sp,i)
+ (signature_of_arity genv ib.mind_nf_arity, []))
+ mib.mind_packets;
+ (* second pass: we extract constructors arities and we accumulate
+ all flexible variables. *)
+ let fl =
+ array_foldi
+ (fun i ib fl ->
+ let mis = build_mis ((sp,i),[||]) mib in
+ array_foldi
+ (fun j _ fl ->
+ let t = mis_constructor_type (succ j) mis in
+ match extract_type genv t with
+ | Tarity -> assert false
+ | Tmltype (mlt, s, f) ->
+ let l = list_of_ml_arrows mlt in
+ add_constructor_extraction ((sp,i),succ j) (l,s);
+ f @ fl)
+ ib.mind_nf_lc fl)
+ mib.mind_packets []
+ in
+ (* third pass: we update the inductive flexible variables. *)
+ for i = 0 to mib.mind_ntypes - 1 do
+ let (s,_) = lookup_inductive_extraction (sp,i) in
+ add_inductive_extraction (sp,i) (s,fl)
+ done
+ end
(*s Extraction of a global reference i.e. a constant or an inductive. *)
-and extract_reference = function
- | ConstRef sp -> extract_constant sp
- | IndRef (sp,_) -> extract_inductive sp
- | VarRef _ | ConstructRef _ -> assert false
+and extract_inductive_declaration sp =
+ extract_mib sp;
+ let mib = Global.lookup_mind sp in
+ let one_constructor ind j id =
+ let (t,_) = lookup_constructor_extraction (ind,succ j) in (id, t)
+ in
+ let one_inductive i ip =
+ let (s,fl) = lookup_inductive_extraction (sp,i) in
+ (params_of_sign s @ fl, ip.mind_typename,
+ Array.to_list (Array.mapi (one_constructor (sp,i)) ip.mind_consnames))
+ in
+ Dtype (Array.to_list (Array.mapi one_inductive mib.mind_packets))
(*s ML declaration from a reference. *)
-let params_of_sign =
- List.fold_left (fun l v -> match v with Vskip,_ -> l | _,id -> id :: l) []
+let extract_declaration = function
+ | ConstRef sp ->
+ let id = basename sp in (* FIXME *)
+ (match extract_constant sp with
+ | Emltype (mlt, s, fl) -> Dabbrev (id, params_of_sign s @ fl, mlt)
+ | Emlterm t -> Dglob (id, t))
+ | IndRef (sp,_) -> extract_inductive_declaration sp
+ | ConstructRef ((sp,_),_) -> extract_inductive_declaration sp
+ | VarRef _ -> assert false
+
+(*s Registration of vernac commands for extraction. *)
+
+module Pp = Ocaml.Make(struct let pp_global = Printer.pr_global end)
+
+open Vernacinterp
+
+let _ =
+ vinterp_add "Extraction"
+ (function
+ | [VARG_CONSTR ast] ->
+ (fun () ->
+ let c = Astterm.interp_constr Evd.empty (Global.env()) ast in
+ match kind_of_term c with
+ (* If it is a global reference, then output the declaration *)
+ | IsConst (sp,_) ->
+ mSGNL (Pp.pp_decl (extract_declaration (ConstRef sp)))
+ | IsMutInd (ind,_) ->
+ mSGNL (Pp.pp_decl (extract_declaration (IndRef ind)))
+ | IsMutConstruct (cs,_) ->
+ mSGNL (Pp.pp_decl (extract_declaration (ConstructRef cs)))
+ (* Otherwise, output the ML type or expression *)
+ | _ ->
+ match extract_constr c with
+ | Emltype (t,_,_) -> mSGNL (Pp.pp_type t)
+ | Emlterm a -> mSGNL (Pp.pp_ast a))
+ | _ -> assert false)
-let extract_declaration r =
- let id = basename (Global.sp_of_global r) in (* FIXME *)
- match extract_reference r with
- | Emltype (mlt, s, fl) -> Dabbrev (id, params_of_sign s @ fl, mlt)
- | Emlterm t -> Dglob (id, t)