aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Maxime Dénès <mail@maximedenes.fr>2013-12-22 04:03:40 -0500
committerGravatar Maxime Dénès <mail@maximedenes.fr>2014-07-22 16:52:26 -0400
commit9b272a861bc3263c69b699cd2ac40ab2606543fa (patch)
treecd56502b7bc95f22edcede303273c44bf0353f45
parentccd7546cd32c8a7901a4234f86aa23b4a7e1a043 (diff)
Tentative fix for the commutative cut subterm rule.
Some fixpoints are now rejected in the standard library, but that's probably because we compare trees for equality instead of intersecting them.
-rw-r--r--kernel/inductive.ml42
1 files changed, 35 insertions, 7 deletions
diff --git a/kernel/inductive.ml b/kernel/inductive.ml
index 7698eed0f..24763b79e 100644
--- a/kernel/inductive.ml
+++ b/kernel/inductive.ml
@@ -611,16 +611,14 @@ let check_inductive_codomain env p =
isInd i
let get_codomain_tree env p =
- let absctx, ar = dest_lam_assum env p in
- let arctx, s = dest_prod_assum env ar in
+ let absctx, ar = dest_lam_assum env p in (* TODO: reduce or preserve lets? *)
+ let arctx, s = dest_prod_assum env ar in (* TODO: check number of prods *)
let i,l' = decompose_app (whd_betadeltaiota env s) in
match kind_of_term i with
| Ind i ->
let (_,mip) = lookup_mind_specif env i in Subterm(Strict,mip.mind_recargs)
| _ -> Not_subterm
-
-
(* [subterm_specif renv t] computes the recursive structure of [t] and
compare its size with the size of the initial recursive argument of
the fixpoint we are checking. [renv] collects such information
@@ -650,6 +648,7 @@ let rec subterm_specif renv stack t =
furthermore when f is applied to a term which is strictly less than
n, one may assume that x itself is strictly less than n
*)
+ (* TODO: is this necessary? *)
if not (check_inductive_codomain renv.env typarray.(i)) then Not_subterm
else
let (ctxt,clfix) = dest_prod renv.env typarray.(i) in
@@ -686,7 +685,7 @@ let rec subterm_specif renv stack t =
| Lambda (x,a,b) ->
let () = assert (List.is_empty l) in
- let spec,stack' = extract_stack renv a stack in
+ let spec,stack' = extract_stack stack in
subterm_specif (push_var renv (x,a,spec)) stack' b
(* Metas and evars are considered OK *)
@@ -702,7 +701,7 @@ and stack_element_specif = function
|SClosure (h_renv,h) -> lazy_subterm_specif h_renv [] h
|SArg x -> x
-and extract_stack renv a = function
+and extract_stack = function
| [] -> Lazy.lazy_from_val Not_subterm , []
| h::t -> stack_element_specif h, t
@@ -732,6 +731,34 @@ let error_illegal_rec_call renv fx (arg_renv,arg) =
let error_partial_apply renv fx =
raise (FixGuardError (renv.env,NotEnoughArgumentsForFixCall fx))
+let filter_stack_domain env ci p stack =
+ let absctx, ar = dest_lam_assum env p in
+ let env = push_rel_context absctx env in
+ let rec filter_stack env ar stack =
+ let t = whd_betadeltaiota env ar in
+ match stack, kind_of_term t with
+ | elt :: stack', Prod (n,a,c0) ->
+ let d = (n,None,a) in
+ let ty, _ = decompose_app a in (* TODO: reduce a? *)
+ let elt = match kind_of_term ty with
+ | Ind i ->
+ let (_,mip) = lookup_mind_specif env i in
+ let spec' = stack_element_specif elt in (* TODO: this is recomputed
+ each time*)
+ (match (Lazy.force spec') with (* TODO: are we forcing too much? *)
+ | Not_subterm -> elt
+ | Subterm(_,path) ->
+ if eq_wf_paths path mip.mind_recargs then elt
+ else (SArg (lazy Not_subterm))) (* TODO: intersection *)
+ (* TODO: not really an SArg *)
+ | _ -> (SArg (lazy Not_subterm))
+ in
+ elt :: filter_stack (push_rel d env) c0 stack'
+ | _,_ -> List.fold_right (fun _ l -> SArg (lazy Not_subterm) :: l) stack []
+ (* TODO: is it correct to empty the stack instead? *)
+ in
+ filter_stack env ar stack
+
(* Check if [def] is a guarded fixpoint body with decreasing arg.
given [recpos], the decreasing arguments of each mutually defined
fixpoint. *)
@@ -786,6 +813,7 @@ let check_one_fix renv recpos def =
let case_spec = branches_specif renv
(lazy_subterm_specif renv [] c_0) ci in
let stack' = push_stack_closures renv l stack in
+ let stack' = filter_stack_domain renv.env ci p stack' in
Array.iteri (fun k br' ->
let stack_br = push_stack_args case_spec.(k) stack' in
check_rec_call renv stack_br br') lrest
@@ -828,7 +856,7 @@ let check_one_fix renv recpos def =
| Lambda (x,a,b) ->
let () = assert (List.is_empty l) in
check_rec_call renv [] a ;
- let spec, stack' = extract_stack renv a stack in
+ let spec, stack' = extract_stack stack in
check_rec_call (push_var renv (x,a,spec)) stack' b
| Prod (x,a,b) ->