diff options
| author | msozeau | 2006-03-13 17:38:17 +0000 |
|---|---|---|
| committer | msozeau | 2006-03-13 17:38:17 +0000 |
| commit | db6c97df4dde8b1ccb2e5b314a4747f66fd524c1 (patch) | |
| tree | 39ba546322e7f3d4bd4cc9d58260d3f1b4114bd5 | |
| parent | d9cc734c4cd2a75a303cc08c3df0973077099ab1 (diff) | |
Update of Subtac contrib. Add {wf n R} as an alternative to {struct n}.
May cause make world to fail because of dependency problems, make depend clean
world should fix that (hopefully).
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@8624 85f007b7-540e-0410-9357-904b9bb8a0f7
| -rw-r--r-- | .depend.camlp4 | 2 | ||||
| -rw-r--r-- | Makefile | 3 | ||||
| -rw-r--r-- | contrib/funind/indfun.ml | 4 | ||||
| -rw-r--r-- | contrib/interface/xlate.ml | 4 | ||||
| -rw-r--r-- | contrib/subtac/FixSub.v | 20 | ||||
| -rw-r--r-- | contrib/subtac/eterm.ml | 8 | ||||
| -rw-r--r-- | contrib/subtac/g_eterm.ml4 | 2 | ||||
| -rw-r--r-- | contrib/subtac/interp.ml | 351 | ||||
| -rw-r--r-- | contrib/subtac/scoq.ml | 51 | ||||
| -rw-r--r-- | contrib/subtac/sparser.ml4 | 125 | ||||
| -rw-r--r-- | contrib/subtac/subtac_command.ml | 257 | ||||
| -rw-r--r-- | interp/constrextern.ml | 8 | ||||
| -rw-r--r-- | interp/constrintern.ml | 27 | ||||
| -rw-r--r-- | interp/topconstr.ml | 10 | ||||
| -rw-r--r-- | interp/topconstr.mli | 9 | ||||
| -rw-r--r-- | parsing/g_constr.ml4 | 20 | ||||
| -rw-r--r-- | parsing/g_vernac.ml4 | 12 | ||||
| -rw-r--r-- | parsing/g_xml.ml4 | 25 | ||||
| -rw-r--r-- | parsing/ppconstr.ml | 15 | ||||
| -rw-r--r-- | parsing/ppvernac.ml | 12 | ||||
| -rw-r--r-- | pretyping/detyping.ml | 2 | ||||
| -rw-r--r-- | pretyping/evarutil.mli | 3 | ||||
| -rw-r--r-- | pretyping/pretyping.ml | 4 | ||||
| -rw-r--r-- | pretyping/pretyping.mli | 4 | ||||
| -rw-r--r-- | pretyping/rawterm.ml | 6 | ||||
| -rw-r--r-- | pretyping/rawterm.mli | 6 | ||||
| -rw-r--r-- | toplevel/command.ml | 2 |
27 files changed, 579 insertions, 413 deletions
diff --git a/.depend.camlp4 b/.depend.camlp4 index 95f25b75b2..741158e9b1 100644 --- a/.depend.camlp4 +++ b/.depend.camlp4 @@ -31,7 +31,7 @@ parsing/q_util.ml: parsing/q_coqast.ml: parsing/g_prim.ml: parsing/g_minicoq.ml: -parsing/g_vernac.ml: +parsing/g_vernac.ml: parsing/grammar.cma parsing/g_proofs.ml: parsing/g_xml.ml: parsing/g_constr.ml: @@ -299,6 +299,9 @@ SUBTACCMO=\ contrib/subtac/subtac_errors.cmo \ contrib/subtac/subtac_coercion.cmo \ contrib/subtac/interp.cmo \ + contrib/subtac/interp_fixpoint.cmo \ + contrib/subtac/subtac_command.cmo \ + contrib/subtac/subtac.cmo \ contrib/subtac/sparser.cmo diff --git a/contrib/funind/indfun.ml b/contrib/funind/indfun.ml index 606352d220..c1c835b923 100644 --- a/contrib/funind/indfun.ml +++ b/contrib/funind/indfun.ml @@ -304,7 +304,7 @@ let do_generate_principle fixpoint_exprl = snd (Topconstr.names_of_local_assums args) in - let annot = Util.list_index (Name id) names - 1 in + let annot = Util.list_index (Name id) names - 1, Topconstr.CStructRec in (name,annot,args,types,body),(None:Vernacexpr.decl_notation) | (name,None,args,types,body),recdef -> let names = (Topconstr.names_of_local_assums args) in @@ -313,7 +313,7 @@ let do_generate_principle fixpoint_exprl = (Util.dummy_loc,"GenFixpoint", Pp.str "the recursive argument needs to be specified") else - (name,0,args,types,body),(None:Vernacexpr.decl_notation) + (name,(0, Topconstr.CStructRec),args,types,body),(None:Vernacexpr.decl_notation) | (_,Some (Wf _),_,_,_),_ | (_,Some (Mes _),_,_,_),_-> error ("Cannot use mutual definition with well-founded recursion") diff --git a/contrib/interface/xlate.ml b/contrib/interface/xlate.ml index 323d885a27..4556d818e0 100644 --- a/contrib/interface/xlate.ml +++ b/contrib/interface/xlate.ml @@ -415,7 +415,7 @@ and (xlate_formula:Topconstr.constr_expr -> Ascent.ct_FORMULA) = function CT_cofixc(xlate_ident id, (CT_cofix_rec_list (strip_mutcorec lm, List.map strip_mutcorec lmi))) | CFix (_, (_, id), lm::lmi) -> - let strip_mutrec (fid, n, bl, arf, ardef) = + let strip_mutrec (fid, (n, ro), bl, arf, ardef) = let (struct_arg,bl,arf,ardef) = if bl = [] then let (bl,arf,ardef) = Ppconstr.split_fix (n+1) arf ardef in @@ -1860,7 +1860,7 @@ let rec xlate_vernac = (CT_co_ind co_or_ind, CT_ind_spec_list (List.map strip_mutind lmi)) | VernacFixpoint ([],_) -> xlate_error "mutual recursive" | VernacFixpoint ((lm :: lmi),boxed) -> - let strip_mutrec ((fid, n, bl, arf, ardef), ntn) = + let strip_mutrec ((fid, (n, ro), bl, arf, ardef), ntn) = let (struct_arg,bl,arf,ardef) = if bl = [] then let (bl,arf,ardef) = Ppconstr.split_fix (n+1) arf ardef in diff --git a/contrib/subtac/FixSub.v b/contrib/subtac/FixSub.v index 4279c17f57..14990a24c5 100644 --- a/contrib/subtac/FixSub.v +++ b/contrib/subtac/FixSub.v @@ -1,18 +1,28 @@ -Require Import Coq.Init.Wf. - -Section FixPoint. +Require Import Wf. +Section Well_founded. Variable A : Set. Variable R : A -> A -> Prop. Hypothesis Rwf : well_founded R. + +Section FixPoint. + Variable P : A -> Set. Variable F_sub : forall x:A, (forall y: { y : A | R y x }, P (proj1_sig y)) -> P x. -Fixpoint Fix_F_sub (x:A) (r:Acc R x) {struct r} : P x := - F_sub x (fun y: { y : A | R y x } => Fix_F_sub (proj1_sig y) (Acc_inv r (proj1_sig y) (proj2_sig y))). +Fixpoint Fix_F_sub (x : A) (r : Acc R x) {struct r} : P x := + F_sub x (fun y: { y : A | R y x} => Fix_F_sub (proj1_sig y) + (Acc_inv r (proj1_sig y) (proj2_sig y))). Definition Fix_sub (x : A) := Fix_F_sub x (Rwf x). End FixPoint. +End Well_founded. + +Check Fix_sub. + +Notation "'forall' { x : A | P } , Q" := + (forall x:{x:A|P}, (fun x => Q) (proj1_sig x)) + (at level 200, x ident, right associativity).
\ No newline at end of file diff --git a/contrib/subtac/eterm.ml b/contrib/subtac/eterm.ml index 99727e5f25..66a2b36019 100644 --- a/contrib/subtac/eterm.ml +++ b/contrib/subtac/eterm.ml @@ -96,7 +96,7 @@ let eterm evm t = y' :: l) [] evl in - let t' = (* Substitute evar refs in the term to De Bruijn indices *) + let t' = (* Substitute evar refs in the term by De Bruijn indices *) subst_evars evts 0 t in let t'' = @@ -106,8 +106,6 @@ let eterm evm t = mkLambda (Name (id_of_string ("Evar" ^ string_of_int id)), c, acc)) t' evts - - in let _declare_evar (id, c) = let id = id_of_string ("Evar" ^ string_of_int id) in @@ -120,8 +118,8 @@ let eterm evm t = in msgnl (str "Term constructed in Eterm" ++ Termops.print_constr_env (Global.env ()) t''); - Tactics.apply_term (Reduction.nf_betaiota t'') (map (fun _ -> Evarutil.mk_new_meta ()) evts) - + Tactics.apply_term t'' (List.map (fun _ -> Evarutil.mk_new_meta ()) evts) + open Tacmach let etermtac (evm, t) = eterm evm t diff --git a/contrib/subtac/g_eterm.ml4 b/contrib/subtac/g_eterm.ml4 index 095e5fafc9..f435219936 100644 --- a/contrib/subtac/g_eterm.ml4 +++ b/contrib/subtac/g_eterm.ml4 @@ -23,5 +23,5 @@ TACTIC EXTEND eterm [ "eterm" ] -> [ (fun gl -> let evm = Tacmach.project gl and t = Tacmach.pf_concl gl in - Eterm.etermtac (evm, t) gl) ] + Eterm.etermtac (Global.env ()) (evm, t) gl) ] END diff --git a/contrib/subtac/interp.ml b/contrib/subtac/interp.ml index f4827c7549..d338c34452 100644 --- a/contrib/subtac/interp.ml +++ b/contrib/subtac/interp.ml @@ -30,6 +30,7 @@ open Rawterm open Evarconv open Pattern open Dyn +open Pretyping open Subtac_coercion open Scoq @@ -178,9 +179,9 @@ let my_print_tycon env = function (* in environment [env], with existential variables [(evars_of isevars)] and *) (* the type constraint tycon *) let rec pretype tycon env isevars lvar c = -(* trace (str "pretype for " ++ (my_print_rawconstr env c) ++ *) -(* str " and tycon "++ my_print_tycon env tycon ++ *) -(* str " in environment: " ++ my_print_env env); *) + trace (str "pretype for " ++ (my_print_rawconstr env c) ++ + str " and tycon "++ my_print_tycon env tycon ++ + str " in environment: " ++ my_print_env env); match c with | RRef (loc,ref) -> @@ -255,8 +256,8 @@ let rec pretype tycon env isevars lvar c = evar_type_fixpoint loc env isevars names ftys vdefj; let fixj = match fixkind with - | RFix (vn,i as vni) -> - let fix = (vni,(names,ftys,Array.map j_val vdefj)) in + | RFix (vn,i) -> + let fix = ((Array.map fst vn, i),(names,ftys,Array.map j_val vdefj)) in (try check_fix env fix with e -> Stdpp.raise_with_loc loc e); make_judge (mkFix fix) ftys.(i) | RCoFix i -> @@ -444,7 +445,7 @@ let rec pretype tycon env isevars lvar c = Cases.compile_cases loc ((fun vtyc env -> pretype vtyc env isevars lvar),isevars) tycon env (* loc *) (po,tml,eqns) - + | RCast(loc,c,k,t) -> let tj = pretype_type empty_tycon env isevars lvar t in let cj = pretype (mk_tycon tj.utj_val) env isevars lvar c in @@ -497,7 +498,88 @@ and pretype_type valcon env isevars lvar = function (loc_of_rawconstr c) env (evars_of !isevars) tj.utj_val v) -type typing_constraint = OfType of types option | IsType + +let merge_evms x y = + Evd.fold (fun ev evi evm -> Evd.add evm ev evi) x y + +let interp env isevars c tycon = + let j = pretype tycon env isevars ([],[]) c in + j.uj_val, j.uj_type + +let find_with_index x l = + let rec aux i = function + (y, _, _) as t :: tl -> if x = y then i, t else aux (succ i) tl + | [] -> raise Not_found + in aux 0 l + +let list_split_at index l = + let rec aux i acc = function + hd :: tl when i = index -> (List.rev acc), tl + | hd :: tl -> aux (succ i) (hd :: acc) tl + | [] -> failwith "list_split_at: Invalid argument" + in aux 0 [] l + +open Vernacexpr + +let coqintern evd env : Topconstr.constr_expr -> Rawterm.rawconstr = Constrintern.intern_constr (evars_of evd) env +let coqinterp evd env : Topconstr.constr_expr -> Term.constr = Constrintern.interp_constr (evars_of evd) env + +let env_with_binders env isevars l = + let rec aux ((env, rels) as acc) = function + Topconstr.LocalRawDef ((loc, name), def) :: tl -> + let rawdef = coqintern !isevars env def in + let coqdef, deftyp = interp env isevars rawdef empty_tycon in + let reldecl = (name, Some coqdef, deftyp) in + aux (push_rel reldecl env, reldecl :: rels) tl + | Topconstr.LocalRawAssum (bl, typ) :: tl -> + let rawtyp = coqintern !isevars env typ in + let coqtyp, typtyp = interp env isevars rawtyp empty_tycon in + let acc = + List.fold_left (fun (env, rels) (loc, name) -> + let reldecl = (name, None, coqtyp) in + (push_rel reldecl env, + reldecl :: rels)) + (env, rels) bl + in aux acc tl + | [] -> acc + in aux (env, []) l + +let subtac_process env isevars id l c tycon = + let evars () = evars_of !isevars in + let _ = trace (str "Creating env with binders") in + let env_binders, binders_rel = env_with_binders env isevars l in + let _ = trace (str "New env created:" ++ my_print_context env_binders) in + let tycon = + match tycon with + None -> empty_tycon + | Some t -> + let t = coqintern !isevars env_binders t in + let _ = trace (str "Internalized specification: " ++ my_print_rawconstr env_binders t) in + let coqt, ttyp = interp env_binders isevars t empty_tycon in + let _ = trace (str "Interpreted type: " ++ my_print_constr env_binders coqt) in + mk_tycon coqt + in + let c = coqintern !isevars env_binders c in + let _ = trace (str "Internalized term: " ++ my_print_rawconstr env c) in + let coqc, ctyp = interp env_binders isevars c tycon in + let _ = trace (str "Interpreted term: " ++ my_print_constr env_binders coqc ++ spc () ++ + str "Coq type: " ++ my_print_constr env_binders ctyp) + in + let _ = trace (str "Original evar map: " ++ Evd.pr_evar_map (evars ())) in + + let fullcoqc = it_mkLambda_or_LetIn coqc binders_rel + and fullctyp = it_mkProd_or_LetIn ctyp binders_rel + in + let fullcoqc = Evarutil.nf_evar (evars_of !isevars) fullcoqc in + let fullctyp = Evarutil.nf_evar (evars_of !isevars) fullctyp in + + let _ = trace (str "After evar normalization: " ++ spc () ++ + str "Coq term: " ++ my_print_constr env fullcoqc ++ spc () + ++ str "Coq type: " ++ my_print_constr env fullctyp) + in + let evm = non_instanciated_map env isevars in + let _ = trace (str "Non instanciated evars map: " ++ Evd.pr_evar_map evm) in + evm, fullcoqc, fullctyp let pretype_gen isevars env lvar kind c = let c' = match kind with @@ -520,6 +602,10 @@ let check_evars env initial_sigma isevars c = assert (Evd.in_dom sigma ev); if not (Evd.in_dom initial_sigma ev) then let (loc,k) = evar_source ev !isevars in + let _ = trace (str "Evar " ++ int ev ++ str " not solved, applied to args : " ++ + Scoq.print_args env args ++ str " in evar map: " ++ + Evd.pr_evar_map sigma) + in error_unsolvable_implicit loc env sigma k | _ -> iter_constr proc_rec c in @@ -542,256 +628,39 @@ let check_evars env initial_sigma isevars c = retourne aussi le nouveau sigma... *) -let understand_judgment sigma env c = - let isevars = ref (create_evar_defs sigma) in +let understand_judgment isevars env c = let j = pretype empty_tycon env isevars ([],[]) c in let j = j_nf_evar (evars_of !isevars) j in - check_evars env sigma isevars (mkCast(j.uj_val,DEFAULTcast, j.uj_type)); + check_evars env (Evd.evars_of !isevars) isevars (mkCast(j.uj_val,DEFAULTcast, j.uj_type)); j (* Raw calls to the unsafe inference machine: boolean says if we must fail on unresolved evars; the unsafe_judgment list allows us to extend env with some bindings *) -let ise_pretype_gen fail_evar sigma env lvar kind c = - let isevars = ref (create_evar_defs sigma) in +let ise_pretype_gen fail_evar isevars env lvar kind c : Evd.open_constr = let c = pretype_gen isevars env lvar kind c in - if fail_evar then check_evars env sigma isevars c; - (!isevars, c) + if fail_evar then check_evars env (Evd.evars_of !isevars) isevars c; + let c = nf_evar (evars_of !isevars) c in + let evm = non_instanciated_map env isevars in + (evm, c) (** Entry points of the high-level type synthesis algorithm *) -type var_map = (identifier * unsafe_judgment) list -type unbound_ltac_var_map = (identifier * identifier option) list - -let understand_gen kind sigma env c = - snd (ise_pretype_gen true sigma env ([],[]) kind c) +let understand_gen kind isevars env c = + ise_pretype_gen false isevars env ([],[]) kind c -let understand sigma env ?expected_type:exptyp c = - snd (ise_pretype_gen true sigma env ([],[]) (OfType exptyp) c) +let understand isevars env ?expected_type:exptyp c = + ise_pretype_gen false isevars env ([],[]) (OfType exptyp) c -let understand_type sigma env c = - snd (ise_pretype_gen true sigma env ([],[]) IsType c) +let understand_type isevars env c = + ise_pretype_gen false isevars env ([],[]) IsType c -let understand_ltac sigma env lvar kind c = - ise_pretype_gen false sigma env lvar kind c +let understand_ltac isevars env lvar kind c = + ise_pretype_gen false isevars env lvar kind c -let understand_tcc sigma env ?expected_type:exptyp c = - let evars,c = ise_pretype_gen false sigma env ([],[]) (OfType exptyp) c in - evars_of evars,c +let understand_tcc isevars env ?expected_type:exptyp c = + ise_pretype_gen false isevars env ([],[]) (OfType exptyp) c -(** Miscellaneous interpretation functions *) -let interp_sort = function - | RProp c -> Prop c - | RType _ -> new_Type_sort () - -let interp_elimination_sort = function - | RProp Null -> InProp - | RProp Pos -> InSet - | RType _ -> InType - -let global_kind = Decl_kinds.IsDefinition Decl_kinds.Definition -let goal_kind = Decl_kinds.Global, Decl_kinds.DefinitionBody Decl_kinds.Definition - -let make_fixpoint t id term = - let term = it_mkLambda_or_LetIn term t.args_after in - let term' = mkLambda (Name id, t.f_fulltype, term) in - mkApp (Lazy.force fixsub, - [| t.arg_type; t.wf_relation; t.wf_proof; t.f_type; - mkLambda (t.arg_name, t.arg_type, term') |]) - -let merge_evms x y = - Evd.fold (fun ev evi evm -> Evd.add evm ev evi) x y - -let interp env isevars c tycon = - let j = pretype tycon env isevars ([],[]) c in - j.uj_val, j.uj_type - -let find_with_index x l = - let rec aux i = function - (y, _, _) as t :: tl -> if x = y then i, t else aux (succ i) tl - | [] -> raise Not_found - in aux 0 l - -let require_library dirpath = - let qualid = (dummy_loc, qualid_of_dirpath (dirpath_of_string dirpath)) in - Library.require_library [qualid] None - -let list_split_at index l = - let rec aux i acc = function - hd :: tl when i = index -> (List.rev acc), tl - | hd :: tl -> aux (succ i) (hd :: acc) tl - | [] -> failwith "list_split_at: Invalid argument" - in aux 0 [] l - -let subtac' recursive id l env (s, t) = - check_required_library ["Coq";"Init";"Datatypes"]; - check_required_library ["Coq";"Init";"Specif"]; - require_library "Coq.subtac.FixSub"; - try - let evd = ref (create_evar_defs Evd.empty) in - let coqintern evd env = Constrintern.intern_constr (evars_of evd) env in - let coqinterp evd env = Constrintern.interp_constr (evars_of evd) env in - let rec env_with_binders ((env, rels) as acc) = function - Topconstr.LocalRawDef ((loc, name), def) :: tl -> - let rawdef = coqintern !evd env def in - let coqdef, deftyp = interp env evd rawdef empty_tycon in - let reldecl = (name, Some coqdef, deftyp) in - env_with_binders (push_rel reldecl env, reldecl :: rels) tl - | Topconstr.LocalRawAssum (bl, typ) :: tl -> - let rawtyp = coqintern !evd env typ in - let coqtyp, typtyp = interp env evd rawtyp empty_tycon in - let acc = - List.fold_left (fun (env, rels) (loc, name) -> - let reldecl = (name, None, coqtyp) in - (push_rel reldecl env, - reldecl :: rels)) - (env, rels) bl - in - env_with_binders acc tl - | [] -> acc - in - trace (str "Creating env with binders"); - let env', binders_rel = env_with_binders (env, []) l in - trace (str "New env created:" ++ my_print_context env'); - let s = coqintern !evd env' s in - trace (str "Internalized specification: " ++ my_print_rawconstr env s); - let coqtype, rec_info, env', binders_type, binders_term = - match recursive with - Some (Some (StructRec _) | None) -> assert(false) - | Some (Some (WfRec (rel, (loc, n)))) -> - let index, ((n, def, ntype) as nrel) = find_with_index n (rel_context env') in - let after, before = list_split_at index (rel_context env') in - let envbefore = push_rel_context before env in - let typeenv = env' in - let coqrel = coqinterp !evd envbefore rel in - let coqs, styp = interp env' evd s empty_tycon in - let fullcoqs = it_mkProd_or_LetIn coqs after in - let ntype = lift index ntype in - let ftype = mkLambda (n, ntype, fullcoqs) in - (*let termenv = - push_rel_context (subst_ctx (mkApp ((Lazy.force _sig).proj1, mkRel 1)) after) *) - - let argtype = - mkApp ((Lazy.force sig_).typ, - [| ntype; - mkLambda (n, ntype, - mkApp (coqrel, [| mkRel 1; mkRel (index + 2)|])) |]) - in - let fulltype = mkProd (n, argtype, fullcoqs) in - let proof = - let wf_rel = mkApp (Lazy.force well_founded, [| ntype; coqrel |]) in - make_existential dummy_loc envbefore evd wf_rel - in - let rec_info = - { arg_name = n; - arg_type = ntype; - args_after = after; - wf_relation = coqrel; - wf_proof = proof; - f_type = ftype; - f_fulltype = fulltype; - } - in - let env' = push_rel (Name id, None, fulltype) env' in - coqs, Some rec_info, env', binders_rel, before - | None -> - let coqs, _ = interp env' evd s empty_tycon in - coqs, None, env', binders_rel, binders_rel - in - (match rec_info with - Some rec_info -> trace (str "Got recursion info: " ++ my_print_rec_info env rec_info) - | None -> ()); - trace (str "Interpreted type: " ++ my_print_constr env' coqtype); - let tycon = mk_tycon coqtype in - let t = coqintern !evd env' t in - trace (str "Internalized term: " ++ my_print_rawconstr env t); - let coqt, ttyp = interp env' evd t tycon in - trace (str "Interpreted term: " ++ my_print_constr env' coqt ++ spc () ++ - str "Infered type: " ++ my_print_constr env' ttyp); - let coercespec = Subtac_coercion.coerce dummy_loc env' evd ttyp coqtype in - trace (str "Specs coercion successfull"); - let realt = app_opt coercespec coqt in - trace (str "Term Specs coercion successfull: " ++ my_print_constr env' realt); - let realt = - match rec_info with - Some t -> make_fixpoint t id realt - | None -> realt - in - (try trace (str "Original evar map: " ++ Evd.pr_evar_map (evars_of !evd)); - with Not_found -> trace (str "Not found in pr_evar_map")); - let realt = it_mkLambda_or_LetIn realt binders_term and - coqtype = it_mkProd_or_LetIn coqtype binders_type - in - let realt = Evarutil.nf_evar (evars_of !evd) realt in - let coqtype = Evarutil.nf_evar (evars_of !evd) coqtype in - trace (str "Coq term: " ++ my_print_constr env realt ++ spc () - ++ str "Coq type: " ++ my_print_constr env coqtype); - let evm = non_instanciated_map env evd in - (try trace (str "Non instanciated evars map: " ++ Evd.pr_evar_map evm); - with Not_found -> trace (str "Not found in pr_evar_map")); - let tac = Eterm.etermtac (evm, realt) in - msgnl (str "Starting proof"); - Command.start_proof id goal_kind coqtype (fun _ _ -> ()); - msgnl (str "Started proof"); - Pfedit.by tac - with - | Typing_error e -> - msg_warning (str "Type error in Program tactic:"); - let cmds = - (match e with - | NonFunctionalApp (loc, x, mux, e) -> - str "non functional application of term " ++ - e ++ str " to function " ++ x ++ str " of (mu) type " ++ mux - | NonSigma (loc, t) -> - str "Term is not of Sigma type: " ++ t - | NonConvertible (loc, x, y) -> - str "Unconvertible terms:" ++ spc () ++ - x ++ spc () ++ str "and" ++ spc () ++ y - | IllSorted (loc, t) -> - str "Term is ill-sorted:" ++ spc () ++ t - ) - in msg_warning cmds - - | Subtyping_error e -> - msg_warning (str "(Program tactic) Subtyping error:"); - let cmds = - match e with - | UncoercibleInferType (loc, x, y) -> - str "Uncoercible terms:" ++ spc () - ++ x ++ spc () ++ str "and" ++ spc () ++ y - | UncoercibleInferTerm (loc, x, y, tx, ty) -> - str "Uncoercible terms:" ++ spc () - ++ tx ++ spc () ++ str "of" ++ spc () ++ str "type" ++ spc () ++ x - ++ str "and" ++ spc() ++ ty ++ spc () ++ str "of" ++ spc () ++ str "type" ++ spc () ++ y - | UncoercibleRewrite (x, y) -> - str "Uncoercible terms:" ++ spc () - ++ x ++ spc () ++ str "and" ++ spc () ++ y - in msg_warning cmds - | Type_errors.TypeError (env, e) -> - debug 2 (Himsg.explain_type_error env e) - - | Pretype_errors.PretypeError (env, e) -> - debug 2 (Himsg.explain_pretype_error env e) - - | Stdpp.Exc_located (loc, e) -> - debug 2 (str "Parsing exception: "); - (match e with - | Type_errors.TypeError (env, e) -> - debug 2 (Himsg.explain_type_error env e) - - | Pretype_errors.PretypeError (env, e) -> - debug 2 (Himsg.explain_pretype_error env e) - | e -> raise e) - - | e -> - msg_warning (str "Uncatched exception: " ++ str (Printexc.to_string e)); - raise e - - - - -let subtac recursive id l env (s, t) = - subtac' recursive id l (Global.env ()) (s, t) diff --git a/contrib/subtac/scoq.ml b/contrib/subtac/scoq.ml index 7a84898890..eb9888c161 100644 --- a/contrib/subtac/scoq.ml +++ b/contrib/subtac/scoq.ml @@ -10,11 +10,23 @@ open Util let contrib_name = "subtac" -let subtac_dir = ["subtac"] -let subfix_module = subtac_dir @ ["FixSub"] +let subtac_dir = [contrib_name] +let fix_sub_module = "FixSub" +let fixsub_module = subtac_dir @ [fix_sub_module] let init_constant dir s = gen_constant contrib_name dir s +let init_reference dir s = gen_reference contrib_name dir s -let fixsub = lazy (init_constant subfix_module "Fix_sub") +let fixsub = lazy (init_constant fixsub_module "Fix_sub") + +let make_ref s = Qualid (dummy_loc, (qualid_of_string s)) +let well_founded_ref = make_ref "Init.Wf.Well_founded" +let acc_ref = make_ref "Init.Wf.Acc" +let acc_inv_ref = make_ref "Init.Wf.Acc_inv" +let fix_sub_ref = make_ref "Coq.subtac.FixSub.Fix_sub" +let lt_wf_ref = make_ref "Coq.Wf_nat.lt_wf" +let sig_ref = make_ref "Init.Specif.sig" +let proj1_sig_ref = make_ref "Init.Specif.proj1_sig" +let proj2_sig_ref = make_ref "Init.Specif.proj2_sig" let build_sig () = { proj1 = init_constant ["Init"; "Specif"] "proj1_sig"; @@ -26,6 +38,8 @@ let build_sig () = let sig_ = lazy (build_sig ()) let eqind = lazy (init_constant ["Init"; "Logic"] "eq") +let eqind_ref = lazy (init_reference ["Init"; "Logic"] "eq") +let refl_equal_ref = lazy (init_reference ["Init"; "Logic"] "refl_equal") let boolind = lazy (init_constant ["Init"; "Datatypes"] "bool") let sumboolind = lazy (init_constant ["Init"; "Specif"] "sumbool") @@ -49,12 +63,6 @@ let my_print_context = Termops.print_rel_context let my_print_env = Termops.print_env let my_print_rawconstr = Printer.pr_rawconstr_env -let mknewexist = - let exist_counter = ref 0 in - fun () -> let i = exist_counter in - incr exist_counter; - !i - let debug_level = ref 0 let debug n s = @@ -80,15 +88,6 @@ let std_relations () = let std_relations = Lazy.lazy_from_fun std_relations -type wf_proof_type = - AutoProof - | ManualProof of Topconstr.constr_expr - | ExistentialProof - -type recursion_order = - | StructRec of name located - | WfRec of Topconstr.constr_expr * name located - type binders = Topconstr.local_binder list let app_opt c e = @@ -96,11 +95,20 @@ let app_opt c e = Some constr -> constr e | None -> e +let print_args env args = + Array.fold_right (fun a acc -> my_print_constr env a ++ spc () ++ acc) args (str "") + let make_existential loc env isevars c = let evar = Evarutil.e_new_evar isevars env ~src:(loc, QuestionMark) c in let (key, args) = destEvar evar in debug 2 (str "Constructed evar " ++ int key ++ str " applied to args: " ++ - Array.fold_right (fun a acc -> my_print_constr env a ++ spc () ++ acc) args (str "")); + print_args env args); + evar + +let make_existential_expr loc env c = + let key = Evarutil.new_untyped_evar () in + let evar = Topconstr.CEvar (loc, key) in + debug 2 (str "Constructed evar " ++ int key); evar let string_of_hole_kind = function @@ -125,3 +133,8 @@ let non_instanciated_map env evd = Pretype_errors.error_unsolvable_implicit loc env evm k) Evd.empty (Evarutil.non_instantiated evm) +let global_kind = Decl_kinds.IsDefinition Decl_kinds.Definition +let goal_kind = Decl_kinds.Global, Decl_kinds.DefinitionBody Decl_kinds.Definition + +let global_fix_kind = Decl_kinds.IsDefinition Decl_kinds.Fixpoint +let goal_fix_kind = Decl_kinds.Global, Decl_kinds.DefinitionBody Decl_kinds.Fixpoint diff --git a/contrib/subtac/sparser.ml4 b/contrib/subtac/sparser.ml4 index 657f11b306..43214c87bd 100644 --- a/contrib/subtac/sparser.ml4 +++ b/contrib/subtac/sparser.ml4 @@ -29,110 +29,53 @@ open Topconstr *) module Gram = Pcoq.Gram -module Constr = Pcoq.Constr -module Tactic = Pcoq.Tactic -module Prim = Pcoq.Prim - -module Subtac = - struct - let gec s = Gram.Entry.create ("Subtac."^s) - (* types *) - let subtac_wf_proof_type : Scoq.wf_proof_type Gram.Entry.e = gec "subtac_wf_proof_type" - let subtac_binders : Scoq.binders Gram.Entry.e = gec "subtac_binders" - let subtac_fixannot : Scoq.recursion_order option Gram.Entry.e = gec "subtac_fixannot" - - (* Hack to parse "(x:=t)" as an explicit argument without conflicts with the *) - (* admissible notation "(x t)" - taken from g_constrnew.ml4 *) - let test_lpar_id_coloneq = - Gram.Entry.of_parser "test_lpar_id_coloneq" - (fun strm -> - Pp.msgnl (Pp.str ("Testing lpar_id_coloneq:" ^ - (snd (List.hd (Stream.npeek 1 strm))))); - - match Stream.npeek 1 strm with - | [("","(")] -> - (match Stream.npeek 2 strm with - | [_; ("IDENT",s)] -> - (match Stream.npeek 3 strm with - | [_; _; ("", ":=")] -> - Stream.junk strm; Stream.junk strm; Stream.junk strm; - Pp.msgnl (Pp.str "Success"); - Names.id_of_string s - | _ -> raise Stream.Failure) - | _ -> raise Stream.Failure) - | _ -> raise Stream.Failure) - - let test_id_coloneq = - Gram.Entry.of_parser "test_id_coloneq" - (fun strm -> - Pp.msgnl (Pp.str ("Testing id_coloneq:" ^ - (snd (List.hd (Stream.npeek 1 strm))))); - - (match Stream.npeek 1 strm with - | [("IDENT",s)] -> - (match Stream.npeek 2 strm with - | [_; ("", ":=")] -> - Stream.junk strm; Stream.junk strm; - Pp.msgnl (Pp.str "Success"); - Names.id_of_string s - | _ -> raise Stream.Failure) - | _ -> raise Stream.Failure)) -end - -open Subtac +module Vernac = Pcoq.Vernac_ + +module SubtacGram = +struct + let gec s = Gram.Entry.create ("Subtac."^s) + (* types *) + let subtac_gallina_loc : Vernacexpr.vernac_expr located Gram.Entry.e = gec "subtac_gallina_loc" +end + +open SubtacGram open Util GEXTEND Gram - GLOBAL: subtac_wf_proof_type subtac_binders subtac_fixannot; + GLOBAL: subtac_gallina_loc; - subtac_wf_proof_type: - [ [ IDENT "proof"; t = Constr.constr -> - Scoq.ManualProof t - | IDENT "auto" -> Scoq.AutoProof - | -> Scoq.ExistentialProof - ] - ] + subtac_gallina_loc: + [ [ g = Vernac.gallina -> loc, g ] ] ; - - subtac_fixannot: - [ [ "{"; IDENT "struct"; id=Prim.name; "}" -> Some (Scoq.StructRec id) - | "{"; IDENT "wf"; rel= Constr.constr; id=Prim.name; "}" -> Some (Scoq.WfRec (rel, id)) - | -> None ] ] - ; - - subtac_binders: [ [ bl = LIST0 Constr.binder_let -> bl ] ] - ; END -type wf_proof_type_argtype = (Scoq.wf_proof_type, constr_expr, Tacexpr.raw_tactic_expr) Genarg.abstract_argument_type +(* type wf_proof_type_argtype = (Scoq.wf_proof_type, constr_expr, Tacexpr.raw_tactic_expr) Genarg.abstract_argument_type *) -let (wit_subtac_wf_proof_type : wf_proof_type_argtype), - (globwit_subtac_wf_proof_type : wf_proof_type_argtype), - (rawwit_subtac_wf_proof_type : wf_proof_type_argtype) = - Genarg.create_arg "subtac_wf_proof_type" +(* let (wit_subtac_wf_proof_type : wf_proof_type_argtype), *) +(* (globwit_subtac_wf_proof_type : wf_proof_type_argtype), *) +(* (rawwit_subtac_wf_proof_type : wf_proof_type_argtype) = *) +(* Genarg.create_arg "subtac_wf_proof_type" *) -type subtac_binders_argtype = (Scoq.binders, constr_expr, Tacexpr.raw_tactic_expr) Genarg.abstract_argument_type +type gallina_loc_argtype = (Vernacexpr.vernac_expr located, constr_expr, Tacexpr.raw_tactic_expr) Genarg.abstract_argument_type -let (wit_subtac_binders : subtac_binders_argtype), - (globwit_subtac_binders : subtac_binders_argtype), - (rawwit_subtac_binders : subtac_binders_argtype) = - Genarg.create_arg "subtac_binders" +let (wit_subtac_gallina_loc : gallina_loc_argtype), + (globwit_subtac_gallina_loc : gallina_loc_argtype), + (rawwit_subtac_gallina_loc : gallina_loc_argtype) = + Genarg.create_arg "subtac_gallina_loc" -type subtac_fixannot_argtype = (Scoq.recursion_order option, constr_expr, Tacexpr.raw_tactic_expr) Genarg.abstract_argument_type +(* type subtac_recdef_argtype = (Scoq.recursion_order option, constr_expr, Tacexpr.raw_tactic_expr) Genarg.abstract_argument_type *) -let (wit_subtac_fixannot : subtac_fixannot_argtype), - (globwit_subtac_fixannot : subtac_fixannot_argtype), - (rawwit_subtac_fixannot : subtac_fixannot_argtype) = - Genarg.create_arg "subtac_fixannot" +(* let (wit_subtac_recdef : subtac_recdef_argtype), *) +(* (globwit_subtac_recdef : subtac_recdef_argtype), *) +(* (rawwit_subtac_recdef : subtac_recdef_argtype) = *) +(* Genarg.create_arg "subtac_recdef" *) -VERNAC COMMAND EXTEND SubtacRec -[ "Recursive" "program" ident(id) subtac_binders(l) subtac_fixannot(f) - ":" lconstr(s) ":=" lconstr(t) ] -> - [ Interp.subtac (Some f) id l Environ.empty_env (s, t) ] -END +(* VERNAC COMMAND EXTEND SubtacRec *) +(* [ "Recursive" "program" ident(id) subtac_binders(l) subtac_recdef(f) ] -> *) +(* [ Interp.subtac id l Environ.empty_env f ] *) +(* END *) VERNAC COMMAND EXTEND Subtac -[ "Program" ident(id) subtac_binders(l) ":" lconstr(s) ":=" lconstr(t) ] -> - [ Interp.subtac None id l Environ.empty_env (s, t) ] +[ "Program" subtac_gallina_loc(g) ] -> + [ Subtac.subtac g ] END diff --git a/contrib/subtac/subtac_command.ml b/contrib/subtac/subtac_command.ml new file mode 100644 index 0000000000..34eff9a176 --- /dev/null +++ b/contrib/subtac/subtac_command.ml @@ -0,0 +1,257 @@ + +open Closure +open RedFlags +open Declarations +open Entries +open Dyn +open Libobject +open Pattern +open Matching +open Pp +open Rawterm +open Sign +open Tacred +open Util +open Names +open Nameops +open Libnames +open Nametab +open Pfedit +open Proof_type +open Refiner +open Tacmach +open Tactic_debug +open Topconstr +open Term +open Termops +open Tacexpr +open Safe_typing +open Typing +open Hiddentac +open Genarg +open Decl_kinds +open Mod_subst +open Printer +open Inductiveops +open Syntax_def +open Pretyping + +open Tacinterp +open Vernacexpr +open Notation + +open Interp +open Scoq + + +(*********************************************************************) +(* Functions to parse and interpret constructions *) + +let interp_gen kind isevars env + ?(impls=([],[])) ?(allow_soapp=false) ?(ltacvars=([],[])) + c = + let c' = Constrintern.intern_gen (kind=Pretyping.IsType) ~impls ~allow_soapp ~ltacvars (Evd.evars_of !isevars) env c in + let c'' = Interp_fixpoint.rewrite_cases c' in + understand_gen kind isevars env c'' + + +let interp_constr isevars env c = + interp_gen (OfType None) isevars env c + +let interp_type isevars env ?(impls=([],[])) c = + interp_gen IsType isevars env ~impls c + +let interp_casted_constr isevars env ?(impls=([],[])) c typ = + interp_gen (OfType (Some typ)) isevars env ~impls c + +let interp_open_constr isevars env c = + understand_tcc isevars env (Constrintern.intern_constr (Evd.evars_of !isevars) env c) + +let interp_constr_judgment isevars env c = + understand_judgment isevars env (Constrintern.intern_constr (Evd.evars_of !isevars) env c) + +(* try to find non recursive definitions *) + +let list_chop_hd i l = match list_chop i l with + | (l1,x::l2) -> (l1,x,l2) + | _ -> assert false + +let collect_non_rec env = + let rec searchrec lnonrec lnamerec ldefrec larrec nrec = + try + let i = + list_try_find_i + (fun i f -> + if List.for_all (fun (_, def) -> not (occur_var env f def)) ldefrec + then i else failwith "try_find_i") + 0 lnamerec + in + let (lf1,f,lf2) = list_chop_hd i lnamerec in + let (ldef1,def,ldef2) = list_chop_hd i ldefrec in + let (lar1,ar,lar2) = list_chop_hd i larrec in + let newlnv = + try + match list_chop i nrec with + | (lnv1,_::lnv2) -> (lnv1@lnv2) + | _ -> [] (* nrec=[] for cofixpoints *) + with Failure "list_chop" -> [] + in + searchrec ((f,def,ar)::lnonrec) + (lf1@lf2) (ldef1@ldef2) (lar1@lar2) newlnv + with Failure "try_find_i" -> + (List.rev lnonrec, + (Array.of_list lnamerec, Array.of_list ldefrec, + Array.of_list larrec, Array.of_list nrec)) + in + searchrec [] + +let recursive_message v = + match Array.length v with + | 0 -> error "no recursive definition" + | 1 -> (Printer.pr_global v.(0) ++ str " is recursively defined") + | _ -> hov 0 (prvect_with_sep pr_coma Printer.pr_global v ++ + spc () ++ str "are recursively defined") + +let build_recursive (lnameargsardef:(fixpoint_expr * decl_notation) list) boxed = + let sigma = Evd.empty + and env0 = Global.env() + and protos = List.map (fun ((f, n, _, _, _),_) -> f,n) lnameargsardef + in + let lnameargsardef = + List.map (fun (f, d) -> Interp_fixpoint.rewrite_fixpoint env0 protos (f, d)) + lnameargsardef + in + let lrecnames = List.map (fun ((f,_,_,_,_),_) -> f) lnameargsardef + and nv = List.map (fun ((_,n,_,_,_),_) -> n) lnameargsardef + in + (* Build the recursive context and notations for the recursive types *) + let (rec_sign,rec_impls,arityl) = + List.fold_left + (fun (env,impls,arl) ((recname,_,bl,arityc,_),_) -> + let arityc = Command.generalize_constr_expr arityc bl in + let isevars = ref (Evd.create_evar_defs sigma) in + let isevars, arity = interp_type isevars env0 arityc in + let impl = + if Impargs.is_implicit_args() + then Impargs.compute_implicits env0 arity + else [] in + let impls' =(recname,([],impl,compute_arguments_scope arity))::impls in + (Environ.push_named (recname,None,arity) env, impls', (isevars, arity)::arl)) + (env0,[],[]) lnameargsardef in + let arityl = List.rev arityl in + let notations = + List.fold_right (fun (_,ntnopt) l -> option_cons ntnopt l) + lnameargsardef [] in + + let recdef = + + (* Declare local notations *) + let fs = States.freeze() in + let def = + try + List.iter (fun (df,c,scope) -> (* No scope for tmp notation *) + Metasyntax.add_notation_interpretation df rec_impls c None) notations; + List.map2 + (fun ((_,_,bl,_,def),_) (evm, arity) -> + let def = abstract_constr_expr def bl in + interp_casted_constr (ref (Evd.create_evar_defs evm)) rec_sign ~impls:([],rec_impls) + def arity) + lnameargsardef arityl + with e -> + States.unfreeze fs; raise e in + States.unfreeze fs; def + in + + let (lnonrec,(namerec,defrec,arrec,nvrec)) = + collect_non_rec env0 lrecnames recdef arityl nv in + let nvrec' = Array.map fst nvrec in(* ignore rec order *) + let declare arrec defrec = + let recvec = + Array.map (subst_vars (List.rev (Array.to_list namerec))) defrec in + let recdecls = (Array.map (fun id -> Name id) namerec, arrec, recvec) in + let rec declare i fi = + trace (str "Declaring: " ++ pr_id fi); + let ce = + { const_entry_body = mkFix ((nvrec',i),recdecls); + const_entry_type = Some arrec.(i); + const_entry_opaque = false; + const_entry_boxed = boxed} in + let kn = Declare.declare_constant fi (DefinitionEntry ce,IsDefinition Fixpoint) + in (ConstRef kn) + in + (* declare the recursive definitions *) + let lrefrec = Array.mapi declare namerec in + Options.if_verbose ppnl (recursive_message lrefrec); + (* (* The others are declared as normal definitions *) + let var_subst id = (id, Constrintern.global_reference id) in + let _ = + List.fold_left + (fun subst (f,def,t) -> + let ce = { const_entry_body = replace_vars subst def; + const_entry_type = Some t; + const_entry_opaque = false; + const_entry_boxed = boxed } in + let _ = + Declare.declare_constant f (DefinitionEntry ce,IsDefinition Definition) + in + warning ((string_of_id f)^" is non-recursively defined"); + (var_subst f) :: subst) + (List.map var_subst (Array.to_list namerec)) + lnonrec + in*) + List.iter (fun (df,c,scope) -> + Metasyntax.add_notation_interpretation df [] c scope) notations + in + let declare l = + let recvec = Array.of_list l + and arrec = Array.map snd arrec + in declare arrec recvec + in + let recdefs = Array.length defrec in + trace (int recdefs ++ str " recursive definitions"); + (* Solve remaining evars *) + let rec solve_evars i acc = + if i < recdefs then + let (evm, def) = defrec.(i) in + if Evd.dom evm = [] then + solve_evars (succ i) (def :: acc) + else + let _,typ = arrec.(i) in + let id = namerec.(i) in + (* Generalize by the recursive prototypes *) + let def = + Termops.it_mkNamedLambda_or_LetIn def (Environ.named_context rec_sign) + and typ = + Termops.it_mkNamedProd_or_LetIn typ (Environ.named_context rec_sign) in + let tac = Eterm.etermtac (evm, def) in + let _ = + trace (str "Starting proof of a fixpoint def:" ++ spc () ++ my_print_constr env0 def ++ + spc () ++ str " with goal: " ++ my_print_constr env0 typ ++ + spc () ++ str " with evar map = " ++ Evd.pr_evar_map evm) + in + begin + Command.start_proof (id_of_string (string_of_id id ^ "_evars")) goal_kind typ + (fun _ gr -> + let _ = trace (str "Got a proof of: " ++ pr_global gr) in + let constant = match gr with Libnames.ConstRef c -> c + | _ -> assert(false) + in + try + let def = Environ.constant_value (Global.env ()) constant in + let _ = trace (str "Got constant value") in + let _, c = decompose_lam_n recdefs def in + let _ = trace (str "Fixpoint body is: " ++ spc () ++ my_print_constr (Global.env ()) c) in + solve_evars (succ i) (c :: acc) + with Environ.NotEvaluableConst cer -> + match cer with + Environ.NoBody -> trace (str "Constant has no body") + | Environ.Opaque -> trace (str "Constant is opaque") + ); + trace (str "Started proof"); + Pfedit.by tac; + trace (str "Applied eterm tac"); + end + else declare (List.rev acc) + in solve_evars 0 [] + + diff --git a/interp/constrextern.ml b/interp/constrextern.ml index ff494c7825..0fe01799e1 100644 --- a/interp/constrextern.ml +++ b/interp/constrextern.ml @@ -719,7 +719,8 @@ let rec extern inctx scopes vars r = let (ids,bl) = extern_local_binder scopes vars bl in let vars0 = List.fold_right (name_fold Idset.add) ids vars in let vars1 = List.fold_right (name_fold Idset.add) ids vars' in - (fi,nv.(i), bl, extern_typ scopes vars0 ty, + let n, ro = fst nv.(i), extern_recursion_order scopes vars (snd nv.(i)) in + (fi, (n, ro), bl, extern_typ scopes vars0 ty, extern false scopes vars1 def)) idv in CFix (loc,(loc,idv.(n)),Array.to_list listdecl) @@ -834,6 +835,11 @@ and extern_symbol (tmp_scope,scopes as allscopes) vars t = function with No_match -> extern_symbol allscopes vars t rules +and extern_recursion_order scopes vars = function + RStructRec -> CStructRec + | RWfRec c -> CWfRec (extern true scopes vars c) + + let extern_rawconstr vars c = extern false (None,Notation.current_scopes()) vars c diff --git a/interp/constrintern.ml b/interp/constrintern.ml index 608e1bc900..bda43f8121 100644 --- a/interp/constrintern.ml +++ b/interp/constrintern.ml @@ -785,18 +785,29 @@ let internalise sigma globalenv env allow_soapp lvar c = raise (InternalisationError (locid,UnboundFixName (false,iddef))) in let idl = Array.map - (fun (id,n,bl,ty,bd) -> - let ((ids',_,_),rbl) = - List.fold_left intern_local_binder (env,[]) bl in + (fun (id,(n,order),bl,ty,bd) -> + let ro, ((ids',_,_),rbl) = + (match order with + CStructRec -> + RStructRec, + List.fold_left intern_local_binder (env,[]) bl + | CWfRec c -> + let before, after = list_chop (succ n) bl in + let ((ids',_,_),rafter) = + List.fold_left intern_local_binder (env,[]) after in + let ro = RWfRec (intern (ids', tmp_scope, scopes) c) in + ro, List.fold_left intern_local_binder (env,rafter) before) + in let ids'' = List.fold_right Idset.add lf ids' in - (List.rev rbl, + ((n, ro), List.rev rbl, intern_type (ids',tmp_scope,scopes) ty, intern (ids'',None,scopes) bd)) dl in - RRec (loc,RFix (Array.map (fun (_,n,_,_,_) -> n) dl,n), + RRec (loc,RFix + (Array.map (fun (ro,_,_,_) -> ro) idl,n), Array.of_list lf, - Array.map (fun (bl,_,_) -> bl) idl, - Array.map (fun (_,ty,_) -> ty) idl, - Array.map (fun (_,_,bd) -> bd) idl) + Array.map (fun (_,bl,_,_) -> bl) idl, + Array.map (fun (_,_,ty,_) -> ty) idl, + Array.map (fun (_,_,_,bd) -> bd) idl) | CCoFix (loc, (locid,iddef), dl) -> let lf = List.map (fun (id,_,_,_) -> id) dl in let dl = Array.of_list dl in diff --git a/interp/topconstr.ml b/interp/topconstr.ml index 6a4ad1f59b..4d4e3f88a0 100644 --- a/interp/topconstr.ml +++ b/interp/topconstr.ml @@ -530,8 +530,9 @@ type constr_expr = | CDelimiters of loc * string * constr_expr | CDynamic of loc * Dyn.t + and fixpoint_expr = - identifier * int * local_binder list * constr_expr * constr_expr + identifier * (int * recursion_order_expr) * local_binder list * constr_expr * constr_expr and local_binder = | LocalRawDef of name located * constr_expr @@ -540,6 +541,10 @@ and local_binder = and cofixpoint_expr = identifier * local_binder list * constr_expr * constr_expr +and recursion_order_expr = + | CStructRec + | CWfRec of constr_expr + (***********************) (* For binders parsing *) @@ -551,6 +556,9 @@ let rec local_binders_length = function let names_of_local_assums bl = List.flatten (List.map (function LocalRawAssum(l,_)->l|_->[]) bl) +let names_of_local_binders bl = + List.flatten (List.map (function LocalRawAssum(l,_)->l|LocalRawDef(l,_)->[l]) bl) + (**********************************************************************) (* Functions on constr_expr *) diff --git a/interp/topconstr.mli b/interp/topconstr.mli index 11475cdaa2..073f9ba0b3 100644 --- a/interp/topconstr.mli +++ b/interp/topconstr.mli @@ -114,11 +114,15 @@ type constr_expr = | CDynamic of loc * Dyn.t and fixpoint_expr = - identifier * int * local_binder list * constr_expr * constr_expr + identifier * (int * recursion_order_expr) * local_binder list * constr_expr * constr_expr and cofixpoint_expr = identifier * local_binder list * constr_expr * constr_expr +and recursion_order_expr = + | CStructRec + | CWfRec of constr_expr + and local_binder = | LocalRawDef of name located * constr_expr | LocalRawAssum of name located list * constr_expr @@ -157,6 +161,9 @@ val local_binders_length : local_binder list -> int (* Does not take let binders into account *) val names_of_local_assums : local_binder list -> name located list +(* With let binders *) +val names_of_local_binders : local_binder list -> name located list + (* Used in correctness and interface; absence of var capture not guaranteed *) (* in pattern-matching clauses and in binders of the form [x,y:T(x)] *) diff --git a/parsing/g_constr.ml4 b/parsing/g_constr.ml4 index 6208952d32..9c39878c7d 100644 --- a/parsing/g_constr.ml4 +++ b/parsing/g_constr.ml4 @@ -57,29 +57,29 @@ let rec mkCLambdaN loc bll c = | [] -> c | LocalRawAssum ([],_) :: bll -> mkCLambdaN loc bll c -let rec index_of_annot loc bl ann = +let rec index_and_rec_order_of_annot loc bl ann = match names_of_local_assums bl,ann with - | [_], None -> 0 - | lids, Some x -> + | [_], (None, r) -> 0, r + | lids, (Some x, ro) -> let ids = List.map snd lids in - (try list_index (snd x) ids - 1 + (try list_index (snd x) ids - 1, ro with Not_found -> user_err_loc(fst x,"index_of_annot", Pp.str"no such fix variable")) | _ -> user_err_loc(loc,"index_of_annot", Pp.str "cannot guess decreasing argument of fix") let mk_fixb (id,bl,ann,body,(loc,tyc)) = - let n = index_of_annot (fst id) bl ann in + let n,ro = index_and_rec_order_of_annot (fst id) bl ann in let ty = match tyc with Some ty -> ty | None -> CHole loc in - (snd id,n,bl,ty,body) + (snd id,(n,ro),bl,ty,body) let mk_cofixb (id,bl,ann,body,(loc,tyc)) = let _ = option_app (fun (aloc,_) -> Util.user_err_loc (aloc,"Constr:mk_cofixb", - Pp.str"Annotation forbidden in cofix expression")) ann in + Pp.str"Annotation forbidden in cofix expression")) (fst ann) in let ty = match tyc with Some ty -> ty | None -> CHole loc in @@ -243,8 +243,10 @@ GEXTEND Gram c=operconstr LEVEL "200" -> (id,bl,ann,c,ty) ] ] ; fixannot: - [ [ "{"; IDENT "struct"; id=name; "}" -> Some id - | -> None ] ] + [ [ "{"; IDENT "struct"; id=name; "}" -> (Some id, CStructRec) + | "{"; IDENT "wf"; id=name; rel=lconstr; "}" -> (Some id, CWfRec rel) + | -> (None, CStructRec) + ] ] ; match_constr: [ [ "match"; ci=LIST1 case_item SEP ","; ty=OPT case_type; "with"; diff --git a/parsing/g_vernac.ml4 b/parsing/g_vernac.ml4 index ad3cc5b363..87f388a748 100644 --- a/parsing/g_vernac.ml4 +++ b/parsing/g_vernac.ml4 @@ -7,6 +7,7 @@ (************************************************************************) (* $Id$ *) +(*i camlp4deps: "parsing/grammar.cma" i*) open Pp open Util @@ -211,11 +212,11 @@ GEXTEND Gram (* (co)-fixpoints *) rec_definition: [ [ id = ident; bl = LIST1 binder_let; - annot = OPT rec_annotation; type_ = type_cstr; + annot = rec_annotation; type_ = type_cstr; ":="; def = lconstr; ntn = decl_notation -> let names = List.map snd (names_of_local_assums bl) in let ni = - match annot with + match fst annot with Some id -> (try list_index (Name id) names - 1 with Not_found -> Util.user_err_loc @@ -227,7 +228,7 @@ GEXTEND Gram (loc,"Fixpoint", Pp.str "the recursive argument needs to be specified"); 0 in - ((id, ni, bl, type_, def),ntn) ] ] + ((id, (ni, snd annot), bl, type_, def),ntn) ] ] ; corec_definition: [ [ id = ident; bl = LIST0 binder_let; c = type_cstr; ":="; @@ -235,7 +236,10 @@ GEXTEND Gram (id,bl,c ,def) ] ] ; rec_annotation: - [ [ "{"; IDENT "struct"; id=IDENT; "}" -> id_of_string id ] ] + [ [ "{"; IDENT "struct"; id=IDENT; "}" -> (Some (id_of_string id), CStructRec) + | "{"; IDENT "wf"; id=IDENT; rel=lconstr; "}" -> (Some (id_of_string id), CWfRec rel) + | -> (None, CStructRec) + ] ] ; type_cstr: [ [ ":"; c=lconstr -> c diff --git a/parsing/g_xml.ml4 b/parsing/g_xml.ml4 index 7b7e471c64..1df3d1f256 100644 --- a/parsing/g_xml.ml4 +++ b/parsing/g_xml.ml4 @@ -187,12 +187,31 @@ and interp_xml_decl_alias s x = and interp_xml_def x = interp_xml_decl_alias "def" x and interp_xml_decl x = interp_xml_decl_alias "decl" x +and interp_xml_recursionOrder x = + let (loc, al, l) = interp_xml_tag "RecursionOrder" x in + let (locs, s) = get_xml_attr "type" al in + match s with + "Structural" -> + (match l with [] -> RStructRec + | _ -> user_err_loc (loc, "", str "wrong number of arguments (expected none)")) + | "WellFounded" -> + (match l with + [c] -> RWfRec (interp_xml_type c) + | _ -> user_err_loc (loc, "", str "wrong number of arguments (expected one)")) + | _ -> + user_err_loc (locs,"",str "invalid recursion order") + + and interp_xml_FixFunction x = match interp_xml_tag "FixFunction" x with - | (loc,al,[x1;x2]) -> - (nmtoken (get_xml_attr "recIndex" al), + | (loc,al,[x1;x2;x3]) -> + ((nmtoken (get_xml_attr "recIndex" al), + interp_xml_recursionOrder x1), + (get_xml_ident al, interp_xml_type x2, interp_xml_body x3)) + | (loc,al,[x1;x2]) -> (* For backwards compatibility *) + ((nmtoken (get_xml_attr "recIndex" al), RStructRec), (get_xml_ident al, interp_xml_type x1, interp_xml_body x2)) - | (loc,_,_) -> + | (loc,_,_) -> user_err_loc (loc,"",str "wrong number of arguments (expect one)") and interp_xml_CoFixFunction x = diff --git a/parsing/ppconstr.ml b/parsing/ppconstr.ml index 8bf2f42075..a95fa4bad8 100644 --- a/parsing/ppconstr.ml +++ b/parsing/ppconstr.ml @@ -374,13 +374,18 @@ let pr_recursive_decl pr pr_dangling dangling_with_for id bl annot t c = pr_opt_type_spc pr t ++ str " :=" ++ pr_sep_com (fun () -> brk(1,2)) (pr_body ltop) c -let pr_fixdecl pr prd dangling_with_for (id,n,bl,t,c) = +let pr_fixdecl pr prd dangling_with_for (id,(n,ro),bl,t,c) = let annot = let ids = names_of_local_assums bl in - if List.length ids > 1 then - spc() ++ str "{struct " ++ pr_name (snd (List.nth ids n)) ++ str"}" - else mt() in - pr_recursive_decl pr prd dangling_with_for id bl annot t c + match ro with + CStructRec -> + if List.length ids > 1 then + spc() ++ str "{struct " ++ pr_name (snd (List.nth ids n)) ++ str"}" + else mt() + | CWfRec c -> + spc () ++ str "{wf " ++ pr lsimple c ++ pr_name (snd (List.nth ids n)) ++ str"}" + in + pr_recursive_decl pr prd dangling_with_for id bl annot t c let pr_cofixdecl pr prd dangling_with_for (id,bl,t,c) = pr_recursive_decl pr prd dangling_with_for id bl (mt()) t c diff --git a/parsing/ppvernac.ml b/parsing/ppvernac.ml index e7fc0e01ff..c08b076173 100644 --- a/parsing/ppvernac.ml +++ b/parsing/ppvernac.ml @@ -549,7 +549,7 @@ let rec pr_vernac = function | LocalRawAssum (nal,_) -> nal | LocalRawDef (_,_) -> [] in let pr_onerec = function - | (id,n,bl,type_,def),ntn -> + | (id,(n,ro),bl,type_,def),ntn -> let (bl',def,type_) = if Options.do_translate() then extract_def_binders def type_ else ([],def,type_) in @@ -561,9 +561,13 @@ let rec pr_vernac = function warn (str "non-printable fixpoint \""++pr_id id++str"\""); Anonymous in let annot = - if List.length ids > 1 then - spc() ++ str "{struct " ++ pr_name name ++ str"}" - else mt() in + match (ro : Topconstr.recursion_order_expr) with + CStructRec -> + if List.length ids > 1 then + spc() ++ str "{struct " ++ pr_name name ++ str"}" + else mt() + | CWfRec c -> spc() ++ str "{wf " ++ pr_name name ++ spc() ++ pr_lconstr_expr c ++ str"}" + in pr_id id ++ pr_binders_arg bl ++ annot ++ spc() ++ pr_type_option (fun c -> spc() ++ pr_lconstr_expr c) type_ ++ str" :=" ++ brk(1,1) ++ pr_lconstr def ++ diff --git a/pretyping/detyping.ml b/pretyping/detyping.ml index 38675da786..a815e5d2f8 100644 --- a/pretyping/detyping.ml +++ b/pretyping/detyping.ml @@ -421,7 +421,7 @@ and detype_fix isgoal avoid env (vn,_ as nvn) (names,tys,bodies) = let v = array_map3 (fun c t i -> share_names isgoal (i+1) [] def_avoid def_env c (lift n t)) bodies tys vn in - RRec(dl,RFix nvn,Array.of_list (List.rev lfi), + RRec(dl,RFix (Array.map (fun i -> i, RStructRec) (fst nvn), snd nvn),Array.of_list (List.rev lfi), Array.map (fun (bl,_,_) -> bl) v, Array.map (fun (_,_,ty) -> ty) v, Array.map (fun (_,bd,_) -> bd) v) diff --git a/pretyping/evarutil.mli b/pretyping/evarutil.mli index e6bdcbd9bb..8550258c45 100644 --- a/pretyping/evarutil.mli +++ b/pretyping/evarutil.mli @@ -28,6 +28,9 @@ open Reductionops val new_meta : unit -> metavariable val mk_new_meta : unit -> constr +(* [new_untyped_evar] is a generator of unique evar keys *) +val new_untyped_evar : unit -> existential_key + (***********************************************************) (* Creating a fresh evar given their type and context *) val new_evar : diff --git a/pretyping/pretyping.ml b/pretyping/pretyping.ml index 7d0c926fac..df76f992d0 100644 --- a/pretyping/pretyping.ml +++ b/pretyping/pretyping.ml @@ -232,8 +232,8 @@ let rec pretype tycon env isevars lvar = function evar_type_fixpoint loc env isevars names ftys vdefj; let fixj = match fixkind with - | RFix (vn,i as vni) -> - let fix = (vni,(names,ftys,Array.map j_val vdefj)) in + | RFix (vn,i) -> + let fix = ((Array.map fst vn, i),(names,ftys,Array.map j_val vdefj)) in (try check_fix env fix with e -> Stdpp.raise_with_loc loc e); make_judge (mkFix fix) ftys.(i) | RCoFix i -> diff --git a/pretyping/pretyping.mli b/pretyping/pretyping.mli index d07b83ebac..8a7946cd72 100644 --- a/pretyping/pretyping.mli +++ b/pretyping/pretyping.mli @@ -75,8 +75,8 @@ val constr_out : Dyn.t -> constr *) val pretype : type_constraint -> env -> evar_defs ref -> - var_map * (identifier * identifier option) list -> - rawconstr -> unsafe_judgment + var_map * (identifier * identifier option) list -> + rawconstr -> unsafe_judgment val pretype_type : val_constraint -> env -> evar_defs ref -> diff --git a/pretyping/rawterm.ml b/pretyping/rawterm.ml index d06395b09d..1c59004175 100644 --- a/pretyping/rawterm.ml +++ b/pretyping/rawterm.ml @@ -34,8 +34,6 @@ type patvar = identifier type rawsort = RProp of Term.contents | RType of Univ.universe option -type fix_kind = RFix of (int array * int) | RCoFix of int - type binder_kind = BProd | BLambda | BLetIn type quantified_hypothesis = AnonHyp of int | NamedHyp of identifier @@ -73,6 +71,10 @@ type rawconstr = and rawdecl = name * rawconstr option * rawconstr +and fix_recursion_order = RStructRec | RWfRec of rawconstr + +and fix_kind = RFix of ((int * fix_recursion_order) array * int) | RCoFix of int + let cases_predicate_names tml = List.flatten (List.map (function | (tm,(na,None)) -> [na] diff --git a/pretyping/rawterm.mli b/pretyping/rawterm.mli index 11b43ddfcc..cbd215d85e 100644 --- a/pretyping/rawterm.mli +++ b/pretyping/rawterm.mli @@ -31,8 +31,6 @@ type patvar = identifier type rawsort = RProp of Term.contents | RType of Univ.universe option -type fix_kind = RFix of (int array * int) | RCoFix of int - type binder_kind = BProd | BLambda | BLetIn type quantified_hypothesis = AnonHyp of int | NamedHyp of identifier @@ -70,6 +68,10 @@ type rawconstr = and rawdecl = name * rawconstr option * rawconstr +and fix_recursion_order = RStructRec | RWfRec of rawconstr + +and fix_kind = RFix of ((int * fix_recursion_order) array * int) | RCoFix of int + val cases_predicate_names : (rawconstr * (name * (loc * inductive * name list) option)) list -> name list diff --git a/toplevel/command.ml b/toplevel/command.ml index 72139404b5..9f8bbad25f 100644 --- a/toplevel/command.ml +++ b/toplevel/command.ml @@ -501,7 +501,7 @@ let build_recursive (lnameargsardef:(fixpoint_expr *decl_notation) list) let recdecls = (Array.map (fun id -> Name id) namerec, arrec, recvec) in let rec declare i fi = let ce = - { const_entry_body = mkFix ((nvrec,i),recdecls); + { const_entry_body = mkFix ((Array.map fst nvrec,i),recdecls); (* ignore rec order *) const_entry_type = Some arrec.(i); const_entry_opaque = false; const_entry_boxed = boxed} in |
