aboutsummaryrefslogtreecommitdiff
path: root/pretyping/evarutil.ml
diff options
context:
space:
mode:
Diffstat (limited to 'pretyping/evarutil.ml')
-rw-r--r--pretyping/evarutil.ml188
1 files changed, 107 insertions, 81 deletions
diff --git a/pretyping/evarutil.ml b/pretyping/evarutil.ml
index 8cab61c947..ce08a0f390 100644
--- a/pretyping/evarutil.ml
+++ b/pretyping/evarutil.ml
@@ -125,6 +125,7 @@ let do_restrict_hyps sigma c =
* operations on the evar constraints *
*------------------------------------*)
+type evar_constraint = conv_pb * constr * constr
type 'a evar_defs = 'a Evd.evar_map ref
(* ise_try [f1;...;fn] tries fi() for i=1..n, restoring the evar constraints
@@ -169,10 +170,6 @@ let restrict_hyps isevars c =
end else
c
-let has_ise sigma t =
- try let _ = whd_ise sigma t in false
- with Uninstantiated_evar _ -> true
-
(* We try to instanciate the evar assuming the body won't depend
* on arguments that are not Rels or Vars, or appearing several times.
*)
@@ -247,8 +244,7 @@ let keep_rels_and_vars c = match kind_of_term c with
| IsVar _ | IsRel _ -> c
| _ -> mkImplicit (* Mettre mkMeta ?? *)
-let evar_define isevars lhs rhs =
- let (ev,argsv) = destEvar lhs in
+let evar_define isevars (ev,argsv) rhs =
if occur_evar ev rhs then error_occur_check CCI empty_env ev rhs;
let args = List.map keep_rels_and_vars (Array.to_list argsv) in
let evd = ise_map isevars ev in
@@ -258,23 +254,108 @@ let evar_define isevars lhs rhs =
ise_define isevars ev body;
[ev]
+(*-------------------*)
+(* Auxiliary functions for the conversion algorithms modulo evars
+ *)
+
+let has_undefined_isevars isevars t =
+ try let _ = whd_ise !isevars t in false
+ with Uninstantiated_evar _ -> true
+
+let head_is_evar isevars =
+ let rec hrec k = match kind_of_term k with
+ | IsEvar (n,_) -> not (Evd.is_defined !isevars n)
+ | IsApp (f,_) -> hrec f
+ | IsCast (c,_) -> hrec c
+ | _ -> false
+ in
+ hrec
+
+let rec is_eliminator c = match kind_of_term c with
+ | IsApp _ -> true
+ | IsMutCase _ -> true
+ | IsCast (c,_) -> is_eliminator c
+ | _ -> false
+
+let head_is_embedded_evar isevars c =
+ (head_is_evar isevars c) & (is_eliminator c)
+
+let head_evar =
+ let rec hrec c = match kind_of_term c with
+ | IsEvar (ev,_) -> ev
+ | IsMutCase (_,_,c,_) -> hrec c
+ | IsApp (c,_) -> hrec c
+ | IsCast (c,_) -> hrec c
+ | _ -> failwith "headconstant"
+ in
+ hrec
+(* This code (i.e. solve_pb, etc.) takes a unification
+ * problem, and tries to solve it. If it solves it, then it removes
+ * all the conversion problems, and re-runs conversion on each one, in
+ * the hopes that the new solution will aid in solving them.
+ *
+ * The kinds of problems it knows how to solve are those in which
+ * the usable arguments of an existential var are all themselves
+ * universal variables.
+ * The solution to this problem is to do renaming for the Var's,
+ * to make them match up with the Var's which are found in the
+ * hyps of the existential, to do a "pop" for each Rel which is
+ * not an argument of the existential, and a subst1 for each which
+ * is, again, with the corresponding variable. This is done by
+ * Tradevar.evar_define
+ *
+ * Thus, we take the arguments of the existential which we are about
+ * to assign, and zip them with the identifiers in the hypotheses.
+ * Then, we process all the Var's in the arguments, and sort the
+ * Rel's into ascending order. Then, we just march up, doing
+ * subst1's and pop's.
+ *
+ * NOTE: We can do this more efficiently for the relative arguments,
+ * by building a long substituend by hand, but this is a pain in the
+ * ass.
+ *)
+
+let conversion_problems = ref ([] : evar_constraint list)
+
+let reset_problems () = conversion_problems := []
+
+let add_conv_pb pb = (conversion_problems := pb::!conversion_problems)
+
+let status_changed lev (pbty,t1,t2) =
+ try
+ List.mem (head_evar t1) lev or List.mem (head_evar t2) lev
+ with Failure _ ->
+ try List.mem (head_evar t2) lev with Failure _ -> false
+
+let get_changed_pb lev =
+ let (pbs,pbs1) =
+ List.fold_left
+ (fun (pbs,pbs1) pb ->
+ if status_changed lev pb then
+ (pb::pbs,pbs1)
+ else
+ (pbs,pb::pbs1))
+ ([],[])
+ !conversion_problems
+ in
+ conversion_problems := pbs1;
+ pbs
(* Solve pbs (?i x1..xn) = (?i y1..yn) which arises often in fixpoint
* definitions. We try to unify the xi with the yi pairwise. The pairs
* that don't unify are discarded (i.e. ?i is redefined so that it does not
* depend on these args). *)
-let solve_refl conv_algo isevars c1 c2 =
- let (ev,argsv1) = destEvar c1
- and (_,argsv2) = destEvar c2 in
+let solve_refl conv_algo env isevars ev argsv1 argsv2 =
+ if argsv1 = argsv2 then [] else
let evd = Evd.map !isevars ev in
let env = evd.evar_env in
let hyps = named_context env in
let (_,rsign) =
array_fold_left2
(fun (sgn,rsgn) a1 a2 ->
- if conv_algo a1 a2 then
+ if conv_algo env isevars CONV a1 a2 then
(List.tl sgn, add_named_decl (List.hd sgn) rsgn)
else
(List.tl sgn, rsgn))
@@ -288,87 +369,32 @@ let solve_refl conv_algo isevars c1 c2 =
evar_body = Evar_empty; evar_info = None } in
isevars :=
Evd.define (Evd.add !isevars newev info) ev (mkEvar (newev,nargs));
- Some [ev]
+ [ev]
(* Tries to solve problem t1 = t2.
- * Precondition: one of t1,t2 is an uninstanciated evar, possibly
- * applied to arguments.
+ * Precondition: t1 is an uninstanciated evar
* Returns an optional list of evars that were instantiated, or None
* if the problem couldn't be solved. *)
(* Rq: uncomplete algorithm if pbty = CONV_X_LEQ ! *)
-let rec solve_simple_eqn conv_algo isevars ((pbty,t1,t2) as pb) =
- let t1 = nf_ise1 !isevars t1 in
+let solve_simple_eqn conv_algo env isevars (pbty,(n1,args1 as ev1),t2) =
let t2 = nf_ise1 !isevars t2 in
- if eq_constr t1 t2 then
- Some []
- else
- match (ise_undefined isevars t1, ise_undefined isevars t2) with
- | (true,true) ->
- if num_of_evar t1 = num_of_evar t2 then
- solve_refl conv_algo isevars t1 t2
- else if Array.length(snd (destEvar t1)) <
- Array.length(snd (destEvar t2)) then
- Some (evar_define isevars t2 t1)
- else
- Some (evar_define isevars t1 t2)
- | (true,false) -> Some (evar_define isevars t1 t2)
- | (false,true) -> Some (evar_define isevars t2 t1)
- | _ -> None
-
-(*-------------------*)
-(* Now several auxiliary functions for the conversion algorithms modulo
- * evars. used in trad and progmach
- *)
-
-
-let has_undefined_isevars isevars c =
- let rec hasrec k = match splay_constr k with
- | OpEvar ev, cl when ise_in_dom isevars ev ->
- if ise_defined isevars k then
- hasrec (existential_value !isevars (ev,cl))
+ let lsp = match kind_of_term t2 with
+ | IsEvar (n2,args2 as ev2) when not (Evd.is_defined !isevars n2) ->
+ if n1 = n2 then
+ solve_refl conv_algo env isevars n1 args1 args2
else
- failwith "caught"
- | _, cl -> Array.iter hasrec cl
- in
- (try (hasrec c ; false) with Failure "caught" -> true)
-
-let head_is_exist isevars =
- let rec hrec k = match kind_of_term k with
- | IsEvar _ -> ise_undefined isevars k
- | IsApp (f,_) -> hrec f
- | IsCast (c,_) -> hrec c
- | _ -> false
- in
- hrec
-
-let rec is_eliminator c = match kind_of_term c with
- | IsApp _ -> true
- | IsMutCase _ -> true
- | IsCast (c,_) -> is_eliminator c
- | _ -> false
-
-let head_is_embedded_exist isevars c =
- (head_is_exist isevars c) & (is_eliminator c)
-
-let head_evar =
- let rec hrec c = match kind_of_term c with
- | IsEvar (ev,_) -> ev
- | IsMutCase (_,_,c,_) -> hrec c
- | IsApp (c,_) -> hrec c
- | IsCast (c,_) -> hrec c
- | _ -> failwith "headconstant"
- in
- hrec
-
-let status_changed lev (pbty,t1,t2) =
- try
- List.mem (head_evar t1) lev or List.mem (head_evar t2) lev
- with Failure _ ->
- try List.mem (head_evar t2) lev with Failure _ -> false
+ if Array.length args1 < Array.length args2 then
+ evar_define isevars ev2 (mkEvar ev1)
+ else
+ evar_define isevars ev1 t2
+ | _ ->
+ evar_define isevars ev1 t2 in
+ let pbs = get_changed_pb lsp in
+ List.for_all (fun (pbty,t1,t2) -> conv_algo env isevars pbty t1 t2) pbs
-(* Operations on value/type constraints used in trad and progmach *)
+(* Operations on value/type constraints *)
type type_constraint = constr option
type val_constraint = constr option