aboutsummaryrefslogtreecommitdiff
path: root/pretyping
diff options
context:
space:
mode:
Diffstat (limited to 'pretyping')
-rw-r--r--pretyping/clenv.ml478
-rw-r--r--pretyping/clenv.mli143
-rw-r--r--pretyping/evarutil.ml22
-rw-r--r--pretyping/evarutil.mli4
-rw-r--r--pretyping/evd.ml59
-rw-r--r--pretyping/evd.mli11
-rw-r--r--pretyping/pretyping.mllib1
-rw-r--r--pretyping/typeclasses.ml15
-rw-r--r--pretyping/typeclasses.mli4
9 files changed, 78 insertions, 659 deletions
diff --git a/pretyping/clenv.ml b/pretyping/clenv.ml
deleted file mode 100644
index 7cbaf124a7..0000000000
--- a/pretyping/clenv.ml
+++ /dev/null
@@ -1,478 +0,0 @@
-(************************************************************************)
-(* v * The Coq Proof Assistant / The Coq Development Team *)
-(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(************************************************************************)
-
-(* $Id$ *)
-
-open Pp
-open Util
-open Names
-open Nameops
-open Term
-open Termops
-open Namegen
-open Sign
-open Environ
-open Evd
-open Reduction
-open Reductionops
-open Rawterm
-open Pattern
-open Tacred
-open Pretype_errors
-open Evarutil
-open Unification
-open Mod_subst
-open Coercion.Default
-
-(* Abbreviations *)
-
-let pf_env gls = Global.env_of_context gls.it.evar_hyps
-let pf_hyps gls = named_context_of_val gls.it.evar_hyps
-let pf_type_of gls c = Typing.type_of (pf_env gls) gls.sigma c
-let pf_concl gl = gl.it.evar_concl
-
-(******************************************************************)
-(* Clausal environments *)
-
-type clausenv = {
- env : env;
- evd : evar_map;
- templval : constr freelisted;
- templtyp : constr freelisted }
-
-let cl_env ce = ce.env
-let cl_sigma ce = ce.evd
-
-let subst_clenv sub clenv =
- { templval = map_fl (subst_mps sub) clenv.templval;
- templtyp = map_fl (subst_mps sub) clenv.templtyp;
- evd = subst_evar_defs_light sub clenv.evd;
- env = clenv.env }
-
-let clenv_nf_meta clenv c = nf_meta clenv.evd c
-let clenv_term clenv c = meta_instance clenv.evd c
-let clenv_meta_type clenv mv = Typing.meta_type clenv.evd mv
-let clenv_value clenv = meta_instance clenv.evd clenv.templval
-let clenv_type clenv = meta_instance clenv.evd clenv.templtyp
-
-
-let clenv_hnf_constr ce t = hnf_constr (cl_env ce) (cl_sigma ce) t
-
-let clenv_get_type_of ce c = Retyping.get_type_of (cl_env ce) (cl_sigma ce) c
-
-exception NotExtensibleClause
-
-let clenv_push_prod cl =
- let typ = whd_betadeltaiota (cl_env cl) (cl_sigma cl) (clenv_type cl) in
- let rec clrec typ = match kind_of_term typ with
- | Cast (t,_,_) -> clrec t
- | Prod (na,t,u) ->
- let mv = new_meta () in
- let dep = dependent (mkRel 1) u in
- let na' = if dep then na else Anonymous in
- let e' = meta_declare mv t ~name:na' cl.evd in
- let concl = if dep then subst1 (mkMeta mv) u else u in
- let def = applist (cl.templval.rebus,[mkMeta mv]) in
- { templval = mk_freelisted def;
- templtyp = mk_freelisted concl;
- evd = e';
- env = cl.env }
- | _ -> raise NotExtensibleClause
- in clrec typ
-
-(* Instantiate the first [bound] products of [t] with metas (all products if
- [bound] is [None]; unfold local defs *)
-
-let clenv_environments evd bound t =
- let rec clrec (e,metas) n t =
- match n, kind_of_term t with
- | (Some 0, _) -> (e, List.rev metas, t)
- | (n, Cast (t,_,_)) -> clrec (e,metas) n t
- | (n, Prod (na,t1,t2)) ->
- let mv = new_meta () in
- let dep = dependent (mkRel 1) t2 in
- let na' = if dep then na else Anonymous in
- let e' = meta_declare mv t1 ~name:na' e in
- clrec (e', (mkMeta mv)::metas) (Option.map ((+) (-1)) n)
- (if dep then (subst1 (mkMeta mv) t2) else t2)
- | (n, LetIn (na,b,_,t)) -> clrec (e,metas) n (subst1 b t)
- | (n, _) -> (e, List.rev metas, t)
- in
- clrec (evd,[]) bound t
-
-(* Instantiate the first [bound] products of [t] with evars (all products if
- [bound] is [None]; unfold local defs *)
-
-let clenv_environments_evars env evd bound t =
- let rec clrec (e,ts) n t =
- match n, kind_of_term t with
- | (Some 0, _) -> (e, List.rev ts, t)
- | (n, Cast (t,_,_)) -> clrec (e,ts) n t
- | (n, Prod (na,t1,t2)) ->
- let e',constr = Evarutil.new_evar e env t1 in
- let dep = dependent (mkRel 1) t2 in
- clrec (e', constr::ts) (Option.map ((+) (-1)) n)
- (if dep then (subst1 constr t2) else t2)
- | (n, LetIn (na,b,_,t)) -> clrec (e,ts) n (subst1 b t)
- | (n, _) -> (e, List.rev ts, t)
- in
- clrec (evd,[]) bound t
-
-let clenv_conv_leq env sigma t c bound =
- let ty = Retyping.get_type_of env sigma c in
- let evd = Evd.create_goal_evar_defs sigma in
- let evars,args,_ = clenv_environments_evars env evd (Some bound) ty in
- let evars = Evarconv.the_conv_x_leq env t (applist (c,args)) evars in
- let evars = Evarconv.consider_remaining_unif_problems env evars in
- let args = List.map (whd_evar evars) args in
- check_evars env sigma evars (applist (c,args));
- args
-
-let mk_clenv_from_env environ sigma n (c,cty) =
- let evd = create_goal_evar_defs sigma in
- let (evd,args,concl) = clenv_environments evd n cty in
- { templval = mk_freelisted (match args with [] -> c | _ -> applist (c,args));
- templtyp = mk_freelisted concl;
- evd = evd;
- env = environ }
-
-let mk_clenv_from_n gls n (c,cty) =
- mk_clenv_from_env (Global.env_of_context gls.it.evar_hyps) gls.sigma n (c, cty)
-
-let mk_clenv_from gls = mk_clenv_from_n gls None
-
-let mk_clenv_rename_from_n gls n (c,t) =
- mk_clenv_from_n gls n (c,rename_bound_vars_as_displayed [] t)
-
-let mk_clenv_type_of gls t = mk_clenv_from gls (t,pf_type_of gls t)
-
-(******************************************************************)
-
-(* [mentions clenv mv0 mv1] is true if mv1 is defined and mentions
- * mv0, or if one of the free vars on mv1's freelist mentions
- * mv0 *)
-
-let mentions clenv mv0 =
- let rec menrec mv1 =
- mv0 = mv1 ||
- let mlist =
- try match meta_opt_fvalue clenv.evd mv1 with
- | Some (b,_) -> b.freemetas
- | None -> Metaset.empty
- with Not_found -> Metaset.empty in
- meta_exists menrec mlist
- in menrec
-
-let error_incompatible_inst clenv mv =
- let na = meta_name clenv.evd mv in
- match na with
- Name id ->
- errorlabstrm "clenv_assign"
- (str "An incompatible instantiation has already been found for " ++
- pr_id id)
- | _ ->
- anomaly "clenv_assign: non dependent metavar already assigned"
-
-(* TODO: replace by clenv_unify (mkMeta mv) rhs ? *)
-let clenv_assign mv rhs clenv =
- let rhs_fls = mk_freelisted rhs in
- if meta_exists (mentions clenv mv) rhs_fls.freemetas then
- error "clenv_assign: circularity in unification";
- try
- if meta_defined clenv.evd mv then
- if not (eq_constr (fst (meta_fvalue clenv.evd mv)).rebus rhs) then
- error_incompatible_inst clenv mv
- else
- clenv
- else
- let st = (ConvUpToEta 0,TypeNotProcessed) in
- {clenv with evd = meta_assign mv (rhs_fls.rebus,st) clenv.evd}
- with Not_found ->
- error "clenv_assign: undefined meta"
-
-
-
-(* [clenv_dependent hyps_only clenv]
- * returns a list of the metavars which appear in the template of clenv,
- * and which are dependent, This is computed by taking the metavars in cval,
- * in right-to-left order, and collecting the metavars which appear
- * in their types, and adding in all the metavars appearing in the
- * type of clenv.
- * If [hyps_only] then metavariables occurring in the type are _excluded_ *)
-
-(* [clenv_metavars clenv mv]
- * returns a list of the metavars which appear in the type of
- * the metavar mv. The list is unordered. *)
-
-let clenv_metavars evd mv =
- (mk_freelisted (meta_instance evd (meta_ftype evd mv))).freemetas
-
-let dependent_metas clenv mvs conclmetas =
- List.fold_right
- (fun mv deps ->
- Metaset.union deps (clenv_metavars clenv.evd mv))
- mvs conclmetas
-
-let duplicated_metas c =
- let rec collrec (one,more as acc) c =
- match kind_of_term c with
- | Meta mv -> if List.mem mv one then (one,mv::more) else (mv::one,more)
- | _ -> fold_constr collrec acc c
- in
- snd (collrec ([],[]) c)
-
-let clenv_dependent hyps_only clenv =
- let mvs = undefined_metas clenv.evd in
- let ctyp_mvs = (mk_freelisted (clenv_type clenv)).freemetas in
- let deps = dependent_metas clenv mvs ctyp_mvs in
- let nonlinear = duplicated_metas (clenv_value clenv) in
- (* Make the assumption that duplicated metas have internal dependencies *)
- List.filter
- (fun mv -> if Metaset.mem mv deps
- then not (hyps_only && Metaset.mem mv ctyp_mvs)
- else List.mem mv nonlinear)
- mvs
-
-let clenv_missing ce = clenv_dependent true ce
-
-(******************************************************************)
-
-let clenv_unify allow_K ?(flags=default_unify_flags) cv_pb t1 t2 clenv =
- { clenv with
- evd = w_unify allow_K ~flags:flags clenv.env cv_pb t1 t2 clenv.evd }
-
-let clenv_unify_meta_types ?(flags=default_unify_flags) clenv =
- { clenv with evd = w_unify_meta_types ~flags:flags clenv.env clenv.evd }
-
-let clenv_unique_resolver allow_K ?(flags=default_unify_flags) clenv gl =
- if isMeta (fst (whd_stack clenv.evd clenv.templtyp.rebus)) then
- clenv_unify allow_K CUMUL ~flags:flags (clenv_type clenv) (pf_concl gl)
- (clenv_unify_meta_types ~flags:flags clenv)
- else
- clenv_unify allow_K CUMUL ~flags:flags
- (meta_reducible_instance clenv.evd clenv.templtyp) (pf_concl gl) clenv
-
-(* [clenv_pose_metas_as_evars clenv dep_mvs]
- * For each dependent evar in the clause-env which does not have a value,
- * pose a value for it by constructing a fresh evar. We do this in
- * left-to-right order, so that every evar's type is always closed w.r.t.
- * metas.
-
- * Node added 14/4/08 [HH]: before this date, evars were collected in
- clenv_dependent by collect_metas in the fold_constr order which is
- (almost) the left-to-right order of dependencies in term. However,
- due to K-redexes, collect_metas was sometimes missing some metas.
- The call to collect_metas has been replaced by a call to
- undefined_metas, but then the order was the one of definition of
- the metas (numbers in increasing order) which is _not_ the
- dependency order when a clenv_fchain occurs (because clenv_fchain
- plugs a term with a list of consecutive metas in place of a - a priori -
- arbitrary metavariable belonging to another sequence of consecutive metas:
- e.g., clenv_fchain may plug (H ?1 ?2) at the position ?6 of
- (nat_ind ?3 ?4 ?5 ?6), leading to a dependency order 3<4<5<1<2).
- To ensure the dependency order, we check that the type of each meta
- to pose is already meta-free, otherwise we postpone the transformation,
- hoping that no cycle may happen.
-
- Another approach could have been to use decimal numbers for metas so that
- in the example above, (H ?1 ?2) would have been renumbered (H ?6.1 ?6.2)
- then making the numeric order match the dependency order.
-*)
-
-let clenv_pose_metas_as_evars clenv dep_mvs =
- let rec fold clenv = function
- | [] -> clenv
- | mv::mvs ->
- let ty = clenv_meta_type clenv mv in
- (* Postpone the evar-ization if dependent on another meta *)
- (* This assumes no cycle in the dependencies - is it correct ? *)
- if occur_meta ty then fold clenv (mvs@[mv])
- else
- let (evd,evar) =
- new_evar clenv.evd (cl_env clenv) ~src:(dummy_loc,GoalEvar) ty in
- let clenv = clenv_assign mv evar {clenv with evd=evd} in
- fold clenv mvs in
- fold clenv dep_mvs
-
-let evar_clenv_unique_resolver = clenv_unique_resolver
-
-(******************************************************************)
-
-let connect_clenv gls clenv =
- { clenv with
- evd = evars_reset_evd gls.sigma clenv.evd;
- env = Global.env_of_context gls.it.evar_hyps }
-
-(* [clenv_fchain mv clenv clenv']
- *
- * Resolves the value of "mv" (which must be undefined) in clenv to be
- * the template of clenv' be the value "c", applied to "n" fresh
- * metavars, whose types are chosen by destructing "clf", which should
- * be a clausale forme generated from the type of "c". The process of
- * resolution can cause unification of already-existing metavars, and
- * of the fresh ones which get created. This operation is a composite
- * of operations which pose new metavars, perform unification on
- * terms, and make bindings.
-
- Otherwise said, from
-
- [clenv] = [env;sigma;metas |- c:T]
- [clenv'] = [env';sigma';metas' |- d:U]
- [mv] = [mi] of type [Ti] in [metas]
-
- then, if the unification of [Ti] and [U] produces map [rho], the
- chaining is [env';sigma';rho'(metas),rho(metas') |- c:rho'(T)] for
- [rho'] being [rho;mi:=d].
-
- In particular, it assumes that [env'] and [sigma'] extend [env] and [sigma].
-*)
-let clenv_fchain ?(allow_K=true) ?(flags=default_unify_flags) mv clenv nextclenv =
- (* Add the metavars of [nextclenv] to [clenv], with their name-environment *)
- let clenv' =
- { templval = clenv.templval;
- templtyp = clenv.templtyp;
- evd =
- evar_merge (meta_merge clenv.evd nextclenv.evd) clenv.evd;
- env = nextclenv.env } in
- (* unify the type of the template of [nextclenv] with the type of [mv] *)
- let clenv'' =
- clenv_unify allow_K ~flags:flags CUMUL
- (clenv_term clenv' nextclenv.templtyp)
- (clenv_meta_type clenv' mv)
- clenv' in
- (* assign the metavar *)
- let clenv''' =
- clenv_assign mv (clenv_term clenv' nextclenv.templval) clenv''
- in
- clenv'''
-
-(***************************************************************)
-(* Bindings *)
-
-type arg_bindings = constr explicit_bindings
-
-(* [clenv_independent clenv]
- * returns a list of metavariables which appear in the term cval,
- * and which are not dependent. That is, they do not appear in
- * the types of other metavars which are in cval, nor in the type
- * of cval, ctyp. *)
-
-let clenv_independent clenv =
- let mvs = collect_metas (clenv_value clenv) in
- let ctyp_mvs = (mk_freelisted (clenv_type clenv)).freemetas in
- let deps = dependent_metas clenv mvs ctyp_mvs in
- List.filter (fun mv -> not (Metaset.mem mv deps)) mvs
-
-let check_bindings bl =
- match list_duplicates (List.map pi2 bl) with
- | NamedHyp s :: _ ->
- errorlabstrm ""
- (str "The variable " ++ pr_id s ++
- str " occurs more than once in binding list.");
- | AnonHyp n :: _ ->
- errorlabstrm ""
- (str "The position " ++ int n ++
- str " occurs more than once in binding list.")
- | [] -> ()
-
-let meta_of_binder clause loc mvs = function
- | NamedHyp s -> meta_with_name clause.evd s
- | AnonHyp n ->
- try List.nth mvs (n-1)
- with (Failure _|Invalid_argument _) ->
- errorlabstrm "" (str "No such binder.")
-
-let error_already_defined b =
- match b with
- | NamedHyp id ->
- errorlabstrm ""
- (str "Binder name \"" ++ pr_id id ++
- str"\" already defined with incompatible value.")
- | AnonHyp n ->
- anomalylabstrm ""
- (str "Position " ++ int n ++ str" already defined.")
-
-let clenv_unify_binding_type clenv c t u =
- if isMeta (fst (whd_stack clenv.evd u)) then
- (* Not enough information to know if some subtyping is needed *)
- CoerceToType, clenv, c
- else
- (* Enough information so as to try a coercion now *)
- try
- let evd,c = w_coerce_to_type (cl_env clenv) clenv.evd c t u in
- TypeProcessed, { clenv with evd = evd }, c
- with
- | PretypeError (_,NotClean _) as e -> raise e
- | e when precatchable_exception e ->
- TypeNotProcessed, clenv, c
-
-let clenv_assign_binding clenv k c =
- let k_typ = clenv_hnf_constr clenv (clenv_meta_type clenv k) in
- let c_typ = nf_betaiota clenv.evd (clenv_get_type_of clenv c) in
- let status,clenv',c = clenv_unify_binding_type clenv c c_typ k_typ in
- { clenv' with evd = meta_assign k (c,(UserGiven,status)) clenv'.evd }
-
-let clenv_match_args bl clenv =
- if bl = [] then
- clenv
- else
- let mvs = clenv_independent clenv in
- check_bindings bl;
- List.fold_left
- (fun clenv (loc,b,c) ->
- let k = meta_of_binder clenv loc mvs b in
- if meta_defined clenv.evd k then
- if eq_constr (fst (meta_fvalue clenv.evd k)).rebus c then clenv
- else error_already_defined b
- else
- clenv_assign_binding clenv k c)
- clenv bl
-
-let clenv_constrain_last_binding c clenv =
- let all_mvs = collect_metas clenv.templval.rebus in
- let k =
- try list_last all_mvs
- with Failure _ -> anomaly "clenv_constrain_with_bindings" in
- clenv_assign_binding clenv k c
-
-let clenv_constrain_dep_args hyps_only bl clenv =
- if bl = [] then
- clenv
- else
- let occlist = clenv_dependent hyps_only clenv in
- if List.length occlist = List.length bl then
- List.fold_left2 clenv_assign_binding clenv occlist bl
- else
- errorlabstrm ""
- (strbrk "Not the right number of missing arguments (expected " ++
- int (List.length occlist) ++ str ").")
-
-(****************************************************************)
-(* Clausal environment for an application *)
-
-let make_clenv_binding_gen hyps_only n gls (c,t) = function
- | ImplicitBindings largs ->
- let clause = mk_clenv_from_n gls n (c,t) in
- clenv_constrain_dep_args hyps_only largs clause
- | ExplicitBindings lbind ->
- let clause = mk_clenv_rename_from_n gls n (c,t) in
- clenv_match_args lbind clause
- | NoBindings ->
- mk_clenv_from_n gls n (c,t)
-
-let make_clenv_binding_apply gls n = make_clenv_binding_gen true n gls
-let make_clenv_binding = make_clenv_binding_gen false None
-
-(****************************************************************)
-(* Pretty-print *)
-
-let pr_clenv clenv =
- h 0
- (str"TEMPL: " ++ print_constr clenv.templval.rebus ++
- str" : " ++ print_constr clenv.templtyp.rebus ++ fnl () ++
- pr_evar_map clenv.evd)
diff --git a/pretyping/clenv.mli b/pretyping/clenv.mli
deleted file mode 100644
index 4f7ac40920..0000000000
--- a/pretyping/clenv.mli
+++ /dev/null
@@ -1,143 +0,0 @@
-(************************************************************************)
-(* v * The Coq Proof Assistant / The Coq Development Team *)
-(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
-(* \VV/ **************************************************************)
-(* // * This file is distributed under the terms of the *)
-(* * GNU Lesser General Public License Version 2.1 *)
-(************************************************************************)
-
-(*i $Id$ i*)
-
-(*i*)
-open Util
-open Names
-open Term
-open Sign
-open Environ
-open Evd
-open Evarutil
-open Mod_subst
-open Rawterm
-open Unification
-(*i*)
-
-(***************************************************************)
-(* The Type of Constructions clausale environments. *)
-
-(* [env] is the typing context
- * [evd] is the mapping from metavar and evar numbers to their types
- * and values.
- * [templval] is the template which we are trying to fill out.
- * [templtyp] is its type.
- *)
-type clausenv = {
- env : env;
- evd : evar_map;
- templval : constr freelisted;
- templtyp : constr freelisted }
-
-(* Substitution is not applied on templenv (because [subst_clenv] is
- applied only on hints which typing env is overwritten by the
- goal env) *)
-val subst_clenv : substitution -> clausenv -> clausenv
-
-(* subject of clenv (instantiated) *)
-val clenv_value : clausenv -> constr
-(* type of clenv (instantiated) *)
-val clenv_type : clausenv -> types
-(* substitute resolved metas *)
-val clenv_nf_meta : clausenv -> constr -> constr
-(* type of a meta in clenv context *)
-val clenv_meta_type : clausenv -> metavariable -> types
-
-val mk_clenv_from : evar_info sigma -> constr * types -> clausenv
-val mk_clenv_from_n :
- evar_info sigma -> int option -> constr * types -> clausenv
-val mk_clenv_type_of : evar_info sigma -> constr -> clausenv
-val mk_clenv_from_env : env -> evar_map -> int option -> constr * types -> clausenv
-
-(***************************************************************)
-(* linking of clenvs *)
-
-val connect_clenv : evar_info sigma -> clausenv -> clausenv
-val clenv_fchain :
- ?allow_K:bool -> ?flags:unify_flags -> metavariable -> clausenv -> clausenv -> clausenv
-
-(***************************************************************)
-(* Unification with clenvs *)
-
-(* Unifies two terms in a clenv. The boolean is [allow_K] (see [Unification]) *)
-val clenv_unify :
- bool -> ?flags:unify_flags -> conv_pb -> constr -> constr -> clausenv -> clausenv
-
-(* unifies the concl of the goal with the type of the clenv *)
-val clenv_unique_resolver :
- bool -> ?flags:unify_flags -> clausenv -> evar_info sigma -> clausenv
-
-(* same as above ([allow_K=false]) but replaces remaining metas
- with fresh evars if [evars_flag] is [true] *)
-val evar_clenv_unique_resolver :
- bool -> ?flags:unify_flags -> clausenv -> evar_info sigma -> clausenv
-
-val clenv_dependent : bool -> clausenv -> metavariable list
-
-val clenv_pose_metas_as_evars : clausenv -> metavariable list -> clausenv
-
-(***************************************************************)
-(* Bindings *)
-
-type arg_bindings = constr explicit_bindings
-
-(* bindings where the key is the position in the template of the
- clenv (dependent or not). Positions can be negative meaning to
- start from the rightmost argument of the template. *)
-val clenv_independent : clausenv -> metavariable list
-val clenv_missing : clausenv -> metavariable list
-
-val clenv_constrain_last_binding : constr -> clausenv -> clausenv
-
-(* defines metas corresponding to the name of the bindings *)
-val clenv_match_args : arg_bindings -> clausenv -> clausenv
-
-val clenv_unify_meta_types : ?flags:unify_flags -> clausenv -> clausenv
-
-(* start with a clenv to refine with a given term with bindings *)
-
-(* the arity of the lemma is fixed *)
-(* the optional int tells how many prods of the lemma have to be used *)
-(* use all of them if None *)
-val make_clenv_binding_apply :
- evar_info sigma -> int option -> constr * constr -> constr bindings ->
- clausenv
-val make_clenv_binding :
- evar_info sigma -> constr * constr -> constr bindings -> clausenv
-
-(* [clenv_environments sigma n t] returns [sigma',lmeta,ccl] where
- [lmetas] is a list of metas to be applied to a proof of [t] so that
- it produces the unification pattern [ccl]; [sigma'] is [sigma]
- extended with [lmetas]; if [n] is defined, it limits the size of
- the list even if [ccl] is still a product; otherwise, it stops when
- [ccl] is not a product; example: if [t] is [forall x y, x=y -> y=x]
- and [n] is [None], then [lmetas] is [Meta n1;Meta n2;Meta n3] and
- [ccl] is [Meta n1=Meta n2]; if [n] is [Some 1], [lmetas] is [Meta n1]
- and [ccl] is [forall y, Meta n1=y -> y=Meta n1] *)
-val clenv_environments :
- evar_map -> int option -> types -> evar_map * constr list * types
-
-(* [clenv_environments_evars env sigma n t] does the same but returns
- a list of Evar's defined in [env] and extends [sigma] accordingly *)
-val clenv_environments_evars :
- env -> evar_map -> int option -> types -> evar_map * constr list * types
-
-(* [clenv_conv_leq env sigma t c n] looks for c1...cn s.t. [t <= c c1...cn] *)
-val clenv_conv_leq :
- env -> evar_map -> types -> constr -> int -> constr list
-
-(* if the clause is a product, add an extra meta for this product *)
-exception NotExtensibleClause
-val clenv_push_prod : clausenv -> clausenv
-
-(***************************************************************)
-(* Pretty-print *)
-val pr_clenv : clausenv -> Pp.std_ppcmds
-
diff --git a/pretyping/evarutil.ml b/pretyping/evarutil.ml
index 24850b4baf..6d37cf80f5 100644
--- a/pretyping/evarutil.ml
+++ b/pretyping/evarutil.ml
@@ -150,12 +150,11 @@ let evars_to_metas sigma (emap, c) =
(* The list of non-instantiated existential declarations *)
let non_instantiated sigma =
- let listev = to_list sigma in
- List.fold_left
- (fun l (ev,evi) ->
- if evi.evar_body = Evar_empty then
- ((ev,nf_evar_info sigma evi)::l) else l)
- [] listev
+ List.rev begin
+ Evd.fold_undefined begin fun ev evi l ->
+ (ev,nf_evar_info sigma evi)::l
+ end sigma []
+ end
(**********************)
(* Creating new evars *)
@@ -478,6 +477,10 @@ type clear_dependency_error =
exception ClearDependencyError of identifier * clear_dependency_error
+open Store.Field
+
+let cleared = Store.field ()
+
let rec check_and_clear_in_constr evdref err ids c =
(* returns a new constr where all the evars have been 'cleaned'
(ie the hypotheses ids have been removed from the contexts of
@@ -539,6 +542,13 @@ let rec check_and_clear_in_constr evdref err ids c =
let ev'= e_new_evar evdref env ~src:(evar_source evk !evdref) nconcl in
evdref := Evd.define evk ev' !evdref;
let (evk',_) = destEvar ev' in
+ (* spiwack: hacking session to mark the old [evk] as having been "cleared" *)
+ let evi = Evd.find !evdref evk in
+ let extra = evi.evar_extra in
+ let extra' = cleared.set true extra in
+ let evi' = { evi with evar_extra = extra' } in
+ evdref := Evd.add !evdref evk evi' ;
+ (* spiwack: /hacking session *)
mkEvar(evk', Array.of_list nargs)
end
diff --git a/pretyping/evarutil.mli b/pretyping/evarutil.mli
index 205ca8bd64..39f8dd05ac 100644
--- a/pretyping/evarutil.mli
+++ b/pretyping/evarutil.mli
@@ -193,6 +193,10 @@ type clear_dependency_error =
exception ClearDependencyError of identifier * clear_dependency_error
+(* spiwack: marks an evar that has been "defined" by clear.
+ used by [Goal] and (indirectly) [Proofview] to handle the clear tactic gracefully*)
+val cleared : bool Store.Field.t
+
val clear_hyps_in_evi : evar_map ref -> named_context_val -> types ->
identifier list -> named_context_val * types
diff --git a/pretyping/evd.ml b/pretyping/evd.ml
index a9b42f052b..5b4a3f214d 100644
--- a/pretyping/evd.ml
+++ b/pretyping/evd.ml
@@ -51,7 +51,7 @@ type evar_info = {
evar_body : evar_body;
evar_filter : bool list;
evar_source : hole_kind located;
- evar_extra : Dyn.t option}
+ evar_extra : Store.t }
let make_evar hyps ccl = {
evar_concl = ccl;
@@ -59,7 +59,7 @@ let make_evar hyps ccl = {
evar_body = Evar_empty;
evar_filter = List.map (fun _ -> true) (named_context_of_val hyps);
evar_source = (dummy_loc,InternalHole);
- evar_extra = None
+ evar_extra = Store.empty
}
let evar_concl evi = evi.evar_concl
@@ -93,26 +93,31 @@ module ExistentialSet = Intset
(* This exception is raised by *.existential_value *)
exception NotInstantiatedEvar
+
module EvarInfoMap = struct
- type t = evar_info ExistentialMap.t
+ type t = evar_info ExistentialMap.t
- let empty = ExistentialMap.empty
+ let empty = ExistentialMap.empty
+ let is_empty = ExistentialMap.is_empty
let to_list evc = (* Workaround for change in Map.fold behavior *)
+ (* spiwack: seems to arrange the items in decreasing order.
+ Which would also be the behaviour of a naive [fold].
+ I don't understand above comment. *)
let l = ref [] in
ExistentialMap.iter (fun evk x -> l := (evk,x)::!l) evc;
!l
let dom evc = ExistentialMap.fold (fun evk _ acc -> evk::acc) evc []
let find evc k = ExistentialMap.find k evc
- let remove evc k = ExistentialMap.remove k evc
+ let remove evc k = ExistentialMap.remove k evc
let mem evc k = ExistentialMap.mem k evc
let fold = ExistentialMap.fold
let exists evc f = ExistentialMap.fold (fun k v b -> b || f k v) evc false
let add evd evk newinfo = ExistentialMap.add evk newinfo evd
- let equal = ExistentialMap.equal
+ let map = ExistentialMap.map
let define evd evk body =
let oldinfo =
@@ -182,6 +187,14 @@ module EvarInfoMap = struct
try Some (existential_value sigma ev)
with NotInstantiatedEvar -> None
+ (* Combinators on undefined evars. *)
+ let fold_undefined f = ExistentialMap.fold begin fun ev evi acc ->
+ match evar_body evi with
+ | Evar_empty -> f ev evi acc
+ | _ -> acc
+ end
+
+ let undefined evm = fold_undefined ExistentialMap.add evm empty
end
(*******************************************************************)
@@ -336,7 +349,23 @@ module EvarMap = struct
(EvarInfoMap.find sigma2 k).evar_body <> Evar_empty)
|| not (UniverseMap.equal (=) sm1 sm2))
- let merge e e' = fold (fun n v sigma -> add sigma n v) e' e
+ (* spiwack: used to workaround a bug in clenv: evar_merge
+ could merge an "old" version of an evar map into
+ a more up to date and erase evar definitions (in the case
+ of [constructor_tac] it actually erased a goal in some cases).
+ This is due to the fact that [open_constr] carry around their own
+ sigma which can be outdated by other operations. *)
+ let add_if_more_recent evd evk newinfo =
+ if newinfo.evar_body = Evar_empty && mem evd evk then
+ evd
+ else
+ add evd evk newinfo
+
+ let merge e e' = fold (fun n v sigma -> add_if_more_recent sigma n v) e' e
+
+ (* combinators on undefined values *)
+ let undefined (sigma,sm) = (EvarInfoMap.undefined sigma,sm)
+ let fold_undefined f (sigma,_) = EvarInfoMap.fold_undefined f sigma
end
@@ -441,7 +470,6 @@ let progress_evar_map d1 d2 =
(* spiwack: tentative. It might very well not be the semantics we want
for merging evar_map *)
let merge d1 d2 = {
-(* d1 with evars = EvarMap.merge d1.evars d2.evars*)
evars = EvarMap.merge d1.evars d2.evars ;
conv_pbs = List.rev_append d1.conv_pbs d2.conv_pbs ;
last_mods = ExistentialSet.union d1.last_mods d2.last_mods ;
@@ -488,7 +516,7 @@ let subst_evar_defs_light sub evd =
assert (evd.conv_pbs = []);
{ evd with
metas = Metamap.map (map_clb (subst_mps sub)) evd.metas;
- evars = ExistentialMap.map (subst_evar_info sub) (fst evd.evars), snd evd.evars
+ evars = EvarInfoMap.map (subst_evar_info sub) (fst evd.evars), (snd evd.evars)
}
let subst_evar_map = subst_evar_defs_light
@@ -536,7 +564,7 @@ let evar_declare hyps evk ty ?(src=(dummy_loc,InternalHole)) ?filter evd =
evar_body = Evar_empty;
evar_filter = filter;
evar_source = src;
- evar_extra = None} }
+ evar_extra = Store.empty } }
let is_defined_evar evd (evk,_) = EvarMap.is_defined evd.evars evk
@@ -546,12 +574,10 @@ let is_undefined_evar evd c = match kind_of_term c with
| _ -> false
let undefined_evars evd =
- let evars =
- EvarMap.fold (fun evk evi sigma -> if evi.evar_body = Evar_empty then
- EvarMap.add sigma evk evi else sigma)
- evd.evars EvarMap.empty
- in
- { evd with evars = evars }
+ let evars = EvarMap.undefined evd.evars in
+ { evd with evars = evars }
+
+let fold_undefined f evd = EvarMap.fold_undefined f evd.evars
(* extracts conversion problems that satisfy predicate p *)
(* Note: conv_pbs not satisying p are stored back in reverse order *)
@@ -694,7 +720,6 @@ let meta_with_name evd id =
strbrk "\" occurs more than once in clause.")
-(* spiwack: we should try and replace this List.fold_left by a Metamap.fold. *)
let meta_merge evd1 evd2 =
{evd2 with
metas = List.fold_left (fun m (n,v) -> Metamap.add n v m)
diff --git a/pretyping/evd.mli b/pretyping/evd.mli
index b82e6d998d..f895ead42c 100644
--- a/pretyping/evd.mli
+++ b/pretyping/evd.mli
@@ -123,7 +123,7 @@ type evar_info = {
evar_body : evar_body;
evar_filter : bool list;
evar_source : hole_kind located;
- evar_extra : Dyn.t option}
+ evar_extra : Store.t }
val eq_evar_info : evar_info -> evar_info -> bool
@@ -185,6 +185,15 @@ val evars_reset_evd : evar_map -> evar_map -> evar_map
for moving to evarutils *)
val is_undefined_evar : evar_map -> constr -> bool
val undefined_evars : evar_map -> evar_map
+(* [fold_undefined f m] iterates ("folds") function [f] over the undefined
+ evars (that is, whose value is [Evar_empty]) of map [m].
+ Making it effectively equivalent to {!Evd.fold} applies to
+ [f] and [undefined_evars m] *)
+(* spiwack: at the moment, [fold_undefined] is defined rather naively.
+ But we can hope to enable some optimisation in the future, as
+ an evar_map contains typically few undefined evars compared to all
+ its evars. *)
+val fold_undefined : (evar -> evar_info -> 'a -> 'a) -> evar_map -> 'a -> 'a
val evar_declare :
named_context_val -> evar -> types -> ?src:loc * hole_kind ->
?filter:bool list -> evar_map -> evar_map
diff --git a/pretyping/pretyping.mllib b/pretyping/pretyping.mllib
index cea33c1e98..6aa00c5f25 100644
--- a/pretyping/pretyping.mllib
+++ b/pretyping/pretyping.mllib
@@ -21,7 +21,6 @@ Typeclasses
Classops
Coercion
Unification
-Clenv
Detyping
Indrec
Cases
diff --git a/pretyping/typeclasses.ml b/pretyping/typeclasses.ml
index 4ec5cf1f17..88d4a4d6b3 100644
--- a/pretyping/typeclasses.ml
+++ b/pretyping/typeclasses.ml
@@ -355,18 +355,15 @@ let is_implicit_arg k =
calls (e.g. when doing apply in an External hint in typeclass_instances).
Would be solved by having real evars-as-goals. *)
-let ((bool_in : bool -> Dyn.t),
- (bool_out : Dyn.t -> bool)) = Dyn.create "bool"
-
-let bool_false = bool_in false
+let resolvable = Store.field ()
+open Store.Field
let is_resolvable evi =
- match evi.evar_extra with
- Some t -> if Dyn.tag t = "bool" then bool_out t else true
- | None -> true
+ Option.default true (resolvable.get evi.evar_extra)
let mark_unresolvable evi =
- { evi with evar_extra = Some bool_false }
+ let t = resolvable.set false evi.evar_extra in
+ { evi with evar_extra = t }
let mark_unresolvables sigma =
Evd.fold (fun ev evi evs ->
@@ -374,7 +371,7 @@ let mark_unresolvables sigma =
sigma Evd.empty
let has_typeclasses evd =
- Evd.fold (fun ev evi has -> has ||
+ Evd.fold_undefined (fun ev evi has -> has ||
(evi.evar_body = Evar_empty && is_class_evar evd evi && is_resolvable evi))
evd false
diff --git a/pretyping/typeclasses.mli b/pretyping/typeclasses.mli
index 997b28c105..e53be5c0bf 100644
--- a/pretyping/typeclasses.mli
+++ b/pretyping/typeclasses.mli
@@ -77,10 +77,6 @@ val is_implicit_arg : hole_kind -> bool
val instance_constructor : typeclass -> constr list -> constr * types
-(* Use evar_extra for marking resolvable evars. *)
-val bool_in : bool -> Dyn.t
-val bool_out : Dyn.t -> bool
-
val is_resolvable : evar_info -> bool
val mark_unresolvable : evar_info -> evar_info
val mark_unresolvables : evar_map -> evar_map