aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar herbelin <herbelin@85f007b7-540e-0410-9357-904b9bb8a0f7>2003-08-11 10:25:04 +0000
committerGravatar herbelin <herbelin@85f007b7-540e-0410-9357-904b9bb8a0f7>2003-08-11 10:25:04 +0000
commitead31bf3e2fe220d02dec59dce66471cc2c66fce (patch)
treef2dc8aa43dda43200654e8e28a7556f7b84ae200
parentaad98c46631f3acb3c71ff7a7f6ae9887627baa8 (diff)
Nouvelle mouture du traducteur v7->v8
Option -v8 à coqtop lance coqtopnew Le terminateur reste "." en v8 Ajout construction primitive CLetTuple/RLetTuple Introduction typage dans le traducteur pour traduire les Case/Cases/Match Ajout mutables dans RCases or ROrderedCase pour permettre la traduction Ajout option -no-strict pour traduire les "Set Implicits" en implicites stricts + Bugs ou améliorations diverses Raffinement affichage projections de Record/Structure. git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@4257 85f007b7-540e-0410-9357-904b9bb8a0f7
-rw-r--r--contrib/correctness/pcic.ml4
-rw-r--r--contrib/correctness/psyntax.ml44
-rw-r--r--contrib/interface/pbp.ml2
-rw-r--r--contrib/interface/xlate.ml9
-rw-r--r--interp/constrextern.ml193
-rw-r--r--interp/constrextern.mli1
-rw-r--r--interp/constrintern.ml54
-rw-r--r--interp/reserve.ml10
-rw-r--r--interp/topconstr.ml101
-rw-r--r--interp/topconstr.mli11
-rw-r--r--parsing/egrammar.ml9
-rw-r--r--parsing/g_cases.ml412
-rw-r--r--parsing/g_constr.ml48
-rw-r--r--parsing/g_constrnew.ml4119
-rw-r--r--parsing/g_ltacnew.ml410
-rw-r--r--parsing/g_primnew.ml44
-rw-r--r--parsing/g_proofs.ml44
-rw-r--r--parsing/g_proofsnew.ml45
-rw-r--r--parsing/g_tacticnew.ml48
-rw-r--r--parsing/g_vernac.ml412
-rw-r--r--parsing/g_vernacnew.ml495
-rw-r--r--parsing/lexer.ml42
-rw-r--r--parsing/pcoq.ml47
-rw-r--r--parsing/pcoq.mli2
-rw-r--r--parsing/ppconstr.ml29
-rw-r--r--parsing/q_coqast.ml44
-rw-r--r--parsing/termast.ml13
-rw-r--r--pretyping/cases.ml115
-rw-r--r--pretyping/cases.mli5
-rw-r--r--pretyping/detyping.ml106
-rw-r--r--pretyping/detyping.mli2
-rw-r--r--pretyping/indrec.ml20
-rw-r--r--pretyping/inductiveops.ml25
-rw-r--r--pretyping/pattern.ml5
-rw-r--r--pretyping/pretyping.ml312
-rw-r--r--pretyping/rawterm.ml56
-rw-r--r--pretyping/rawterm.mli10
-rw-r--r--states/MakeInitialNew.v6
-rw-r--r--tactics/eauto.ml42
-rw-r--r--tactics/extraargs.ml44
-rw-r--r--tactics/tacinterp.ml12
-rw-r--r--toplevel/toplevel.ml5
-rw-r--r--toplevel/vernacentries.ml6
-rw-r--r--toplevel/vernacexpr.ml3
-rw-r--r--translate/ppconstrnew.ml409
-rw-r--r--translate/ppconstrnew.mli12
-rw-r--r--translate/pptacticnew.ml8
-rw-r--r--translate/ppvernacnew.ml242
48 files changed, 1493 insertions, 604 deletions
diff --git a/contrib/correctness/pcic.ml b/contrib/correctness/pcic.ml
index 66ac7b97e..7394a41c5 100644
--- a/contrib/correctness/pcic.ml
+++ b/contrib/correctness/pcic.ml
@@ -180,7 +180,7 @@ let rawconstr_of_prog p =
let (bl',avoid',nenv') = push_vars avoid nenv bl in
let c1 = trad avoid nenv e1
and c2 = trad avoid' nenv' e2 in
- ROrderedCase (dummy_loc, LetStyle, None, c1, [| raw_lambda bl' c2 |])
+ ROrderedCase (dummy_loc, LetStyle, None, c1, [| raw_lambda bl' c2 |], ref None)
| CC_lam (bl,e) ->
let bl',avoid',nenv' = push_vars avoid nenv bl in
@@ -214,7 +214,7 @@ let rawconstr_of_prog p =
let c = trad avoid nenv b in
let cl = List.map (trad avoid nenv) el in
let ty = Detyping.detype (Global.env()) avoid nenv ty in
- ROrderedCase (dummy_loc, RegularStyle, Some ty, c, Array.of_list cl)
+ ROrderedCase (dummy_loc, RegularStyle, Some ty, c, Array.of_list cl, ref None)
| CC_expr c ->
Detyping.detype (Global.env()) avoid nenv c
diff --git a/contrib/correctness/psyntax.ml4 b/contrib/correctness/psyntax.ml4
index 0e6b3b7d2..2e3fcac41 100644
--- a/contrib/correctness/psyntax.ml4
+++ b/contrib/correctness/psyntax.ml4
@@ -107,7 +107,7 @@ open Coqast
let mk_id loc id = mkRefC (Ident (loc, id))
let mk_ref loc s = mk_id loc (id_of_string s)
let mk_appl loc1 loc2 f args =
- CApp (join_loc loc1 loc2, (false,mk_ref loc1 f), List.map (fun a -> a,None) args)
+ CApp (join_loc loc1 loc2, (None,mk_ref loc1 f), List.map (fun a -> a,None) args)
let conj_assert {a_name=n;a_value=a} {a_value=b} =
let loc1 = constr_loc a in
@@ -166,7 +166,7 @@ let rec coqast_of_program loc = function
(function Term t -> (coqast_of_program t.loc t.desc,None)
| _ -> invalid_arg "coqast_of_program") l
in
- CApp (dummy_loc, (false,f), args)
+ CApp (dummy_loc, (None,f), args)
| Expression c -> bdize c
| _ -> invalid_arg "coqast_of_program"
diff --git a/contrib/interface/pbp.ml b/contrib/interface/pbp.ml
index 487f45057..3d01dd92f 100644
--- a/contrib/interface/pbp.ml
+++ b/contrib/interface/pbp.ml
@@ -144,7 +144,7 @@ let (imply_intro1: pbp_rule) = function
let make_var id = CRef (Ident(zz, id))
-let make_app f l = CApp (zz,(false,f),List.map (fun x -> (x,None)) l)
+let make_app f l = CApp (zz,(None,f),List.map (fun x -> (x,None)) l)
let make_pbp_pattern x =
make_app (make_var (id_of_string "PBP_META"))
diff --git a/contrib/interface/xlate.ml b/contrib/interface/xlate.ml
index c0ba10bdd..8d82da7e1 100644
--- a/contrib/interface/xlate.ml
+++ b/contrib/interface/xlate.ml
@@ -313,14 +313,17 @@ and (xlate_formula:Topconstr.constr_expr -> Ascent.ct_FORMULA) = function
xlate_formula_ne_list l)
| CApp(_, (_,f), l) -> (* TODO: proj notation *)
CT_appc(xlate_formula f, xlate_formula_expl_ne_list l)
- | CCases (_,po,tml,eqns)-> CT_cases(xlate_formula_opt po,
- xlate_formula_ne_list tml,
+ | CCases (_,(po,None),tml,eqns)-> CT_cases(xlate_formula_opt po,
+ xlate_formula_ne_list (List.map fst tml),
CT_eqn_list (List.map
(fun x -> translate_one_equation x)
eqns))
+ | CCases (_,(po,Some _),tml,eqns)-> xlate_error "TODO"
| COrderedCase (_,Term.IfStyle,po,c,[b1;b2]) ->
CT_if(xlate_formula_opt po,
xlate_formula c,xlate_formula b1,xlate_formula b2)
+ | CLetTuple (_,l, (na,po), c, b) -> xlate_error "LetTuple: TODO"
+
| COrderedCase (_,Term.LetStyle, po, c, [CLambdaN(_,[l,_],b)]) ->
CT_inductive_let(xlate_formula_opt po,
xlate_id_opt_ne_list l,
@@ -1500,7 +1503,7 @@ let xlate_vernac =
| (*Record from tactics/Record.v *)
VernacRecord
- ((add_coercion, s), binders, CSort (_,c1), rec_constructor_or_none, field_list) ->
+ (_, (add_coercion, s), binders, CSort (_,c1), rec_constructor_or_none, field_list) ->
let record_constructor = xlate_ident_opt rec_constructor_or_none in
CT_record
((if add_coercion then CT_coercion_atm else
diff --git a/interp/constrextern.ml b/interp/constrextern.ml
index 102754384..29f3c437c 100644
--- a/interp/constrextern.ml
+++ b/interp/constrextern.ml
@@ -103,8 +103,8 @@ let idopt_of_name = function
| Anonymous -> None
let extern_evar loc n =
- warning
- "Existential variable turned into meta-variable during externalization";
+ msgerrnl (str
+ "Warning: existential variable turned into meta-variable during externalization");
CPatVar (loc,(false,make_ident "META" (Some n)))
let raw_string_of_ref = function
@@ -120,6 +120,15 @@ let raw_string_of_ref = function
(* v7->v8 translation *)
+let translate_keyword = function
+ | ("forall" | "fun" | "match" | "fix" | "cofix" | "for" | "let"
+ | "if" | "then" | "else" | "return" as s) ->
+ let s' = s^"_" in
+ msgerrnl
+ (str ("Warning: "^s^" is now a keyword; it has been translated to "^s'));
+ s'
+ | s -> s
+
let is_coq_root d =
let d = repr_dirpath d in d <> [] & string_of_id (list_last d) = "Coq"
@@ -174,6 +183,7 @@ let translate_v7_string = function
| "fact_growing" -> "fact_le"
(* Lists *)
| "idempot_rev" -> "involutive_rev"
+ | "forall" -> "HereAndFurther"
(* Bool *)
| "orb_sym" -> "orb_comm"
| "andb_sym" -> "andb_comm"
@@ -192,9 +202,13 @@ let id_of_v7_string s =
id_of_string (if !Options.v7 then s else translate_v7_string s)
let v7_to_v8_dir_id dir id =
- if Options.do_translate()
- & (is_coq_root (Lib.library_dp()) or is_coq_root dir)
- then id_of_string (translate_v7_string (string_of_id id)) else id
+ if Options.do_translate() then
+ let s = string_of_id id in
+ let s =
+ if (is_coq_root (Lib.library_dp()) or is_coq_root dir)
+ then translate_v7_string s else s in
+ id_of_string (translate_keyword s)
+ else id
let v7_to_v8_id = v7_to_v8_dir_id empty_dirpath
@@ -209,6 +223,90 @@ let extern_reference loc vars r =
(* happens in debugger *)
Ident (loc,id_of_string (raw_string_of_ref r))
+(***********************************************************************)
+(* Equality up to location (useful for translator v8) *)
+
+let rec check_same_pattern p1 p2 =
+ match p1, p2 with
+ | CPatAlias(_,a1,i1), CPatAlias(_,a2,i2) when i1=i2 ->
+ check_same_pattern a1 a2
+ | CPatCstr(_,c1,a1), CPatCstr(_,c2,a2) when c1=c2 ->
+ List.iter2 check_same_pattern a1 a2
+ | CPatAtom(_,r1), CPatAtom(_,r2) when r1=r2 -> ()
+ | CPatNumeral(_,i1), CPatNumeral(_,i2) when i1=i2 -> ()
+ | CPatDelimiters(_,s1,e1), CPatDelimiters(_,s2,e2) when s1=s2 ->
+ check_same_pattern e1 e2
+ | _ -> failwith "not same pattern"
+
+let check_same_ref r1 r2 =
+ match r1,r2 with
+ | Qualid(_,q1), Qualid(_,q2) when q1=q2 -> ()
+ | Ident(_,i1), Ident(_,i2) when i1=i2 -> ()
+ | _ -> failwith "not same ref"
+
+let rec check_same_type ty1 ty2 =
+ match ty1, ty2 with
+ | CRef r1, CRef r2 -> check_same_ref r1 r2
+ | CFix(_,(_,id1),fl1), CFix(_,(_,id2),fl2) when id1=id2 ->
+ List.iter2 (fun (id1,i1,a1,b1) (id2,i2,a2,b2) ->
+ if id1<>id2 || i1<>i2 then failwith "not same fix";
+ check_same_type a1 a2;
+ check_same_type b1 b2)
+ fl1 fl2
+ | CCoFix(_,(_,id1),fl1), CCoFix(_,(_,id2),fl2) when id1=id2 ->
+ List.iter2 (fun (id1,a1,b1) (id2,a2,b2) ->
+ if id1<>id2 then failwith "not same fix";
+ check_same_type a1 a2;
+ check_same_type b1 b2)
+ fl1 fl2
+ | CArrow(_,a1,b1), CArrow(_,a2,b2) ->
+ check_same_type a1 a2;
+ check_same_type b1 b2
+ | CProdN(_,bl1,a1), CProdN(_,bl2,a2) ->
+ List.iter2 check_same_binder bl1 bl2;
+ check_same_type a1 a2
+ | CLambdaN(_,bl1,a1), CLambdaN(_,bl2,a2) ->
+ List.iter2 check_same_binder bl1 bl2;
+ check_same_type a1 a2
+ | CLetIn(_,(_,na1),a1,b1), CLetIn(_,(_,na2),a2,b2) when na1=na2 ->
+ check_same_type a1 a2;
+ check_same_type b1 b2
+ | CAppExpl(_,r1,al1), CAppExpl(_,r2,al2) when r1=r2 ->
+ List.iter2 check_same_type al1 al2
+ | CApp(_,(_,e1),al1), CApp(_,(_,e2),al2) ->
+ check_same_type e1 e2;
+ List.iter2 (fun (a1,e1) (a2,e2) ->
+ if e1<>e2 then failwith "not same expl";
+ check_same_type a1 a2) al1 al2
+ | CCases(_,_,a1,brl1), CCases(_,_,a2,brl2) ->
+ List.iter2 (fun (tm1,_) (tm2,_) -> check_same_type tm1 tm2) a1 a2;
+ List.iter2 (fun (_,pl1,r1) (_,pl2,r2) ->
+ List.iter2 check_same_pattern pl1 pl2;
+ check_same_type r1 r2) brl1 brl2
+ | COrderedCase(_,_,_,a1,bl1), COrderedCase(_,_,_,a2,bl2) ->
+ check_same_type a1 a2;
+ List.iter2 check_same_type bl1 bl2
+ | CHole _, CHole _ -> ()
+ | CPatVar(_,i1), CPatVar(_,i2) when i1=i2 -> ()
+ | CSort(_,s1), CSort(_,s2) when s1=s2 -> ()
+ | CCast(_,a1,b1), CCast(_,a2,b2) ->
+ check_same_type a1 a2;
+ check_same_type b1 b2
+ | CNotation(_,n1,e1), CNotation(_,n2,e2) when n1=n2 ->
+ List.iter2 check_same_type e1 e2
+ | CNumeral(_,i1), CNumeral(_,i2) when i1=i2 -> ()
+ | CDelimiters(_,s1,e1), CDelimiters(_,s2,e2) when s1=s2 ->
+ check_same_type e1 e2
+ | _ when ty1=ty2 -> ()
+ | _ -> failwith "not same type"
+
+and check_same_binder (nal1,e1) (nal2,e2) =
+ List.iter2 (fun (_,na1) (_,na2) ->
+ if na1<>na2 then failwith "not same name") nal1 nal2;
+ check_same_type e1 e2
+
+let same c d = try check_same_type c d; true with _ -> false
+
(**********************************************************************)
(* conversion of terms and cases patterns *)
@@ -225,14 +323,14 @@ let rec extern_cases_pattern_in_scope scopes vars pat =
insert_pat_delimiters (CPatNumeral (loc,n)) key
with No_match ->
match pat with
- | PatVar (loc,Name id) -> CPatAtom (loc,Some (Ident (loc,id)))
+ | PatVar (loc,Name id) -> CPatAtom (loc,Some (Ident (loc,v7_to_v8_id id)))
| PatVar (loc,Anonymous) -> CPatAtom (loc, None)
| PatCstr(loc,cstrsp,args,na) ->
let args = List.map (extern_cases_pattern_in_scope scopes vars) args in
let p = CPatCstr
(loc,extern_reference loc vars (ConstructRef cstrsp),args) in
(match na with
- | Name id -> CPatAlias (loc,p,id)
+ | Name id -> CPatAlias (loc,p,v7_to_v8_id id)
| Anonymous -> p)
let occur_name na aty =
@@ -241,12 +339,21 @@ let occur_name na aty =
| Anonymous -> false
let is_projection nargs = function
+ | Some r ->
+ (try
+ let n = Recordops.find_projection_nparams r + 1 in
+ if n <= nargs then Some n else None
+ with Not_found -> None)
+ | None -> None
+
+let stdlib = function
| Some r ->
- (try Recordops.find_projection_nparams r + 1 = nargs
- with Not_found -> false)
- | None ->
- false
-
+ let dir,id = repr_path (sp_of_global r) in
+ (is_coq_root (Lib.library_dp()) or is_coq_root dir)
+ && not (List.mem (string_of_id id)
+ ["Zlength";"Zlength_correct";"eq_ind"])
+ | None -> false
+
(* Implicit args indexes are in ascending order *)
(* inctx is useful only if there is a last argument to be deduced from ctxt *)
let explicitize loc inctx impl (cf,f) args =
@@ -256,16 +363,27 @@ let explicitize loc inctx impl (cf,f) args =
let tail = exprec (q+1) (args,impl) in
let visible =
(!print_implicits & !print_implicits_explicit_args)
- or not (is_inferable_implicit inctx n imp)
- or ((match a with CHole _ -> false | _ -> true)
- & Options.do_translate()) in
+ or (not (is_inferable_implicit inctx n imp))
+ or ((match a with CHole _ -> false | _ -> true)
+ & Options.do_translate() & not (stdlib cf)) in
if visible then (a,Some q) :: tail else tail
| a::args, _::impl -> (a,None) :: exprec (q+1) (args,impl)
| args, [] -> List.map (fun a -> (a,None)) args (*In case of polymorphism*)
| [], _ -> [] in
- let isproj = is_projection (List.length args) cf in
- let args = exprec 1 (args,impl) in
- if args = [] then f else CApp (loc, (isproj, f), args)
+ match is_projection (List.length args) cf with
+ | Some i as ip ->
+ if impl <> [] & is_status_implicit (List.nth impl (i-1)) then
+ let f' = match f with CRef f -> f | _ -> assert false in
+ CAppExpl (loc,(ip,f'),args)
+ else
+ let (args1,args2) = list_chop i args in
+ let (impl1,impl2) = if impl=[] then [],[] else list_chop i impl in
+ let args1 = exprec 1 (args1,impl1) in
+ let args2 = exprec (i+1) (args2,impl2) in
+ CApp (loc,(Some (List.length args1),f),args1@args2)
+ | None ->
+ let args = exprec 1 (args,impl) in
+ if args = [] then f else CApp (loc, (None, f), args)
let rec skip_coercion dest_ref (f,args as app) =
if !print_coercions or Options.do_translate () then app
@@ -362,19 +480,35 @@ let rec extern inctx scopes vars r =
let (idl,c) = factorize_lambda inctx scopes (add_vname vars na) t c in
CLambdaN (loc,[(dummy_loc,na)::idl,t],c)
- | RCases (loc,typopt,tml,eqns) ->
+ | RCases (loc,(typopt,rtntypopt),tml,eqns) ->
let pred = option_app (extern_type scopes vars) typopt in
- let tml = List.map (extern false scopes vars) tml in
+ let rtntypopt = option_app (extern_type scopes vars) !rtntypopt in
+ let vars' =
+ List.fold_right (name_fold Idset.add)
+ (cases_predicate_names tml) vars in
+ let tml = List.map (fun (tm,{contents=(na,x)}) ->
+ (extern false scopes vars tm,
+ (na,option_app (fun (loc,ind,nal) ->
+ (loc,extern_reference loc vars (IndRef ind),nal)) x))) tml in
let eqns = List.map (extern_eqn (typopt<>None) scopes vars) eqns in
- CCases (loc,pred,tml,eqns)
-
- | ROrderedCase (loc,cs,typopt,tm,bv) ->
+ CCases (loc,(pred,rtntypopt),tml,eqns)
+
+ | ROrderedCase (loc,cs,typopt,tm,bv,{contents = Some x}) ->
+ extern false scopes vars x
+
+ | ROrderedCase (loc,cs,typopt,tm,bv,_) ->
let bv = Array.to_list (Array.map (extern (typopt<>None) scopes vars) bv)
in
COrderedCase
(loc,cs,option_app (extern_type scopes vars) typopt,
extern false scopes vars tm,bv)
+ | RLetTuple (loc,nal,(na,typopt),tm,b) ->
+ CLetTuple (loc,nal,
+ (na,option_app (extern_type scopes (add_vname vars na)) typopt),
+ extern false scopes vars tm,
+ extern false scopes (List.fold_left add_vname vars nal) b)
+
| RRec (loc,fk,idv,tyv,bv) ->
let vars' = Array.fold_right Idset.add idv vars in
(match fk with
@@ -411,7 +545,7 @@ and extern_type (_,scopes) = extern true (Some Symbols.type_scope,scopes)
and factorize_prod scopes vars aty = function
| RProd (loc,(Name id as na),ty,c)
- when aty = extern true scopes vars (anonymize_if_reserved na ty)
+ when same aty (extern true scopes vars (anonymize_if_reserved na ty))
& not (occur_var_constr_expr id aty) (* avoid na in ty escapes scope *)
-> let (nal,c) = factorize_prod scopes (Idset.add id vars) aty c in
((loc,Name id)::nal,c)
@@ -419,7 +553,7 @@ and factorize_prod scopes vars aty = function
and factorize_lambda inctx scopes vars aty = function
| RLambda (loc,na,ty,c)
- when aty = extern inctx scopes vars (anonymize_if_reserved na ty)
+ when same aty (extern inctx scopes vars (anonymize_if_reserved na ty))
& not (occur_name na aty) (* To avoid na in ty' escapes scope *)
-> let (nal,c) =
factorize_lambda inctx scopes (add_vname vars na) aty c in
@@ -521,16 +655,17 @@ let rec raw_of_pat tenv env = function
RLambda (loc,na,raw_of_pat tenv env t, raw_of_pat tenv (na::env) c)
| PCase ((_,(IfStyle|LetStyle as cs)),typopt,tm,bv) ->
ROrderedCase (loc,cs,option_app (raw_of_pat tenv env) typopt,
- raw_of_pat tenv env tm,Array.map (raw_of_pat tenv env) bv)
+ raw_of_pat tenv env tm,Array.map (raw_of_pat tenv env) bv, ref None)
| PCase ((_,cs),typopt,tm,[||]) ->
- RCases (loc,option_app (raw_of_pat tenv env) typopt,
- [raw_of_pat tenv env tm],[])
+ RCases (loc,(option_app (raw_of_pat tenv env) typopt,ref None (* TODO *)),
+ [raw_of_pat tenv env tm,ref (Anonymous,None)],[])
| PCase ((Some ind,cs),typopt,tm,bv) ->
let avoid = List.fold_right (name_fold (fun x l -> x::l)) env [] in
+ let k = (snd (lookup_mind_specif (Global.env()) ind)).Declarations.mind_nrealargs in
Detyping.detype_case false
(fun tenv _ -> raw_of_pat tenv)
(fun tenv _ -> raw_of_eqn tenv)
- tenv avoid env ind cs typopt tm bv
+ tenv avoid env ind cs typopt k tm bv
| PCase _ -> error "Unsupported case-analysis while printing pattern"
| PFix f -> Detyping.detype tenv [] env (mkFix f)
| PCoFix c -> Detyping.detype tenv [] env (mkCoFix c)
diff --git a/interp/constrextern.mli b/interp/constrextern.mli
index e5cfd0190..008957e1b 100644
--- a/interp/constrextern.mli
+++ b/interp/constrextern.mli
@@ -26,6 +26,7 @@ open Symbols
val id_of_v7_string : string -> identifier
val v7_to_v8_id : identifier -> identifier (* v7->v8 translation *)
val shortest_qualid_of_v7_global : Idset.t -> global_reference -> qualid
+val check_same_type : constr_expr -> constr_expr -> unit
(* Translation of pattern, cases pattern, rawterm and term into syntax
trees for printing *)
diff --git a/interp/constrintern.ml b/interp/constrintern.ml
index 17405769a..d1c32e998 100644
--- a/interp/constrintern.ml
+++ b/interp/constrintern.ml
@@ -178,6 +178,20 @@ let intern_qualid loc qid =
with Not_found ->
error_global_not_found_loc loc qid
+let intern_inductive r =
+ let loc,qid = qualid_of_reference r in
+ try match Nametab.extended_locate qid with
+ | TrueGlobal (IndRef ind) -> ind, []
+ | TrueGlobal _ -> raise Not_found
+ | SyntacticDef sp ->
+ (match Syntax_def.search_syntactic_definition loc sp with
+ | RApp (_,RRef(_,IndRef ind),l)
+ when List.for_all (function RHole _ -> true | _ -> false) l ->
+ (ind, List.map (fun _ -> Anonymous) l)
+ | _ -> raise Not_found)
+ with Not_found ->
+ error_global_not_found_loc loc qid
+
let intern_reference env lvar = function
| Qualid (loc, qid) ->
intern_qualid loc qid
@@ -373,20 +387,26 @@ let locate_if_isevar loc na = function
with Not_found -> RHole (loc, BinderType na))
| x -> x
+let push_name_env (ids,impls,tmpsc,scopes as env) = function
+ | Anonymous -> env
+ | Name id -> (Idset.add id ids,impls,tmpsc,scopes)
+
(**********************************************************************)
(* Utilities for application *)
-let check_projection nargs = function
- | RRef (loc, ref) ->
+let check_projection isproj nargs r =
+ match (r,isproj) with
+ | RRef (loc, ref), Some nth ->
(try
let n = Recordops.find_projection_nparams ref in
- if nargs <> n+1 then
+ if nargs < nth then
user_err_loc (loc,"",str "Projection has not enough parameters");
with Not_found ->
user_err_loc
(loc,"",pr_global_env Idset.empty ref ++ str " is not a registered projection"))
- | r -> user_err_loc (loc_of_rawconstr r, "", str "Not a projection")
+ | _, Some _ -> user_err_loc (loc_of_rawconstr r, "", str "Not a projection")
+ | _, None -> ()
let set_hole_implicit i = function
| RRef (loc,r) -> (loc,ImplicitArg (r,i))
@@ -498,7 +518,7 @@ let internalise sigma env allow_soapp lvar c =
intern (ids,impls,None,find_delimiters_scope loc key::scopes) e
| CAppExpl (loc, (isproj,ref), args) ->
let (f,_,args_scopes) = intern_reference env lvar ref in
- if isproj then check_projection (List.length args) f;
+ check_projection isproj (List.length args) f;
RApp (loc, f, intern_args env args_scopes args)
| CApp (loc, (isproj,f), args) ->
let (c, impargs, args_scopes) =
@@ -507,20 +527,34 @@ let internalise sigma env allow_soapp lvar c =
| _ -> (intern env f, [], [])
in
let args = intern_impargs c env impargs args_scopes args in
- if isproj then check_projection (List.length args) c;
+ check_projection isproj (List.length args) c;
(match c with
| RApp (loc', f', args') ->
(* May happen with the ``...`` and `...` grammars *)
RApp (join_loc loc' loc, f',args'@args)
| _ -> RApp (loc, c, args))
- | CCases (loc, po, tms, eqns) ->
- RCases (loc, option_app (intern_type env) po,
- List.map (intern env) tms,
+ | CCases (loc, (po,rtnpo), tms, eqns) ->
+ let rtnids = List.fold_right (fun (_,(na,x)) ids ->
+ let ids = match x with
+ | Some (_,_,nal) -> List.fold_right (name_fold Idset.add) nal ids
+ | _ -> ids in
+ name_fold Idset.add na ids) tms ids in
+ let rtnpo =
+ option_app (intern_type (rtnids,impls,tmp_scope,scopes)) rtnpo in
+ RCases (loc, (option_app (intern_type env) po, ref rtnpo),
+ List.map (fun (tm,(na,indnalo)) ->
+ (intern env tm,ref (na,option_app (fun (loc,r,nal) ->
+ let ind,l = intern_inductive r in
+ (loc,ind,l@nal)) indnalo))) tms,
List.map (intern_eqn (List.length tms) env) eqns)
| COrderedCase (loc, tag, po, c, cl) ->
ROrderedCase (loc, tag, option_app (intern_type env) po,
intern env c,
- Array.of_list (List.map (intern env) cl))
+ Array.of_list (List.map (intern env) cl),ref None)
+ | CLetTuple (loc, nal, (na,po), b, c) ->
+ RLetTuple (loc, nal,
+ (na, option_app (intern_type (push_name_env env na)) po),
+ intern env b, intern (List.fold_left push_name_env env nal) c)
| CHole loc ->
RHole (loc, QuestionMark)
| CPatVar (loc, n) when allow_soapp ->
diff --git a/interp/reserve.ml b/interp/reserve.ml
index f6f9fe60d..5287ce5a2 100644
--- a/interp/reserve.ml
+++ b/interp/reserve.ml
@@ -43,12 +43,14 @@ let rec unloc = function
| RLambda (_,na,ty,c) -> RLambda (dummy_loc,na,unloc ty,unloc c)
| RProd (_,na,ty,c) -> RProd (dummy_loc,na,unloc ty,unloc c)
| RLetIn (_,na,b,c) -> RLetIn (dummy_loc,na,unloc b,unloc c)
- | RCases (_,tyopt,tml,pl) ->
- RCases (dummy_loc,option_app unloc tyopt,List.map unloc tml,
+ | RCases (_,(tyopt,rtntypopt),tml,pl) ->
+ RCases (dummy_loc,
+ (option_app unloc tyopt,ref (option_app unloc !rtntypopt)),
+ List.map (fun (tm,x) -> (unloc tm,x)) tml,
List.map (fun (_,idl,p,c) -> (dummy_loc,idl,p,unloc c)) pl)
- | ROrderedCase (_,b,tyopt,tm,bv) ->
+ | ROrderedCase (_,b,tyopt,tm,bv,x) ->
ROrderedCase
- (dummy_loc,b,option_app unloc tyopt,unloc tm, Array.map unloc bv)
+ (dummy_loc,b,option_app unloc tyopt,unloc tm, Array.map unloc bv,x)
| RRec (_,fk,idl,tyl,bv) ->
RRec (dummy_loc,fk,idl,Array.map unloc tyl,Array.map unloc bv)
| RCast (_,c,t) -> RCast (dummy_loc,unloc c,unloc t)
diff --git a/interp/topconstr.ml b/interp/topconstr.ml
index 5b1d2813b..d2ef146bf 100644
--- a/interp/topconstr.ml
+++ b/interp/topconstr.ml
@@ -28,9 +28,11 @@ type aconstr =
| ALambda of name * aconstr * aconstr
| AProd of name * aconstr * aconstr
| ALetIn of name * aconstr * aconstr
- | ACases of aconstr option * aconstr list *
+ | ACases of aconstr option * aconstr option *
+ (aconstr * (name * (inductive * name list) option)) list *
(identifier list * cases_pattern list * aconstr) list
| AOrderedCase of case_style * aconstr option * aconstr * aconstr array
+ | ALetTuple of name list * (name * aconstr option) * aconstr * aconstr
| ASort of rawsort
| AHole of hole_kind
| APatVar of patvar
@@ -49,13 +51,24 @@ let map_aconstr_with_binders_loc loc g f e = function
let na,e = name_app g e na in RProd (loc,na,f e ty,f e c)
| ALetIn (na,b,c) ->
let na,e = name_app g e na in RLetIn (loc,na,f e b,f e c)
- | ACases (tyopt,tml,eqnl) ->
+ | ACases (tyopt,rtntypopt,tml,eqnl) ->
+ let cases_predicate_names tml =
+ List.flatten (List.map (function
+ | (tm,(na,None)) -> [na]
+ | (tm,(na,Some (_,nal))) -> na::nal) tml) in
+ (* TODO: apply g to na (in fact not used) *)
+ let e' = List.fold_right
+ (fun na e -> snd (name_app g e na)) (cases_predicate_names tml) e in
let fold id (idl,e) = let (id,e) = g id e in (id::idl,e) in
let eqnl = List.map (fun (idl,pat,rhs) ->
let (idl,e) = List.fold_right fold idl ([],e) in (loc,idl,pat,f e rhs)) eqnl in
- RCases (loc,option_app (f e) tyopt,List.map (f e) tml,eqnl)
+ RCases (loc,(option_app (f e) tyopt, ref (option_app (f e') rtntypopt)),
+ List.map (fun (tm,(na,x)) ->
+ (f e tm,ref (na,option_app (fun (x,y) -> (loc,x,y)) x))) tml,eqnl)
| AOrderedCase (b,tyopt,tm,bv) ->
- ROrderedCase (loc,b,option_app (f e) tyopt,f e tm,Array.map (f e) bv)
+ ROrderedCase (loc,b,option_app (f e) tyopt,f e tm,Array.map (f e) bv,ref None)
+ | ALetTuple (nal,(na,po),b,c) ->
+ RLetTuple (loc,nal,(na,option_app (f e) po),f e b,f e c)
| ACast (c,t) -> RCast (loc,f e c,f e t)
| ASort x -> RSort (loc,x)
| AHole x -> RHole (loc,x)
@@ -101,9 +114,17 @@ let rec subst_aconstr subst raw =
if r1' == r1 && r2' == r2 then raw else
ALetIn (n,r1',r2')
- | ACases (ro,rl,branches) ->
+ | ACases (ro,rtntypopt,rl,branches) ->
let ro' = option_smartmap (subst_aconstr subst) ro
- and rl' = list_smartmap (subst_aconstr subst) rl
+ and rtntypopt' = option_smartmap (subst_aconstr subst) rtntypopt
+ and rl' = list_smartmap
+ (fun (a,(n,signopt) as x) ->
+ let a' = subst_aconstr subst a in
+ let signopt' = option_app (fun ((indkn,i),nal as z) ->
+ let indkn' = subst_kn subst indkn in
+ if indkn == indkn' then z else ((indkn',i),nal)) signopt in
+ if a' == a && signopt' == signopt then x else (a',(n,signopt')))
+ rl
and branches' = list_smartmap
(fun (idl,cpl,r as branch) ->
let cpl' = list_smartmap (subst_pat subst) cpl
@@ -112,8 +133,9 @@ let rec subst_aconstr subst raw =
(idl,cpl',r'))
branches
in
- if ro' == ro && rl' == rl && branches' == branches then raw else
- ACases (ro',rl',branches')
+ if ro' == ro && rtntypopt == rtntypopt' &
+ rl' == rl && branches' == branches then raw else
+ ACases (ro',rtntypopt',rl',branches')
| AOrderedCase (b,ro,r,ra) ->
let ro' = option_smartmap (subst_aconstr subst) ro
@@ -122,6 +144,13 @@ let rec subst_aconstr subst raw =
if ro' == ro && r' == r && ra' == ra then raw else
AOrderedCase (b,ro',r',ra')
+ | ALetTuple (nal,(na,po),b,c) ->
+ let po' = option_smartmap (subst_aconstr subst) po
+ and b' = subst_aconstr subst b
+ and c' = subst_aconstr subst c in
+ if po' == po && b' == b && c' == c then raw else
+ ALetTuple (nal,(na,po'),b',c')
+
| APatVar _ | ASort _ -> raw
| AHole (ImplicitArg (ref,i)) ->
@@ -151,13 +180,22 @@ let aconstr_of_rawconstr vars a =
| RLambda (_,na,ty,c) -> add_name bound_binders na; ALambda (na,aux ty,aux c)
| RProd (_,na,ty,c) -> add_name bound_binders na; AProd (na,aux ty,aux c)
| RLetIn (_,na,b,c) -> add_name bound_binders na; ALetIn (na,aux b,aux c)
- | RCases (_,tyopt,tml,eqnl) ->
+ | RCases (_,(tyopt,rtntypopt),tml,eqnl) ->
let f (_,idl,pat,rhs) =
bound_binders := idl@(!bound_binders);
(idl,pat,aux rhs) in
- ACases (option_app aux tyopt,List.map aux tml, List.map f eqnl)
- | ROrderedCase (_,b,tyopt,tm,bv) ->
+ ACases (option_app aux tyopt,
+ option_app aux !rtntypopt,
+ List.map (fun (tm,{contents = (na,x)}) ->
+ add_name bound_binders na;
+ option_iter
+ (fun (_,_,nl) -> List.iter (add_name bound_binders) nl) x;
+ (aux tm,(na,option_app (fun (_,ind,nal) -> (ind,nal)) x))) tml,
+ List.map f eqnl)
+ | ROrderedCase (_,b,tyopt,tm,bv,_) ->
AOrderedCase (b,option_app aux tyopt,aux tm, Array.map aux bv)
+ | RLetTuple (loc,nal,(na,po),b,c) ->
+ ALetTuple (nal,(na,option_app aux po),aux b,aux c)
| RCast (_,c,t) -> ACast (aux c,aux t)
| RSort (_,s) -> ASort s
| RHole (_,w) -> AHole w
@@ -279,11 +317,13 @@ let rec match_ alp metas sigma a1 a2 = match (a1,a2) with
match_binders alp metas (match_ alp metas sigma t1 t2) b1 b2 na1 na2
| RLetIn (_,na1,t1,b1), AProd (na2,t2,b2) ->
match_binders alp metas (match_ alp metas sigma t1 t2) b1 b2 na1 na2
- | RCases (_,po1,tml1,eqnl1), ACases (po2,tml2,eqnl2) ->
+ | RCases (_,(po1,rtno1),tml1,eqnl1), ACases (po2,rtno2,tml2,eqnl2) ->
let sigma = option_fold_left2 (match_ alp metas) sigma po1 po2 in
- let sigma = List.fold_left2 (match_ alp metas) sigma tml1 tml2 in
+ (* TODO: match rtno' with their contexts *)
+ let sigma = List.fold_left2
+ (fun s (tm1,_) (tm2,_) -> match_ alp metas s tm1 tm2) sigma tml1 tml2 in
List.fold_left2 (match_equations alp metas) sigma eqnl1 eqnl2
- | ROrderedCase (_,st,po1,c1,bl1), AOrderedCase (st2,po2,c2,bl2) ->
+ | ROrderedCase (_,st,po1,c1,bl1,_), AOrderedCase (st2,po2,c2,bl2) ->
let sigma = option_fold_left2 (match_ alp metas) sigma po1 po2 in
array_fold_left2 (match_ alp metas) (match_ alp metas sigma c1 c2) bl1 bl2
| RCast(_,c1,t1), ACast(c2,t2) ->
@@ -349,7 +389,7 @@ type notation = string
type explicitation = int
-type proj_flag = bool (* [true] = is projection *)
+type proj_flag = int option (* [Some n] = proj of the n-th visible argument *)
type cases_pattern_expr =
| CPatAlias of loc * cases_pattern_expr * identifier
@@ -369,10 +409,13 @@ type constr_expr =
| CAppExpl of loc * (proj_flag * reference) * constr_expr list
| CApp of loc * (proj_flag * constr_expr) *
(constr_expr * explicitation option) list
- | CCases of loc * constr_expr option * constr_expr list *
+ | CCases of loc * (constr_expr option * constr_expr option) *
+ (constr_expr * (name * (loc * reference * name list) option)) list *
(loc * cases_pattern_expr list * constr_expr) list
| COrderedCase of loc * case_style * constr_expr option * constr_expr
* constr_expr list
+ | CLetTuple of loc * name list * (name * constr_expr option) *
+ constr_expr * constr_expr
| CHole of loc
| CPatVar of loc * (bool * patvar)
| CEvar of loc * existential_key
@@ -410,6 +453,7 @@ let constr_loc = function
| CApp (loc,_,_) -> loc
| CCases (loc,_,_,_) -> loc
| COrderedCase (loc,_,_,_,_) -> loc
+ | CLetTuple (loc,_,_,_,_) -> loc
| CHole loc -> loc
| CPatVar (loc,_) -> loc
| CEvar (loc,_) -> loc
@@ -448,6 +492,7 @@ let rec occur_var_constr_expr id = function
| CHole _ | CEvar _ | CPatVar _ | CSort _ | CNumeral _ | CDynamic _ -> false
| CCases (loc,_,_,_)
| COrderedCase (loc,_,_,_,_)
+ | CLetTuple (loc,_,_,_,_)
| CFix (loc,_,_)
| CCoFix (loc,_,_) ->
Pp.warning "Capture check in multiple binders not done"; false
@@ -461,7 +506,7 @@ and occur_var_binders id b = function
let mkIdentC id = CRef (Ident (dummy_loc, id))
let mkRefC r = CRef r
-let mkAppC (f,l) = CApp (dummy_loc, (false,f), List.map (fun x -> (x,None)) l)
+let mkAppC (f,l) = CApp (dummy_loc, (None,f), List.map (fun x -> (x,None)) l)
let mkCastC (a,b) = CCast (dummy_loc,a,b)
let mkLambdaC (idl,a,b) = CLambdaN (dummy_loc,[idl,a],b)
let mkLetInC (id,a,b) = CLetIn (dummy_loc,id,a,b)
@@ -469,10 +514,11 @@ let mkProdC (idl,a,b) = CProdN (dummy_loc,[idl,a],b)
(* Used in correctness and interface *)
+let map_binder g e nal = List.fold_right (fun (_,na) -> name_fold g na) nal e
+
let map_binders f g e bl =
(* TODO: avoid variable capture in [t] by some [na] in [List.tl nal] *)
- let h (nal,t) (e,bl) =
- (List.fold_right (fun (_,na) -> name_fold g na) nal e,(nal,f e t)::bl) in
+ let h (nal,t) (e,bl) = (map_binder g e nal,(nal,f e t)::bl) in
List.fold_right h bl (e,[])
let map_constr_expr_with_binders f g e = function
@@ -490,12 +536,25 @@ let map_constr_expr_with_binders f g e = function
| CDelimiters (loc,s,a) -> CDelimiters (loc,s,f e a)
| CHole _ | CEvar _ | CPatVar _ | CSort _
| CNumeral _ | CDynamic _ | CRef _ as x -> x
- | CCases (loc,po,a,bl) ->
+ | CCases (loc,(po,rtnpo),a,bl) ->
(* TODO: apply g on the binding variables in pat... *)
let bl = List.map (fun (loc,pat,rhs) -> (loc,pat,f e rhs)) bl in
- CCases (loc,option_app (f e) po,List.map (f e) a,bl)
+ let e' =
+ List.fold_right
+ (fun (tm,(na,indnal)) e ->
+ option_fold_right
+ (fun (loc,ind,nal) ->
+ List.fold_right (name_fold g) nal) indnal (name_fold g na e))
+ a e
+ in
+ CCases (loc,(option_app (f e) po, option_app (f e') rtnpo),
+ List.map (fun (tm,x) -> (f e tm,x)) a,bl)
| COrderedCase (loc,s,po,a,bl) ->
COrderedCase (loc,s,option_app (f e) po,f e a,List.map (f e) bl)
+ | CLetTuple (loc,nal,(na,po),b,c) ->
+ let e' = List.fold_right (name_fold g) nal e in
+ let e'' = name_fold g na e in
+ CLetTuple (loc,nal,(na,option_app (f e'') po),f e b,f e' c)
| CFix (loc,id,dl) ->
CFix (loc,id,List.map (fun (id,n,t,d) -> (id,n,f e t,f e d)) dl)
| CCoFix (loc,id,dl) ->
diff --git a/interp/topconstr.mli b/interp/topconstr.mli
index f5f620528..55cd20290 100644
--- a/interp/topconstr.mli
+++ b/interp/topconstr.mli
@@ -29,9 +29,11 @@ type aconstr =
| ALambda of name * aconstr * aconstr
| AProd of name * aconstr * aconstr
| ALetIn of name * aconstr * aconstr
- | ACases of aconstr option * aconstr list *
+ | ACases of aconstr option * aconstr option *
+ (aconstr * (name * (inductive * name list) option)) list *
(identifier list * cases_pattern list * aconstr) list
| AOrderedCase of case_style * aconstr option * aconstr * aconstr array
+ | ALetTuple of name list * (name * aconstr option) * aconstr * aconstr
| ASort of rawsort
| AHole of hole_kind
| APatVar of patvar
@@ -62,7 +64,7 @@ type notation = string
type explicitation = int
-type proj_flag = bool (* [true] = is projection *)
+type proj_flag = int option (* [Some n] = proj of the n-th visible argument *)
type cases_pattern_expr =
| CPatAlias of loc * cases_pattern_expr * identifier
@@ -82,10 +84,13 @@ type constr_expr =
| CAppExpl of loc * (proj_flag * reference) * constr_expr list
| CApp of loc * (proj_flag * constr_expr) *
(constr_expr * explicitation option) list
- | CCases of loc * constr_expr option * constr_expr list *
+ | CCases of loc * (constr_expr option * constr_expr option) *
+ (constr_expr * (name * (loc * reference * name list) option)) list *
(loc * cases_pattern_expr list * constr_expr) list
| COrderedCase of loc * case_style * constr_expr option * constr_expr
* constr_expr list
+ | CLetTuple of loc * name list * (name * constr_expr option) *
+ constr_expr * constr_expr
| CHole of loc
| CPatVar of loc * (bool * patvar)
| CEvar of loc * existential_key
diff --git a/parsing/egrammar.ml b/parsing/egrammar.ml
index 397189271..60848fdfd 100644
--- a/parsing/egrammar.ml
+++ b/parsing/egrammar.ml
@@ -284,12 +284,17 @@ let subst_constr_expr a loc subs =
| CDelimiters (_,s,a) -> CDelimiters (loc,s,subst a)
| CHole _ | CEvar _ | CPatVar _ | CSort _
| CNumeral _ | CDynamic _ | CRef _ as x -> x
- | CCases (_,po,a,bl) ->
+ | CCases (_,(po,rtntypo),a,bl) ->
(* TODO: apply g on the binding variables in pat... *)
let bl = List.map (fun (_,pat,rhs) -> (loc,pat,subst rhs)) bl in
- CCases (loc,option_app subst po,List.map subst a,bl)
+ CCases (loc,(option_app subst po,option_app subst rtntypo),
+ List.map (fun (tm,x) -> subst tm,x) a,bl)
| COrderedCase (_,s,po,a,bl) ->
COrderedCase (loc,s,option_app subst po,subst a,List.map subst bl)
+ | CLetTuple (_,nal,(na,po),a,b) ->
+ let na = name_app (subst_id subs) na in
+ let nal = List.map (name_app (subst_id subs)) nal in
+ CLetTuple (loc,nal,(na,option_app subst po),subst a,subst b)
| CFix (_,id,dl) ->
CFix (loc,id,List.map (fun (id,n,t,d) -> (id,n,subst t,subst d)) dl)
| CCoFix (_,id,dl) ->
diff --git a/parsing/g_cases.ml4 b/parsing/g_cases.ml4
index 679d174c2..4d4000b23 100644
--- a/parsing/g_cases.ml4
+++ b/parsing/g_cases.ml4
@@ -55,13 +55,17 @@ GEXTEND Gram
operconstr: LEVEL "1"
[ [ "<"; p = annot; ">"; "Cases"; lc = LIST1 constr; "of";
OPT "|"; eqs = ne_eqn_list; "end" ->
- CCases (loc, Some p, lc, eqs)
+ let lc = List.map (fun c -> c,(Names.Anonymous,None)) lc in
+ CCases (loc, (Some p,None), lc, eqs)
| "Cases"; lc = LIST1 constr; "of";
OPT "|"; eqs = ne_eqn_list; "end" ->
- CCases (loc, None, lc, eqs)
+ let lc = List.map (fun c -> c,(Names.Anonymous,None)) lc in
+ CCases (loc, (None,None), lc, eqs)
| "<"; p = annot; ">"; "Cases"; lc = LIST1 constr; "of"; "end" ->
- CCases (loc, Some p, lc, [])
+ let lc = List.map (fun c -> c,(Names.Anonymous,None)) lc in
+ CCases (loc, (Some p,None), lc, [])
| "Cases"; lc = LIST1 constr; "of"; "end" ->
- CCases (loc, None, lc, []) ] ]
+ let lc = List.map (fun c -> c,(Names.Anonymous,None)) lc in
+ CCases (loc, (None,None), lc, []) ] ]
;
END;
diff --git a/parsing/g_constr.ml4 b/parsing/g_constr.ml4
index 43dc060a5..5904906b0 100644
--- a/parsing/g_constr.ml4
+++ b/parsing/g_constr.ml4
@@ -127,12 +127,12 @@ GEXTEND Gram
operconstr:
[ "10" RIGHTA
[ "!"; f = global; args = LIST0 (operconstr LEVEL "9") ->
- CAppExpl (loc, (false,f), args)
+ CAppExpl (loc, (None,f), args)
(*
| "!"; f = global; "with"; b = binding_list ->
<:ast< (APPLISTWITH $f $b) >>
*)
- | f = operconstr; args = LIST1 constr91 -> CApp (loc, (false,f), args) ]
+ | f = operconstr; args = LIST1 constr91 -> CApp (loc, (None,f), args) ]
| "9" RIGHTA
[ c1 = operconstr; "::"; c2 = operconstr LEVEL "9" -> CCast (loc, c1, c2) ]
| "8" RIGHTA
@@ -196,7 +196,7 @@ GEXTEND Gram
| "("; lc1 = lconstr; ")"; "@"; "["; cl = ne_constr_list; "]" ->
(match lc1 with
| CPatVar (loc2,(false,n)) ->
- CApp (loc,(false,CPatVar (loc2, (true,n))), List.map (fun c -> c, None) cl)
+ CApp (loc,(None,CPatVar (loc2, (true,n))), List.map (fun c -> c, None) cl)
| _ ->
Util.error "Second-order pattern-matching expects a head metavariable")
| IDENT "Fix"; id = identref; "{"; fbinders = fixbinders; "}" ->
@@ -208,7 +208,7 @@ GEXTEND Gram
| s = sort -> CSort (loc, s)
| v = global -> CRef v
| n = bigint -> CNumeral (loc,n)
- | "!"; f = global -> CAppExpl (loc,(false,f),[])
+ | "!"; f = global -> CAppExpl (loc,(None,f),[])
| "'"; test_ident_colon; key = IDENT; ":"; c = constr; "'" ->
CDelimiters (loc,key,c) ] ]
;
diff --git a/parsing/g_constrnew.ml4 b/parsing/g_constrnew.ml4
index 16691158f..f8bb62a22 100644
--- a/parsing/g_constrnew.ml4
+++ b/parsing/g_constrnew.ml4
@@ -20,8 +20,9 @@ open Topconstr
open Util
let constr_kw =
- [ "fun"; "match"; "fix"; "cofix"; "with"; "in"; "for"; "end"; "as";
- "let"; "if"; "then"; "else"; "struct"; "Prop"; "Set"; "Type"; ".(" ]
+ [ "forall"; "fun"; "match"; "fix"; "cofix"; "with"; "in"; "for";
+ "end"; "as"; "let"; "if"; "then"; "else"; "return";
+ "Prop"; "Set"; "Type"; ".(" ]
let _ = List.iter (fun s -> Lexer.add_token("",s)) constr_kw
let _ = Options.v7 := false
@@ -56,6 +57,7 @@ let match_bind_of_pat loc (oid,ty) =
l1@l2
let mk_match (loc,cil,rty,br) =
+(*
let (lc,pargs) = List.split cil in
let pr =
match rty with
@@ -64,7 +66,8 @@ let mk_match (loc,cil,rty,br) =
let idargs = (* TODO: not forget the list lengths for PP! *)
List.flatten (List.map (match_bind_of_pat loc) pargs) in
Some (CLambdaN(loc,idargs,ty)) in
- CCases(loc,pr,lc,br)
+*)
+ CCases(loc,(None,rty),cil,br)
let mk_fixb (loc,id,bl,ann,body,(tloc,tyc)) =
let n =
@@ -101,9 +104,28 @@ let mk_fix(loc,kw,id,dcls) =
let binder_constr =
create_constr_entry (get_univ "constr") "binder_constr"
+
+let rec mkCProdN loc bll c =
+ match bll with
+ | LocalRawAssum ((loc1,_)::_ as idl,t) :: bll ->
+ CProdN (loc,[idl,t],mkCProdN (join_loc loc1 loc) bll c)
+ | LocalRawDef ((loc1,_) as id,b) :: bll ->
+ CLetIn (loc,id,b,mkCProdN (join_loc loc1 loc) bll c)
+ | [] -> c
+ | LocalRawAssum ([],_) :: bll -> mkCProdN loc bll c
+
+let rec mkCLambdaN loc bll c =
+ match bll with
+ | LocalRawAssum ((loc1,_)::_ as idl,t) :: bll ->
+ CLambdaN (loc,[idl,t],mkCLambdaN (join_loc loc1 loc) bll c)
+ | LocalRawDef ((loc1,_) as id,b) :: bll ->
+ CLetIn (loc,id,b,mkCLambdaN (join_loc loc1 loc) bll c)
+ | [] -> c
+ | LocalRawAssum ([],_) :: bll -> mkCLambdaN loc bll c
+
GEXTEND Gram
GLOBAL: binder_constr lconstr constr operconstr sort global
- constr_pattern Constr.ident;
+ constr_pattern Constr.ident binder_let tuple_constr;
Constr.ident:
[ [ id = Prim.ident -> id
@@ -130,6 +152,12 @@ GEXTEND Gram
constr:
[ [ c = operconstr LEVEL "9" -> c ] ]
;
+ tuple_constr:
+ [
+ [ (*c1 = tuple_constr; ","; c2 = tuple_constr ->
+ CNotation (loc,"_ , _",[c1;c2])
+ | *) c = operconstr -> c ] ]
+ ;
operconstr:
[ "200" RIGHTA
[ c = binder_constr -> c ]
@@ -142,33 +170,39 @@ GEXTEND Gram
| "40L" LEFTA
[ "-"; c = operconstr -> CNotation(loc,"- _",[c]) ]
| "10L" LEFTA
- [ f=operconstr; args=LIST1 appl_arg -> CApp(loc,(false,f),args)
- | "@"; f=global; args=LIST0 NEXT -> CAppExpl(loc,(false,f),args) ]
+ [ f=operconstr; args=LIST1 appl_arg -> CApp(loc,(None,f),args)
+ | "@"; f=global; args=LIST0 NEXT -> CAppExpl(loc,(None,f),args)
+ | c=operconstr; ".("; f=global; args1=LIST0 appl_arg; ")";
+ args2=LIST0 appl_arg ->
+ CApp(loc,(Some (List.length args1+1),CRef f),args1@(c,None)::args2)
+ | c=operconstr; ".("; "@"; f=global; args1=LIST0 NEXT; ")";
+ args2=LIST0 NEXT ->
+ CAppExpl(loc,(Some (List.length args1+1),f),args1@c::args2) ]
| "9" [ ]
| "1L" LEFTA
- [ c=operconstr; "%"; key=IDENT -> CDelimiters (loc,key,c)
- | c=operconstr; ".("; f=global; args=LIST0 appl_arg; ")" ->
- CApp(loc,(true,CRef f),args@[c,None])
- | c=operconstr; ".("; "@"; f=global; args=LIST0 NEXT ->
- CAppExpl(loc,(false,f),args@[c]) ]
+ [ c=operconstr; "%"; key=IDENT -> CDelimiters (loc,key,c) ]
| "0"
[ c=atomic_constr -> c
| c=match_constr -> c
- | "("; c=operconstr; ")" -> c ] ]
+ | "("; c=tuple_constr; ")" -> c ] ]
;
binder_constr:
- [ [ "!"; bl = binder_list; "."; c = operconstr LEVEL "200" ->
- CProdN(loc,bl,c)
- | "fun"; bl = LIST1 binder; ty = type_cstr; "=>";
+ [ [ "forall"; bl = binder_list; ","; c = operconstr LEVEL "200" ->
+ mkCProdN loc bl c
+ | "fun"; bl = binder_list; ty = type_cstr; "=>";
c = operconstr LEVEL "200" ->
- CLambdaN(loc,bl,mk_cast(c,ty))
- | "let"; id=name; bl = LIST0 binder; ty = type_cstr; ":=";
- c1 = operconstr; "in"; c2 = operconstr LEVEL "200" ->
- CLetIn(loc,id,mk_lam(bl,mk_cast(c1,ty)),c2)
- | "let"; "("; lb = LIST1 name SEP ","; ")"; ":=";
+ mkCLambdaN loc bl (mk_cast(c,ty))
+ | "let"; id=name; bl = LIST0 binder_let; ty = type_cstr; ":=";
c1 = operconstr; "in"; c2 = operconstr LEVEL "200" ->
- COrderedCase (loc, LetStyle, None, c1,
- [CLambdaN (loc, [lb, CHole loc], c2)])
+ let loc1 = match bl with
+ | LocalRawAssum ((loc,_)::_,_)::_ -> loc
+ | LocalRawDef ((loc,_),_)::_ -> loc
+ | _ -> dummy_loc in
+ CLetIn(loc,id,mkCLambdaN loc1 bl (mk_cast(c1,ty)),c2)
+ | "let"; lb = ["("; l=LIST0 name SEP ","; ")" -> l | "()" -> []];
+ po = return_type;
+ ":="; c1 = operconstr; "in"; c2 = operconstr LEVEL "200" ->
+ CLetTuple (loc,List.map snd lb,po,c1,c2)
| "if"; c1=operconstr; "then"; c2=operconstr LEVEL "200";
"else"; c3=operconstr LEVEL "200" ->
COrderedCase (loc, IfStyle, None, c1, [c2; c3])
@@ -205,7 +239,7 @@ GEXTEND Gram
c=operconstr LEVEL "200" -> (loc,id,bl,ann,c,ty) ] ]
;
fixannot:
- [ [ "{"; "struct"; id=name; "}" -> Some id
+ [ [ "{"; IDENT "struct"; id=name; "}" -> Some id
| -> None ] ]
;
match_constr:
@@ -213,14 +247,23 @@ GEXTEND Gram
br=branches; "end" -> mk_match (loc,ci,ty,br) ] ]
;
case_item:
- [ [ c=operconstr LEVEL "80"; p=pred_pattern -> (c,p) ] ]
+ [ [ c=operconstr LEVEL "100"; p=pred_pattern ->
+ match c,p with
+ | CRef (Ident (_,id)), (Names.Anonymous,x) -> (c,(Name id,x))
+ | _ -> (c,p) ] ]
;
pred_pattern:
- [ [ oid = OPT ["as"; id=name -> id];
- (_,ty) = type_cstr -> (oid,ty) ] ]
+ [ [ oid = ["as"; id=name -> snd id | -> Names.Anonymous];
+ ty = OPT ["in"; r=global; nal=LIST0 name ->
+ (loc,r,List.map snd nal)] ->
+ (oid,ty) ] ]
;
case_type:
- [ [ ty = OPT [ "=>"; c = lconstr -> c ] -> ty ] ]
+ [ [ ty = OPT [ "return"; c = operconstr LEVEL "100" -> c ] -> ty ] ]
+ ;
+ return_type:
+ [ [ na = ["as"; id=name -> snd id | -> Names.Anonymous];
+ ty = case_type -> (na,ty) ] ]
;
branches:
[ [ OPT"|"; br=LIST0 eqn SEP "|" -> br ] ]
@@ -252,9 +295,25 @@ GEXTEND Gram
| p1=pattern; ","; p2=lpattern -> CPatCstr (loc, pair loc, [p1;p2]) ] ]
;
binder_list:
- [ [ idl=LIST1 name; bl=LIST0 binder -> (idl,CHole loc)::bl
- | "("; idl=LIST1 name; ":"; c=lconstr; ")"; bl=LIST0 binder ->(idl,c)::bl
- | idl=LIST1 name; ":"; c=constr -> [(idl,c)] ] ]
+ [ [ idl=LIST1 name; bl=LIST0 binder_let ->
+ LocalRawAssum (idl,CHole loc)::bl
+ | idl=LIST1 name; ":"; c=lconstr ->
+ [LocalRawAssum (idl,c)]
+ | "("; idl=LIST1 name; ":"; c=lconstr; ")"; bl=LIST0 binder_let ->
+ LocalRawAssum (idl,c)::bl ] ]
+ ;
+ binder_let:
+ [ [ id=name ->
+ LocalRawAssum ([id],CHole loc)
+ | "("; id=name; idl=LIST1 name; ":"; c=lconstr; ")" ->
+ LocalRawAssum (id::idl,c)
+ | "("; id=name; ":"; c=lconstr; ")" ->
+ LocalRawAssum ([id],c)
+ | "("; id=name; ":="; c=lconstr; ")" ->
+ LocalRawDef (id,c)
+ | "("; id=name; ":"; t=lconstr; ":="; c=lconstr; ")" ->
+ LocalRawDef (id,CCast (join_loc (constr_loc t) loc,c,t))
+ ] ]
;
binder:
[ [ id=name -> ([id],CHole loc)
diff --git a/parsing/g_ltacnew.ml4 b/parsing/g_ltacnew.ml4
index 986e6b058..ad78104cf 100644
--- a/parsing/g_ltacnew.ml4
+++ b/parsing/g_ltacnew.ml4
@@ -73,8 +73,8 @@ GEXTEND Gram
tactic_expr:
[ "5" LEFTA
- [ ta0 = tactic_expr; "&"; ta1 = tactic_expr -> TacThen (ta0, ta1)
- | ta = tactic_expr; "&"; "["; lta = LIST0 tactic_expr SEP "|"; "]" ->
+ [ ta0 = tactic_expr; ";"; ta1 = tactic_expr -> TacThen (ta0, ta1)
+ | ta = tactic_expr; ";"; "["; lta = LIST0 tactic_expr SEP "|"; "]" ->
TacThens (ta, lta) ]
| "4"
[ ]
@@ -186,10 +186,12 @@ GEXTEND Gram
;
(* Definitions for tactics *)
+(*
deftok:
[ [ IDENT "Meta"
| IDENT "Tactic" ] ]
;
+*)
tacdef_body:
[ [ name = identref; it=LIST1 input_fun; ":="; body = tactic_expr ->
(name, TacFun (it, body))
@@ -200,9 +202,7 @@ GEXTEND Gram
[ [ tac = tactic_expr -> tac ] ]
;
Vernac_.command:
- [ [ deftok; "Definition"; b = tacdef_body ->
- VernacDeclareTacticDefinition (false, [b])
- | IDENT "Recursive"; deftok; "Definition";
+ [ [ IDENT "Ltac";
l = LIST1 tacdef_body SEP "with" ->
VernacDeclareTacticDefinition (true, l) ] ]
;
diff --git a/parsing/g_primnew.ml4 b/parsing/g_primnew.ml4
index de18ab764..4ca29e232 100644
--- a/parsing/g_primnew.ml4
+++ b/parsing/g_primnew.ml4
@@ -22,7 +22,7 @@ let _ =
f Prim.ast;
f Prim.reference
-let prim_kw = ["{"; "}"; "["; "]"; "("; ")"; "<>"; "<<"; ">>"; "'";"."]
+let prim_kw = ["{"; "}"; "["; "]"; "("; ")"; "<>"; "<<"; ">>"; "'"]
let _ = List.iter (fun s -> Lexer.add_token("",s)) prim_kw
ifdef Quotify then
@@ -83,7 +83,7 @@ GEXTEND Gram
[ [ s = METAIDENT -> Nmeta (loc,s) ] ]
;
field:
- [ [ "."; s = IDENT -> local_id_of_string s ] ]
+ [ [ s = FIELD -> local_id_of_string s ] ]
;
fields:
[ [ id = field; (l,id') = fields -> (local_append l id,id')
diff --git a/parsing/g_proofs.ml4 b/parsing/g_proofs.ml4
index 5b2e165ac..0c9e0ce26 100644
--- a/parsing/g_proofs.ml4
+++ b/parsing/g_proofs.ml4
@@ -124,11 +124,11 @@ GEXTEND Gram
[ [ IDENT "Resolve"; l = LIST1 global; dbnames = opt_hintbases ->
(dbnames,
HintsResolve
- (List.map (fun qid -> (None, CAppExpl(loc,(false,qid),[]))) l))
+ (List.map (fun qid -> (None, CAppExpl(loc,(None,qid),[]))) l))
| IDENT "Immediate"; l = LIST1 global; dbnames = opt_hintbases ->
(dbnames,
HintsImmediate
- (List.map (fun qid-> (None, CAppExpl (loc,(false,qid),[]))) l))
+ (List.map (fun qid-> (None, CAppExpl (loc,(None,qid),[]))) l))
| IDENT "Unfold"; l = LIST1 global; dbnames = opt_hintbases ->
(dbnames, HintsUnfold (List.map (fun qid -> (None,qid)) l)) ] ]
;
diff --git a/parsing/g_proofsnew.ml4 b/parsing/g_proofsnew.ml4
index 82896099f..e0e374426 100644
--- a/parsing/g_proofsnew.ml4
+++ b/parsing/g_proofsnew.ml4
@@ -61,9 +61,8 @@ GEXTEND Gram
| IDENT "Unfocus" -> VernacUnfocus
| IDENT "Show" -> VernacShow (ShowGoal None)
| IDENT "Show"; n = natural -> VernacShow (ShowGoal (Some n))
- | IDENT "Show"; IDENT "Implicits"; n = natural ->
- VernacShow (ShowGoalImplicitly (Some n))
- | IDENT "Show"; IDENT "Implicits" -> VernacShow (ShowGoalImplicitly None)
+ | IDENT "Show"; IDENT "Implicit"; IDENT "Arguments"; n = OPT natural ->
+ VernacShow (ShowGoalImplicitly n)
| IDENT "Show"; IDENT "Node" -> VernacShow ShowNode
| IDENT "Show"; IDENT "Script" -> VernacShow ShowScript
| IDENT "Show"; IDENT "Existentials" -> VernacShow ShowExistentials
diff --git a/parsing/g_tacticnew.ml4 b/parsing/g_tacticnew.ml4
index bd71bbd5c..017cfd18f 100644
--- a/parsing/g_tacticnew.ml4
+++ b/parsing/g_tacticnew.ml4
@@ -135,7 +135,7 @@ GEXTEND Gram
(Some (nl,c1), c2) ] ]
;
pattern_occ:
- [ [ nl = LIST0 integer; c = [c=constr->c | g=global->Topconstr.CRef g]-> (nl,c) ] ]
+ [ [ c = constr; nl = LIST0 integer -> (nl,c) ] ]
;
pattern_occ_hyp_tail_list:
[ [ pl = pattern_occ_hyp_list -> pl | -> (None,[]) ] ]
@@ -176,7 +176,7 @@ GEXTEND Gram
[ [ "with"; bl = binding_list -> bl | -> NoBindings ] ]
;
unfold_occ:
- [ [ nl = LIST0 integer; c = global -> (nl,c) ] ]
+ [ [ c = global; nl = LIST0 integer -> (nl,c) ] ]
;
red_flag:
[ [ IDENT "beta" -> FBeta
@@ -194,9 +194,9 @@ GEXTEND Gram
| IDENT "cbv"; s = LIST1 red_flag -> Cbv (make_red_flag s)
| IDENT "lazy"; s = LIST1 red_flag -> Lazy (make_red_flag s)
| IDENT "compute" -> Cbv (make_red_flag [FBeta;FIota;FDeltaBut [];FZeta])
- | IDENT "unfold"; ul = LIST1 unfold_occ -> Unfold ul
+ | IDENT "unfold"; ul = LIST1 unfold_occ SEP "," -> Unfold ul
| IDENT "fold"; cl = LIST1 constr -> Fold cl
- | IDENT "pattern"; pl = LIST1 pattern_occ -> Pattern pl ] ]
+ | IDENT "pattern"; pl = LIST1 pattern_occ SEP "," -> Pattern pl ] ]
;
(* This is [red_tactic] including possible extensions *)
red_expr:
diff --git a/parsing/g_vernac.ml4 b/parsing/g_vernac.ml4
index 0d431ea93..d038e7d8c 100644
--- a/parsing/g_vernac.ml4
+++ b/parsing/g_vernac.ml4
@@ -183,8 +183,8 @@ GEXTEND Gram
;
gallina:
(* Definition, Theorem, Variable, Axiom, ... *)
- [ [ thm = thm_token; id = base_ident; bl = binders_list; ":"; c = constr ->
- VernacStartTheoremProof (thm, id, (bl, c), false, (fun _ _ -> ()))
+ [ [ thm = thm_token; id = base_ident; ":"; c = constr ->
+ VernacStartTheoremProof (thm, id, ([], c), false, (fun _ _ -> ()))
| (f,d,e) = def_token; id = base_ident; b = def_body ->
VernacDefinition (d, id, b, f, e)
| stre = assumption_token; bl = ne_params_list ->
@@ -200,7 +200,7 @@ GEXTEND Gram
| "CoInductive" -> false ] ]
;
record_token:
- [ [ IDENT "Record" -> () | IDENT "Structure" -> () ] ]
+ [ [ IDENT "Record" -> true | IDENT "Structure" -> false ] ]
;
constructor:
[ [ idl = LIST1 base_ident SEP ","; coe = of_type_with_opt_coercion;
@@ -305,10 +305,10 @@ GEXTEND Gram
indl = block_old_style ->
let indl' = List.map (fun (id,ar,c) -> (id,None,bl,ar,c)) indl in
VernacInductive (f,indl')
- | record_token; oc = opt_coercion; name = base_ident;
+ | b = record_token; oc = opt_coercion; name = base_ident;
ps = simple_binders_list; ":";
s = constr; ":="; c = rec_constructor; "{"; fs = fields; "}" ->
- VernacRecord ((oc,name),ps,s,c,fs)
+ VernacRecord (b,(oc,name),ps,s,c,fs)
] ]
;
gallina:
@@ -422,7 +422,7 @@ GEXTEND Gram
let c = match n with
| Some n ->
let l = list_tabulate (fun _ -> (CHole (loc),None)) n in
- CApp (loc,(false,c),l)
+ CApp (loc,(None,c),l)
| None -> c in
VernacNotation (false,c,Some("'"^id^"'",[]),None,None)
| IDENT "Implicits"; qid = global; "["; l = LIST0 natural; "]" ->
diff --git a/parsing/g_vernacnew.ml4 b/parsing/g_vernacnew.ml4
index 809ba58cf..a9866b7e8 100644
--- a/parsing/g_vernacnew.ml4
+++ b/parsing/g_vernacnew.ml4
@@ -42,13 +42,13 @@ let def_body = Gram.Entry.create "vernac:def_body"
GEXTEND Gram
GLOBAL: vernac gallina_ext;
vernac:
- (* Better to parse ";" here: in case of failure (e.g. in coerce_to_var), *)
- (* ";" is still in the stream and discard_to_dot works correctly *)
- [ [ g = gallina; ";" -> g
- | g = gallina_ext; ";" -> g
- | c = command; ";" -> c
- | c = syntax; ";" -> c
- | "["; l = LIST1 located_vernac; "]"; ";" -> VernacList l
+ (* Better to parse "." here: in case of failure (e.g. in coerce_to_var), *)
+ (* "." is still in the stream and discard_to_dot works correctly *)
+ [ [ g = gallina; "." -> g
+ | g = gallina_ext; "." -> g
+ | c = command; "." -> c
+ | c = syntax; "." -> c
+ | "["; l = LIST1 located_vernac; "]"; "." -> VernacList l
] ]
;
vernac: FIRST
@@ -56,7 +56,7 @@ GEXTEND Gram
;
vernac: LAST
[ [ gln = OPT[n=natural; ":" -> n];
- tac = subgoal_command; ";" -> tac gln ] ]
+ tac = subgoal_command; "." -> tac gln ] ]
;
subgoal_command:
[ [ c = check_command -> c
@@ -86,22 +86,27 @@ let no_coercion loc (c,x) =
(loc,"no_coercion",Pp.str"no coercion allowed here");
x
+let flatten_assum l =
+ List.flatten
+ (List.map (fun (oc,(idl,t)) -> List.map (fun id -> (oc,(id,t))) idl) l)
+
(* Gallina declarations *)
GEXTEND Gram
GLOBAL: gallina gallina_ext thm_token def_body;
gallina:
(* Definition, Theorem, Variable, Axiom, ... *)
- [ [ thm = thm_token; id = base_ident; bl = LIST0 binder; ":";
+ [ [ thm = thm_token; id = base_ident; (* bl = LIST0 binder; *) ":";
c = lconstr ->
+ let bl = [] in
VernacStartTheoremProof (thm, id, (bl, c), false, (fun _ _ -> ()))
| (f,d,e) = def_token; id = base_ident; b = def_body ->
VernacDefinition (d, id, b, f, e)
- | stre = assumption_token; bl = LIST1 simple_binder_coe ->
- VernacAssumption (stre, bl)
- | stre = assumptions_token; bl = LIST1 simple_binder_coe ->
+ | stre = assumption_token; bl = LIST1 assum_coe ->
+ VernacAssumption (stre, flatten_assum bl)
+ | stre = assumptions_token; bl = LIST1 assum_coe ->
test_plurial_form bl;
- VernacAssumption (stre, bl)
+ VernacAssumption (stre, flatten_assum bl)
(* Gallina inductive declarations *)
| (* Non porté (?) : OPT[IDENT "Mutual"];*) f = finite_token;
indl = LIST1 inductive_definition SEP "with" ->
@@ -113,11 +118,11 @@ GEXTEND Gram
| IDENT "Scheme"; l = LIST1 scheme SEP "with" -> VernacScheme l ] ]
;
gallina_ext:
- [ [ record_token; oc = opt_coercion; name = base_ident;
+ [ [ b = record_token; oc = opt_coercion; name = base_ident;
ps = LIST0 simple_binder; ":";
s = lconstr; ":="; cstr = OPT base_ident; "{";
- fs = LIST0 local_decl_expr; "}" ->
- VernacRecord ((oc,name),ps,s,cstr,fs)
+ fs = LIST0 record_field SEP ";"; "}" ->
+ VernacRecord (b,(oc,name),ps,s,cstr,fs)
(* Non porté ?
| f = finite_token; s = csort; id = base_ident;
indpar = LIST0 simple_binder; ":="; lc = constructor_list ->
@@ -154,17 +159,17 @@ GEXTEND Gram
| "CoInductive" -> false ] ]
;
record_token:
- [ [ IDENT "Record" -> () | IDENT "Structure" -> () ] ]
+ [ [ IDENT "Record" -> true | IDENT "Structure" -> false ] ]
;
(* Simple definitions *)
def_body:
- [ [ bl = LIST0 binder; ":="; red = reduce; c = lconstr ->
+ [ [ bl = LIST0 binder_let; ":="; red = reduce; c = lconstr ->
(match c with
CCast(_,c,t) -> DefineBody (bl, red, c, Some t)
| _ -> DefineBody (bl, red, c, None))
- | bl = LIST0 binder; ":"; t = lconstr; ":="; red = reduce; c = lconstr ->
+ | bl = LIST0 binder_let; ":"; t = lconstr; ":="; red = reduce; c = lconstr ->
DefineBody (bl, red, c, Some t)
- | bl = LIST0 binder; ":"; t = lconstr ->
+ | bl = LIST0 binder_let; ":"; t = lconstr ->
ProveBody (bl, t) ] ]
;
reduce:
@@ -182,8 +187,8 @@ GEXTEND Gram
(id,ntn,indpar,c,lc) ] ]
;
constructor_list:
- [ [ "|"; l = LIST1 constructor_binder SEP "|" -> l
- | l = LIST1 constructor_binder SEP "|" -> l
+ [ [ "|"; l = LIST1 constructor SEP "|" -> l
+ | l = LIST1 constructor SEP "|" -> l
| -> [] ] ]
;
(*
@@ -225,7 +230,7 @@ GEXTEND Gram
(id,CProdN(loc,bl,c),CLambdaN(loc,bl,def)) ] ]
;
rec_annotation:
- [ [ "{"; "struct"; id=IDENT; "}" -> id_of_string id ] ]
+ [ [ "{"; IDENT "struct"; id=IDENT; "}" -> id_of_string id ] ]
;
type_cstr:
[ [ ":"; c=lconstr -> c
@@ -246,17 +251,8 @@ GEXTEND Gram
simple_binder:
[ [ b = simple_binder_coe -> no_coercion loc b ] ]
;
- binder:
- [ [ na = name -> LocalRawAssum([na],CHole loc)
- | "("; na = name; ")" -> LocalRawAssum([na],CHole loc)
- | "("; na = name; ":"; c = lconstr; ")"
- -> LocalRawAssum([na],c)
- | "("; na = name; ":="; c = lconstr; ")" ->
- LocalRawDef (na,c)
- ] ]
- ;
binder_nodef:
- [ [ b = binder ->
+ [ [ b = binder_let ->
(match b with
LocalRawAssum(l,ty) -> (l,ty)
| LocalRawDef _ ->
@@ -264,20 +260,21 @@ GEXTEND Gram
(loc,"fix_param",Pp.str"defined binder not allowed here")) ] ]
;
(* ... with coercions *)
- local_decl_expr:
+ record_field:
[ [ id = base_ident -> (false,AssumExpr(id,CHole loc))
- | "("; id = base_ident; ")" -> (false,AssumExpr(id,CHole loc))
- | "("; id = base_ident; oc = of_type_with_opt_coercion;
- t = lconstr; ")" ->
+ | id = base_ident; oc = of_type_with_opt_coercion; t = lconstr ->
(oc,AssumExpr (id,t))
- | "("; id = base_ident; oc = of_type_with_opt_coercion;
- t = lconstr; ":="; b = lconstr; ")" ->
- (oc,DefExpr (id,b,Some t))
- | "("; id = base_ident; ":="; b = lconstr; ")" ->
+ | id = base_ident; oc = of_type_with_opt_coercion;
+ t = lconstr; ":="; b = lconstr -> (oc,DefExpr (id,b,Some t))
+ | id = base_ident; ":="; b = lconstr ->
match b with
CCast(_,b,t) -> (false,DefExpr(id,b,Some t))
| _ -> (false,DefExpr(id,b,None)) ] ]
;
+ assum_coe:
+ [ [ "("; idl = LIST1 base_ident; oc = of_type_with_opt_coercion;
+ c = lconstr; ")" -> (oc,(idl,c)) ] ]
+ ;
simple_binder_coe:
[ [ id=base_ident -> (false,(id,CHole loc))
| "("; id = base_ident; ")" -> (false,(id,CHole loc))
@@ -285,7 +282,7 @@ GEXTEND Gram
t = lconstr; ")" ->
(oc,(id,t)) ] ]
;
- constructor_binder:
+ constructor:
[ [ id = base_ident; coe = of_type_with_opt_coercion; c = lconstr ->
(coe,(id,c)) ] ]
;
@@ -431,8 +428,10 @@ GEXTEND Gram
| None -> c in
VernacNotation (false,c,Some("'"^id^"'",[]),None,None)
*)
- | IDENT "Implicits"; qid = global; "["; l = LIST0 natural; "]" ->
- VernacDeclareImplicits (qid,Some l)
+ | IDENT "Implicit"; IDENT "Arguments"; qid = global;
+ pos = OPT [ "["; l = LIST0 natural; "]" -> l ] ->
+ VernacDeclareImplicits (qid,pos)
+
| IDENT "Implicits"; qid = global -> VernacDeclareImplicits (qid,None)
| IDENT "Implicit"; ["Variable"; "Type" | IDENT "Variables"; "Type"];
@@ -598,8 +597,8 @@ GEXTEND Gram
| IDENT "Scope"; s = IDENT -> PrintScope s ] ]
;
class_rawexpr:
- [ [ IDENT "FUNCLASS" -> FunClass
- | IDENT "SORTCLASS" -> SortClass
+ [ [ IDENT "Funclass" -> FunClass
+ | IDENT "Sortclass" -> SortClass
| qid = global -> RefClass qid ] ]
;
locatable:
@@ -669,11 +668,11 @@ GEXTEND Gram
| IDENT "Arguments"; IDENT "Scope"; qid = global;
"["; scl = LIST0 opt_scope; "]" -> VernacArgumentsScope (qid,scl)
- | IDENT "Infix"; local = locality; a = entry_prec; n = OPT natural;
+ | IDENT "Infix"; local = locality; (*a = entry_prec; n = OPT natural; *)
op = STRING; p = global;
modl = [ "("; l = LIST1 syntax_modifier SEP ","; ")" -> l | -> [] ];
sc = OPT [ ":"; sc = IDENT -> sc ] ->
- let (a,n,b) = Metasyntax.interp_infix_modifiers a n modl in
+ let (a,n,b) = Metasyntax.interp_infix_modifiers None None modl in
VernacInfix (local,a,n,op,p,b,None,sc)
| IDENT "Notation"; local = locality; s = IDENT; ":="; c = constr;
l = [ "("; IDENT "only"; IDENT "parsing"; ")" -> [SetOnlyParsing]
diff --git a/parsing/lexer.ml4 b/parsing/lexer.ml4
index 5e27f9ca8..5545f0077 100644
--- a/parsing/lexer.ml4
+++ b/parsing/lexer.ml4
@@ -309,7 +309,7 @@ let parse_226_tail tk = parser
(* Parse what follows a dot *)
let parse_after_dot bp c strm =
- if !Options.v7 then
+ if (* !Options.v7 *) true then
match strm with parser
| [< ' ('_' | 'a'..'z' | 'A'..'Z' as c); len = ident (store 0 c) >] ->
("FIELD", get_buff len)
diff --git a/parsing/pcoq.ml4 b/parsing/pcoq.ml4
index 39047e688..476b3abd5 100644
--- a/parsing/pcoq.ml4
+++ b/parsing/pcoq.ml4
@@ -353,6 +353,8 @@ module Constr =
let pattern = Gram.Entry.create "constr:pattern"
let annot = Gram.Entry.create "constr:annot"
let constr_pattern = gec_constr "constr_pattern"
+ let binder_let = Gram.Entry.create "constr:binder_list"
+ let tuple_constr = Gram.Entry.create "constr:tuple_constr"
end
module Module =
@@ -618,6 +620,11 @@ let get_constr_entry en =
snd (get_entry (get_univ "constr") "binder_constr"),
None,
false
+ | ETConstr(250,()) when not !Options.v7 ->
+ weaken_entry Constr.tuple_constr,
+(* snd (get_entry (get_univ "constr") "tuple_construple"),*)
+ None,
+ false
| _ -> compute_entry true (fun (n,()) -> Some n) en
(* This computes the name to give to a production knowing the name and
diff --git a/parsing/pcoq.mli b/parsing/pcoq.mli
index 7bf1d837d..a591f57b2 100644
--- a/parsing/pcoq.mli
+++ b/parsing/pcoq.mli
@@ -138,6 +138,8 @@ module Constr :
val pattern : cases_pattern_expr Gram.Entry.e
val annot : constr_expr Gram.Entry.e
val constr_pattern : constr_expr Gram.Entry.e
+ val binder_let : local_binder Gram.Entry.e
+ val tuple_constr : constr_expr Gram.Entry.e
end
module Module :
diff --git a/parsing/ppconstr.ml b/parsing/ppconstr.ml
index 361e24647..b3118f7e7 100644
--- a/parsing/ppconstr.ml
+++ b/parsing/ppconstr.ml
@@ -203,13 +203,13 @@ let pr_eqn pr (_,patl,rhs) =
str "=>" ++
brk (1,1) ++ pr ltop rhs) ++ spc ()
-let pr_cases pr po tml eqns =
+let pr_cases pr (po,_) tml eqns =
hov 0 (
pr_annotation pr po ++
hv 0 (
hv 0 (
str "Cases" ++ brk (1,2) ++
- prlist_with_sep spc (pr ltop) tml ++ spc() ++ str "of") ++ brk(1,2) ++
+ prlist_with_sep spc (fun (tm,_) -> pr ltop tm) tml ++ spc() ++ str "of") ++ brk(1,2) ++
prlist_with_sep (fun () -> str "| ") (pr_eqn pr) eqns ++
str "end"))
@@ -247,15 +247,10 @@ let rec pr inherited a =
hv 1 (
hv 1 (str "[" ++ pr_let_binder pr (snd x) a ++ bll ++ str "]") ++
brk (0,1) ++ b), lletin
- | CAppExpl (_,(true,f),l) ->
- let a,l = list_sep_last l in
- pr_proj pr pr_explapp a f l, lapp
- | CAppExpl (_,(false,f),l) -> pr_explapp pr f l, lapp
- | CApp (_,(true,a),l) ->
- let c,l = list_sep_last l in
- assert (snd c = None);
- pr_proj pr pr_app (fst c) a l, lapp
- | CApp (_,(false,a),l) -> pr_app pr a l, lapp
+ | CAppExpl (_,((* V7 don't know about projections *)_,f),l) ->
+ pr_explapp pr f l, lapp
+ | CApp (_,(_,a),l) ->
+ pr_app pr a l, lapp
| CCases (_,po,tml,eqns) ->
pr_cases pr po tml eqns, lcases
| COrderedCase (_,IfStyle,po,c,[b1;b2]) ->
@@ -267,15 +262,9 @@ let rec pr inherited a =
str "if " ++ pr ltop c ++ spc () ++
hov 0 (str "then" ++ brk (1,1) ++ pr ltop b1) ++ spc () ++
hov 0 (str "else" ++ brk (1,1) ++ pr ltop b2))), lif
- | COrderedCase (_,LetStyle,po,c,[CLambdaN(_,[_,CHole _ as bd],b)]) ->
- hov 0 (
- pr_annotation pr po ++
- hv 0 (
- str "let" ++ brk (1,1) ++
- hov 0 (str "(" ++ pr_binder pr bd ++ str ")") ++
- str " =" ++ brk (1,2) ++
- pr ltop c ++ spc () ++
- str "in " ++ pr ltop b)), lletin
+ | CLetTuple (_,nal,(na,po),c,b) ->
+ error "Let tuple not supported in v7"
+
| COrderedCase (_,(MatchStyle|RegularStyle as style),po,c,bl) ->
hov 0 (
hov 0 (
diff --git a/parsing/q_coqast.ml4 b/parsing/q_coqast.ml4
index 697c78890..9326ff538 100644
--- a/parsing/q_coqast.ml4
+++ b/parsing/q_coqast.ml4
@@ -194,8 +194,8 @@ let rec mlexpr_of_constr = function
| Topconstr.CProdN (loc,l,a) -> <:expr< Topconstr.CProdN $dloc$ $mlexpr_of_list (mlexpr_of_pair (mlexpr_of_list (mlexpr_of_pair (fun _ -> dloc) mlexpr_of_name)) mlexpr_of_constr) l$ $mlexpr_of_constr a$ >>
| Topconstr.CLambdaN (loc,l,a) -> <:expr< Topconstr.CLambdaN $dloc$ $mlexpr_of_list (mlexpr_of_pair (mlexpr_of_list (mlexpr_of_pair (fun _ -> dloc) mlexpr_of_name)) mlexpr_of_constr) l$ $mlexpr_of_constr a$ >>
| Topconstr.CLetIn (loc,_,_,_) -> failwith "mlexpr_of_constr: TODO"
- | Topconstr.CAppExpl (loc,a,l) -> <:expr< Topconstr.CAppExpl $dloc$ $mlexpr_of_pair mlexpr_of_bool mlexpr_of_reference a$ $mlexpr_of_list mlexpr_of_constr l$ >>
- | Topconstr.CApp (loc,a,l) -> <:expr< Topconstr.CApp $dloc$ $mlexpr_of_pair mlexpr_of_bool mlexpr_of_constr a$ $mlexpr_of_list (mlexpr_of_pair mlexpr_of_constr (mlexpr_of_option mlexpr_of_int)) l$ >>
+ | Topconstr.CAppExpl (loc,a,l) -> <:expr< Topconstr.CAppExpl $dloc$ $mlexpr_of_pair (mlexpr_of_option mlexpr_of_int) mlexpr_of_reference a$ $mlexpr_of_list mlexpr_of_constr l$ >>
+ | Topconstr.CApp (loc,a,l) -> <:expr< Topconstr.CApp $dloc$ $mlexpr_of_pair (mlexpr_of_option mlexpr_of_int) mlexpr_of_constr a$ $mlexpr_of_list (mlexpr_of_pair mlexpr_of_constr (mlexpr_of_option mlexpr_of_int)) l$ >>
| Topconstr.CCases (loc,_,_,_) -> failwith "mlexpr_of_constr: TODO"
| Topconstr.COrderedCase (loc,_,_,_,_) -> failwith "mlexpr_of_constr: TODO"
| Topconstr.CHole loc -> <:expr< Topconstr.CHole $dloc$ >>
diff --git a/parsing/termast.ml b/parsing/termast.ml
index 9f09c14be..9cc66a37f 100644
--- a/parsing/termast.ml
+++ b/parsing/termast.ml
@@ -222,14 +222,15 @@ let rec ast_of_raw = function
(* Pour compatibilité des theories, il faut LAMBDALIST partout *)
ope("LAMBDALIST",[ast_of_raw t;a])
- | RCases (_,typopt,tml,eqns) ->
+ | RCases (_,(typopt,_),tml,eqns) ->
let pred = ast_of_rawopt typopt in
let tag = "CASES" in
- let asttomatch = ope("TOMATCH", List.map ast_of_raw tml) in
+ let asttomatch =
+ ope("TOMATCH", List.map (fun (tm,_) -> ast_of_raw tm) tml) in
let asteqns = List.map ast_of_eqn eqns in
ope(tag,pred::asttomatch::asteqns)
- | ROrderedCase (_,LetStyle,typopt,tm,[|bv|]) ->
+ | ROrderedCase (_,LetStyle,typopt,tm,[|bv|],_) ->
let nvar' = function Anonymous -> nvar wildcard | Name id -> nvar id in
let rec f l = function
| RLambda (_,na,RHole _,c) -> f (nvar' na :: l) c
@@ -239,7 +240,7 @@ let rec ast_of_raw = function
let eqn = ope ("EQN", [c;ope ("PATTCONSTRUCT",(nvar wildcard)::l)]) in
ope ("FORCELET",[(ast_of_rawopt typopt);(ast_of_raw tm);eqn])
- | ROrderedCase (_,st,typopt,tm,bv) ->
+ | ROrderedCase (_,st,typopt,tm,bv,_) ->
let tag = match st with
| IfStyle -> "FORCEIF"
| RegularStyle -> "CASE"
@@ -250,6 +251,10 @@ let rec ast_of_raw = function
ope(tag,(ast_of_rawopt typopt)
::(ast_of_raw tm)
::(Array.to_list (Array.map ast_of_raw bv)))
+
+ | RLetTuple (loc,nal,(na,typopt),tm,b) ->
+ error "Let tuple not supported in v7"
+
| RRec (_,fk,idv,tyv,bv) ->
let alfi = Array.map ast_of_ident idv in
(match fk with
diff --git a/pretyping/cases.ml b/pretyping/cases.ml
index c24748970..e2aa74cba 100644
--- a/pretyping/cases.ml
+++ b/pretyping/cases.ml
@@ -591,11 +591,15 @@ let occur_rawconstr id =
| RLambda (loc,na,ty,c) -> (occur ty) or ((na <> Name id) & (occur c))
| RProd (loc,na,ty,c) -> (occur ty) or ((na <> Name id) & (occur c))
| RLetIn (loc,na,b,c) -> (occur b) or ((na <> Name id) & (occur c))
- | RCases (loc,tyopt,tml,pl) ->
- (occur_option tyopt) or (List.exists occur tml)
+ | RCases (loc,(tyopt,rtntypopt),tml,pl) ->
+ (occur_option tyopt) or (occur_option !rtntypopt)
+ or (List.exists (fun (tm,_) -> occur tm) tml)
or (List.exists occur_pattern pl)
- | ROrderedCase (loc,b,tyopt,tm,bv) ->
+ | ROrderedCase (loc,b,tyopt,tm,bv,_) ->
(occur_option tyopt) or (occur tm) or (array_exists occur bv)
+ | RLetTuple (loc,nal,(na,tyopt),b,c) ->
+ (na <> Name id & occur_option tyopt)
+ or (occur b) or (not (List.mem (Name id) nal) & (occur c))
| RRec (loc,fk,idl,tyl,bv) ->
(array_exists occur tyl) or
(not (array_exists (fun id2 -> id=id2) idl) & array_exists occur bv)
@@ -1546,6 +1550,45 @@ let extract_predicate_conclusion nargs pred =
| _ -> (* eta-expansion *) applist (lift 1 p, [mkRel 1]) in
iterate decomp_lam_force nargs pred
+let set_arity_signature dep n arsign tomatchl pred x =
+ (* avoid is not exhaustive ! *)
+ let rec decomp_lam_force n avoid l p =
+ if n = 0 then (List.rev l,p,avoid) else
+ match p with
+ | RLambda (_,(Name id as na),_,c) ->
+ decomp_lam_force (n-1) (id::avoid) (na::l) c
+ | RLambda (_,(Anonymous as na),_,c) -> decomp_lam_force (n-1) avoid (na::l) c
+ | _ ->
+ let x = next_ident_away (id_of_string "x") avoid in
+ decomp_lam_force (n-1) (x::avoid) (Name x :: l)
+ (* eta-expansion *)
+ (let a = RVar (dummy_loc,x) in
+ match p with
+ | RApp (loc,p,l) -> RApp (loc,p,l@[a])
+ | _ -> (RApp (dummy_loc,p,[a]))) in
+ let rec decomp_block avoid p = function
+ | ([], _) -> x := Some p
+ | ((_,IsInd (_,IndType(indf,realargs)))::l),(y::l') ->
+ let (ind,params) = dest_ind_family indf in
+ let (nal,p,avoid') = decomp_lam_force (List.length realargs) avoid [] p
+ in
+ let na,p,avoid' =
+ if dep then decomp_lam_force 1 avoid' [] p else [Anonymous],p,avoid'
+ in
+ y :=
+ (List.hd na,
+ if List.for_all ((=) Anonymous) nal then
+ None
+ else
+ Some (dummy_loc, ind, (List.map (fun _ -> Anonymous) params)@nal));
+ decomp_block avoid' p (l,l')
+ | (_::l),(y::l') ->
+ y := (Anonymous,None);
+ decomp_block avoid p (l,l')
+ | _ -> anomaly "set_arity_signature"
+ in
+ decomp_block [] pred (tomatchl,arsign)
+
let prepare_predicate_from_tycon loc dep env isevars tomatchs c =
let cook (n, l, env) = function
| c,IsInd (_,IndType(indf,realargs)) ->
@@ -1571,7 +1614,7 @@ let prepare_predicate_from_tycon loc dep env isevars tomatchs c =
map_constr_with_full_binders push_rel build_skeleton env c in
build_skeleton env (lift n c)
-(* Here, [pred] is assumed to be in the context build from all *)
+(* Here, [pred] is assumed to be in the context built from all *)
(* realargs and terms to match *)
let build_initial_predicate env sigma isdep pred tomatchl =
let cook n = function
@@ -1595,6 +1638,45 @@ let build_initial_predicate env sigma isdep pred tomatchl =
PrLetIn ((realargs,None), buildrec (n+nrealargs) q ltm)
in buildrec 0 0 tomatchl
+let extract_arity_signature env0 tomatchl tmsign =
+ let get_one_sign n tm {contents = (na,t)} =
+ match tm with
+ | NotInd _ ->
+ (match t with
+ | None -> []
+ | Some (loc,_,_) ->
+ user_err_loc (loc,"",
+ str "Unexpected type annotation for a term of non inductive type"))
+ | IsInd (_,IndType(indf,realargs)) ->
+ let indf' = lift_inductive_family n indf in
+ let (ind,params) = dest_ind_family indf' in
+ let nrealargs = List.length realargs in
+ let realnal =
+ match t with
+ | Some (loc,ind',nal) ->
+ let nparams = List.length params in
+ if ind <> ind' then
+ user_err_loc (loc,"",str "Wrong inductive type");
+ if List.length nal <> nparams + nrealargs then
+ user_err_loc (loc,"",
+ str "Wrong number of arguments for inductive type");
+ let parnal,realnal = list_chop nparams nal in
+ if List.exists ((<>) Anonymous) parnal then
+ user_err_loc (loc,"",
+ str "The parameters of inductive type must be implicit");
+ List.rev realnal
+ | None -> list_tabulate (fun _ -> Anonymous) nrealargs in
+ let arsign = fst (get_arity env0 indf') in
+ (na,None,build_dependent_inductive env0 indf')
+ ::(List.map2 (fun x (_,c,t) ->(x,c,t)) realnal arsign) in
+ let rec buildrec n = function
+ | [],[] -> []
+ | (_,tm)::ltm, x::tmsign ->
+ let l = get_one_sign n tm x in
+ (buildrec (n + List.length l) (ltm,tmsign)) @ l
+ | _ -> assert false
+ in buildrec 0 (tomatchl,tmsign)
+
(* determines wether the multiple case is dependent or not. For that
* the predicate given by the user is eta-expanded. If the result
* of expansion is pred, then :
@@ -1606,15 +1688,28 @@ let build_initial_predicate env sigma isdep pred tomatchl =
* else error! (can not treat mixed dependent and non dependent case
*)
-let prepare_predicate loc typing_fun isevars env tomatchs tycon = function
- | None ->
+let prepare_predicate loc typing_fun isevars env tomatchs sign tycon = function
+ (* No type annotation at all *)
+ | (None,{contents = None}) ->
(match tycon with
| None -> None
| Some t ->
let pred = prepare_predicate_from_tycon loc false env isevars tomatchs t in
Some
(build_initial_predicate env (evars_of isevars) false pred tomatchs))
- | Some pred ->
+
+ (* v8 style type annotation *)
+ | (None,{contents = Some rtntyp}) ->
+
+ (* We extract the signature of the arity *)
+ let arsign = extract_arity_signature env tomatchs sign in
+ let env = push_rels arsign env in
+ let predccl = (typing_fun empty_tycon env rtntyp).uj_val in
+ Some
+ (build_initial_predicate env (evars_of isevars) true predccl tomatchs)
+
+ (* v7 style type annotation; set the v8 annotation by side effect *)
+ | (Some pred,x) ->
let loc = loc_of_rawconstr pred in
let dep, n, predj =
let isevars_copy = evars_of isevars in
@@ -1643,6 +1738,7 @@ let prepare_predicate loc typing_fun isevars env tomatchs tycon = function
(*
let etapred,cdep = case_dependent env (evars_of isevars) loc predj tomatchs in
*)
+ set_arity_signature dep n sign tomatchs pred x;
Some(build_initial_predicate env (evars_of isevars) dep predccl tomatchs)
@@ -1656,11 +1752,12 @@ let compile_cases loc (typing_fun,isevars) tycon env (predopt, tomatchl, eqns)=
(* We build the vector of terms to match consistently with the *)
(* constructors found in patterns *)
- let tomatchs = coerce_to_indtype typing_fun isevars env matx tomatchl in
+ let rawtms, tmsign = List.split tomatchl in
+ let tomatchs = coerce_to_indtype typing_fun isevars env matx rawtms in
(* We build the elimination predicate if any and check its consistency *)
(* with the type of arguments to match *)
- let pred = prepare_predicate loc typing_fun isevars env tomatchs tycon predopt in
+ let pred = prepare_predicate loc typing_fun isevars env tomatchs tmsign tycon predopt in
(* We deal with initial aliases *)
let matx = prepare_initial_aliases (known_dependent pred) tomatchs matx in
diff --git a/pretyping/cases.mli b/pretyping/cases.mli
index 287e78f76..1c4e6b92c 100644
--- a/pretyping/cases.mli
+++ b/pretyping/cases.mli
@@ -41,6 +41,8 @@ type ml_case_error =
exception NotInferable of ml_case_error
+val occur_rawconstr : identifier -> rawconstr -> bool
+
val pred_case_ml : (* raises [NotInferable] if not inferable *)
env -> evar_map -> bool -> inductive_type -> int * types -> constr
@@ -49,6 +51,7 @@ val pred_case_ml : (* raises [NotInferable] if not inferable *)
val compile_cases :
loc -> (type_constraint -> env -> rawconstr -> unsafe_judgment)
* evar_defs -> type_constraint -> env ->
- rawconstr option * rawconstr list *
+ (rawconstr option * rawconstr option ref) *
+ (rawconstr * (name * (loc * inductive * name list) option) ref) list *
(loc * identifier list * cases_pattern list * rawconstr) list ->
unsafe_judgment
diff --git a/pretyping/detyping.ml b/pretyping/detyping.ml
index 9e4eaf8a1..a82b2b90a 100644
--- a/pretyping/detyping.ml
+++ b/pretyping/detyping.ml
@@ -162,7 +162,6 @@ let computable p k =
noccur_between 1 (k+1) ccl
-
let lookup_name_as_renamed env t s =
let rec lookup avoid env_names n c = match kind_of_term c with
| Prod (name,_,c') ->
@@ -195,7 +194,7 @@ let lookup_index_as_renamed env t n =
| _ -> None
in lookup n 1 t
-let detype_case computable detype detype_eqn tenv avoid env indsp st p c bl =
+let detype_case computable detype detype_eqn tenv avoid env indsp st p k c bl =
let synth_type = synthetize_type () in
let tomatch = detype tenv avoid env c in
@@ -207,11 +206,41 @@ let detype_case computable detype detype_eqn tenv avoid env indsp st p c bl =
List.rev (fst (decompose_prod_assum t)) in
let consnargs = Array.init (Array.length mip.mind_consnames) get_consnarg in
let consnargsl = Array.map List.length consnargs in
- let pred =
+ let alias, aliastyp, newpred, pred =
if synth_type & computable & bl <> [||] then
- None
- else
- option_app (detype tenv avoid env) p in
+ Anonymous, None, None, None
+ else
+ let p = option_app (detype tenv avoid env) p in
+ match p with
+ | None -> Anonymous, None, None, None
+ | Some p ->
+ let decompose_lam k c =
+ let name_cons = function
+ Anonymous -> fun l -> l | Name id -> fun l -> id::l in
+ let rec lamdec_rec l avoid k c =
+ if k = 0 then l,c else match c with
+ | RLambda (_,x,t,c) ->
+ lamdec_rec (x::l) (name_cons x avoid) (k-1) c
+ | c ->
+ let x = next_ident_away (id_of_string "xx") avoid in
+ lamdec_rec ((Name x)::l) (x::avoid) (k-1)
+ (let a = RVar (dummy_loc,x) in
+ match c with
+ | RApp (loc,p,l) -> RApp (loc,p,l@[a])
+ | _ -> (RApp (dummy_loc,c,[a])))
+ in
+ lamdec_rec [] [] k c in
+ let nl,typ = decompose_lam k p in
+ let n,typ = match typ with
+ | RLambda (_,x,t,c) -> x, c
+ | _ -> Anonymous, typ in
+ let aliastyp =
+ if List.for_all ((=) Anonymous) nl then None
+ else
+ let pars = list_tabulate (fun _ -> Anonymous) mip.mind_nparams
+ in Some (dummy_loc,indsp,pars@nl) in
+ n, aliastyp, Some typ, Some p
+ in
let constructs = Array.init (Array.length bl) (fun i -> (indsp,i+1)) in
let eqnv = array_map3 (detype_eqn tenv avoid env) constructs consnargsl bl in
let eqnl = Array.to_list eqnv in
@@ -226,29 +255,48 @@ let detype_case computable detype detype_eqn tenv avoid env indsp st p c bl =
with Not_found -> st
in
if tag = RegularStyle then
- RCases (dummy_loc,pred,[tomatch],eqnl)
+ RCases (dummy_loc,(pred,ref newpred),[tomatch,ref (alias,aliastyp)],eqnl)
else
- let rec remove_type avoid args c =
- match c,args with
- | RLambda (loc,na,t,c), _::args ->
- let h = RHole (loc,BinderType na) in
- RLambda (loc,na,h,remove_type avoid args c)
- | RLetIn (loc,na,b,c), _::args ->
- RLetIn (loc,na,b,remove_type avoid args c)
- | c, (na,None,t)::args ->
- let id = next_name_away_with_default "x" na avoid in
- let h = RHole (dummy_loc,BinderType na) in
- let c = remove_type (id::avoid) args
- (RApp (dummy_loc,c,[RVar (dummy_loc,id)])) in
- RLambda (dummy_loc,Name id,h,c)
- | c, (na,Some b,t)::args ->
- let h = RHole (dummy_loc,BinderType na) in
- let avoid = name_fold (fun x l -> x::l) na avoid in
- RLetIn (dummy_loc,na,h,remove_type avoid args c)
- | c, [] -> c in
let bl = Array.map (detype tenv avoid env) bl in
- let bl = array_map2 (remove_type avoid) consnargs bl in
- ROrderedCase (dummy_loc,tag,pred,tomatch,bl)
+ if not !Options.v7 && tag = LetStyle && aliastyp = None then
+ let rec decomp_lam_force n avoid l p =
+ if n = 0 then (List.rev l,p) else
+ match p with
+ | RLambda (_,(Name id as na),_,c) ->
+ decomp_lam_force (n-1) (id::avoid) (na::l) c
+ | RLambda (_,(Anonymous as na),_,c) ->
+ decomp_lam_force (n-1) avoid (na::l) c
+ | _ ->
+ let x = Nameops.next_ident_away (id_of_string "x") avoid in
+ decomp_lam_force (n-1) (x::avoid) (Name x :: l)
+ (* eta-expansion *)
+ (let a = RVar (dummy_loc,x) in
+ match p with
+ | RApp (loc,p,l) -> RApp (loc,p,l@[a])
+ | _ -> (RApp (dummy_loc,p,[a]))) in
+ let (nal,d) = decomp_lam_force consnargsl.(0) avoid [] bl.(0) in
+ RLetTuple (dummy_loc,nal,(alias,newpred),tomatch,d)
+ else
+ let rec remove_type avoid args c =
+ match c,args with
+ | RLambda (loc,na,t,c), _::args ->
+ let h = RHole (dummy_loc,BinderType na) in
+ RLambda (loc,na,h,remove_type avoid args c)
+ | RLetIn (loc,na,b,c), _::args ->
+ RLetIn (loc,na,b,remove_type avoid args c)
+ | c, (na,None,t)::args ->
+ let id = next_name_away_with_default "x" na avoid in
+ let h = RHole (dummy_loc,BinderType na) in
+ let c = remove_type (id::avoid) args
+ (RApp (dummy_loc,c,[RVar (dummy_loc,id)])) in
+ RLambda (dummy_loc,Name id,h,c)
+ | c, (na,Some b,t)::args ->
+ let h = RHole (dummy_loc,BinderType na) in
+ let avoid = name_fold (fun x l -> x::l) na avoid in
+ RLetIn (dummy_loc,na,h,remove_type avoid args c)
+ | c, [] -> c in
+ let bl = array_map2 (remove_type avoid) consnargs bl in
+ ROrderedCase (dummy_loc,tag,pred,tomatch,bl,ref None)
let rec detype tenv avoid env t =
match kind_of_term (collapse_appl t) with
@@ -291,8 +339,8 @@ let rec detype tenv avoid env t =
let comp = computable p (annot.ci_pp_info.ind_nargs) in
let ind = annot.ci_ind in
let st = annot.ci_pp_info.style in
- detype_case comp detype detype_eqn tenv avoid env ind st (Some p) c bl
-
+ detype_case comp detype detype_eqn tenv avoid env ind st (Some p)
+ annot.ci_pp_info.ind_nargs c bl
| Fix (nvn,recdef) -> detype_fix tenv avoid env nvn recdef
| CoFix (n,recdef) -> detype_cofix tenv avoid env n recdef
diff --git a/pretyping/detyping.mli b/pretyping/detyping.mli
index 13d37c843..5cf174875 100644
--- a/pretyping/detyping.mli
+++ b/pretyping/detyping.mli
@@ -29,7 +29,7 @@ val detype_case :
'a -> Rawterm.loc * Names.identifier list * Rawterm.cases_pattern list *
Rawterm.rawconstr) ->
env -> identifier list -> names_context -> inductive -> case_style ->
- 'a option -> 'a -> 'a array -> rawconstr
+ 'a option -> int -> 'a -> 'a array -> rawconstr
(* look for the index of a named var or a nondep var as it is renamed *)
val lookup_name_as_renamed : env -> constr -> identifier -> int option
diff --git a/pretyping/indrec.ml b/pretyping/indrec.ml
index 161c37ae8..ca25938b6 100644
--- a/pretyping/indrec.ml
+++ b/pretyping/indrec.ml
@@ -69,14 +69,20 @@ let mis_make_case_com depopt env sigma (ind,mib,mip) kind =
let indf = make_ind_family(ind,extended_rel_list nbprod lnamespar) in
let lnamesar,_ = get_arity env indf in
let ci = make_default_case_info env RegularStyle ind in
+ let depind = build_dependent_inductive env indf in
+ let deparsign = (Anonymous,None,depind)::lnamesar in
+ let p = (* mkRel nbprod *)
it_mkLambda_or_LetIn_name env'
- (lambda_create env'
- (build_dependent_inductive env indf,
- mkCase (ci,
- mkRel (nbprod+nbargsprod),
- mkRel 1,
- rel_vect nbargsprod k)))
- lnamesar
+ (appvect
+ (mkRel ((if dep then nbargsprod else mip.mind_nrealargs) + nbprod),
+ if dep then extended_rel_vect 0 deparsign
+ else extended_rel_vect 0 lnamesar))
+ (if dep then deparsign else lnamesar) in
+ it_mkLambda_or_LetIn_name env'
+ (mkCase (ci, lift nbargsprod p,
+ mkRel 1,
+ rel_vect nbargsprod k))
+ deparsign
else
let cs = lift_constructor (k+1) constrs.(k) in
let t = build_branch_type env dep (mkRel (k+1)) cs in
diff --git a/pretyping/inductiveops.ml b/pretyping/inductiveops.ml
index a64c55389..adc5932f1 100644
--- a/pretyping/inductiveops.ml
+++ b/pretyping/inductiveops.ml
@@ -239,6 +239,28 @@ let find_coinductive env sigma c =
(* find appropriate names for pattern variables. Useful in the
Case tactic. *)
+let is_dep_predicate env kelim pred nodep_ar =
+ let rec srec env pval pt nodep_ar =
+ let pt' = whd_betadeltaiota env Evd.empty pt in
+ let pv' = whd_betadeltaiota env Evd.empty pval in
+ match kind_of_term pv', kind_of_term pt', kind_of_term nodep_ar with
+ | Lambda (na,t,b), Prod (_,_,a), Prod (_,_,a') ->
+ srec (push_rel_assum (na,t) env) b a a'
+ | _, Prod (na,t,a), Prod (_,_,a') ->
+ srec (push_rel_assum (na,t) env) (lift 1 pv') a a'
+ | Lambda (_,_,b), Prod (_,_,_), _ -> (*dependent (mkRel 1) b*) true
+ | _, Prod (_,_,_), _ -> true
+ | _ -> false in
+ srec env pred.uj_val pred.uj_type nodep_ar
+
+let is_dependent_elimination_predicate env pred indf =
+ let (ind,params) = indf in
+ let (_,mip) = Inductive.lookup_mind_specif env ind in
+ let kelim = mip.mind_kelim in
+ let arsign,s = get_arity env indf in
+ let glob_t = it_mkProd_or_LetIn (mkSort s) arsign in
+ is_dep_predicate env kelim pred glob_t
+
let is_dep_arity env kelim predty nodep_ar =
let rec srec pt nodep_ar =
let pt' = whd_betadeltaiota env Evd.empty pt in
@@ -256,7 +278,6 @@ let is_dependent_elimination env predty indf =
let glob_t = it_mkProd_or_LetIn (mkSort s) arsign in
is_dep_arity env kelim predty glob_t
-
let set_names env n brty =
let (ctxt,cl) = decompose_prod_n_assum n brty in
it_mkProd_or_LetIn_name env cl ctxt
@@ -277,7 +298,7 @@ let type_case_branches_with_names env indspec pj c =
let (lbrty,conclty,_) = Inductive.type_case_branches env indspec pj c in
let (mib,mip) = Inductive.lookup_mind_specif env ind in
let params = list_firstn mip.mind_nparams args in
- if is_dependent_elimination env pj.uj_type (ind,params) then
+ if is_dependent_elimination_predicate env pj (ind,params) then
(set_pattern_names env ind lbrty, conclty)
else (lbrty, conclty)
diff --git a/pretyping/pattern.ml b/pretyping/pattern.ml
index 92c581c71..d3479a846 100644
--- a/pretyping/pattern.ml
+++ b/pretyping/pattern.ml
@@ -237,15 +237,16 @@ let rec pat_of_raw metas vars = function
Options.if_verbose
Pp.warning "Cast not taken into account in constr pattern";
pat_of_raw metas vars c
- | ROrderedCase (_,st,po,c,br) ->
+ | ROrderedCase (_,st,po,c,br,_) ->
PCase ((None,st),option_app (pat_of_raw metas vars) po,
pat_of_raw metas vars c,
Array.map (pat_of_raw metas vars) br)
- | RCases (loc,po,[c],brs) ->
+ | RCases (loc,(po,_),[c,_],brs) ->
let sp =
match brs with
| (_,_,[PatCstr(_,(ind,_),_,_)],_)::_ -> Some ind
| _ -> None in
+ (* When po disappears: switch to rtn type *)
PCase ((sp,Term.RegularStyle),option_app (pat_of_raw metas vars) po,
pat_of_raw metas vars c,
Array.init (List.length brs)
diff --git a/pretyping/pretyping.ml b/pretyping/pretyping.ml
index 0b665d4b2..e86d60c77 100644
--- a/pretyping/pretyping.ml
+++ b/pretyping/pretyping.ml
@@ -50,7 +50,7 @@ let transform_rec loc env sigma (pj,c,lf) indt =
let (mib,mip) = lookup_mind_specif env ind in
let recargs = mip.mind_recargs in
let mI = mkInd ind in
- let ci = make_default_case_info env MatchStyle ind in
+ let ci = make_default_case_info env (if Options.do_translate() then RegularStyle else MatchStyle) ind in
let nconstr = Array.length mip.mind_consnames in
if Array.length lf <> nconstr then
(let cj = {uj_val=c; uj_type=mkAppliedInd indt} in
@@ -146,6 +146,8 @@ let inh_conv_coerce_to_tycon loc env isevars j = function
| None -> j
| Some typ -> inh_conv_coerce_to loc env isevars j typ
+let push_rels vars env = List.fold_right push_rel vars env
+
(*
let evar_type_case isevars env ct pt lft p c =
let (mind,bty,rslty) = type_case_branches env (evars_of isevars) ct pt p c
@@ -330,8 +332,7 @@ let rec pretype tycon env isevars lvar = function
{ uj_val = mkLetIn (name, j.uj_val, t, j'.uj_val) ;
uj_type = type_app (subst1 j.uj_val) j'.uj_type }
- (* Special Case for let constructions to avoid exponential behavior *)
- | ROrderedCase (loc,st,po,c,[|f|]) when st <> MatchStyle ->
+ | RLetTuple (loc,nal,(na,po),c,d) ->
let cj = pretype empty_tycon env isevars lvar c in
let (IndType (indf,realargs) as indt) =
try find_rectype env (evars_of isevars) cj.uj_type
@@ -339,8 +340,67 @@ let rec pretype tycon env isevars lvar = function
let cloc = loc_of_rawconstr c in
error_case_not_inductive_loc cloc env (evars_of isevars) cj
in
+ let cstrs = get_constructors env indf in
+ if Array.length cstrs <> 1 then
+ user_err_loc (loc,"",str "Destructing let is only for inductive types with one constructor");
+ let cs = cstrs.(0) in
+ if List.length nal <> cs.cs_nargs then
+ user_err_loc (loc,"", str "Destructing let on this type expects " ++ int cs.cs_nargs ++ str " variables");
+ let fsign = List.map2 (fun na (_,c,t) -> (na,c,t))
+ (List.rev nal) cs.cs_args in
+ let env_f = push_rels fsign env in
+ let arsgn,_ = get_arity env indf in
+ let psign = (na,None,build_dependent_inductive env indf)::arsgn in
+ let nar = List.length arsgn in
(match po with
| Some p ->
+ let env_p = push_rels psign env in
+ let pj = pretype_type empty_valcon env_p isevars lvar p in
+ let ccl = nf_evar (evars_of isevars) pj.utj_val in
+ let fty =
+ let inst = (Array.to_list cs.cs_concl_realargs)
+ @[build_dependent_constructor cs]
+ in substl inst (liftn cs.cs_nargs nar ccl) in
+ let fj = pretype (mk_tycon fty) env_f isevars lvar d in
+ let f = it_mkLambda_or_LetIn fj.uj_val fsign in
+ let p = it_mkLambda_or_LetIn ccl psign in
+ let v =
+ let mis,_ = dest_ind_family indf in
+ let ci = make_default_case_info env LetStyle mis in
+ mkCase (ci, p, cj.uj_val,[|f|]) in
+ let cs = build_dependent_constructor cs in
+ { uj_val = v; uj_type = substl (realargs@[cj.uj_val]) ccl }
+
+ | None ->
+ let tycon = option_app (lift cs.cs_nargs) tycon in
+ let fj = pretype tycon env_f isevars lvar d in
+ let f = it_mkLambda_or_LetIn fj.uj_val fsign in
+ let ccl = nf_evar (evars_of isevars) fj.uj_type in
+ let ccl =
+ if noccur_between 1 cs.cs_nargs ccl then
+ lift (- cs.cs_nargs) ccl
+ else
+ error_cant_find_case_type_loc loc env (evars_of isevars)
+ cj.uj_val in
+ let p = it_mkLambda_or_LetIn (lift (nar+1) ccl) psign in
+ let v =
+ let mis,_ = dest_ind_family indf in
+ let ci = make_default_case_info env LetStyle mis in
+ mkCase (ci, p, cj.uj_val,[|f|] )
+ in
+ { uj_val = v; uj_type = ccl })
+
+ (* Special Case for let constructions to avoid exponential behavior *)
+ | ROrderedCase (loc,st,po,c,[|f|],xx) when st <> MatchStyle ->
+ let cj = pretype empty_tycon env isevars lvar c in
+ let (IndType (indf,realargs) as indt) =
+ try find_rectype env (evars_of isevars) cj.uj_type
+ with Not_found ->
+ let cloc = loc_of_rawconstr c in
+ error_case_not_inductive_loc cloc env (evars_of isevars) cj
+ in
+ let j = match po with
+ | Some p ->
let pj = pretype empty_tycon env isevars lvar p in
let dep = is_dependent_elimination env pj.uj_type indf in
let ar =
@@ -425,9 +485,110 @@ let rec pretype tycon env isevars lvar = function
let ci = make_default_case_info env st mis in
mkCase (ci, (nf_betaiota pj.uj_val), cj.uj_val,[|fv|] )
in
- { uj_val = v; uj_type = rsty })
+ { uj_val = v; uj_type = rsty } in
+
+ (* Build the LetTuple form for v8 *)
+ let c =
+ let (ind,params) = dest_ind_family indf in
+ let rtntypopt, indnalopt = match po with
+ | None -> None, (Anonymous,None)
+ | Some p ->
+ let pj = pretype empty_tycon env isevars lvar p in
+ let dep = is_dependent_elimination env pj.uj_type indf in
+ let rec decomp_lam_force n avoid l p =
+ (* avoid is not exhaustive ! *)
+ if n = 0 then (List.rev l,p,avoid) else
+ match p with
+ | RLambda (_,(Name id as na),_,c) ->
+ decomp_lam_force (n-1) (id::avoid) (na::l) c
+ | RLambda (_,(Anonymous as na),_,c) ->
+ decomp_lam_force (n-1) avoid (na::l) c
+ | _ ->
+ let x = Nameops.next_ident_away (id_of_string "x") avoid in
+ decomp_lam_force (n-1) (x::avoid) (Name x :: l)
+ (* eta-expansion *)
+ (RApp (dummy_loc,p, [RVar (dummy_loc,x)])) in
+ let (nal,p,avoid) =
+ decomp_lam_force (List.length realargs) [] [] p in
+ let na,rtntyp,_ =
+ if dep then decomp_lam_force 1 avoid [] p
+ else [Anonymous],p,[] in
+ let intyp =
+ if List.for_all
+ (function
+ | Anonymous -> true
+ | Name id -> not (Cases.occur_rawconstr id rtntyp)) nal
+ then (* No dependency in realargs *)
+ None
+ else
+ let args = List.map (fun _ -> Anonymous) params @ nal in
+ Some (dummy_loc,ind,args) in
+ (Some rtntyp,(List.hd na,intyp)) in
+ let cs = (get_constructors env indf).(0) in
+ match indnalopt with
+ | (na,None) -> (* Represented as a let *)
+ let rec decomp_lam_force n avoid l p =
+ if n = 0 then (List.rev l,p) else
+ match p with
+ | RLambda (_,(Name id as na),_,c) ->
+ decomp_lam_force (n-1) (id::avoid) (na::l) c
+ | RLambda (_,(Anonymous as na),_,c) ->
+ decomp_lam_force (n-1) avoid (na::l) c
+ | _ ->
+ let x = Nameops.next_ident_away (id_of_string "x") avoid in
+ decomp_lam_force (n-1) (x::avoid) (Name x :: l)
+ (* eta-expansion *)
+ (let a = RVar (dummy_loc,x) in
+ match p with
+ | RApp (loc,p,l) -> RApp (loc,p,l@[a])
+ | _ -> (RApp (dummy_loc,p,[a]))) in
+ let (nal,d) = decomp_lam_force cs.cs_nargs [] [] f in
+ RLetTuple (loc,nal,(na,rtntypopt),c,d)
+ | _ -> (* Represented as a match *)
+ let detype_eqn constr construct_nargs branch =
+ let name_cons = function
+ | Anonymous -> fun l -> l
+ | Name id -> fun l -> id::l in
+ let make_pat na avoid b ids =
+ PatVar (dummy_loc,na),
+ name_cons na avoid,name_cons na ids
+ in
+ let rec buildrec ids patlist avoid n b =
+ if n=0 then
+ (dummy_loc, ids,
+ [PatCstr(dummy_loc, constr, List.rev patlist,Anonymous)],
+ b)
+ else
+ match b with
+ | RLambda (_,x,_,b) ->
+ let pat,new_avoid,new_ids = make_pat x avoid b ids in
+ buildrec new_ids (pat::patlist) new_avoid (n-1) b
+
+ | RLetIn (_,x,_,b) ->
+ let pat,new_avoid,new_ids = make_pat x avoid b ids in
+ buildrec new_ids (pat::patlist) new_avoid (n-1) b
+
+ | RCast (_,c,_) -> (* Oui, il y a parfois des cast *)
+ buildrec ids patlist avoid n c
+
+ | _ -> (* eta-expansion *)
+ (* nommage de la nouvelle variable *)
+ let id = Nameops.next_ident_away (id_of_string "x") avoid in
+ let new_b = RApp (dummy_loc, b, [RVar(dummy_loc,id)])in
+ let pat,new_avoid,new_ids =
+ make_pat (Name id) avoid new_b ids in
+ buildrec new_ids (pat::patlist) new_avoid (n-1) new_b
+
+ in
+ buildrec [] [] [] construct_nargs branch in
+ let eqn = detype_eqn (ind,1) cs.cs_nargs f in
+ RCases (loc,(po,ref rtntypopt),[c,ref indnalopt],[eqn])
+ in
+ xx := Some c;
+ (* End building the v8 syntax *)
+ j
- | ROrderedCase (loc,st,po,c,lf) ->
+ | ROrderedCase (loc,st,po,c,lf,x) ->
let isrec = (st = MatchStyle) in
let cj = pretype empty_tycon env isevars lvar c in
let (IndType (indf,realargs) as indt) =
@@ -503,6 +664,147 @@ let rec pretype tycon env isevars lvar = function
mkCase (ci, (nf_betaiota pj.uj_val), cj.uj_val,
Array.map (fun j-> j.uj_val) lfj)
in
+ (* Build the Cases form for v8 *)
+ let c =
+ let (ind,params) = dest_ind_family indf in
+ let (mib,mip) = lookup_mind_specif env ind in
+ let recargs = mip.mind_recargs in
+ let mI = mkInd ind in
+ let nconstr = Array.length mip.mind_consnames in
+ let tyi = snd ind in
+ if isrec && mis_is_recursive_subset [tyi] recargs then
+ Some (Detyping.detype env [] (names_of_rel_context env)
+ (nf_evar (evars_of isevars) v))
+ (*
+ let sigma = evars_of isevars in
+ let init_depFvec i = if i = tyi then Some(dep,mkRel 1) else None in
+ let depFvec = Array.init mib.mind_ntypes init_depFvec in
+ (* build now the fixpoint *)
+ let lnames,_ = get_arity env indf in
+ let nar = List.length lnames in
+ let nparams = mip.mind_nparams in
+ let constrs = get_constructors env (lift_inductive_family (nar+2) indf) in
+ let branches =
+ array_map3
+ (fun f t reca ->
+ whd_beta
+ (Indrec.make_rec_branch_arg env sigma
+ (nparams,depFvec,nar+1)
+ f t reca))
+ (Array.map (lift (nar+2)) lfv) constrs (dest_subterms recargs)
+ in
+ let ci = make_default_case_info env RegularStyle ind in
+ let deffix =
+ it_mkLambda_or_LetIn_name env
+ (lambda_create env
+ (applist (mI,List.append (List.map (lift (nar+1)) params)
+ (extended_rel_list 0 lnames)),
+ mkCase (ci, lift (nar+2) pj.uj_val, mkRel 1, branches)))
+ (lift_rel_context 1 lnames)
+ in
+ if noccurn 1 deffix then
+ Some
+ (Detyping.detype env [] (names_of_rel_context env)
+ (whd_beta (applist (pop deffix,realargs@[cj.uj_val]))))
+ else
+ let ind = applist (mI,(List.append
+ (List.map (lift nar) params)
+ (extended_rel_list 0 lnames))) in
+ let typPfix =
+ let rec aux = function
+ | (na,Some b,t)::l ->
+ | (na,None,t)::l -> RProd (dummy_loc,na,
+ | [] ->
+ it_mkProd_or_LetIn_name env
+ (prod_create env
+ (ind,
+ (if dep then
+ let ext_lnames = (Anonymous,None,ind)::lnames in
+ let args = extended_rel_list 0 ext_lnames in
+ whd_beta (applist (lift (nar+1) p, args))
+ else
+ let args = extended_rel_list 1 lnames in
+ whd_beta (applist (lift (nar+1) p, args)))))
+ lnames in
+ let fix =
+ RRec (dummy_loc,RFix ([|nar|],0),
+ ([|(id_of_string "F")|],[|typPfix|],[|deffix|])) in
+ RApp (dummy_loc,fix,realargs@[c])
+ (msgerrnl (str "Warning: could't translate Match"); None)
+*)
+ else
+ let rtntypopt, indnalopt = match po with
+ | None -> None, (Anonymous,None)
+ | Some p ->
+ let rec decomp_lam_force n avoid l p =
+ (* avoid is not exhaustive ! *)
+ if n = 0 then (List.rev l,p,avoid) else
+ match p with
+ | RLambda (_,(Name id as na),_,c) ->
+ decomp_lam_force (n-1) (id::avoid) (na::l) c
+ | RLambda (_,(Anonymous as na),_,c) ->
+ decomp_lam_force (n-1) avoid (na::l) c
+ | _ ->
+ let x = Nameops.next_ident_away (id_of_string "x") avoid in
+ decomp_lam_force (n-1) (x::avoid) (Name x :: l)
+ (* eta-expansion *)
+ (RApp (dummy_loc,p, [RVar (dummy_loc,x)])) in
+ let (nal,p,avoid) =
+ decomp_lam_force (List.length realargs) [] [] p in
+ let na,rtntyopt,_ =
+ if dep then decomp_lam_force 1 avoid [] p
+ else [Anonymous],p,[] in
+ let args = List.map (fun _ -> Anonymous) params @ nal in
+ (Some rtntyopt,(List.hd na,Some (dummy_loc,ind,args))) in
+
+ let detype_eqn constr construct_nargs branch =
+ let name_cons = function
+ | Anonymous -> fun l -> l
+ | Name id -> fun l -> id::l in
+ let make_pat na avoid b ids =
+ PatVar (dummy_loc,na),
+ name_cons na avoid,name_cons na ids
+ in
+ let rec buildrec ids patlist avoid n b =
+ if n=0 then
+ (dummy_loc, ids,
+ [PatCstr(dummy_loc, constr, List.rev patlist,Anonymous)],
+ b)
+ else
+ match b with
+ | RLambda (_,x,_,b) ->
+ let pat,new_avoid,new_ids = make_pat x avoid b ids in
+ buildrec new_ids (pat::patlist) new_avoid (n-1) b
+
+ | RLetIn (_,x,_,b) ->
+ let pat,new_avoid,new_ids = make_pat x avoid b ids in
+ buildrec new_ids (pat::patlist) new_avoid (n-1) b
+
+ | RCast (_,c,_) -> (* Oui, il y a parfois des cast *)
+ buildrec ids patlist avoid n c
+
+ | _ -> (* eta-expansion *)
+ (* nommage de la nouvelle variable *)
+ let id = Nameops.next_ident_away (id_of_string "x") avoid in
+ let new_b = RApp (dummy_loc, b, [RVar(dummy_loc,id)])in
+ let pat,new_avoid,new_ids =
+ make_pat (Name id) avoid new_b ids in
+ buildrec new_ids (pat::patlist) new_avoid (n-1) new_b
+
+ in
+ buildrec [] [] [] construct_nargs branch in
+ let (mib,mip) = Inductive.lookup_mind_specif (Global.env()) ind in
+ let get_consnarg j =
+ let typi = mis_nf_constructor_type (ind,mib,mip) (j+1) in
+ let _,t = decompose_prod_n_assum mip.mind_nparams typi in
+ List.rev (fst (decompose_prod_assum t)) in
+ let consnargs = Array.init (Array.length mip.mind_consnames) get_consnarg in
+ let consnargsl = Array.map List.length consnargs in
+ let constructs = Array.init (Array.length lf) (fun i -> (ind,i+1)) in
+ let eqns = array_map3 detype_eqn constructs consnargsl lf in
+ Some (RCases (loc,(po,ref rtntypopt),[c,ref indnalopt],Array.to_list eqns)) in
+ x := c;
+ (* End build the Cases form for v8 *)
{ uj_val = v;
uj_type = rsty }
diff --git a/pretyping/rawterm.ml b/pretyping/rawterm.ml
index 3e13cd861..bdb6914c2 100644
--- a/pretyping/rawterm.ml
+++ b/pretyping/rawterm.ml
@@ -67,10 +67,14 @@ type rawconstr =
| RLambda of loc * name * rawconstr * rawconstr
| RProd of loc * name * rawconstr * rawconstr
| RLetIn of loc * name * rawconstr * rawconstr
- | RCases of loc * rawconstr option * rawconstr list *
+ | RCases of loc * (rawconstr option * rawconstr option ref) *
+ (rawconstr * (name * (loc * inductive * name list) option) ref) list *
(loc * identifier list * cases_pattern list * rawconstr) list
+ (* Rem: "ref" used for the v7->v8 translation only *)
| ROrderedCase of loc * case_style * rawconstr option * rawconstr *
- rawconstr array
+ rawconstr array * rawconstr option ref
+ | RLetTuple of loc * name list * (name * rawconstr option) *
+ rawconstr * rawconstr
| RRec of loc * fix_kind * identifier array *
rawconstr array * rawconstr array
| RSort of loc * rawsort
@@ -78,6 +82,10 @@ type rawconstr =
| RCast of loc * rawconstr * rawconstr
| RDynamic of loc * Dyn.t
+let cases_predicate_names tml =
+ List.flatten (List.map (function
+ | (tm,{contents=(na,None)}) -> [na]
+ | (tm,{contents=(na,Some (_,_,nal))}) -> na::nal) tml)
(*i - if PRec (_, names, arities, bodies) is in env then arities are
typed in env too and bodies are typed in env enriched by the
@@ -96,7 +104,8 @@ let loc = function
| RProd (loc,_,_,_) -> loc
| RLetIn (loc,_,_,_) -> loc
| RCases (loc,_,_,_) -> loc
- | ROrderedCase (loc,_,_,_,_) -> loc
+ | ROrderedCase (loc,_,_,_,_,_) -> loc
+ | RLetTuple (loc,_,_,_,_) -> loc
| RRec (loc,_,_,_,_) -> loc
| RCast (loc,_,_) -> loc
| RSort (loc,_) -> loc
@@ -112,11 +121,14 @@ let map_rawconstr f = function
| RLambda (loc,na,ty,c) -> RLambda (loc,na,f ty,f c)
| RProd (loc,na,ty,c) -> RProd (loc,na,f ty,f c)
| RLetIn (loc,na,b,c) -> RLetIn (loc,na,f b,f c)
- | RCases (loc,tyopt,tml,pl) ->
- RCases (loc,option_app f tyopt,List.map f tml,
+ | RCases (loc,(tyopt,rtntypopt),tml,pl) ->
+ RCases (loc,(option_app f tyopt,ref (option_app f !rtntypopt)),
+ List.map (fun (tm,x) -> (f tm,x)) tml,
List.map (fun (loc,idl,p,c) -> (loc,idl,p,f c)) pl)
- | ROrderedCase (loc,b,tyopt,tm,bv) ->
- ROrderedCase (loc,b,option_app f tyopt,f tm, Array.map f bv)
+ | ROrderedCase (loc,b,tyopt,tm,bv,x) ->
+ ROrderedCase (loc,b,option_app f tyopt,f tm, Array.map f bv,ref (option_app f !x))
+ | RLetTuple (loc,nal,(na,po),b,c) ->
+ RLetTuple (loc,nal,(na,option_app f po),f b,f c)
| RRec (loc,fk,idl,tyl,bv) -> RRec (loc,fk,idl,Array.map f tyl,Array.map f bv)
| RCast (loc,c,t) -> RCast (loc,f c,f t)
| (RSort _ | RHole _ | RRef _ | REvar _ | RPatVar _ | RDynamic _) as x -> x
@@ -202,9 +214,17 @@ let rec subst_raw subst raw =
if r1' == r1 && r2' == r2 then raw else
RLetIn (loc,n,r1',r2')
- | RCases (loc,ro,rl,branches) ->
+ | RCases (loc,(ro,rtno),rl,branches) ->
let ro' = option_smartmap (subst_raw subst) ro
- and rl' = list_smartmap (subst_raw subst) rl
+ and rtno' = ref (option_smartmap (subst_raw subst) !rtno)
+ and rl' = list_smartmap (fun (a,x as y) ->
+ let a' = subst_raw subst a in
+ let (n,topt) = !x in
+ let topt' = option_smartmap
+ (fun (loc,(sp,i),x as t) ->
+ let sp' = subst_kn subst sp in
+ if sp == sp' then t else (loc,(sp',i),x)) topt in
+ if a == a' && topt == topt' then y else (a',ref (n,topt'))) rl
and branches' = list_smartmap
(fun (loc,idl,cpl,r as branch) ->
let cpl' = list_smartmap (subst_pat subst) cpl
@@ -214,15 +234,22 @@ let rec subst_raw subst raw =
branches
in
if ro' == ro && rl' == rl && branches' == branches then raw else
- RCases (loc,ro',rl',branches')
+ RCases (loc,(ro',rtno'),rl',branches')
- | ROrderedCase (loc,b,ro,r,ra) ->
+ | ROrderedCase (loc,b,ro,r,ra,x) ->
let ro' = option_smartmap (subst_raw subst) ro
and r' = subst_raw subst r
and ra' = array_smartmap (subst_raw subst) ra in
if ro' == ro && r' == r && ra' == ra then raw else
- ROrderedCase (loc,b,ro',r',ra')
-
+ ROrderedCase (loc,b,ro',r',ra',x)
+
+ | RLetTuple (loc,nal,(na,po),b,c) ->
+ let po' = option_smartmap (subst_raw subst) po
+ and b' = subst_raw subst b
+ and c' = subst_raw subst c in
+ if po' == po && b' == b && c' == c then raw else
+ RLetTuple (loc,nal,(na,po),b,c)
+
| RRec (loc,fix,ida,ra1,ra2) ->
let ra1' = array_smartmap (subst_raw subst) ra1
and ra2' = array_smartmap (subst_raw subst) ra2 in
@@ -255,7 +282,8 @@ let loc_of_rawconstr = function
| RProd (loc,_,_,_) -> loc
| RLetIn (loc,_,_,_) -> loc
| RCases (loc,_,_,_) -> loc
- | ROrderedCase (loc,_,_,_,_) -> loc
+ | ROrderedCase (loc,_,_,_,_,_) -> loc
+ | RLetTuple (loc,_,_,_,_) -> loc
| RRec (loc,_,_,_,_) -> loc
| RSort (loc,_) -> loc
| RHole (loc,_) -> loc
diff --git a/pretyping/rawterm.mli b/pretyping/rawterm.mli
index fbd01db9a..27bb76b69 100644
--- a/pretyping/rawterm.mli
+++ b/pretyping/rawterm.mli
@@ -65,10 +65,13 @@ type rawconstr =
| RLambda of loc * name * rawconstr * rawconstr
| RProd of loc * name * rawconstr * rawconstr
| RLetIn of loc * name * rawconstr * rawconstr
- | RCases of loc * rawconstr option * rawconstr list *
+ | RCases of loc * (rawconstr option * rawconstr option ref) *
+ (rawconstr * (name * (loc * inductive * name list) option) ref) list *
(loc * identifier list * cases_pattern list * rawconstr) list
| ROrderedCase of loc * case_style * rawconstr option * rawconstr *
- rawconstr array
+ rawconstr array * rawconstr option ref
+ | RLetTuple of loc * name list * (name * rawconstr option) *
+ rawconstr * rawconstr
| RRec of loc * fix_kind * identifier array *
rawconstr array * rawconstr array
| RSort of loc * rawsort
@@ -76,6 +79,9 @@ type rawconstr =
| RCast of loc * rawconstr * rawconstr
| RDynamic of loc * Dyn.t
+val cases_predicate_names :
+ (rawconstr * (name * (loc * inductive * name list) option) ref) list ->
+ name list
(*i - if PRec (_, names, arities, bodies) is in env then arities are
typed in env too and bodies are typed in env enriched by the
diff --git a/states/MakeInitialNew.v b/states/MakeInitialNew.v
index 8a321839b..02235e1b8 100644
--- a/states/MakeInitialNew.v
+++ b/states/MakeInitialNew.v
@@ -5,6 +5,6 @@
(* // * This file is distributed under the terms of the *)
(* * GNU Lesser General Public License Version 2.1 *)
(***********************************************************************)
-Require Export Prelude;
-Require Export Logic_Type;
-Require Export Logic_TypeSyntax;
+Require Export Prelude.
+Require Export Logic_Type.
+Require Export Logic_TypeSyntax.
diff --git a/tactics/eauto.ml4 b/tactics/eauto.ml4
index 2bd30c5eb..ddd5e4220 100644
--- a/tactics/eauto.ml4
+++ b/tactics/eauto.ml4
@@ -358,7 +358,7 @@ open Genarg
let pr_hintbases _prc _prt = function
| None -> str " with *"
| Some [] -> mt ()
- | Some l -> str " with " ++ Util.prlist str l
+ | Some l -> str " with " ++ Util.prlist_with_sep spc str l
ARGUMENT EXTEND hintbases
TYPED AS preident_list_opt
diff --git a/tactics/extraargs.ml4 b/tactics/extraargs.ml4
index 37b8b3356..2a2db30f8 100644
--- a/tactics/extraargs.ml4
+++ b/tactics/extraargs.ml4
@@ -19,7 +19,9 @@ open Genarg
let _ = Metasyntax.add_token_obj "<-"
let _ = Metasyntax.add_token_obj "->"
-let pr_orient _prc _prt = function true -> Pp.str " ->" | false -> Pp.str " <-"
+let pr_orient _prc _prt = function
+ | true -> Pp.mt ()
+ | false -> Pp.str " <-"
ARGUMENT EXTEND orient TYPED AS bool PRINTED BY pr_orient
| [ "->" ] -> [ true ]
diff --git a/tactics/tacinterp.ml b/tactics/tacinterp.ml
index 9462a7423..2efdabafc 100644
--- a/tactics/tacinterp.ml
+++ b/tactics/tacinterp.ml
@@ -408,8 +408,14 @@ let intern_constr {ltacvars=lfun; gsigma=sigma; genv=env} c =
let warn = if !strict_check then fun x -> x else Constrintern.for_grammar in
let c' =
warn (Constrintern.interp_rawconstr_gen false sigma env []
- false (fst lfun,[])) c
- in (c',if !strict_check then None else Some c)
+ false (fst lfun,[])) c in
+ begin if Options.do_translate () then try
+ (* Try to infer old case and type annotations *)
+ let _ = Pretyping.understand_gen_tcc sigma env [] None c' in
+ (* msgerrnl (str "Typage tactique OK");*)
+ ()
+ with e -> (*msgerrnl (str "Warning: can't type tactic");*) () end;
+ (c',if !strict_check then None else Some c)
(* Globalize bindings *)
let intern_binding ist (loc,b,c) =
@@ -2014,7 +2020,7 @@ let make_empty_glob_sign () =
gsigma = Evd.empty; genv = Global.env() }
let add_tacdef isrec tacl =
- let isrec = if !Options.p1 then isrec else true in
+(* let isrec = if !Options.p1 then isrec else true in*)
let rfun = List.map (fun ((loc,id as locid),_) -> (id,make_absolute_name locid)) tacl in
let ist =
{(make_empty_glob_sign()) with ltacrecvars = if isrec then rfun else []} in
diff --git a/toplevel/toplevel.ml b/toplevel/toplevel.ml
index 33f8e488f..399134d11 100644
--- a/toplevel/toplevel.ml
+++ b/toplevel/toplevel.ml
@@ -237,13 +237,10 @@ let print_toplevel_error exc =
(if is_pervasive_exn exc then (mt ()) else locstrm) ++
Cerrors.explain_exn exc
-let is_term s =
- if !Options.v7 then s="." else s=";"
-
(* Read the input stream until a dot is encountered *)
let parse_to_dot =
let rec dot st = match Stream.next st with
- | ("", c) when is_term c -> ()
+ | ("", ".") -> ()
| ("EOI", "") -> raise End_of_input
| _ -> dot st
in
diff --git a/toplevel/vernacentries.ml b/toplevel/vernacentries.ml
index 1d2ccecbb..2b3b05b30 100644
--- a/toplevel/vernacentries.ml
+++ b/toplevel/vernacentries.ml
@@ -159,7 +159,7 @@ let show_intro all =
(* "Print" commands *)
let print_path_entry (s,l) =
- (str s ++ tbrk (0,2) ++ str (string_of_dirpath l))
+ (str s ++ str " " ++ tbrk (0,2) ++ str (string_of_dirpath l))
let print_loadpath () =
let l = Library.get_full_load_path () in
@@ -703,7 +703,7 @@ let vernac_syntactic_definition id c = function
| None -> syntax_definition id c
| Some n ->
let l = list_tabulate (fun _ -> (CHole (dummy_loc),None)) n in
- let c = CApp (dummy_loc,(false,c),l) in
+ let c = CApp (dummy_loc,(None,c),l) in
syntax_definition id c
let vernac_declare_implicits locqid = function
@@ -1172,7 +1172,7 @@ let interp c = match c with
| VernacEndSegment id -> vernac_end_segment id
- | VernacRecord (id,bl,s,idopt,fs) -> vernac_record id bl s idopt fs
+ | VernacRecord (_,id,bl,s,idopt,fs) -> vernac_record id bl s idopt fs
| VernacRequire (export,spec,qidl) -> vernac_require export spec qidl
| VernacImport (export,qidl) -> vernac_import export qidl
| VernacCanonical qid -> vernac_canonical qid
diff --git a/toplevel/vernacexpr.ml b/toplevel/vernacexpr.ml
index e03658cfd..266e6c094 100644
--- a/toplevel/vernacexpr.ml
+++ b/toplevel/vernacexpr.ml
@@ -183,7 +183,8 @@ type vernac_expr =
| VernacScheme of (identifier * bool * reference * sort_expr) list
(* Gallina extensions *)
- | VernacRecord of identifier with_coercion * simple_binder list
+ | VernacRecord of bool (* = Record or Structure *)
+ * identifier with_coercion * simple_binder list
* constr_expr * identifier option * local_decl_expr with_coercion list
| VernacBeginSection of identifier
| VernacEndSegment of identifier
diff --git a/translate/ppconstrnew.ml b/translate/ppconstrnew.ml
index f8af13256..6d3974069 100644
--- a/translate/ppconstrnew.ml
+++ b/translate/ppconstrnew.ml
@@ -95,7 +95,7 @@ let pr_expl_args pr (a,expl) =
let pr_opt_type pr = function
| CHole _ -> mt ()
- | t -> cut () ++ str ":" ++ pr (if !Options.p1 then ltop else (latom,E)) t
+ | t -> cut () ++ str ":" ++ pr t
let pr_opt_type_spc pr = function
| CHole _ -> mt ()
@@ -103,7 +103,7 @@ let pr_opt_type_spc pr = function
let pr_name = function
| Anonymous -> str"_"
- | Name id -> pr_id id
+ | Name id -> pr_id (Constrextern.v7_to_v8_id id)
let pr_located pr (loc,x) = pr x
@@ -139,67 +139,66 @@ let pr_binder pr (nal,t) =
prlist_with_sep sep (pr_located pr_name) nal ++
pr_opt_type pr t)
*)
-(* Option 1a *)
-let pr_oneb pr t na =
- match t with
- CHole _ -> pr_located pr_name na
- | _ -> hov 1
- (str "(" ++ pr_located pr_name na ++ pr_opt_type pr t ++ str ")")
-let pr_binder1 pr (nal,t) =
- hov 0 (prlist_with_sep sep (pr_oneb pr t) nal)
-let pr_binders1 pr bl =
- hv 0 (prlist_with_sep sep (pr_binder1 pr) bl)
+let surround p = str"(" ++ p ++ str")"
-(* Option 1b *)
-let pr_binder1 pr (nal,t) =
+let pr_binder many pr (nal,t) =
match t with
- CHole _ -> prlist_with_sep sep (pr_located pr_name) nal
- | _ -> hov 1
- (str "(" ++ prlist_with_sep sep (pr_located pr_name) nal ++ str ":" ++
- pr ltop t ++ str ")")
-
-let pr_binders1 pr bl =
- hv 0 (prlist_with_sep sep (pr_binder1 pr) bl)
-
-let pr_opt_type' pr = function
- | CHole _ -> mt ()
- | t -> cut () ++ str ":" ++ pr (latom,E) t
-
-let pr_prod_binders1 pr = function
-(* | [nal,t] -> hov 1 (prlist_with_sep sep (pr_located pr_name) nal ++ pr_opt_type' pr t)*)
- | bl -> pr_binders1 pr bl
+ CHole _ ->
+ prlist_with_sep sep (pr_located pr_name) nal
+ | _ ->
+ let s =
+ (prlist_with_sep sep (pr_located pr_name) nal ++ str ":" ++ pr t) in
+ hov 1 (if many then surround s else s)
+
+let pr_binder_among_many pr_c = function
+ | LocalRawAssum (nal,t) ->
+ pr_binder true pr_c (nal,t)
+ | LocalRawDef (na,c) ->
+ let c,topt = match c with
+ | CCast(_,c,t) -> c, t
+ | _ -> c, CHole dummy_loc in
+ hov 1 (surround
+ (pr_located pr_name na ++ pr_opt_type pr_c topt ++
+ str":=" ++ cut() ++ pr_c c))
+
+let pr_undelimited_binders pr_c =
+ prlist_with_sep sep (pr_binder_among_many pr_c)
+
+let pr_delimited_binders pr_c = function
+ | [LocalRawAssum (nal,t)] -> pr_binder false pr_c (nal,t)
+ | LocalRawAssum _ :: _ as bdl -> pr_undelimited_binders pr_c bdl
+ | _ -> assert false
-(* Option 2 *)
let pr_let_binder pr x a =
hov 0 (hov 0 (pr_name x ++ brk(0,1) ++ str ":=") ++ brk(0,1) ++ pr ltop a)
-let pr_binder2 pr (nal,t) =
- hov 0 (
- prlist_with_sep sep (pr_located pr_name) nal ++
- pr_opt_type pr t)
-
-let pr_binders2 pr bl =
- hv 0 (prlist_with_sep sep (pr_binder2 pr) bl)
-
-let pr_prod_binder2 pr (nal,t) =
- str "forall " ++ hov 0 (
- prlist_with_sep sep (pr_located pr_name) nal ++
- pr_opt_type pr t) ++ str ","
-
-let pr_prod_binders2 pr bl =
- hv 0 (prlist_with_sep sep (pr_prod_binder2 pr) bl)
-
-(**)
-let pr_binders pr = (if !Options.p1 then pr_binders1 else pr_binders2) pr
-let pr_prod_binders pr bl =
- if !Options.p1 then
- str "!" ++ pr_prod_binders1 pr bl ++ str "."
- else
- pr_prod_binders2 pr bl
-
+let rec extract_prod_binders = function
+ | CLetIn (loc,na,b,c) ->
+ let bl,c = extract_prod_binders c in
+ LocalRawDef (na,b) :: bl, c
+ | CProdN (loc,[],c) ->
+ extract_prod_binders c
+ | CProdN (loc,(nal,t)::bl,c) ->
+ let bl,c = extract_prod_binders (CProdN(loc,bl,c)) in
+ LocalRawAssum (nal,t) :: bl, c
+ | c -> [], c
+
+let rec extract_lam_binders = function
+ | CLetIn (loc,na,b,c) ->
+ let bl,c = extract_lam_binders c in
+ LocalRawDef (na,b) :: bl, c
+ | CLambdaN (loc,[],c) ->
+ extract_lam_binders c
+ | CLambdaN (loc,(nal,t)::bl,c) ->
+ let bl,c = extract_lam_binders (CLambdaN(loc,bl,c)) in
+ LocalRawAssum (nal,t) :: bl, c
+ | c -> [], c
+
+(*
let pr_arg_binders pr bl =
if bl = [] then mt() else (spc() ++ pr_binders pr bl)
+*)
let pr_global vars ref =
(* pr_global_env vars ref *)
@@ -212,106 +211,20 @@ let split_lambda = function
| CLambdaN (loc,(na::nal,t)::bl,c) -> (na,t,CLambdaN(loc,(nal,t)::bl,c))
| _ -> anomaly "ill-formed fixpoint body"
-let split_product = function
- | CArrow (loc,t,c) -> ((loc,Anonymous),t,c)
- | CProdN (loc,[[na],t],c) -> (na,t,c)
- | CProdN (loc,([na],t)::bl,c) -> (na,t,CProdN(loc,bl,c))
- | CProdN (loc,(na::nal,t)::bl,c) -> (na,t,CProdN(loc,(nal,t)::bl,c))
+let rename na na' t c =
+ match (na,na') with
+ | (_,Name id), (_,Name id') -> (na',t,replace_vars_constr_expr [id,id'] c)
+ | (_,Name id), (_,Anonymous) -> (na,t,c)
+ | _ -> (na',t,c)
+
+let split_product na' = function
+ | CArrow (loc,t,c) -> (na',t,c)
+ | CProdN (loc,[[na],t],c) -> rename na na' t c
+ | CProdN (loc,([na],t)::bl,c) -> rename na na' t (CProdN(loc,bl,c))
+ | CProdN (loc,(na::nal,t)::bl,c) ->
+ rename na na' t (CProdN(loc,(nal,t)::bl,c))
| _ -> anomaly "ill-formed fixpoint body"
-let rec extract_lam_binders c =
- match c with
- CLambdaN(loc,bl1,c') ->
- let (bl,bd) = extract_lam_binders c' in
- (bl1@bl, bd)
- | _ -> ([],c)
-
-let rec extract_prod_binders c =
- match c with
- CProdN(loc,bl1,c') ->
- let (bl,bd) = extract_prod_binders c' in
- (bl1@bl, bd)
- | _ -> ([],c)
-
-let rec check_same_pattern p1 p2 =
- match p1, p2 with
- | CPatAlias(_,a1,i1), CPatAlias(_,a2,i2) when i1=i2 ->
- check_same_pattern a1 a2
- | CPatCstr(_,c1,a1), CPatCstr(_,c2,a2) when c1=c2 ->
- List.iter2 check_same_pattern a1 a2
- | CPatAtom(_,r1), CPatAtom(_,r2) when r1=r2 -> ()
- | CPatNumeral(_,i1), CPatNumeral(_,i2) when i1=i2 -> ()
- | CPatDelimiters(_,s1,e1), CPatDelimiters(_,s2,e2) when s1=s2 ->
- check_same_pattern e1 e2
- | _ -> failwith "not same pattern"
-
-let check_same_ref r1 r2 =
- match r1,r2 with
- | Qualid(_,q1), Qualid(_,q2) when q1=q2 -> ()
- | Ident(_,i1), Ident(_,i2) when i1=i2 -> ()
- | _ -> failwith "not same ref"
-
-let rec check_same_type ty1 ty2 =
- match ty1, ty2 with
- | CRef r1, CRef r2 -> check_same_ref r1 r2
- | CFix(_,(_,id1),fl1), CFix(_,(_,id2),fl2) when id1=id2 ->
- List.iter2 (fun (id1,i1,a1,b1) (id2,i2,a2,b2) ->
- if id1<>id2 || i1<>i2 then failwith "not same fix";
- check_same_type a1 a2;
- check_same_type b1 b2)
- fl1 fl2
- | CCoFix(_,(_,id1),fl1), CCoFix(_,(_,id2),fl2) when id1=id2 ->
- List.iter2 (fun (id1,a1,b1) (id2,a2,b2) ->
- if id1<>id2 then failwith "not same fix";
- check_same_type a1 a2;
- check_same_type b1 b2)
- fl1 fl2
- | CArrow(_,a1,b1), CArrow(_,a2,b2) ->
- check_same_type a1 a2;
- check_same_type b1 b2
- | CProdN(_,bl1,a1), CProdN(_,bl2,a2) ->
- List.iter2 check_same_binder bl1 bl2;
- check_same_type a1 a2
- | CLambdaN(_,bl1,a1), CLambdaN(_,bl2,a2) ->
- List.iter2 check_same_binder bl1 bl2;
- check_same_type a1 a2
- | CLetIn(_,(_,na1),a1,b1), CLetIn(_,(_,na2),a2,b2) when na1=na2 ->
- check_same_type a1 a2;
- check_same_type b1 b2
- | CAppExpl(_,r1,al1), CAppExpl(_,r2,al2) when r1=r2 ->
- List.iter2 check_same_type al1 al2
- | CApp(_,(_,e1),al1), CApp(_,(_,e2),al2) ->
- check_same_type e1 e2;
- List.iter2 (fun (a1,e1) (a2,e2) ->
- if e1<>e2 then failwith "not same expl";
- check_same_type a1 a2) al1 al2
- | CCases(_,_,a1,brl1), CCases(_,_,a2,brl2) ->
- List.iter2 check_same_type a1 a2;
- List.iter2 (fun (_,pl1,r1) (_,pl2,r2) ->
- List.iter2 check_same_pattern pl1 pl2;
- check_same_type r1 r2) brl1 brl2
- | COrderedCase(_,_,_,a1,bl1), COrderedCase(_,_,_,a2,bl2) ->
- check_same_type a1 a2;
- List.iter2 check_same_type bl1 bl2
- | CHole _, CHole _ -> ()
- | CPatVar(_,i1), CPatVar(_,i2) when i1=i2 -> ()
- | CSort(_,s1), CSort(_,s2) when s1=s2 -> ()
- | CCast(_,a1,b1), CCast(_,a2,b2) ->
- check_same_type a1 a2;
- check_same_type b1 b2
- | CNotation(_,n1,e1), CNotation(_,n2,e2) when n1=n2 ->
- List.iter2 check_same_type e1 e2
- | CNumeral(_,i1), CNumeral(_,i2) when i1=i2 -> ()
- | CDelimiters(_,s1,e1), CDelimiters(_,s2,e2) when s1=s2 ->
- check_same_type e1 e2
- | _ when ty1=ty2 -> ()
- | _ -> failwith "not same type"
-
-and check_same_binder (nal1,e1) (nal2,e2) =
- List.iter2 (fun (_,na1) (_,na2) ->
- if na1<>na2 then failwith "not same name") nal1 nal2;
- check_same_type e1 e2
-
let merge_binders (na1,ty1) (na2,ty2) =
let na =
match snd na1, snd na2 with
@@ -325,9 +238,9 @@ let merge_binders (na1,ty1) (na2,ty2) =
CHole _, _ -> ty2
| _, CHole _ -> ty1
| _ ->
- check_same_type ty1 ty2;
+ Constrextern.check_same_type ty1 ty2;
ty2 in
- ([na],ty)
+ LocalRawAssum ([na],ty)
let rec strip_domain bvar c =
match c with
@@ -358,13 +271,15 @@ let rec strip_domains (nal,ty) c =
(* Re-share binders *)
let rec factorize_binders = function
| ([] | [_] as l) -> l
- | (nal,ty)::((nal',ty')::l as l') ->
- try
- let _ = check_same_type ty ty' in
- factorize_binders ((nal@nal',ty)::l)
+ | LocalRawAssum (nal,ty) as d :: (LocalRawAssum (nal',ty')::l as l') ->
+ (try
+ let _ = Constrextern.check_same_type ty ty' in
+ factorize_binders (LocalRawAssum (nal@nal',ty)::l)
with _ ->
- (nal,ty) :: factorize_binders l'
+ d :: factorize_binders l')
+ | d :: l -> d :: factorize_binders l
+(* Extrac lambdas when a type constraint occurs *)
let rec extract_def_binders c ty =
match c with
| CLambdaN(loc,bvar::lams,b) ->
@@ -385,24 +300,29 @@ let rec split_fix n typ def =
if n = 0 then ([],typ,def)
else
let (na,_,def) = split_lambda def in
- let (_,t,typ) = split_product typ in
+ let (na,t,typ) = split_product na typ in
let (bl,typ,def) = split_fix (n-1) typ def in
- (([na],t)::bl,typ,def)
+ (LocalRawAssum ([na],t)::bl,typ,def)
let pr_recursive_decl pr id b t c =
pr_id id ++ b ++ pr_opt_type_spc pr t ++ str " :=" ++
brk(1,2) ++ pr ltop c
+let name_of_binder = function
+ | LocalRawAssum (nal,_) -> nal
+ | LocalRawDef (_,_) -> []
+
let pr_fixdecl pr (id,n,t0,c0) =
let (bl,t,c) = extract_def_binders t0 c0 in
let (bl,t,c) =
if List.length bl <= n then split_fix (n+1) t0 c0 else (bl,t,c) in
let annot =
- let ids = List.flatten (List.map fst bl) in
+ let ids = List.flatten (List.map name_of_binder bl) in
if List.length ids > 1 then
spc() ++ str "{struct " ++ pr_name (snd (list_last ids)) ++ str"}"
else mt() in
- pr_recursive_decl pr id (str" " ++ hov 0 (pr_binders pr bl) ++ annot) t c
+ pr_recursive_decl pr id
+ (str" " ++ hov 0 (pr_undelimited_binders (pr ltop) bl) ++ annot) t c
let pr_cofixdecl pr (id,t,c) =
pr_recursive_decl pr id (mt ()) t c
@@ -414,15 +334,35 @@ let pr_recursive pr_decl id = function
prlist_with_sep (fun () -> fnl() ++ str "with ") pr_decl dl ++
fnl() ++ str "for " ++ pr_id id
-let pr_annotation pr po =
- match po with
- None -> mt()
- | Some p -> spc() ++ str "=> " ++ hov 0 (pr ltop p)
+let pr_arg pr x = spc () ++ pr x
-let pr_annotation2 pr po =
+let is_var id = function
+ | CRef (Ident (_,id')) when id=id' -> true
+ | _ -> false
+
+let pr_case_item pr (tm,(na,indnalopt)) =
+ hov 0 (pr (lcast,E) tm ++
+ (match na with
+ | Name id when not (is_var id tm) -> spc () ++ str "as " ++ pr_id id
+ | _ -> mt ()) ++
+ (match indnalopt with
+ | None -> mt ()
+ | Some (_,ind,nal) ->
+ spc () ++ str "in " ++
+ hov 0 (pr_reference ind ++ prlist (pr_arg pr_name) nal)))
+
+let pr_case_type pr po =
match po with
- None -> mt()
- | Some p -> spc() ++ str "of type " ++ hov 0 (pr ltop p)
+ | None | Some (CHole _) -> mt()
+ | Some p -> spc() ++ str "return " ++ hov 0 (pr (lcast,E) p)
+
+let pr_return_type pr po = pr_case_type pr po
+
+let pr_simple_return_type pr na po =
+ (match na with
+ | Name id -> spc () ++ str "as " ++ pr_id id
+ | _ -> mt ()) ++
+ pr_case_type pr po
let pr_proj pr pr_app a f l =
hov 0 (pr lsimple a ++ cut() ++ str ".(" ++ pr_app pr f l ++ str ")")
@@ -451,57 +391,68 @@ let rec pr inherited a =
larrow
| CProdN _ ->
let (bl,a) = extract_prod_binders a in
- hv 0 (pr_prod_binders pr bl ++ spc() ++ pr ltop a),
+ hov 2 (
+ str"forall" ++ spc() ++ pr_delimited_binders (pr ltop) bl ++
+ str "," ++ spc() ++ pr ltop a),
lprod
| CLambdaN _ ->
let (bl,a) = extract_lam_binders a in
- let left, mid = str"fun" ++ spc(), " =>" in
hov 2 (
- left ++ pr_binders pr bl ++
- str mid ++ spc() ++ pr ltop a),
+ str"fun" ++ spc() ++ pr_delimited_binders (pr ltop) bl ++
+ str " =>" ++ spc() ++ pr ltop a),
llambda
| CLetIn (_,x,a,b) ->
- let (bl,a) = extract_lam_binders a in
hv 0 (
- hov 2 (str "let " ++ pr_located pr_name x ++
- pr_arg_binders pr bl ++ str " :=" ++ spc() ++
+ hov 2 (str "let " ++ pr_located pr_name x ++ str " :=" ++ spc() ++
pr ltop a ++ str " in") ++
spc () ++ pr ltop b),
lletin
- | CAppExpl (_,(true,f),l) ->
- let a,l = list_sep_last l in
- pr_proj pr pr_appexpl a f l, lapp
- | CAppExpl (_,(false,f),l) -> pr_appexpl pr f l, lapp
- | CApp (_,(true,a),l) ->
- let c,l = list_sep_last l in
+ | CAppExpl (_,(Some i,f),l) ->
+ let l1,l2 = list_chop i l in
+ let c,l1 = list_sep_last l1 in
+ pr_proj pr pr_appexpl c f l1 ++
+ prlist (fun a -> spc () ++ pr (lapp,L) a) l2, lapp
+ | CAppExpl (_,(None,f),l) -> pr_appexpl pr f l, lapp
+ | CApp (_,(Some i,f),l) ->
+ let l1,l2 = list_chop i l in
+ let c,l1 = list_sep_last l1 in
assert (snd c = None);
- pr_proj pr pr_app (fst c) a l, lapp
- | CApp (_,(false,a),l) -> pr_app pr a l, lapp
- | CCases (_,po,c,eqns) ->
+ pr_proj pr pr_app (fst c) f l1 ++
+ prlist (fun a -> spc () ++ pr_expl_args pr a) l2, lapp
+ | CApp (_,(None,a),l) -> pr_app pr a l, lapp
+ | CCases (_,(po,rtntypopt),c,eqns) ->
v 0
- (hov 4 (str "match " ++ prlist_with_sep sep_v (pr ltop) c ++
- (if !Options.p1 then pr_annotation pr po else mt ()) ++
- str " with") ++
- prlist (pr_eqn pr) eqns ++
- (if !Options.p1 then mt () else pr_annotation2 pr po)
- ++ spc() ++
- str "end"),
+ (hov 4 (str "match " ++ prlist_with_sep sep_v (pr_case_item pr) c
+ ++ pr_case_type pr rtntypopt ++ str " with") ++
+ prlist (pr_eqn pr) eqns ++ spc() ++ str "end"),
latom
- | COrderedCase (_,_,po,c,[b1;b2]) ->
+ | CLetTuple (_,nal,(na,po),c,b) ->
+ hv 0 (
+ str "let " ++
+ hov 0 (str "(" ++
+ prlist_with_sep sep_v pr_name nal ++
+ str ")" ++
+ pr_simple_return_type pr na po ++ str " :=" ++
+ spc() ++ pr ltop c ++ str " in") ++
+ spc() ++ pr ltop b),
+ lletin
+
+
+ | COrderedCase (_,st,po,c,[b1;b2]) when st = IfStyle ->
(* On force les parenthèses autour d'un "if" sous-terme (même si le
parsing est lui plus tolérant) *)
hv 0 (
- str "if " ++ pr ltop c ++ pr_annotation pr po ++ spc () ++
+ hov 1 (str "if " ++ pr ltop c ++ pr_return_type pr po) ++ spc () ++
hov 0 (str "then" ++ brk (1,1) ++ pr ltop b1) ++ spc () ++
hov 0 (str "else" ++ brk (1,1) ++ pr ltop b2)),
lif
- | COrderedCase (_,_,po,c,[CLambdaN(_,[nal,_],b)]) ->
+ | COrderedCase (_,st,po,c,[CLambdaN(_,[nal,_],b)]) when st = LetStyle ->
hv 0 (
str "let " ++
hov 0 (str "(" ++
prlist_with_sep sep_v (fun (_,n) -> pr_name n) nal ++
str ")" ++
- pr_annotation pr po ++ str " :=" ++
+ pr_return_type pr po ++ str " :=" ++
spc() ++ pr ltop c ++ str " in") ++
spc() ++ pr ltop b),
lletin
@@ -509,7 +460,7 @@ let rec pr inherited a =
hv 0 (
str (if style=MatchStyle then "old_match " else "match ") ++
pr ltop c ++
- pr_annotation pr po ++
+ pr_return_type pr po ++
str " with" ++ brk (1,0) ++
hov 0 (prlist
(fun b -> str "| ??? =>" ++ spc() ++ pr ltop b ++ fnl ()) bl) ++
@@ -530,21 +481,40 @@ let rec pr inherited a =
if prec_less prec inherited then strm
else str"(" ++ strm ++ str")"
-let transf env vars c =
+let rec strip_context n iscast t =
+ if n = 0 then
+ if iscast then match t with RCast (_,c,_) -> c | _ -> t else t
+ else match t with
+ | RLambda (_,_,_,c) -> strip_context (n-1) iscast c
+ | RProd (_,_,_,c) -> strip_context (n-1) iscast c
+ | RLetIn (_,_,_,c) -> strip_context (n-1) iscast c
+ | RCast (_,c,_) -> strip_context n false c
+ | _ -> anomaly "ppconstrnew: strip_context"
+
+let transf env n iscast c =
if Options.do_translate() then
- Constrextern.extern_rawconstr (Termops.vars_of_env env)
- (Constrintern.for_grammar
+ let r =
+ Constrintern.for_grammar
(Constrintern.interp_rawconstr_gen false Evd.empty env [] false
- (vars,[]))
- c)
+ ([],[]))
+ c in
+ begin try
+ (* Try to infer old case and type annotations *)
+ let _ = Pretyping.understand_gen_tcc Evd.empty env [] None r in
+ (*msgerrnl (str "Typage OK");*) ()
+ with e -> (*msgerrnl (str "Warning: can't type")*) () end;
+ Constrextern.extern_rawconstr (Termops.vars_of_env env)
+ (strip_context n iscast r)
else c
-let pr_constr_env env c = pr lsimple (transf env [] c)
-let pr_lconstr_env env c = pr ltop (transf env [] c)
+let pr_constr_env env c = pr lsimple (transf env 0 false c)
+let pr_lconstr_env env c = pr ltop (transf env 0 false c)
let pr_constr c = pr_constr_env (Global.env()) c
let pr_lconstr c = pr_lconstr_env (Global.env()) c
-let pr_lconstr_vars vars c = pr ltop (transf (Global.env()) vars c)
+let pr_lconstr_env_n env n b c = pr ltop (transf env n b c)
+
+let pr_binders = pr_undelimited_binders pr_lconstr
let transf_pattern env c =
if Options.do_translate() then
@@ -561,24 +531,10 @@ let pr_rawconstr_env env c =
let pr_lrawconstr_env env c =
pr_lconstr (Constrextern.extern_rawconstr (Termops.vars_of_env env) c)
-let anonymize_binder na c =
- if Options.do_translate() then
- Constrextern.extern_rawconstr (Termops.vars_of_env (Global.env()))
- (Reserve.anonymize_if_reserved na
- (Constrintern.for_grammar
- (Constrintern.interp_rawconstr Evd.empty (Global.env())) c))
- else c
-
-let pr_binders l =
- prlist_with_sep sep
- (fun (nal,t) -> prlist_with_sep sep
- (fun (_,na as x) -> pr_oneb pr (anonymize_binder na t) x) nal) l
-
let pr_cases_pattern = pr_patt ltop
let pr_occurrences prc (nl,c) =
- prlist (fun n -> int n ++ spc ()) nl ++
- str"(" ++ prc c ++ str")"
+ prc c ++ prlist (fun n -> spc () ++ int n) nl
let pr_qualid qid = str (string_of_qualid qid)
@@ -604,7 +560,7 @@ let pr_metaid id = str"?" ++ pr_id id
let pr_red_expr (pr_constr,pr_lconstr,pr_ref) = function
| Red false -> str "red"
| Hnf -> str "hnf"
- | Simpl o -> str "simpl" ++ pr_opt (pr_occurrences pr_lconstr) o
+ | Simpl o -> str "simpl" ++ pr_opt (pr_occurrences pr_constr) o
| Cbv f ->
if f = {rBeta=true;rIota=true;rZeta=true;rDelta=true;rConst=[]} then
str "compute"
@@ -613,12 +569,13 @@ let pr_red_expr (pr_constr,pr_lconstr,pr_ref) = function
| Lazy f ->
hov 1 (str "lazy" ++ pr_red_flag pr_ref f)
| Unfold l ->
- hov 1 (str "unfold" ++
- prlist (fun (nl,qid) ->
- prlist (pr_arg int) nl ++ spc () ++ pr_ref qid) l)
+ hov 1 (str "unfold " ++
+ prlist_with_sep pr_coma (fun (nl,qid) ->
+ pr_ref qid ++ prlist (pr_arg int) nl) l)
| Fold l -> hov 1 (str "fold" ++ prlist (pr_arg pr_constr) l)
| Pattern l ->
- hov 1 (str "pattern" ++ pr_arg (prlist (pr_occurrences pr_lconstr)) l)
+ hov 1 (str "pattern" ++
+ pr_arg (prlist_with_sep pr_coma (pr_occurrences pr_constr)) l)
| Red true -> error "Shouldn't be accessible from user"
| ExtraRedExpr (s,c) ->
diff --git a/translate/ppconstrnew.mli b/translate/ppconstrnew.mli
index cb2a1a677..40b122520 100644
--- a/translate/ppconstrnew.mli
+++ b/translate/ppconstrnew.mli
@@ -22,15 +22,16 @@ open Util
open Genarg
val extract_lam_binders :
- constr_expr -> (name located list * constr_expr) list * constr_expr
+ constr_expr -> local_binder list * constr_expr
val extract_prod_binders :
- constr_expr -> (name located list * constr_expr) list * constr_expr
+ constr_expr -> local_binder list * constr_expr
val extract_def_binders :
constr_expr -> constr_expr ->
- (name located list * constr_expr) list * constr_expr * constr_expr
+ local_binder list * constr_expr * constr_expr
val split_fix :
int -> constr_expr -> constr_expr ->
- (name located list * constr_expr) list * constr_expr * constr_expr
+ local_binder list * constr_expr * constr_expr
+val pr_binders : local_binder list -> std_ppcmds
val prec_less : int -> int * Ppextend.parenRelation -> bool
@@ -50,9 +51,8 @@ val pr_constr : constr_expr -> std_ppcmds
val pr_lconstr : constr_expr -> std_ppcmds
val pr_constr_env : env -> constr_expr -> std_ppcmds
val pr_lconstr_env : env -> constr_expr -> std_ppcmds
-val pr_lconstr_vars : identifier list -> constr_expr -> std_ppcmds
+val pr_lconstr_env_n : env -> int -> bool -> constr_expr -> std_ppcmds
val pr_cases_pattern : cases_pattern_expr -> std_ppcmds
-val pr_binders : (name located list * constr_expr) list -> std_ppcmds
val pr_may_eval :
('a -> std_ppcmds) -> ('a -> std_ppcmds) -> ('b -> std_ppcmds) -> ('a,'b) may_eval
-> std_ppcmds
diff --git a/translate/pptacticnew.ml b/translate/pptacticnew.ml
index 6801aef28..80ac96492 100644
--- a/translate/pptacticnew.ml
+++ b/translate/pptacticnew.ml
@@ -23,6 +23,8 @@ open Genarg
open Libnames
open Pptactic
+let pr_id id = pr_id (Constrextern.v7_to_v8_id id)
+
let pr_arg pr x = spc () ++ pr x
let pr_ltac_constant sp = pr_qualid (Nametab.shortest_qualid_of_tactic sp)
@@ -48,7 +50,8 @@ let pr_binding prc = function
let pr_esubst prc l =
let pr_qhyp = function
(_,AnonHyp n,c) -> str "(" ++ int n ++ str" := " ++ prc c ++ str ")"
- | (_,NamedHyp id,c) -> str "(" ++ pr_id id ++ str" := " ++ prc c ++ str ")"
+ | (_,NamedHyp id,c) ->
+ str "(" ++ pr_id id ++ str" := " ++ prc c ++ str ")"
in
prlist_with_sep spc pr_qhyp l
@@ -171,8 +174,7 @@ let rec pr_tacarg_using_rule pr_gen = function
| [], [] -> mt ()
| _ -> failwith "Inconsistent arguments of extended tactic"
-let pr_then () =
- if !Options.p1 then str " &" else str ";"
+let pr_then () = str ";"
open Closure
diff --git a/translate/ppvernacnew.ml b/translate/ppvernacnew.ml
index 95055c43c..f8ece8cea 100644
--- a/translate/ppvernacnew.ml
+++ b/translate/ppvernacnew.ml
@@ -37,8 +37,20 @@ let pr_reference r =
try match Nametab.extended_locate (snd (qualid_of_reference r)) with
| TrueGlobal ref ->
pr_reference (Constrextern.extern_reference dummy_loc Idset.empty ref)
- | SyntacticDef sp ->
- pr_reference r
+ | SyntacticDef kn ->
+ let is_coq_root d =
+ let d = repr_dirpath d in
+ d <> [] & string_of_id (list_last d) = "Coq" in
+ let dir,id = repr_path (sp_of_syntactic_definition kn) in
+ let r =
+ if (is_coq_root (Lib.library_dp()) or is_coq_root dir) then
+ (match string_of_id id with
+ | "refl_eqT" ->
+ Constrextern.extern_reference dummy_loc Idset.empty
+ (reference_of_constr (Coqlib.build_coq_eq_data ()).Coqlib.refl)
+ | _ -> r)
+ else r
+ in pr_reference r
with Not_found ->
error_global_not_found (snd (qualid_of_reference r))
@@ -96,6 +108,12 @@ let pr_entry_prec = function
| Some Gramext.NonA -> str"NONA "
| None -> mt()
+let pr_prec = function
+ | Some Gramext.LeftA -> str", left associativity"
+ | Some Gramext.RightA -> str", right associativity"
+ | Some Gramext.NonA -> str", no associativity"
+ | None -> mt()
+
let pr_set_entry_type = function
| ETIdent -> str"ident"
| ETReference -> str"global"
@@ -132,8 +150,8 @@ let pr_search a b pr_c = match a with
let pr_locality local = if local then str "Local " else str ""
let pr_class_rawexpr = function
- | FunClass -> str"FUNCLASS"
- | SortClass -> str"SORTCLASS"
+ | FunClass -> str"Funclass"
+ | SortClass -> str"Sortclass"
| RefClass qid -> pr_reference qid
let pr_option_ref_value = function
@@ -224,7 +242,7 @@ let pr_with_declaration pr_c = function
let rec pr_module_type pr_c = function
| CMTEident qid -> pr_located pr_qualid qid
| CMTEwith (mty,decl) ->
- pr_module_type pr_c mty ++ spc() ++ str" with" ++
+ pr_module_type pr_c mty ++ spc() ++ str" with" ++ spc() ++
pr_with_declaration pr_c decl
let pr_of_module_type prc (mty,b) =
@@ -271,29 +289,17 @@ let anonymize_binder na c =
(Constrintern.interp_rawconstr Evd.empty (Global.env())) c))
else c
-let sep_fields () =
- if !Options.p1 then fnl () else str ";" ++ spc ()
-
-let surround_binder p =
- if !Options.p1 then str"(" ++ p ++ str")" else p
+let surround p = str"(" ++ p ++ str")"
let pr_binder pr_c ty na =
match anonymize_binder (snd na) ty with
CHole _ -> pr_located pr_name na
| _ ->
hov 1
- (surround_binder (pr_located pr_name na ++ str":" ++ cut() ++ pr_c ty))
-
-let pr_valdecls pr_c = function
- | LocalRawAssum (nal,c) ->
- let sep = if !Options.p1 then spc else pr_tight_coma in
- prlist_with_sep sep (pr_binder pr_c c) nal
- | LocalRawDef (na,c) ->
- hov 1
- (surround_binder (pr_located pr_name na ++ str":=" ++ cut() ++ pr_c c))
+ (surround (pr_located pr_name na ++ str":" ++ cut() ++ pr_c ty))
-let pr_vbinders pr_c l =
- hv 0 (prlist_with_sep spc (pr_valdecls pr_c) l)
+let pr_vbinders l =
+ hv 0 (pr_binders l)
let vars_of_valdecls l = function
| LocalRawAssum (nal,c) ->
@@ -310,15 +316,27 @@ let vars_of_binder l (nal,_) =
let vars_of_binders =
List.fold_left vars_of_binder []
+let anonymize_binder na c =
+ if Options.do_translate() then
+ Constrextern.extern_rawconstr (Termops.vars_of_env (Global.env()))
+ (Reserve.anonymize_if_reserved na
+ (Constrintern.for_grammar
+ (Constrintern.interp_rawconstr Evd.empty (Global.env())) c))
+ else c
+
let pr_sbinders sbl =
if sbl = [] then mt () else
- let bl = List.map (fun (id,c) -> ([(dummy_loc,Name id)],c)) sbl in
+ let bl =
+ List.map (fun (id,c) ->
+ let c = anonymize_binder (Name id) c in
+ LocalRawAssum ([(dummy_loc,Name id)],c)) sbl in
pr_binders bl ++ spc ()
let pr_onescheme (id,dep,ind,s) =
- pr_id id ++ str" :=" ++ spc() ++
- (if dep then str"Induction for" else str"Minimality for")
- ++ spc() ++ pr_reference ind ++ spc() ++ str"Sort" ++ spc() ++ pr_sort s
+ hov 0 (pr_id id ++ str" :=") ++ spc() ++
+ hov 0 ((if dep then str"Induction for" else str"Minimality for")
+ ++ spc() ++ pr_reference ind) ++ spc() ++
+ hov 0 (str"Sort" ++ spc() ++ pr_sort s)
let pr_class_rawexpr = function
| FunClass -> str"FUNCLASS"
@@ -340,14 +358,15 @@ let rec factorize = function
| [] -> []
| (c,(x,t))::l ->
match factorize l with
- | (xl,t')::l' when t' = (c,t) & not !Options.p1 -> (x::xl,t')::l'
+ | (xl,t')::l' when t' = (c,t) -> (x::xl,t')::l'
| l' -> ([x],(c,t))::l'
let pr_ne_params_list pr_c l =
- match factorize l with
- | [params] -> surround_binder (pr_params pr_c params)
- | l ->
- prlist_with_sep spc (fun p -> str "(" ++ pr_params pr_c p ++ str ")") l
+ prlist_with_sep spc (fun p -> str "(" ++ pr_params pr_c p ++ str ")")
+(*
+ prlist_with_sep pr_semicolon (pr_params pr_c)
+*)
+ (factorize l)
let pr_thm_token = function
| Decl_kinds.Theorem -> str"Theorem"
@@ -416,7 +435,7 @@ let pr_syntax_entry (p,rl) =
str"level" ++ spc() ++ int p ++ str" :" ++ fnl() ++
prlist_with_sep (fun _ -> fnl() ++ str"| ") pr_syntax_rule rl
-let sep_end () = if !Options.p1 then str";" else str"."
+let sep_end () = str"."
(**************************************)
(* Pretty printer for vernac commands *)
@@ -449,7 +468,7 @@ let rec pr_vernac = function
| VernacShow s ->
let pr_showable = function
| ShowGoal n -> str"Show" ++ pr_opt int n
- | ShowGoalImplicitly n -> str"Show Implicits" ++ pr_opt int n
+ | ShowGoalImplicitly n -> str"Show Implicit Arguments" ++ pr_opt int n
| ShowProof -> str"Show Proof"
| ShowNode -> str"Show Node"
| ShowScript -> str"Show Script"
@@ -479,10 +498,16 @@ let rec pr_vernac = function
| VernacVar id -> pr_id id
(* Syntax *)
- | VernacGrammar _ -> str"(* <Warning> : Grammar is replaced by Notation *)"
+ | VernacGrammar _ ->
+ msgerrnl (str"Warning : constr Grammar is discontinued; use Notation");
+ str"(* <Warning> : Grammar is replaced by Notation *)"
| VernacTacticGrammar l -> hov 1 (str"Grammar tactic simple_tactic :=" ++ spc() ++ prlist_with_sep (fun _ -> brk(1,1) ++ str"|") pr_grammar_tactic_rule l) (***)
- | VernacSyntax (u,el) -> hov 1 (str"Syntax " ++ str u ++ spc() ++
- prlist_with_sep sep_v2 pr_syntax_entry el) (***)
+ | VernacSyntax (u,el) ->
+ msgerrnl (str"Warning : Syntax is discontinued; use Notation");
+ str"(* Syntax is discontinued " ++
+ hov 1 (str"Syntax " ++ str u ++ spc() ++
+ prlist_with_sep sep_v2 pr_syntax_entry el) ++
+ str " *)"
| VernacOpenScope (local,sc) ->
str "Open " ++ pr_locality local ++ str "Scope" ++ spc() ++ str sc
| VernacDelimiters (sc,key) ->
@@ -496,8 +521,11 @@ let rec pr_vernac = function
let (a,p,s) = match ov8 with
Some mv8 -> mv8
| None -> (a,p,s) in
- hov 0 (str"Infix " ++ pr_locality local ++ pr_entry_prec a ++ int p
- ++ spc() ++ qs s ++ spc() ++ pr_reference q ++ (match sn with
+ hov 0 (hov 0 (str"Infix " ++ pr_locality local
+ (* ++ pr_entry_prec a ++ int p ++ spc() *)
+ ++ qs s ++ spc() ++ pr_reference q) ++ spc()
+ ++ str "(at level " ++ int p ++ pr_prec a ++ str")" ++
+ (match sn with
| None -> mt()
| Some sc -> spc() ++ str":" ++ spc() ++ str sc))
| VernacDistfix (local,a,p,s,q,sn) ->
@@ -547,6 +575,20 @@ let rec pr_vernac = function
str"Eval" ++ spc() ++
pr_red_expr (pr_constr, pr_lconstr, pr_reference) r ++
str" in" ++ spc() in
+ let mkLambdaCit = List.fold_right (fun (x,a) b -> mkLambdaC(x,a,b)) in
+ let mkProdCit = List.fold_right (fun (x,a) b -> mkProdC(x,a,b)) in
+ let rec abstract_rawconstr c = function
+ | [] -> c
+ | LocalRawDef (x,b)::bl -> mkLetInC(x,b,abstract_rawconstr c bl)
+ | LocalRawAssum (idl,t)::bl ->
+ List.fold_right (fun x b -> mkLambdaC([x],t,b)) idl
+ (abstract_rawconstr c bl) in
+ let rec prod_rawconstr c = function
+ | [] -> c
+ | LocalRawDef (x,b)::bl -> mkLetInC(x,b,prod_rawconstr c bl)
+ | LocalRawAssum (idl,t)::bl ->
+ List.fold_right (fun x b -> mkProdC([x],t,b)) idl
+ (prod_rawconstr c bl) in
let pr_def_body = function
| DefineBody (bl,red,c,d) ->
let (bl2,body,ty) = match d with
@@ -554,16 +596,25 @@ let rec pr_vernac = function
let bl2,body = extract_lam_binders c in
(bl2,body,mt())
| Some ty ->
- let bl2,body,ty = extract_def_binders c ty in
- (bl2,body, spc() ++ str":" ++ pr_lconstrarg ty) in
+ let bl2,body,ty' = extract_def_binders c ty in
+ (bl2,body, spc() ++ str":" ++ spc () ++
+ pr_lconstr_env_n (Global.env())
+ (List.length (vars_of_vbinders bl @ vars_of_vbinders bl2))
+ false (prod_rawconstr ty bl)) in
let bindings =
- pr_ne_sep spc (pr_vbinders pr_lconstr) bl ++
+ pr_ne_sep spc pr_vbinders bl ++
if bl2 = [] then mt() else (spc() ++ pr_binders bl2) in
- let vars = vars_of_vbinders bl @ vars_of_binders bl2 in
- let ppred = Some (pr_reduce red ++ pr_lconstr_vars vars body) in
+ let vars = vars_of_vbinders bl @ vars_of_vbinders bl2 in
+ let c',iscast = match d with None -> c, false
+ | Some d -> CCast (dummy_loc,c,d), true in
+ let ppred =
+ Some (pr_reduce red ++
+ pr_lconstr_env_n (Global.env())
+ (List.length vars) iscast (abstract_rawconstr c' bl))
+ in
(bindings,ty,ppred)
| ProveBody (bl,t) ->
- (pr_vbinders pr_lconstr bl, str" :" ++ pr_lconstrarg t, None) in
+ (pr_vbinders bl, str" :" ++ pr_lconstrarg t, None) in
let (binds,typ,c) = pr_def_body b in
hov 2 (pr_def_token e ++ spc() ++ pr_id id ++ binds ++ typ ++
(match c with
@@ -574,7 +625,11 @@ let rec pr_vernac = function
hov 1 (pr_thm_token ki ++ spc() ++ pr_id id ++ spc() ++
(match bl with
| [] -> mt()
- | _ -> pr_vbinders pr_lconstr bl ++ spc()) ++ str":" ++ spc() ++ pr_lconstr c ++ sep_end () ++ str "Proof")
+ | _ -> error "Statements with local binders no longer supported")
+(*
+pr_vbinders bl ++ spc())
+*)
+ ++ str":" ++ spc() ++ pr_lconstr c) ++ sep_end () ++ fnl() ++ str "Proof"
| VernacEndProof (opac,o) -> (match o with
| None -> if opac then str"Qed" else str"Defined"
| Some (id,th) -> (match th with
@@ -586,7 +641,8 @@ let rec pr_vernac = function
(pr_assumption_token stre ++ spc() ++ pr_ne_params_list pr_lconstr l)
| VernacInductive (f,l) ->
- (* Copie simplifiée de command.ml pour recalculer les implicites *)
+ (* Copie simplifiée de command.ml pour recalculer les implicites, *)
+ (* les notations, et le contexte d'evaluation *)
let lparams = match l with [] -> assert false | (_,_,la,_,_)::_ -> la in
let nparams = List.length lparams
and sigma = Evd.empty
@@ -598,6 +654,32 @@ let rec pr_vernac = function
(Termops.push_rel_assum (Name id,p) env,
(Name id,None,p)::params))
(env0,[]) lparams in
+
+ let (ind_env,ind_impls,arityl) =
+ List.fold_left
+ (fun (env, ind_impls, arl) (recname, _, _, arityc, _) ->
+ let arity = Constrintern.interp_type sigma env_params arityc in
+ let fullarity =
+ Termops.prod_it arity (List.map (fun (id,_,ty) -> (id,ty)) params) in
+ let env' = Termops.push_rel_assum (Name recname,fullarity) env in
+ let impls =
+ if Impargs.is_implicit_args()
+ then Impargs.compute_implicits false env_params fullarity
+ else [] in
+ (env', (recname,impls)::ind_impls, (arity::arl)))
+ (env0, [], []) l
+ in
+ let lparnames = List.map (fun (na,_,_) -> na) params in
+ let notations =
+ List.map2 (fun (recname,ntnopt,_,_,_) ar ->
+ option_app (fun df ->
+ let larnames =
+ List.rev_append lparnames
+ (List.rev (List.map fst (fst (Term.decompose_prod ar)))) in
+ (recname,larnames,df)) ntnopt)
+ l arityl in
+ let ind_env_params = Environ.push_rel_context params ind_env in
+
let lparnames = List.map (fun (na,_,_) -> na) params in
let impl_ntns = List.map
(fun (recname,ntnopt,_,arityc,_) ->
@@ -629,8 +711,8 @@ let rec pr_vernac = function
let pr_constructor (coe,(id,c)) =
hov 2 (pr_id id ++ str" " ++
- (if coe then str":>" else str":") ++
- pr_lconstrarg c) in
+ (if coe then str":>" else str":") ++ spc () ++
+ pr_lconstr_env ind_env_params c) in
let pr_constructor_list l = match l with
| [] -> mt()
| _ ->
@@ -657,6 +739,7 @@ let rec pr_vernac = function
| VernacFixpoint recs ->
(* Copie simplifiée de command.ml pour recalculer les implicites *)
+ (* les notations, et le contexte d'evaluation *)
let sigma = Evd.empty
and env0 = Global.env() in
let impl_ntns = List.map
@@ -687,14 +770,24 @@ let rec pr_vernac = function
Metasyntax.add_notation_interpretation df
(AVar recname,larnames) scope) no) notations;
+ let rec_sign =
+ List.fold_left
+ (fun env ((recname,_,arityc,_),_) ->
+ let arity = Constrintern.interp_type sigma env0 arityc in
+ Environ.push_named (recname,None,arity) env)
+ (Global.env()) recs in
+
+ let name_of_binder = function
+ | LocalRawAssum (nal,_) -> nal
+ | LocalRawDef (_,_) -> [] in
let pr_onerec = function
| (id,n,type_0,def0),ntn ->
let (bl,def,type_) = extract_def_binders def0 type_0 in
- let ids = List.flatten (List.map fst bl) in
+ let ids = List.flatten (List.map name_of_binder bl) in
let (bl,def,type_) =
if List.length ids <= n then split_fix (n+1) def0 type_0
else (bl,def,type_) in
- let ids = List.flatten (List.map fst bl) in
+ let ids = List.flatten (List.map name_of_binder bl) in
let annot =
if List.length ids > 1 then
spc() ++ str "{struct " ++
@@ -702,7 +795,9 @@ let rec pr_vernac = function
else mt() in
pr_id id ++ str" " ++ pr_binders bl ++ annot ++ spc()
++ pr_type_option (fun c -> spc() ++ pr_lconstr c) type_
- ++ pr_decl_notation ntn ++ str" :=" ++ brk(1,1) ++ pr_lconstr def
+ ++ pr_decl_notation ntn ++ str" :=" ++ brk(1,1) ++
+ pr_lconstr_env_n rec_sign (List.length (vars_of_vbinders bl))
+ true (CCast (dummy_loc,def0,type_0))
in
hov 1 (str"Fixpoint" ++ spc() ++
prlist_with_sep (fun _ -> fnl() ++ str"with ") pr_onerec recs)
@@ -717,32 +812,32 @@ let rec pr_vernac = function
prlist_with_sep (fun _ -> fnl() ++ str"with ") pr_onecorec corecs)
| VernacScheme l ->
hov 2 (str"Scheme" ++ spc() ++
- prlist_with_sep (fun _ -> fnl() ++ str"with") pr_onescheme l)
+ prlist_with_sep (fun _ -> fnl() ++ str"with ") pr_onescheme l)
(* Gallina extensions *)
- | VernacRecord ((oc,name),ps,s,c,fs) ->
+ | VernacRecord (b,(oc,name),ps,s,c,fs) ->
let pr_record_field = function
| (oc,AssumExpr (id,t)) ->
- hov 1 (surround_binder (pr_id id ++
+ hov 1 (pr_id id ++
(if oc then str" :>" else str" :") ++ spc() ++
- pr_lconstr t))
+ pr_lconstr t)
| (oc,DefExpr(id,b,opt)) -> (match opt with
| Some t ->
- hov 1 (surround_binder (pr_id id ++
+ hov 1 (pr_id id ++
(if oc then str" :>" else str" :") ++ spc() ++
- pr_lconstr t ++ str" :=" ++ pr_lconstr b))
+ pr_lconstr t ++ str" :=" ++ pr_lconstr b)
| None ->
- hov 1 (surround_binder (pr_id id ++ str" :=" ++ spc() ++
- pr_lconstr b))) in
+ hov 1 (pr_id id ++ str" :=" ++ spc() ++
+ pr_lconstr b)) in
hov 2
- (str"Record" ++
+ (str (if b then "Record" else "Structure") ++
(if oc then str" > " else str" ") ++ pr_id name ++ spc() ++
pr_sbinders ps ++ str" :" ++ spc() ++ pr_lconstr s ++ str" := " ++
(match c with
| None -> mt()
- | Some sc -> pr_id sc) ++ spc() ++ str"{" ++ cut() ++
- hv 0 (prlist_with_sep sep_fields pr_record_field fs)
- ++ str"}")
+ | Some sc -> pr_id sc) ++
+ spc() ++ str"{" ++
+ hv 0 (prlist_with_sep pr_semicolon pr_record_field fs ++ str"}"))
| VernacBeginSection id -> hov 2 (str"Section" ++ spc () ++ pr_id id)
| VernacEndSegment id -> hov 2 (str"End" ++ spc() ++ pr_id id)
| VernacRequire (exp,spe,l) -> hov 2
@@ -789,7 +884,7 @@ let rec pr_vernac = function
(* Solving *)
| VernacSolve (i,tac,deftac) ->
(if i = 1 then mt() else int i ++ str ": ") ++
- (if !Options.p1 then mt () else str "By ") ++
+(* str "By " ++*)
(if deftac then mt() else str "!! ") ++
Options.with_option Options.translate_syntax (pr_raw_tactic_goal i) tac
| VernacSolveExistential (i,c) ->
@@ -833,9 +928,9 @@ let rec pr_vernac = function
(Global.env())
body in
hov 1
- ((if !Options.p1 then
+ (((*if !Options.p1 then
(if rc then str "Recursive " else mt()) ++
- str "Tactic Definition " else
+ str "Tactic Definition " else*)
(* Rec by default *) str "Ltac ") ++
prlist_with_sep (fun () -> fnl() ++ str"with ") pr_tac_body l)
| VernacHints (local,dbnames,h) -> pr_hints local dbnames h pr_constr
@@ -851,9 +946,9 @@ let rec pr_vernac = function
hov 2 (str"Syntactic Definition " ++ pr_id id ++ str" :=" ++
pr_lconstrarg c ++ spc() ++ str"|" ++ int n)
| VernacDeclareImplicits (q,None) ->
- hov 2 (str"Implicits" ++ spc() ++ pr_reference q)
+ hov 2 (str"Implicit Arguments" ++ spc() ++ pr_reference q)
| VernacDeclareImplicits (q,Some l) ->
- hov 1 (str"Implicits" ++ spc() ++ pr_reference q ++ spc() ++
+ hov 1 (str"Implicit Arguments" ++ spc() ++ pr_reference q ++ spc() ++
str"[" ++ prlist_with_sep sep int l ++ str"]")
| VernacReserve (idl,c) ->
hov 1 (str"Implicit Variable" ++
@@ -864,8 +959,17 @@ let rec pr_vernac = function
spc() ++ prlist_with_sep sep pr_reference l)
| VernacUnsetOption na ->
hov 1 (str"Unset" ++ spc() ++ pr_printoption na None)
- | VernacSetOption (Goptions.SecondaryTable ("Implicit","Arguments"),BoolValue true) -> str"Set Implicit Arguments"
- | VernacSetOption (Goptions.SecondaryTable ("Implicit","Arguments"),BoolValue false) -> str"Unset Implicit Arguments"
+ | VernacSetOption (Goptions.SecondaryTable ("Implicit","Arguments"),BoolValue true) -> str"Set Implicit Arguments"
+ ++
+ (if !Options.translate_strict_impargs then
+ sep_end () ++ fnl () ++ str"Unset Strict Implicits"
+ else mt ())
+ | VernacSetOption (Goptions.SecondaryTable ("Implicit","Arguments"),BoolValue false) ->
+ str"Set Strict Implicits"
+ ++
+ (if !Options.translate_strict_impargs then
+ sep_end () ++ fnl () ++ str"Unset Implicit Arguments"
+ else mt ())
| VernacSetOption (na,v) -> hov 2 (str"Set" ++ spc() ++ pr_set_option na v)
| VernacAddOption (na,l) -> hov 2 (str"Add" ++ spc() ++ pr_printoption na (Some l))
| VernacRemoveOption (na,l) -> hov 2 (str"Remove" ++ spc() ++ pr_printoption na (Some l))