diff options
-rw-r--r-- | pretyping/evarconv.ml | 5 | ||||
-rw-r--r-- | pretyping/evarutil.ml | 202 | ||||
-rw-r--r-- | pretyping/evarutil.mli | 2 | ||||
-rw-r--r-- | pretyping/evd.ml | 9 | ||||
-rw-r--r-- | pretyping/pretyping.ml | 14 | ||||
-rw-r--r-- | pretyping/typing.ml | 61 | ||||
-rw-r--r-- | tactics/equality.ml | 2 |
7 files changed, 170 insertions, 125 deletions
diff --git a/pretyping/evarconv.ml b/pretyping/evarconv.ml index 4af5a43cf..047b306ed 100644 --- a/pretyping/evarconv.ml +++ b/pretyping/evarconv.ml @@ -177,8 +177,9 @@ let rec evar_conv_x env isevars pbty term1 term2 = true else *) - (* Maybe convertible but since reducing can erase evars which [evar_apprec]*) - (* could have found, we do it only if the terms are free of evar *) + (* Maybe convertible but since reducing can erase evars which [evar_apprec] + could have found, we do it only if the terms are free of evar. + Note: incomplete heuristic... *) if (not (has_undefined_evars isevars term1) & not (has_undefined_evars isevars term2) & diff --git a/pretyping/evarutil.ml b/pretyping/evarutil.ml index 746d2cd8e..0e87e5893 100644 --- a/pretyping/evarutil.ml +++ b/pretyping/evarutil.ml @@ -28,25 +28,6 @@ let rec filter_unique = function if List.mem x l then filter_unique (List.filter (fun y -> x<>y) l) else x::filter_unique l -(* -let distinct_id_list = - let rec drec fresh = function - [] -> List.rev fresh - | id::rest -> - let id' = next_ident_away_from id fresh in drec (id'::fresh) rest - in drec [] -*) - -(* -let filter_sign p sign x = - sign_it - (fun id ty (v,ids,sgn) -> - let (disc,v') = p v (id,ty) in - if disc then (v', id::ids, sgn) else (v', ids, add_sign (id,ty) sgn)) - sign - (x,[],nil_sign) -*) - (* Expanding existential variables (pretyping.ml) *) (* 1- whd_ise fails if an existential is undefined *) @@ -133,6 +114,16 @@ let evars_to_metas sigma (emap, c) = | _ -> map_constr replace c in (sigma', replace c) +(* The list of non-instantiated existential declarations *) + +let non_instantiated sigma = + let listev = to_list sigma in + List.fold_left + (fun l (ev,evd) -> + if evd.evar_body = Evar_empty then + ((ev,nf_evar_info sigma evd)::l) else l) + [] listev + (*************************************) (* Metas *) @@ -229,13 +220,79 @@ let e_new_evar evd env ?(src=(dummy_loc,InternalHole)) ty = evd := evd'; ev -(* declare a new evar (tactic style) *) -let w_Declare env sp ty evd = - let sigma = evars_of evd in - if Evd.in_dom sigma sp then - error "w_Declare: cannot redeclare evar"; - let _ = Typing.type_of env sigma ty in (* Checks there is no meta *) - Evd.evar_declare (named_context env) sp ty evd +(*------------------------------------* + * operations on the evar constraints * + *------------------------------------*) + +let is_pattern inst = + let rec is_hopat l = function + [] -> true + | t :: tl -> + (isRel t or isVar t) && not (List.mem t l) && is_hopat (t::l) tl in + is_hopat [] (Array.to_list inst) + +let evar_well_typed_body evd ev evi body = + try + let env = evar_env evi in + let ty = evi.evar_concl in + Typing.check env (evars_of evd) body ty; + true + with e -> + pperrnl + (str "Ill-typed evar instantiation: " ++ fnl() ++ + pr_evar_defs evd ++ fnl() ++ + str "----> " ++ int ev ++ str " := " ++ + print_constr body); + false + +let strict_inverse = false + +let inverse_instance env isevars ev evi inst rhs = + let subst = make_subst (evar_env evi) (Array.to_list inst) in + let subst = List.map (fun (x,y) -> (y,mkVar x)) subst in + let evd = ref isevars in + let error () = + error_not_clean env (evars_of !evd) ev rhs (evar_source ev !evd) in + let rec subs rigid k t = + match kind_of_term t with + | Rel i -> + if i<=k then t + else + (try List.assoc (mkRel (i-k)) subst + with Not_found -> + if rigid then error() + else if strict_inverse then + failwith "cannot solve pb yet" + else t) + | Var id -> + (try List.assoc t subst + with Not_found -> + if rigid then error() + else if + not strict_inverse && + List.exists (fun (id',_,_) -> id=id') evi.evar_hyps + then + failwith "cannot solve pb yet" + else t) + | Evar (ev,args) -> + if Evd.is_defined_evar !evd (ev,args) then + subs rigid k (existential_value (evars_of !evd) (ev,args)) + else + let args' = Array.map (subs false k) args in + mkEvar (ev,args') + | _ -> map_constr_with_binders succ (subs rigid) k t in + let body = subs true 0 (nf_evar (evars_of isevars) rhs) in + (!evd,body) + + +let is_defined_equation env evd (ev,inst) rhs = + is_pattern inst && + not (occur_evar ev rhs) && + try + let evi = Evd.map (evars_of evd) ev in + let (evd',body) = inverse_instance env evd ev evi inst rhs in + evar_well_typed_body evd' ev evi body + with Failure _ -> false (* Redefines an evar with a smaller context (i.e. it may depend on less @@ -259,23 +316,7 @@ let do_restrict_hyps evd ev args = nc - - -(*------------------------------------* - * operations on the evar constraints * - *------------------------------------*) - let need_restriction isevars args = not (array_for_all closed0 args) - -(* The list of non-instantiated existential declarations *) - -let non_instantiated sigma = - let listev = to_list sigma in - List.fold_left - (fun l (ev,evd) -> - if evd.evar_body = Evar_empty then - ((ev,nf_evar_info sigma evd)::l) else l) - [] listev (* We try to instanciate the evar assuming the body won't depend * on arguments that are not Rels or Vars, or appearing several times. @@ -318,30 +359,6 @@ let real_clean env isevars ev evi args rhs = then error_not_clean env (evars_of !evd) ev body (evar_source ev !evd); (!evd,body) -(* [typed_evar_define evd sp c] (tactic style) - * - * Defines evar [sp] with term [c] in evar context [evd]. - * [c] is typed in the context of [sp] and evar context [evd] with - * [sp] removed to avoid circular definitions. - * No unification is performed in order to assert that [c] has the - * correct type. - * -let typed_evar_define sp c evd = - let sigma = evars_of evd in - let spdecl = Evd.map sigma sp in - let env = evar_env spdecl in - let _ = - (* Do not consider the metamap because evars may not depend on metas *) - try Typing.check env (Evd.rmv sigma sp) c spdecl.evar_concl - with - Not_found -> error "Instantiation contains unlegal variables" - | (Type_errors.TypeError (e, Type_errors.UnboundVar v))-> - errorlabstrm "typed_evar_define" - (str "Cannot use variable " ++ pr_id v ++ str " to define " ++ - str (string_of_existential sp)) in - Evd.evar_define sp c evd -*) - (* [evar_define] solves the problem lhs = rhs when lhs is an uninstantiated * evar, i.e. tries to find the body ?sp for lhs=mkEvar (sp,args) * ?sp [ sp.hyps \ args ] unifies to rhs @@ -370,8 +387,20 @@ let evar_define env (ev,argsv) rhs isevars = let (isevars',body) = real_clean env isevars ev evi worklist rhs in if occur_meta body then error "Meta cannot occur in evar body" else - let isevars'' = Evd.evar_define ev body isevars' in - isevars'',[ev] + let _ = +(* try*) + let env = evar_env evi in + let ty = evi.evar_concl in + Typing.check env (evars_of isevars') body ty +(* with e -> + pperrnl + (str "Ill-typed evar instantiation: " ++ fnl() ++ + pr_evar_defs isevars' ++ fnl() ++ + str "----> " ++ int ev ++ str " := " ++ + print_constr body); + raise e*) in + let isevars'' = Evd.evar_define ev body isevars' in + isevars'',[ev] @@ -477,23 +506,26 @@ let solve_refl conv_algo env isevars ev argsv1 argsv2 = (* Rq: uncomplete algorithm if pbty = CONV_X_LEQ ! *) let solve_simple_eqn conv_algo env isevars (pbty,(n1,args1 as ev1),t2) = - let t2 = nf_evar (evars_of isevars) t2 in - let (isevars,lsp) = match kind_of_term t2 with - | Evar (n2,args2 as ev2) -> - if n1 = n2 then - solve_refl conv_algo env isevars n1 args1 args2 - else - if Array.length args1 < Array.length args2 then - evar_define env ev2 (mkEvar ev1) isevars - else - evar_define env ev1 t2 isevars - | _ -> - evar_define env ev1 t2 isevars in - let (isevars,pbs) = get_conv_pbs isevars (status_changed lsp) in - List.fold_left - (fun (isevars,b as p) (pbty,t1,t2) -> - if b then conv_algo env isevars pbty t1 t2 else p) (isevars,true) - pbs + try + let t2 = nf_evar (evars_of isevars) t2 in + let (isevars,lsp) = match kind_of_term t2 with + | Evar (n2,args2 as ev2) -> + if n1 = n2 then + solve_refl conv_algo env isevars n1 args1 args2 + else + if Array.length args1 < Array.length args2 then + evar_define env ev2 (mkEvar ev1) isevars + else + evar_define env ev1 t2 isevars + | _ -> + evar_define env ev1 t2 isevars in + let (isevars,pbs) = get_conv_pbs isevars (status_changed lsp) in + List.fold_left + (fun (isevars,b as p) (pbty,t1,t2) -> + if b then conv_algo env isevars pbty t1 t2 else p) (isevars,true) + pbs + with e when precatchable_exception e -> + (isevars,false) (* Operations on value/type constraints *) diff --git a/pretyping/evarutil.mli b/pretyping/evarutil.mli index 11965812d..4bcec5ef6 100644 --- a/pretyping/evarutil.mli +++ b/pretyping/evarutil.mli @@ -46,8 +46,6 @@ val new_evar_instance : named_context -> evar_defs -> types -> ?src:loc * hole_kind -> constr list -> evar_defs * constr -val w_Declare : env -> evar -> types -> evar_defs -> evar_defs - (***********************************************************) (* Instanciate evars *) diff --git a/pretyping/evd.ml b/pretyping/evd.ml index d1d8d3817..4cf17fb77 100644 --- a/pretyping/evd.ml +++ b/pretyping/evd.ml @@ -221,7 +221,14 @@ let create_evar_defs sigma = let evars_of d = d.evars let evars_reset_evd evd d = {d with evars = evd} let reset_evd (sigma,mmap) d = {d with evars = sigma; metas=mmap} -let add_conv_pb pb d = {d with conv_pbs = pb::d.conv_pbs} +let add_conv_pb pb d = +(* let (pbty,c1,c2) = pb in + pperrnl + (Termops.print_constr c1 ++ + (if pbty=Reduction.CUMUL then str " <="++ spc() + else str" =="++spc()) ++ + Termops.print_constr c2);*) + {d with conv_pbs = pb::d.conv_pbs} let evar_source ev d = try List.assoc ev d.history with Not_found -> (dummy_loc, InternalHole) diff --git a/pretyping/pretyping.ml b/pretyping/pretyping.ml index 098c3e095..6101396a4 100644 --- a/pretyping/pretyping.ml +++ b/pretyping/pretyping.ml @@ -989,7 +989,19 @@ let check_evars fail_evar env initial_sigma isevars c = error_unsolvable_implicit loc env sigma k) | _ -> iter_constr proc_rec c in - proc_rec c + proc_rec c(*; + let (_,pbs) = get_conv_pbs !isevars (fun _ -> true) in + if pbs <> [] then begin + pperrnl + (str"TYPING OF "++Termops.print_constr_env env c++fnl()++ + prlist_with_sep fnl + (fun (pb,c1,c2) -> + Termops.print_constr c1 ++ + (if pb=Reduction.CUMUL then str " <="++ spc() + else str" =="++spc()) ++ + Termops.print_constr c2) + pbs ++ fnl()) + end*) (* TODO: comment faire remonter l'information si le typage a resolu des variables du sigma original. il faudrait que la fonction de typage diff --git a/pretyping/typing.ml b/pretyping/typing.ml index 2f3495702..dd2d781d5 100644 --- a/pretyping/typing.ml +++ b/pretyping/typing.ml @@ -18,6 +18,7 @@ open Pretype_errors open Inductive open Inductiveops open Typeops +open Evd let meta_type env mv = let ty = @@ -31,44 +32,36 @@ let vect_lift_type = Array.mapi (fun i t -> type_app (lift i) t) (* The typing machine without information, without universes but with existential variables. *) -let assumption_of_judgment env evd j = - assumption_of_judgment env (j_nf_evar (Evd.evars_of evd) j) - -let type_judgment env evd j = - type_judgment env (j_nf_evar (Evd.evars_of evd) j) - -let check_type env evd j ty = - let sigma = Evd.evars_of evd in - if not (is_conv_leq env sigma j.uj_type ty) then - error_actual_type env (j_nf_evar sigma j) (nf_evar sigma ty) - +(* cstr must be in n.f. w.r.t. evars and execute returns a judgement + where both the term and type are in n.f. *) let rec execute env evd cstr = match kind_of_term cstr with | Meta n -> - { uj_val = cstr; uj_type = meta_type evd n } + { uj_val = cstr; uj_type = nf_evar (evars_of evd) (meta_type evd n) } | Evar ev -> let sigma = Evd.evars_of evd in let ty = Evd.existential_type sigma ev in - let jty = execute env evd ty in - let jty = assumption_of_judgment env evd jty in + let jty = execute env evd (nf_evar (evars_of evd) ty) in + let jty = assumption_of_judgment env jty in { uj_val = cstr; uj_type = jty } | Rel n -> - judge_of_relative env n + j_nf_evar (evars_of evd) (judge_of_relative env n) | Var id -> - judge_of_variable env id + j_nf_evar (evars_of evd) (judge_of_variable env id) | Const c -> - make_judge cstr (constant_type env c) + make_judge cstr (nf_evar (evars_of evd) (constant_type env c)) | Ind ind -> - make_judge cstr (type_of_inductive env ind) + make_judge cstr (nf_evar (evars_of evd) (type_of_inductive env ind)) | Construct cstruct -> - make_judge cstr (type_of_constructor env cstruct) - + make_judge cstr + (nf_evar (evars_of evd) (type_of_constructor env cstruct)) + | Case (ci,p,c,lf) -> let cj = execute env evd c in let pj = execute env evd p in @@ -102,23 +95,23 @@ let rec execute env evd cstr = | Lambda (name,c1,c2) -> let j = execute env evd c1 in - let var = type_judgment env evd j in + let var = type_judgment env j in let env1 = push_rel (name,None,var.utj_val) env in let j' = execute env1 evd c2 in judge_of_abstraction env1 name var j' | Prod (name,c1,c2) -> let j = execute env evd c1 in - let varj = type_judgment env evd j in + let varj = type_judgment env j in let env1 = push_rel (name,None,varj.utj_val) env in let j' = execute env1 evd c2 in - let varj' = type_judgment env1 evd j' in + let varj' = type_judgment env1 j' in judge_of_product env name varj varj' | LetIn (name,c1,c2,c3) -> let j1 = execute env evd c1 in let j2 = execute env evd c2 in - let j2 = type_judgment env evd j2 in + let j2 = type_judgment env j2 in let _ = judge_of_cast env j1 j2 in let env1 = push_rel (name,Some j1.uj_val,j2.utj_val) env in let j3 = execute env1 evd c3 in @@ -127,13 +120,13 @@ let rec execute env evd cstr = | Cast (c,t) -> let cj = execute env evd c in let tj = execute env evd t in - let tj = type_judgment env evd tj in + let tj = type_judgment env tj in let j, _ = judge_of_cast env cj tj in j and execute_recdef env evd (names,lar,vdef) = let larj = execute_array env evd lar in - let lara = Array.map (assumption_of_judgment env evd) larj in + let lara = Array.map (assumption_of_judgment env) larj in let env1 = push_rec_types (names,lara,vdef) env in let vdefj = execute_array env1 evd vdef in let vdefv = Array.map j_val vdefj in @@ -153,19 +146,21 @@ and execute_list env evd = function j::jr let mcheck env evd c t = - let j = execute env evd c in - check_type env evd j t + let sigma = Evd.evars_of evd in + let j = execute env evd (nf_evar sigma c) in + if not (is_conv_leq env sigma j.uj_type t) then + error_actual_type env j (nf_evar sigma t) (* Type of a constr *) let mtype_of env evd c = - let j = execute env evd c in + let j = execute env evd (nf_evar (evars_of evd) c) in (* No normalization: it breaks Pattern! *) (*nf_betaiota*) (body_of_type j.uj_type) let msort_of env evd c = - let j = execute env evd c in - let a = type_judgment env evd j in + let j = execute env evd (nf_evar (evars_of evd) c) in + let a = type_judgment env j in a.utj_type let type_of env sigma c = @@ -178,5 +173,5 @@ let check env sigma c = (* The typed type of a judgment. *) let mtype_of_type env evd constr = - let j = execute env evd constr in - assumption_of_judgment env evd j + let j = execute env evd (nf_evar (evars_of evd) constr) in + assumption_of_judgment env j diff --git a/tactics/equality.ml b/tactics/equality.ml index f5ccf4286..30a01d6a9 100644 --- a/tactics/equality.ml +++ b/tactics/equality.ml @@ -588,7 +588,7 @@ let sig_clausal_form env sigma sort_of_ty siglen ty dflt = let (a,p_i_minus_1) = match whd_beta_stack p_i with | (_sigS,[a;p]) -> (a,p) | _ -> anomaly "sig_clausal_form: should be a sigma type" in - let ev = Evarutil.e_new_evar isevars env (new_Type ()) in + let ev = Evarutil.e_new_evar isevars env a in let rty = beta_applist(p_i_minus_1,[ev]) in let tuple_tail = sigrec_clausal_form (siglen-1) rty in match |