aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorherbelin2001-11-21 12:03:31 +0000
committerherbelin2001-11-21 12:03:31 +0000
commit86041b8b5d6bc93d545554d1fdded70bf59eb880 (patch)
treef96dcdf8af07f43082c43dbabeaeeccc6517b793
parentba96dbe08616830b9484a36e5b78044283eb49bb (diff)
Solution partielle au problème des alias dépendants pour les rendre compatibles avec l'utilisation de la contrainte de type comme guide de la synthèse du prédicat
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@2229 85f007b7-540e-0410-9357-904b9bb8a0f7
-rw-r--r--pretyping/cases.ml190
1 files changed, 124 insertions, 66 deletions
diff --git a/pretyping/cases.ml b/pretyping/cases.ml
index 4e67a7fc7b..0261062f1a 100644
--- a/pretyping/cases.ml
+++ b/pretyping/cases.ml
@@ -190,10 +190,38 @@ let push_rels vars env = List.fold_right push_rel vars env
let push_rel_defs =
List.fold_right (fun (x,d,t) e -> push_rel (x,Some d,t) e)
+(*
let it_mkSpecialLetIn =
List.fold_left
(fun c (na,b,t) -> if isRel b then subst1 b c else mkLetIn (na,b,t,c))
+*)
+type alias_constr =
+ | DepAlias of types
+ | NonDepAlias of types
+
+let lift_alias_constr k = function
+ | DepAlias t -> DepAlias (lift k t)
+ | NonDepAlias t -> NonDepAlias (lift k t)
+
+let mkSpecialLetInJudge j (na,(deppat,nondeppat,t)) =
+ { uj_val =
+ (match t with
+ | DepAlias t -> mkLetIn (na,deppat,t,j.uj_val)
+ | NonDepAlias t ->
+ if (not (dependent (mkRel 1) j.uj_type))
+ or (* A leaf: *) isRel deppat
+ then
+ (* The body of pat is not needed to type j - see *)
+ (* insert_aliases - and both deppat and nondeppat have the *)
+ (* same type, then one can freely substitute one by the other *)
+ subst1 nondeppat j.uj_val
+ else
+ (* The body of pat is not needed to type j but its value *)
+ (* is dependent in the type of j; our choice is to *)
+ (* enforce this dependency *)
+ mkLetIn (na,deppat,t,j.uj_val));
+ uj_type = subst1 deppat j.uj_type }
(**********************************************************************)
(* Structures used in compiling pattern-matching *)
@@ -250,13 +278,10 @@ type predicate_signature =
| PrCcl of constr
(* We keep a constr for aliases and a cases_pattern for error message *)
-type alias_constr =
- | DepAlias of constr
- | NonDepAlias of constr
type alias_builder =
- | AliasLeaf of constr
- | AliasConstructor of alias_constr * constructor
+ | AliasLeaf of constr * types
+ | AliasConstructor of (constr * constr * alias_constr) * constructor
type history_partial_result =
| HistoryArg of (constr * cases_pattern)
@@ -325,17 +350,19 @@ let rec simplify_lifted_history k = function
| Continuation (0, l, Top) -> [], Result (eval_partial_pattern_args [] l)
| Continuation (0, l, MakeAlias (f, rh)) ->
let (k,(cargs,pargs)) = eval_partial_args 0 ([],[]) l in
- let c, pat = match f with
- | AliasConstructor (c,pci) ->
- let c = match c with
- | DepAlias ci -> applist(lift k ci,cargs)
- | NonDepAlias x -> lift k x
- in c, PatCstr (dummy_loc,pci,pargs,Anonymous)
- | AliasLeaf x ->
+ let (_,nondeppat,_ as d), pat = match f with
+ | AliasConstructor ((c1,c2,d),pci) ->
+ let c1 = applist(lift k c1,cargs) in
+ let c2 = lift k c2 in
+ let d = lift_alias_constr k d in
+ (c1,c2,d), PatCstr (dummy_loc,pci,pargs,Anonymous)
+ | AliasLeaf (x,t) ->
assert (l = []);
- lift k x, PatVar (dummy_loc, Anonymous) in
- let l, h = simplify_lifted_history k (feed_history (c,pat) rh) in
- (c::l, h)
+ let c = lift k x in
+ let t = lift k t in
+ (c,c,NonDepAlias t), PatVar (dummy_loc, Anonymous) in
+ let l, h = simplify_lifted_history k (feed_history (nondeppat,pat) rh) in
+ (d::l, h)
| h -> [], lift_history k h
let simplify_history = simplify_lifted_history 0
@@ -396,6 +423,10 @@ let to_mutind env sigma c t =
try IsInd (t,find_rectype env sigma t)
with Induc -> NotInd (c,t)
+let type_of_tomatch = function
+ | IsInd (t,_) -> t
+ | NotInd (_,t) -> t
+
let mkDeclTomatch na = function
| IsInd (t,_) -> (na,None,t)
| NotInd (c,t) -> (na,c,t)
@@ -691,27 +722,41 @@ let build_aliases_context env sigma names allpats pats =
(* pats is the list of bodies to push as an alias *)
(* They all are defined in env and we turn them into a sign *)
(* cuts in sign need to be done in allpats *)
- let rec insert env sign n newallpats oldallpats = function
+ let rec insert env sign1 sign2 n newallpats oldallpats = function
| _::pats, Anonymous::names ->
- insert env sign n newallpats (List.map List.tl oldallpats) (pats,names)
- | pat::pats, na::names ->
- let pat = lift n pat in
+ insert env sign1 sign2
+ n newallpats (List.map List.tl oldallpats) (pats,names)
+ | (deppat,nondeppat,d as a)::pats, na::names ->
+ let nondeppat = lift n nondeppat in
+ let deppat = lift n deppat in
+ let d = lift_alias_constr n d in
+(*
let t = Retyping.get_type_of env sigma pat in
+*)
let newallpats =
List.map2 (fun l1 l2 -> List.hd l2::l1) newallpats oldallpats in
let oldallpats = List.map List.tl oldallpats in
- let d = (na,pat,t) in
- insert (push_rel (na,Some pat,t) env) (d::sign) (n+1)
- newallpats oldallpats (pats,names)
- | [], [] -> newallpats, sign, env
+ let decl =
+ match d with
+ | DepAlias t ->
+ (* The alias refinement induces a refinement of its type *)
+ (* The body is needed to ensure the type *)
+ (na,Some deppat,t)
+ | NonDepAlias t ->
+ (* The type of alias is the same as its expansion *)
+ (* Do as if it has no body *)
+ (na,Some deppat,t) in
+ insert (push_rel decl env) (decl::sign1) ((na,a)::sign2) (n+1)
+ newallpats oldallpats (pats,names)
+ | [], [] -> newallpats, sign1, sign2, env
| _ -> anomaly "Inconsistent alias and name lists"
- in insert env [] 0 (List.map (fun _ -> []) allpats) allpats (pats, names)
+ in insert env [] [] 0 (List.map (fun _ -> []) allpats) allpats (pats, names)
let insert_aliases_eqn sign eqnnames alias_rest eqn =
let thissign = List.map2 (fun na (_,c,t) -> (na,c,t)) eqnnames sign in
{ eqn with
alias_stack = alias_rest;
- rhs = {eqn.rhs with rhs_env = push_rel_defs thissign eqn.rhs.rhs_env } }
+ rhs = {eqn.rhs with rhs_env = push_rels thissign eqn.rhs.rhs_env } }
let insert_aliases env sigma aliases eqns =
let n = List.length aliases in
@@ -727,10 +772,10 @@ let insert_aliases env sigma aliases eqns =
let names2 =
List.fold_right (merge_names (fun x -> x)) eqnsnames names1 in
(* Only needed aliases are kept by build_aliases_context *)
- let eqnsnames, sign, env =
+ let eqnsnames, sign1, sign2, env =
build_aliases_context env sigma names2 eqnsnames aliases in
- let eqns = list_map3 (insert_aliases_eqn sign) eqnsnames alias_rests eqns in
- sign, env, eqns
+ let eqns = list_map3 (insert_aliases_eqn sign1) eqnsnames alias_rests eqns in
+ sign2, env, eqns
(**********************************************************************)
(* Functions to deal with elimination predicate *)
@@ -936,13 +981,12 @@ let abstract_predicate env sigma indf = function
| (PrProd _ | PrCcl _ | PrNotInd _) ->
anomaly "abstract_predicate: must be some LetIn"
| PrLetIn ((_,copt),pred) ->
- let sign,_ = get_arity env indf in
+ let pred = extract_predicate pred in
+ (* Even if not intrinsically dep, we move the predicate into a dep one *)
let dep = copt <> None in
- let sign' =
- if dep then
- (Anonymous,None,build_dependent_inductive env indf) :: sign
- else sign in
- (dep, it_mkLambda_or_LetIn_name env (extract_predicate pred) sign')
+ let pred = if dep then pred else lift 1 pred in
+ let sign = make_arity_signature env true indf in
+ (true, it_mkLambda_or_LetIn_name env pred sign)
let known_dependent = function
| None -> false
@@ -974,7 +1018,7 @@ let weaken_predicate q pred =
(* We replace 1 product by |realargs| arguments + possibly copt *)
(* Then we need to shift pred accordingly (but *)
let nletargs = (List.length realargs)+p in
- let pred = liftn_predicate (nletargs-1) (p+1) pred in
+ let pred = liftn_predicate (nletargs-p) (p+1) pred in
(* The current lift to refer to the y1...yn is now k+nletargs *)
PrLetIn ((realargs, copt), weakrec (n-1) (nletargs+k) pred)
| PrProd ((dep,_,NotInd _),pred) ->
@@ -1002,7 +1046,8 @@ let specialize_predicate_match tomatchs cs = function
(* Assume some gamma st: gamma, (X,x:=realargs,copt) |- pred *)
let k = List.length args + (if copt = None then 0 else 1) in
(* We adjust pred st: gamma, x1...xn, (X,x:=realargs,copt) |- pred *)
- let pred' = liftn_predicate cs.cs_nargs (k+1) pred in
+ let depth = if copt = None then 0 else cs.cs_nargs in
+ let pred' = liftn_predicate depth (k+1) pred in
let argsi = Array.to_list cs.cs_concl_realargs in
let copti = option_app (fun _ -> build_dependent_constructor cs) copt in
(* The substituends argsi, copti are all defined in gamma, x1...xn *)
@@ -1072,26 +1117,32 @@ let build_leaf pb =
tag, pb.typing_function tycon rhs.rhs_env rhs.it
(* Building the sub-problem when all patterns are variables *)
-let shift_problem current pb =
+let shift_problem (current,t) pb =
{pb with
pred = option_app specialize_predicate_var pb.pred;
- history = push_history_pattern 0 (AliasLeaf current) pb.history;
+ history = push_history_pattern 0
+ (AliasLeaf (current,type_of_tomatch t)) pb.history;
mat = List.map remove_current_pattern pb.mat }
(* Building the sub-pattern-matching problem for a given branch *)
-let build_branch current pb eqns const_info =
+let build_branch current typ pb eqns const_info =
(* We remember that we descend through a constructor *)
- let partialci =
+ let alias_type =
if Array.length const_info.cs_concl_realargs = 0
-(* & not (known_dependent pb.pred)*)
+ & not (known_dependent pb.pred)
then
- NonDepAlias current
+ NonDepAlias (type_of_tomatch typ)
else
- let params = const_info.cs_params in
- DepAlias (applist (mkConstruct const_info.cs_cstr, params)) in
+ let tyi = inductive_of_constructor const_info.cs_cstr in
+ let params = List.map (lift const_info.cs_nargs) const_info.cs_params in
+ DepAlias
+ (applist(mkInd tyi,params@Array.to_list const_info.cs_concl_realargs))
+ in
+ let partialci =
+ applist (mkConstruct const_info.cs_cstr, const_info.cs_params) in
let history =
push_history_pattern const_info.cs_nargs
- (AliasConstructor (partialci, const_info.cs_cstr))
+ (AliasConstructor ((partialci,current,alias_type), const_info.cs_cstr))
pb.history in
(* We find matching clauses *)
@@ -1154,20 +1205,20 @@ let rec compile pb =
| [] -> build_leaf pb
and match_current pb (n,tm) =
- let ((current,typ),info) = lift_tomatch n tm in
+ let ((current,typ as ct),info) = lift_tomatch n tm in
match typ with
| NotInd (_,typ) ->
check_all_variables typ pb.mat;
- compile_aliases (shift_problem current pb)
+ compile_aliases (shift_problem ct pb)
| IsInd (_,(IndType(indf,realargs) as indt)) ->
let mind,_ = dest_ind_family indf in
let cstrs = get_constructors pb.env indf in
let eqns,onlydflt = group_equations mind current cstrs pb.mat in
if (cstrs <> [||] or not (initial_history pb.history)) & onlydflt then
- compile_aliases (shift_problem current pb)
+ compile_aliases (shift_problem ct pb)
else
let constraints = Array.map (solve_constraints indt) cstrs in
- let pbs = array_map2 (build_branch current pb) eqns cstrs in
+ let pbs = array_map2 (build_branch current typ pb) eqns cstrs in
let brs = Array.map compile_aliases pbs in
let brvals = Array.map (fun (_,j) -> j.uj_val) brs in
let brtyps = Array.map (fun (_,j) -> body_of_type j.uj_type) brs in
@@ -1217,8 +1268,11 @@ and compile_aliases pb =
mat = mat } in
let patstat,j = compile pb in
patstat,
+(*
{ uj_val = it_mkSpecialLetIn j.uj_val sign;
uj_type = substl (List.map (fun (_,b,_) -> b) sign) j.uj_type }
+*)
+ List.fold_left mkSpecialLetInJudge j sign
(* pour les alias des initiaux, enrichir les env de ce qu'il faut et
substituer après par les initiaux *)
@@ -1407,26 +1461,23 @@ let build_expected_arity env isevars isdep tomatchl =
in buildrec 0 env tomatchl
(* [nargs] is the length of the arity of [pred] *)
-let extract_predicate_conclusion isdep nargs tomatchl pred =
+let extract_predicate_conclusion nargs pred =
let decomp_lam_force p =
match kind_of_term p with
| Lambda (_,_,c) -> c
| _ -> (* eta-expansion *) applist (lift 1 p, [mkRel 1]) in
- if isdep then
- (* Remove all lambda's of [pred] (up to eta-expansion) *)
- iterate decomp_lam_force nargs pred
- else
- (* Turn pred into a dependent predicate by (virtually) inserting *)
- (* [ntomach] lambda, which means lifting [ntomatch] times the body *)
- lift (List.length tomatchl) (iterate decomp_lam_force nargs pred)
+ iterate decomp_lam_force nargs pred
-let prepare_predicate_from_tycon env isevars tomatchs c =
+let prepare_predicate_from_tycon dep env isevars tomatchs c =
let cook (n, l, env) = function
| c,IsInd (_,IndType(indf,realargs)) ->
let indf' = lift_inductive_family n indf in
- let sign = make_arity_signature env true indf' in
+ let sign = make_arity_signature env dep indf' in
let p = List.length realargs in
- (n + p + 1, c::(List.rev realargs)@l, push_rels sign env)
+ if dep then
+ (n + p + 1, c::(List.rev realargs)@l, push_rels sign env)
+ else
+ (n + p, (List.rev realargs)@l, push_rels sign env)
| c,NotInd _ ->
(n, l, env) in
let n, allargs, env = List.fold_left cook (0, [], env) tomatchs in
@@ -1440,7 +1491,7 @@ let prepare_predicate_from_tycon env isevars tomatchs c =
else
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 *)
(* realargs and terms to match *)
let build_initial_predicate env sigma isdep pred tomatchl =
@@ -1452,10 +1503,17 @@ let build_initial_predicate env sigma isdep pred tomatchl =
| [] -> PrCcl (lift q pred)
| tm::ltm ->
match cook n tm with
- | None, cur -> PrNotInd (cur, buildrec (n+1) (q+1) ltm)
+ | None, cur ->
+ if isdep then
+ PrNotInd (cur, buildrec (n+1) (q+1) ltm)
+ else
+ PrNotInd (None, buildrec n q ltm)
| Some realargs, cur ->
let nrealargs = List.length realargs in
- PrLetIn ((realargs,cur),buildrec (n+nrealargs+1) q ltm)
+ if isdep then
+ PrLetIn ((realargs,cur), buildrec (n+nrealargs+1) q ltm)
+ else
+ PrLetIn ((realargs,None), buildrec (n+nrealargs) q ltm)
in buildrec 0 0 tomatchl
(* determines wether the multiple case is dependent or not. For that
@@ -1474,9 +1532,9 @@ let prepare_predicate typing_fun isevars env tomatchs tycon = function
(match tycon with
| None -> None
| Some t ->
- let pred = prepare_predicate_from_tycon env isevars tomatchs t in
+ let pred = prepare_predicate_from_tycon false env isevars tomatchs t in
Some
- (build_initial_predicate env (evars_of isevars) true pred tomatchs))
+ (build_initial_predicate env (evars_of isevars) false pred tomatchs))
| Some pred ->
let loc = loc_of_rawconstr pred in
let dep, n, predj =
@@ -1502,7 +1560,7 @@ let prepare_predicate typing_fun isevars env tomatchs tycon = function
error_wrong_predicate_arity_loc
loc env predj.uj_val ndep_arity dep_arity
in
- let predccl = extract_predicate_conclusion dep n tomatchs predj.uj_val in
+ let predccl = extract_predicate_conclusion n predj.uj_val in
(*
let etapred,cdep = case_dependent env (evars_of isevars) loc predj tomatchs in
*)