]> matita.cs.unibo.it Git - helm.git/blobdiff - components/tactics/discriminationTactics.ml
cic_acic should be compiled before cic_exportation
[helm.git] / components / tactics / discriminationTactics.ml
index 27baa2b9d9d92262acb364f5e332b364233ad54f..83f676ed33ee6acc471a526bf6fd9f9fbdd1fdaf 100644 (file)
@@ -37,11 +37,11 @@ module CU = CicUniv
 module S = CicSubstitution
 module RT = ReductionTactics
 module PEH = ProofEngineHelpers
+module ET = EqualityTactics
 
 let debug = false
 let debug_print = 
   if debug then (fun x -> prerr_endline (Lazy.force x)) else (fun _ -> ())
-;;
 
 (* funzione generale di rilocazione dei riferimenti locali *)
 
@@ -85,6 +85,12 @@ let relocate_term map t =
 
 let id n = n
 
+let after continuation aftermap beforemap = 
+   continuation ~map:(fun n -> aftermap (beforemap n))
+
+let after2 continuation aftermap beforemap ~map = 
+   continuation ~map:(fun n -> map (aftermap (beforemap n)))
+
 (* term ha tipo t1=t2; funziona solo se t1 e t2 hanno in testa costruttori
 diversi *)
 
@@ -237,7 +243,7 @@ let discriminate_tac ~term =
              ~continuation:
                (T.then_
                  ~start:
-                   (EqualityTactics.rewrite_simpl_tac
+                   (ET.rewrite_simpl_tac
                      ~direction:`RightToLeft
                      ~pattern:(PET.conclusion_pattern None)
                      term [])
@@ -264,7 +270,30 @@ let pp ctx t =
   let names = List.map (function Some (n,_) -> Some n | None -> None) ctx in
   CicPp.pp t names
 
-let injection_tac ~term ~i ~continuation =
+let clear_term first_time context term =
+   let g () = if first_time then raise exn_nothingtodo else T.id_tac in
+   match term with
+      | C.Rel n -> 
+         begin match List.nth context (pred n) with
+            | Some (C.Name id, _) -> PST.clear ~hyps:[id]
+           | _                   -> assert false
+         end
+       | _      -> g ()
+
+let simpl_in_term context = function
+   | Cic.Rel i ->
+      let name = match List.nth context (pred i) with
+         | Some (Cic.Name s, Cic.Def _) -> s
+         | Some (Cic.Name s, Cic.Decl _) -> s
+         | _ -> assert false
+      in
+      RT.simpl_tac ~pattern:(None,[name,Cic.Implicit (Some `Hole)],None)
+   | _ -> raise exn_nonproj
+
+(* ~term vive nel contesto della tattica una volta ~mappato
+ * ~continuation riceve la mappa assoluta
+ *)
+let rec injection_tac ~map ~term ~i ~continuation =
  let give_name seed = function
    | C.Name _ as name -> name
    | C.Anonymous -> C.Name (incr seed; "y" ^ string_of_int !seed)
@@ -277,6 +306,7 @@ let injection_tac ~term ~i ~continuation =
    * del costruttore *)
   let _,metasenv,_subst,_,_, _ = proof in
   let _,context,_ = CicUtil.lookup_meta goal metasenv in
+  let term = relocate_term map term in
   let termty,_ = 
     CTC.type_of_aux' metasenv context term CicUniv.empty_ugraph
   in
@@ -297,7 +327,7 @@ let injection_tac ~term ~i ~continuation =
           when (uri1 = uri2) && (typeno1 = typeno2) && 
                (consno1 = consno2) && (ens1 = ens2) -> 
                (* controllo ridondante *)
-            List.nth applist1 (i-1),List.nth applist2 (i-1),consno2
+            List.nth applist1 (pred i),List.nth applist2 (pred i),consno2
         | _ -> assert false
       in
       let tty',_ = CTC.type_of_aux' metasenv context t1' CU.empty_ugraph in
