aboutsummaryrefslogtreecommitdiff
path: root/interp
diff options
context:
space:
mode:
Diffstat (limited to 'interp')
-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
6 files changed, 303 insertions, 67 deletions
diff --git a/interp/constrextern.ml b/interp/constrextern.ml
index 1027543847..29f3c437c5 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 e5cfd0190f..008957e1bb 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 17405769a5..d1c32e9982 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 f6f9fe60d3..5287ce5a2d 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 5b1d2813b4..d2ef146bf2 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 f5f620528c..55cd20290f 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