aboutsummaryrefslogtreecommitdiff
path: root/pretyping
diff options
context:
space:
mode:
authorgareuselesinge2012-03-22 10:54:14 +0000
committergareuselesinge2012-03-22 10:54:14 +0000
commit4a0fc5c294cf0f6db842bab26df80a3ce7cdf07b (patch)
tree78aa5054da2fc2744cafaae8210d2eb040db0f94 /pretyping
parentc7d396319a1d07bd517b69024ccc6de0a90feaf9 (diff)
evarconv: MaybeFlex/MaybeFlex case infers more Canonical Structures
Canonical Structure inference works on named terms only: i.e. the projection and the value must be named (with few exceptions). The set of named (head) terms is: (Var _|Construct _|Ind _|Const _|Prod _|Sort _) The set of unnamed is thus: (Case _|Fix _|CoFix _|Evar _|Meta _|Rel _) The MaybeFlex/MaybeFlex case, when no CS inference takes place, unfolds the rhs only if it exposes a named term. If it exposes an unnamed term, it tries to unfold on the lhs first. Note that unnamed terms are whd normal terms, since iota and zeta are performed by evar_apprec. So the algorithm behaves as before, but stops unfolding the rhs 1 delta step before it exposes an unnamed term. Then it starts unfolding the lhs. If the lhs exposes a rigid term the rhs is naturally unfolded, going back to same situation in which the algorithm was ending before. But while it unfolds on the left, the rhs is still named, and canonical structure inference can succeed. Ex failing before, the "canon_" prefix marks projections/values declared as canonical. Record test := K { canon_proj : nat } (* canon_proj x := math x with K y => y end *) canon_val x := match x with 0 => 0 | S m => m end Canonical Structure canon_struct x := K (canon_val x) (* aliases *) proj := canon_proj val := canon_val Old alg: proj ? ===?=== val x proj ? ===?=== canon_val x proj ? ===?=== match x with ... end canon_proj ? ===?=== match x with ... end (* no inference *) match ? with K x...end ===?=== match x with 0 ...end (* FAIL *) New alg: proj ? ===?=== val x proj ? ===?=== canon_val x canon_proj ? ===?=== canon_val x (* inference works: ? := canon_struct *) In case canon_struct is not declared for canon_proj and canon_val it continues like that: canon_proj ? ===?=== canon_val x match ? with K x...end ===?=== canon_val x match ? with K x...end ===?=== match x with 0 ...end (* FAIL *) git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@15077 85f007b7-540e-0410-9357-904b9bb8a0f7
Diffstat (limited to 'pretyping')
-rw-r--r--pretyping/evarconv.ml26
1 files changed, 19 insertions, 7 deletions
diff --git a/pretyping/evarconv.ml b/pretyping/evarconv.ml
index bfc2a18dbf..dc7d10b475 100644
--- a/pretyping/evarconv.ml
+++ b/pretyping/evarconv.ml
@@ -196,7 +196,7 @@ let rec evar_conv_x ts env evd pbty term1 term2 =
evar_eqappr_x ts env evd pbty
(decompose_app term1) (decompose_app term2)
-and evar_eqappr_x ?(rhs_is_stuck_proj = false)
+and evar_eqappr_x ?(rhs_is_already_stuck = false)
ts env evd pbty (term1,l1 as appr1) (term2,l2 as appr2) =
(* Evar must be undefined since we have flushed evars *)
match (flex_kind_of_term term1 l1, flex_kind_of_term term2 l2) with
@@ -325,13 +325,25 @@ and evar_eqappr_x ?(rhs_is_stuck_proj = false)
(* heuristic: unfold second argument first, exception made
if the first argument is a beta-redex (expand a constant
only if necessary) or the second argument is potentially
- usable as a canonical projection *)
- let rhs_is_stuck_proj =
- rhs_is_stuck_proj || is_open_canonical_projection env i appr2 in
- if isLambda flex1 || rhs_is_stuck_proj then
+ usable as a canonical projection or canonical value *)
+ let rec is_unnamed (hd, args) = match kind_of_term hd with
+ | (Var _|Construct _|Ind _|Const _|Prod _|Sort _) -> false
+ | (Case _|Fix _|CoFix _|Meta _|Rel _)-> true
+ | Evar _ -> false (* immediate solution without Canon Struct *)
+ | Lambda _ -> assert(args = []); true
+ | LetIn (_,b,_,c) ->
+ is_unnamed (evar_apprec ts env i args (subst1 b c))
+ | App _| Cast _ -> assert false in
+ let rhs_is_stuck_and_unnamed () =
+ match eval_flexible_term ts env flex2 with
+ | None -> false
+ | Some v2 -> is_unnamed (evar_apprec ts env i l2 v2) in
+ let rhs_is_already_stuck =
+ rhs_is_already_stuck || rhs_is_stuck_and_unnamed () in
+ if isLambda flex1 || rhs_is_already_stuck then
match eval_flexible_term ts env flex1 with
| Some v1 ->
- evar_eqappr_x ~rhs_is_stuck_proj
+ evar_eqappr_x ~rhs_is_already_stuck
ts env i pbty (evar_apprec ts env i l1 v1) appr2
| None ->
match eval_flexible_term ts env flex2 with
@@ -545,7 +557,7 @@ and conv_record trs env evd (c,bs,(params,params1),(us,us2),(ts,ts1),c1,(n,t2))
(fun i -> evar_conv_x trs env i CONV c1 (applist (c,(List.rev ks))));
(fun i -> ise_list2 i (fun i -> evar_conv_x trs env i CONV) ts ts1)]
-(* getting rid of the optional argument rhs_is_stuck_proj *)
+(* getting rid of the optional argument rhs_is_already_stuck *)
let evar_eqappr_x ts env evd pbty appr1 appr2 =
evar_eqappr_x ts env evd pbty appr1 appr2