(* and [bo] = Lambda/LetIn [context].(Meta [newmeta]) *)
(* So, lambda_abstract is the core of the implementation of *)
(* the Intros tactic. *)
-let lambda_abstract metasenv context newmeta ty mk_fresh_name =
+(* howmany = -1 means Intros, howmany > 0 means Intros n *)
+let lambda_abstract ?(howmany=(-1)) metasenv context newmeta ty mk_fresh_name =
let module C = Cic in
- let rec collect_context context =
- function
- C.Cast (te,_) -> collect_context context te
- | C.Prod (n,s,t) ->
- let n' = mk_fresh_name metasenv context n ~typ:s in
- let (context',ty,bo) =
- collect_context ((Some (n',(C.Decl s)))::context) t
+ let rec collect_context context howmany ty =
+ match howmany with
+ | 0 ->
+ let irl =
+ CicMkImplicit.identity_relocation_list_for_metavariable context
in
- (context',ty,C.Lambda(n',s,bo))
- | C.LetIn (n,s,t) ->
- let (context',ty,bo) =
- collect_context ((Some (n,(C.Def (s,None))))::context) t
- in
- (context',ty,C.LetIn(n,s,bo))
- | _ as t ->
- let irl =
- CicMkImplicit.identity_relocation_list_for_metavariable context
- in
- context, t, (C.Meta (newmeta,irl))
+ context, ty, (C.Meta (newmeta,irl))
+ | _ ->
+ match ty with
+ C.Cast (te,_) -> collect_context context howmany te
+ | C.Prod (n,s,t) ->
+ let n' = mk_fresh_name metasenv context n ~typ:s in
+ let (context',ty,bo) =
+ collect_context ((Some (n',(C.Decl s)))::context) (howmany - 1) t
+ in
+ (context',ty,C.Lambda(n',s,bo))
+ | C.LetIn (n,s,t) ->
+ let (context',ty,bo) =
+ collect_context ((Some (n,(C.Def (s,None))))::context) (howmany - 1) t
+ in
+ (context',ty,C.LetIn(n,s,bo))
+ | _ as t ->
+ let irl =
+ CicMkImplicit.identity_relocation_list_for_metavariable context
+ in
+ context, t, (C.Meta (newmeta,irl))
in
- collect_context context ty
+ collect_context context howmany ty
let eta_expand metasenv context t arg =
let module T = CicTypeChecker in
let module C = Cic in
let module S = CicSubstitution in
let rec aux newmeta ty =
- let ty' = (*CicReduction.whd context*) ty in
+ let ty' = ty in
match ty' with
C.Cast (he,_) -> aux newmeta he
(* CSC: patch to generate ?1 : ?2 : Type in place of ?1 : Type to simulate ?1 :< Type
let (res,newmetasenv,arguments,lastmeta) =
aux (newmeta + 1) (S.subst newargument t)
in
- res,(newmeta,context,s)::newmetasenv,newargument::arguments,lastmeta
- | t -> t,[],[],newmeta
+ let s' = CicReduction.normalize ~delta:false context s in
+ res,(newmeta,context,s')::newmetasenv,newargument::arguments,lastmeta
+ (** NORMALIZE RATIONALE
+ * we normalize the target only NOW since we may be in this case:
+ * A1 -> A2 -> T where T = (\lambda x.A3 -> P) k
+ * and we want a mesasenv with ?1:A1 and ?2:A2 and not
+ * ?1, ?2, ?3 (that is the one we whould get if we start from the
+ * beta-normalized A1 -> A2 -> A3 -> P **)
+ | t -> (CicReduction.normalize ~delta:false context t),[],[],newmeta
in
(* WARNING: here we are using the invariant that above the most *)
(* recente new_meta() there are no used metas. *)
let termty =
CicSubstitution.subst_vars exp_named_subst_diff termty
in
+(* prerr_endline ("term:" ^ CicPp.ppterm term);*)
+(* prerr_endline ("termty:" ^ CicPp.ppterm termty);*)
let subst,newmetasenv',t =
try
new_metasenv_and_unify_and_t newmeta' metasenv' proof context term' ty
in
let bo' = apply_subst t in
let newmetasenv'' = new_uninstantiatedmetas@old_uninstantiatedmetas in
+(* prerr_endline ("me: " ^ CicMetaSubst.ppmetasenv newmetasenv'' subst); *)
let subst_in =
(* if we just apply the subtitution, the type is irrelevant:
we may use Implicit, since it will be dropped *)
in
mk_tactic (apply_tac ~term)
-let intros_tac ?(mk_fresh_name_callback = FreshNamesGenerator.mk_fresh_name ~subst:[]) ()=
+let intros_tac ?howmany ?(mk_fresh_name_callback = FreshNamesGenerator.mk_fresh_name ~subst:[]) ()=
let intros_tac
?(mk_fresh_name_callback = (FreshNamesGenerator.mk_fresh_name ~subst:[])) ()
(proof, goal)
let metano,context,ty = CicUtil.lookup_meta goal metasenv in
let newmeta = new_meta_of_proof ~proof in
let (context',ty',bo') =
- lambda_abstract metasenv context newmeta ty mk_fresh_name_callback
+ lambda_abstract ?howmany metasenv context newmeta ty mk_fresh_name_callback
in
let (newproof, _) =
subst_meta_in_proof proof metano bo' [newmeta,context',ty']