]> matita.cs.unibo.it Git - helm.git/blobdiff - components/tactics/primitiveTactics.ml
elim tactic: it needs two arguments, a term as well as a pattern
[helm.git] / components / tactics / primitiveTactics.ml
index 2c22aa5ec2c10307dc308f44882367817db9a621..6646157240d93ab648ed54386908b03b51da1a28 100644 (file)
@@ -30,6 +30,7 @@ open ProofEngineTypes
 exception TheTypeOfTheCurrentGoalIsAMetaICannotChooseTheRightElimiantionPrinciple
 exception NotAnInductiveTypeToEliminate
 exception WrongUriToVariable of string
+exception NotAnEliminator
 
 (* lambda_abstract newmeta ty *)
 (* returns a triple [bo],[context],[ty'] where              *)
@@ -477,21 +478,33 @@ let exact_tac ~term =
   mk_tactic (exact_tac ~term)
 
 (* not really "primitive" tactics .... *)
-let elim_tac ?using pattern = 
+  
+module TC  = CicTypeChecker
+module U   = UriManager
+module R   = CicReduction
+module C   = Cic
+module PET = ProofEngineTypes
+module PEH = ProofEngineHelpers
+module PER = ProofEngineReduction
+module MS  = CicMetaSubst 
+module S   = CicSubstitution 
+module T   = Tacticals
+module RT  = ReductionTactics
+
+let elim_tac ?using ?(pattern = PET.conclusion_pattern None) term = 
  let elim_tac (proof, goal) =
-  let module T = CicTypeChecker in
-  let module U = UriManager in
-  let module R = CicReduction in
-  let module C = Cic in
-   let (curi,metasenv,proofbo,proofty, attrs) = proof in
-   let metano,context,ty = CicUtil.lookup_meta goal metasenv in
-    let term, metasenv, _ = match pattern with 
-       | Some f, [], Some _ -> f context metasenv CicUniv.empty_ugraph
-       | _                  -> assert false
+   let ugraph = CicUniv.empty_ugraph in
+   let curi, metasenv, proofbo, proofty, attrs = proof in
+   let conjecture = CicUtil.lookup_meta goal metasenv in
+   let metano, context, ty = conjecture in
+(*    let (term, metasenv, _ugraph), cpatt = match pattern with 
+       | Some f, [], Some cpatt -> f context metasenv ugraph, cpatt
+       | _                      -> assert false
     in
-    let termty,_ = T.type_of_aux' metasenv context term CicUniv.empty_ugraph in
+*)    
+    let termty,_ugraph = TC.type_of_aux' metasenv context term ugraph in
     let termty = CicReduction.whd context termty in
-    let (termty,metasenv',arguments,fresh_meta) =
+    let (termty,metasenv',arguments,_fresh_meta) =
      TermUtil.saturate_term
       (ProofEngineHelpers.new_meta_of_proof proof) metasenv context termty 0 in
     let term = if arguments = [] then term else Cic.Appl (term::arguments) in
@@ -505,14 +518,14 @@ let elim_tac ?using pattern =
      let eliminator_uri =
       let buri = U.buri_of_uri uri in
       let name = 
-        let o,_ = CicEnvironment.get_obj CicUniv.empty_ugraph uri in
+        let o,_ugraph = CicEnvironment.get_obj ugraph uri in
        match o with
           C.InductiveDefinition (tys,_,_,_) ->
            let (name,_,_,_) = List.nth tys typeno in
             name
         | _ -> assert false
       in
-      let ty_ty,_ = T.type_of_aux' metasenv' context ty CicUniv.empty_ugraph in
+      let ty_ty,_ugraph = TC.type_of_aux' metasenv' context ty ugraph in
       let ext =
        match ty_ty with
           C.Sort C.Prop -> "_ind"
@@ -528,47 +541,75 @@ let elim_tac ?using pattern =
          | None   -> C.Const (eliminator_uri,exp_named_subst)
          | Some t -> t 
        in
-       let ety,_ = 
-         T.type_of_aux' metasenv' context eliminator_ref CicUniv.empty_ugraph in
-        let rec find_args_no =
-         function
-            C.Prod (_,_,t) -> 1 + find_args_no t
-          | C.Cast (s,_) -> find_args_no s
-          | C.LetIn (_,_,t) -> 0 + find_args_no t
-          | _ -> 0
-        in
-         let args_no = find_args_no ety in
-(* we find the predicate for the eliminator as in the rewrite tactic ********)
+       let ety,_ugraph = 
+         TC.type_of_aux' metasenv' context eliminator_ref ugraph in
+(* FG: ADDED PART ***********************************************************)
+(* FG: we can not assume eliminator is the default eliminator ***************)
+   let add_lambdas n t =
+      let rec aux n t =
+         if n <= 0 then t 
+        else C.Lambda (C.Anonymous, C.Implicit None, aux (pred n) t)
+      in
+      aux n (S.lift n t)
+   in
+   let rec args_init n f =
+      if n <= 0 then [] else f n :: args_init (pred n) f
+   in
+   let splits, args_no = PEH.split_with_whd (context, ety) in
+   let pred_pos = match List.hd splits with
+      | _, C.Rel i when i > 1 && i <= args_no -> i
+      | _, C.Appl (C.Rel i :: _) when i > 1 && i <= args_no -> i
+      | _ -> raise NotAnEliminator
+   in
+   let _, lambdas = PEH.split_with_whd (List.nth splits pred_pos) in
+   let termty_ty =
+      let termty_ty,_ugraph = TC.type_of_aux' metasenv' context termty ugraph in
+      CicReduction.whd context termty_ty
+   in
 (*   
-   let fresh_name = 
-       FreshNamesGenerator.mk_fresh_name 
-       ~subst:[] metasenv' context C.Anonymous ~typ:termty in
-  let lifted_gty = S.lift 1 ty in
-  let lifted_conjecture =
-    metano, (Some (fresh_name, Cic.Decl ty)) :: context, lifted_gty in
-  let lifted_t1 = S.lift 1 t1x in
-  let lifted_pattern =
-    let lifted_concl_pat =
-      match concl_pat with
-      | None -> None
-      | Some term -> Some (S.lift 1 term) in
-    Some (fun c m u -> 
-       let distance  = pred (List.length c - List.length context) in
-       S.lift distance lifted_t1, m, u),[],lifted_concl_pat
-  in
+   let metasenv', term, pred, upto = match cpatt, termty_ty with
+      | C.Implicit (Some `Hole), _ 
+      | _, C.Sort C.Prop when lambdas = 0 -> metasenv', term, C.Implicit None, 0
+      | _                                 ->
+(* FG: we find the predicate for the eliminator as in the rewrite tactic ****)
+         let fresh_name = 
+             FreshNamesGenerator.mk_fresh_name 
+             ~subst:[] metasenv' context C.Anonymous ~typ:termty
+         in
+         let lazy_term c m u =  
+            let distance  = List.length c - List.length context in
+            S.lift distance term, m, u
+         in
+         let pattern = Some lazy_term, [], Some cpatt in
+         let subst, metasenv', _ugraph, _conjecture, selected_terms =
+            ProofEngineHelpers.select
+            ~metasenv:metasenv' ~ugraph ~conjecture ~pattern
+         in
+         let metasenv' = MS.apply_subst_metasenv subst metasenv' in  
+         let map (_context_of_t, t) l = t :: l in
+         let what = List.fold_right map selected_terms [] in
+         let ty = MS.apply_subst subst ty in
+         let term = MS.apply_subst subst term in
+         let termty = MS.apply_subst subst termty in
+         let abstr_ty = PER.replace_with_rel_1_from ~equality:(==) ~what 1 ty in
+         let abstr_ty = MS.apply_subst subst abstr_ty in
+         let pred_body = C.Lambda (fresh_name, termty, abstr_ty) in
+        metasenv', term, add_lambdas (pred lambdas) pred_body, lambdas 
+   in
+(* FG: END OF ADDED PART ****************************************************)
 *)
-(****************************************************************************)
+         let pred, upto = C.Implicit None, 0 in
+        
         let term_to_refine =
-          let rec make_tl base_case =
-           function
-              0 -> [base_case]
-            | n -> (C.Implicit None)::(make_tl base_case (n - 1))
-          in
-           C.Appl (eliminator_ref :: make_tl term (args_no - 1))
+          let f n =
+          if n = pred_pos then pred else
+          if n = 1 then term else C.Implicit None
+         in
+           C.Appl (eliminator_ref :: args_init args_no f)
          in
-          let refined_term,_,metasenv'',_ = 
+          let refined_term,_refined_termty,metasenv'',_ugraph = 
            CicRefine.type_of_aux' metasenv' context term_to_refine
-             CicUniv.empty_ugraph
+             ugraph
           in
            let new_goals =
             ProofEngineHelpers.compare_metasenvs
@@ -576,7 +617,7 @@ let elim_tac ?using pattern =
            in
            let proof' = curi,metasenv'',proofbo,proofty, attrs in
             let proof'', new_goals' =
-             apply_tactic (apply_tac ~term:refined_term) (proof',goal)
+            apply_tactic (apply_tac ~term:refined_term) (proof',goal)
             in
              (* The apply_tactic can have closed some of the new_goals *)
              let patched_new_goals =
@@ -585,20 +626,30 @@ let elim_tac ?using pattern =
                 (function i -> List.exists (function (j,_,_) -> j=i) metasenv'''
                 ) new_goals @ new_goals'
              in
-              proof'', patched_new_goals
+              let res = proof'', patched_new_goals in
+               if upto = 0 then res else 
+               let pattern = PET.conclusion_pattern None in
+               let continuation =
+                RT.simpl_tac ~pattern
+                (* RT.head_beta_reduce_tac ~delta:false ~upto ~pattern *)
+               in
+                let dummy_status = proof,goal in
+                 PET.apply_tactic
+                  (T.then_ ~start:(PET.mk_tactic (fun _ -> res)) ~continuation)
+                   dummy_status
  in
   mk_tactic elim_tac
 ;;
 
 let cases_intros_tac ?(mk_fresh_name_callback = FreshNamesGenerator.mk_fresh_name ~subst:[]) term =
  let cases_tac ~term (proof, goal) =
-  let module T = CicTypeChecker in
+  let module TC = CicTypeChecker in
   let module U = UriManager in
   let module R = CicReduction in
   let module C = Cic in
    let (curi,metasenv,proofbo,proofty, attrs) = proof in
    let metano,context,ty = CicUtil.lookup_meta goal metasenv in
-    let termty,_ = T.type_of_aux' metasenv context term CicUniv.empty_ugraph in
+    let termty,_ = TC.type_of_aux' metasenv context term CicUniv.empty_ugraph in
     let termty = CicReduction.whd context termty in
     let (termty,metasenv',arguments,fresh_meta) =
      TermUtil.saturate_term
@@ -684,15 +735,15 @@ let cases_intros_tac ?(mk_fresh_name_callback = FreshNamesGenerator.mk_fresh_nam
 
 
 let elim_intros_tac ?(mk_fresh_name_callback = FreshNamesGenerator.mk_fresh_name ~subst:[]) 
-                    ?depth ?using pattern =
- Tacticals.then_ ~start:(elim_tac ?using pattern)
+                    ?depth ?using ?pattern what =
+ Tacticals.then_ ~start:(elim_tac ?using ?pattern what)
   ~continuation:(intros_tac ~mk_fresh_name_callback ?howmany:depth ())
 ;;
 
 (* The simplification is performed only on the conclusion *)
 let elim_intros_simpl_tac ?(mk_fresh_name_callback = FreshNamesGenerator.mk_fresh_name ~subst:[])
-                          ?depth ?using pattern =
- Tacticals.then_ ~start:(elim_tac ?using pattern)
+                          ?depth ?using ?pattern what =
+ Tacticals.then_ ~start:(elim_tac ?using ?pattern what)
   ~continuation:
    (Tacticals.thens
      ~start:(intros_tac ~mk_fresh_name_callback ?howmany:depth ())
@@ -703,8 +754,6 @@ let elim_intros_simpl_tac ?(mk_fresh_name_callback = FreshNamesGenerator.mk_fres
 
 (* FG: insetrts a "hole" in the context (derived from letin_tac) *)
 
-module C = Cic
-
 let letout_tac =
    let mk_fresh_name_callback = FreshNamesGenerator.mk_fresh_name ~subst:[] in
    let term = C.Sort C.Set in