@@ -389,8 +419,8 @@ let injection_tac ~term ~i ~continuation =
         with
         | CTC.TypeCheckerFailure _ -> false
       in
-      if not go_on then
-        PET.apply_tactic T.id_tac status (* FG: ??????? *)
+      if not go_on then 
+        PET.apply_tactic (continuation ~map) status
       else
         let tac term = 
           let tac status =
@@ -412,54 +442,69 @@ let injection_tac ~term ~i ~continuation =
                  RT.change_tac
                      ~pattern:(None, [], Some (PEH.pattern_of ~term:gty [new_t1']))
                      (fun _ m u -> changed,m,u);
-                 EqualityTactics.rewrite_simpl_tac
+                 ET.rewrite_simpl_tac
                      ~direction:`LeftToRight
                      ~pattern:(PET.conclusion_pattern None)
                      term [];
-                  EqualityTactics.reflexivity_tac   
+                  ET.reflexivity_tac   
               ] in
               PET.apply_tactic tac status
           in
           PET.mk_tactic tac
        in
-       debug_print (lazy ("CUT: " ^ pp context cutted));   
+       debug_print (lazy ("CUT: " ^ pp context cutted));  
        PET.apply_tactic   
           (T.thens ~start: (P.cut_tac cutted)
-                   ~continuations:[continuation ~map:succ; tac term] 
+                   ~continuations:[
+                     (destruct ~first_time:false ~term:(C.Rel 1) ~map:id 
+                                ~continuation:(after2 continuation succ map) 
+                     );  
+                     tac term] 
          ) status
    | _ -> raise exn_noneq
  in
   PET.mk_tactic injection_tac
 
-let clear_term first_time context term =
-   let g () = if first_time then raise exn_nothingtodo else T.id_tac in
-   match term with
-      | C.Rel n -> 
-         begin match List.nth context (pred n) with
-            | Some (C.Name id, _) -> PST.clear ~hyps:[id]
-           | _                   -> assert false
-         end
-       | _      -> g ()
-
-let simpl_in_term context = function
-   | Cic.Rel i ->
-      let name = match List.nth context (pred i) with
-         | Some (Cic.Name s, Cic.Def _) -> s
-         | Some (Cic.Name s, Cic.Decl _) -> s
-         | _ -> assert false
-      in
-      RT.simpl_tac ~pattern:(None,[name,Cic.Implicit (Some `Hole)],None)
-   | _ -> raise exn_nonproj
+(* ~term vive nel contesto della tattica una volta ~mappato
+ * ~continuation riceve la mappa assoluta
+ *)
+and subst_tac ~map ~term ~direction ~where ~continuation =
+   let fail_tactic = continuation ~map in
+   let subst_tac status =
+      let term = relocate_term map term in
+      let tactic = match where with
+         | None      -> 
+           let pattern = PET.conclusion_pattern None in
+            let tactic = ET.rewrite_tac ~direction ~pattern term [] in
+            T.then_ ~start:(T.try_tactic ~tactic)
+                   ~continuation:fail_tactic
+        | Some name ->   
+            let pattern = None, [name, PET.hole], None in
+            let start = ET.rewrite_tac ~direction ~pattern term [] in
+            let continuation =
+              destruct ~first_time:false ~term:(C.Rel 1) ~map:id 
+                       ~continuation:(after2 continuation succ map)
+           in
+           T.if_ ~start ~continuation ~fail:fail_tactic
+      in 
+      PET.apply_tactic tactic status
+   in
+   PET.mk_tactic subst_tac
 
-let rec qnify_tac ~first_time ~map ~term ~continuation =
+(* ~term vive nel contesto della tattica una volta ~mappato
+ * ~continuation riceve la mappa assoluta
+ *)
+and destruct ~first_time ~map ~term ~continuation =
  let are_convertible hd1 hd2 metasenv context = 
    fst (CR.are_convertible ~metasenv context hd1 hd2 CicUniv.empty_ugraph)
  in
- let qnify_tac status = 
+ let destruct status = 
   let (proof, goal) = status in
   let _,metasenv,_subst, _,_, _ = proof in
   let _,context,_ = CicUtil.lookup_meta goal metasenv in
   let term = relocate_term map term in
+  debug_print (lazy ("\nqnify di: " ^ pp context term)); 
+  debug_print (lazy ("nel contesto:\n" ^ CicPp.ppcontext context));
   let termty,_ = 
     CTC.type_of_aux' metasenv context term CicUniv.empty_ugraph
   in
@@ -475,25 +520,27 @@ let rec qnify_tac ~first_time ~map ~term ~continuation =
               C.MutConstruct _
               when t1 = t2 ->
                T.then_ ~start:(clear_term first_time context term)
-                        ~continuation:(continuation ~map:id)
+                        ~continuation:(continuation ~map)
             | C.Appl (C.MutConstruct _ as mc1 :: applist1),
               C.Appl (C.MutConstruct _ as mc2 :: applist2)
               when mc1 = mc2 ->
-                let rec traverse_list i l1 l2 = match l1, l2 with
-                  | [], [] -> 
-                    T.then_ ~start:(clear_term first_time context term)
-                             ~continuation:(continuation ~map:id)
-                  | hd1 :: tl1, hd2 :: tl2 -> 
-                     if are_convertible hd1 hd2 metasenv context then
-                       traverse_list (succ i) tl1 tl2
-                     else
-                       injection_tac ~i ~term ~continuation:
-                         (qnify_tac ~first_time:false ~term ~continuation)
-                  | _ -> assert false 
+                let rec traverse_list first_time i l1 l2 = 
+                  match l1, l2 with
+                      | [], [] ->
+                        fun ~map:aftermap ->
+                           T.then_ ~start:(clear_term first_time context term)
+                                    ~continuation:(after continuation aftermap map)
+                      | hd1 :: tl1, hd2 :: tl2 -> 
+                        if are_convertible hd1 hd2 metasenv context then
+                           traverse_list first_time (succ i) tl1 tl2
+                        else
+                          injection_tac ~i ~term ~continuation:
+                             (traverse_list false (succ i) tl1 tl2)
+                      | _ -> assert false 
                       (* i 2 termini hanno in testa lo stesso costruttore, 
                        * ma applicato a un numero diverso di termini *)
                 in
-                  traverse_list 1 applist1 applist2
+                  traverse_list first_time 1 applist1 applist2 ~map:id
             | C.MutConstruct (_,_,consno1,ens1),
               C.MutConstruct (_,_,consno2,ens2)
             | C.MutConstruct (_,_,consno1,ens1),
@@ -504,22 +551,22 @@ let rec qnify_tac ~first_time ~map ~term ~continuation =
               C.Appl ((C.MutConstruct (_,_,consno2,ens2))::_)
               when (consno1 <> consno2) || (ens1 <> ens2) -> 
                 discriminate_tac ~term
-            | _ when not first_time -> continuation ~map:id
+            | _ when not first_time -> continuation ~map
             | _ (* when first_time *) -> 
                T.then_ ~start:(simpl_in_term context term)
-                       ~continuation:(qnify_tac ~first_time:false ~term ~map:id ~continuation)
+                       ~continuation:(destruct ~first_time:false ~term ~map ~continuation)
            end
-        | _ when not first_time -> continuation ~map:id
+        | _ when not first_time -> continuation ~map
         | _ (* when first_time *) -> raise exn_nonproj
         end 
     | _ -> raise exn_nonproj
   in  
     PET.apply_tactic tac status
  in 
-   PET.mk_tactic qnify_tac
+   PET.mk_tactic destruct
 
 (* destruct performs either injection or discriminate *)
 (* equivalent to Coq's "analyze equality"             *)
 let destruct_tac =
- qnify_tac
+ destruct
   ~first_time:true ~map:id ~continuation:(fun ~map -> T.id_tac)