]> matita.cs.unibo.it Git - helm.git/blobdiff - components/tactics/equalityTactics.ml
Removed a couple of assertions.
[helm.git] / components / tactics / equalityTactics.ml
index 1ef330bd230d0ef57122d80954efda2f0f56b518..cd066250fc48d278bfa40386c70b286059cfa783 100644 (file)
  *)
 
 (* $Id$ *)
+
+module C    = Cic
+module U    = UriManager
+module PET  = ProofEngineTypes
+module PER  = ProofEngineReduction
+module PEH  = ProofEngineHelpers
+module PESR = ProofEngineStructuralRules
+module P    = PrimitiveTactics 
+module T    = Tacticals 
+module R    = CicReduction
+module S    = CicSubstitution
+module TC   = CicTypeChecker
+module LO   = LibraryObjects
+module DTI  = DoubleTypeInference
+module HEL  = HExtlib
+
 let rec rewrite_tac ~direction ~(pattern: ProofEngineTypes.lazy_pattern) equality =
  let _rewrite_tac ~direction ~pattern:(wanted,hyps_pat,concl_pat) equality status
  =
-  let module C = Cic in
-  let module U = UriManager in
-  let module PET = ProofEngineTypes in
-  let module PER = ProofEngineReduction in
-  let module PEH = ProofEngineHelpers in
-  let module PT = PrimitiveTactics in
   assert (wanted = None);   (* this should be checked syntactically *)
   let proof,goal = status in
   let curi, metasenv, pbo, pty = proof in
@@ -45,7 +54,7 @@ let rec rewrite_tac ~direction ~(pattern: ProofEngineTypes.lazy_pattern) equalit
           (rewrite_tac ~direction
            ~pattern:(None,[he],None) equality)
           (rewrite_tac ~direction ~pattern:(None,tl,concl_pat)
-            (CicSubstitution.lift 1 equality))
+            (S.lift 1 equality))
         ) status
    | [_] as hyps_pat when concl_pat <> None ->
        PET.apply_tactic
@@ -53,18 +62,18 @@ let rec rewrite_tac ~direction ~(pattern: ProofEngineTypes.lazy_pattern) equalit
           (rewrite_tac ~direction
            ~pattern:(None,hyps_pat,None) equality)
           (rewrite_tac ~direction ~pattern:(None,[],concl_pat)
-            (CicSubstitution.lift 1 equality))
+            (S.lift 1 equality))
         ) status
    | _ ->
   let arg,dir2,tac,concl_pat,gty =
    match hyps_pat with
-      [] -> None,true,(fun ~term _ -> PT.exact_tac term),concl_pat,gty
+      [] -> None,true,(fun ~term _ -> P.exact_tac term),concl_pat,gty
     | [name,pat] ->
       let rec find_hyp n =
        function
           [] -> assert false
         | Some (Cic.Name s,Cic.Decl ty)::_ when name = s ->
-           Cic.Rel n, CicSubstitution.lift n ty
+           Cic.Rel n, S.lift n ty
         | Some (Cic.Name s,Cic.Def _)::_ -> assert false (*CSC: not implemented yet! But does this make any sense?*)
         | _::tl -> find_hyp (n+1) tl
       in
@@ -75,10 +84,10 @@ let rec rewrite_tac ~direction ~(pattern: ProofEngineTypes.lazy_pattern) equalit
            Tacticals.seq
             ~tactics:
               [ProofEngineStructuralRules.rename name dummy;
-               PT.letin_tac
+               P.letin_tac
                 ~mk_fresh_name_callback:(fun _ _ _ ~typ -> Cic.Name name) term;
                ProofEngineStructuralRules.clearbody name;
-               ReductionTactics.change_tac
+              ReductionTactics.change_tac
                 ~pattern:
                   (None,[name,Cic.Implicit (Some `Hole)], None)
                 (ProofEngineTypes.const_lazy_term typ);
@@ -97,7 +106,7 @@ let rec rewrite_tac ~direction ~(pattern: ProofEngineTypes.lazy_pattern) equalit
       CicUniv.empty_ugraph in 
   let (ty_eq,metasenv',arguments,fresh_meta) =
    ProofEngineHelpers.saturate_term
-    (ProofEngineHelpers.new_meta_of_proof proof) metasenv context ty_eq 0 in
+    (ProofEngineHelpers.new_meta_of_proof proof) metasenv context ty_eq 0 in  
   let equality =
    if List.length arguments = 0 then
     equality
@@ -122,22 +131,22 @@ let rec rewrite_tac ~direction ~(pattern: ProofEngineTypes.lazy_pattern) equalit
   let fresh_name = 
     FreshNamesGenerator.mk_fresh_name 
     ~subst:[] metasenv' context C.Anonymous ~typ:ty in
-  let lifted_t1 = CicSubstitution.lift 1 t1x in
-  let lifted_gty = CicSubstitution.lift 1 gty in
+  let lifted_t1 = S.lift 1 t1x in
+  let lifted_gty = S.lift 1 gty in
   let lifted_conjecture =
     metano,(Some (fresh_name,Cic.Decl ty))::context,lifted_gty in
   let lifted_pattern =
     let lifted_concl_pat =
       match concl_pat with
       | None -> None
-      | Some term -> Some (CicSubstitution.lift 1 term) in
+      | Some term -> Some (S.lift 1 term) in
     Some (fun _ m u -> lifted_t1, m, u),[],lifted_concl_pat
   in
   let subst,metasenv',ugraph,_,selected_terms_with_context =
    ProofEngineHelpers.select
     ~metasenv:metasenv' ~ugraph ~conjecture:lifted_conjecture
      ~pattern:lifted_pattern in
-  let metasenv' = CicMetaSubst.apply_subst_metasenv subst metasenv' in
+  let metasenv' = CicMetaSubst.apply_subst_metasenv subst metasenv' in  
   let what,with_what = 
    (* Note: Rel 1 does not live in the context context_of_t           *)
    (* The replace_lifting_csc 0 function will take care of lifting it *)
@@ -161,27 +170,32 @@ let rec rewrite_tac ~direction ~(pattern: ProofEngineTypes.lazy_pattern) equalit
   let metasenv',arg,newtyp =
    match arg with
       None ->
-       let gty' = CicSubstitution.subst t2 abstr_gty in
+       let gty' = S.subst t2 abstr_gty in
        let irl =
         CicMkImplicit.identity_relocation_list_for_metavariable context in
        let metasenv' = (fresh_meta,context,gty')::metasenv' in
         metasenv', C.Meta (fresh_meta,irl), Cic.Rel (-1) (* dummy term, never used *)
     | Some arg ->
-       let gty' = CicSubstitution.subst t1 abstr_gty in
+       let gty' = S.subst t1 abstr_gty in
         metasenv',arg,gty'
   in
   let exact_proof = 
     C.Appl [eq_ind ; ty ; t2 ; pred ; arg ; t1 ;equality]
   in
-  let (proof',goals) =
-    PET.apply_tactic 
-      (tac ~term:exact_proof newtyp) ((curi,metasenv',pbo,pty),goal)
-  in
-  let goals =
-   goals@(ProofEngineHelpers.compare_metasenvs ~oldmetasenv:metasenv
-    ~newmetasenv:metasenv')
-  in
-   (proof',goals)
+  try 
+    let (proof',goals) =
+      PET.apply_tactic 
+        (tac ~term:exact_proof newtyp) ((curi,metasenv',pbo,pty),goal)
+    in
+    let goals =
+     goals@(ProofEngineHelpers.compare_metasenvs ~oldmetasenv:metasenv
+      ~newmetasenv:metasenv')
+    in
+     (proof',goals)
+  with (* FG: this should be PET.Fail _ *)
+     TC.TypeCheckerFailure _ -> 
+      let msg = lazy "rewrite: nothing to rewrite" in
+      raise (PET.Fail msg)
  in
   ProofEngineTypes.mk_tactic (_rewrite_tac ~direction ~pattern equality)
   
@@ -203,10 +217,6 @@ let replace_tac ~(pattern: ProofEngineTypes.lazy_pattern) ~with_what =
  let replace_tac ~(pattern: ProofEngineTypes.lazy_pattern) ~with_what status =
   let _wanted, hyps_pat, concl_pat = pattern in
   let (proof, goal) = status in
-  let module C = Cic in
-  let module U = UriManager in
-  let module P = PrimitiveTactics in
-  let module T = Tacticals in
   let uri,metasenv,pbo,pty = proof in
   let (_,context,ty) as conjecture = CicUtil.lookup_meta goal metasenv in
   assert (hyps_pat = []); (*CSC: not implemented yet *)
@@ -270,9 +280,9 @@ let replace_tac ~(pattern: ProofEngineTypes.lazy_pattern) ~with_what =
    match whats with
       [] -> ProofEngineTypes.apply_tactic T.id_tac status
     | (what,lazy_pattern)::tl ->
-       let what = CicSubstitution.lift n what in
-       let with_what = CicSubstitution.lift n with_what in
-       let ty_of_with_what = CicSubstitution.lift n ty_of_with_what in
+       let what = S.lift n what in
+       let with_what = S.lift n with_what in
+       let ty_of_with_what = S.lift n ty_of_with_what in
        ProofEngineTypes.apply_tactic
          (T.thens
             ~start:(
@@ -320,9 +330,6 @@ let reflexivity_tac =
 
 let symmetry_tac =
  let symmetry_tac (proof, goal) =
-  let module C = Cic in
-  let module R = CicReduction in
-  let module U = UriManager in
    let (_,metasenv,_,_) = proof in
     let metano,context,ty = CicUtil.lookup_meta goal metasenv in
      match (R.whd context ty) with
@@ -341,10 +348,6 @@ let symmetry_tac =
 let transitivity_tac ~term =
  let transitivity_tac ~term status =
   let (proof, goal) = status in
-  let module C = Cic in
-  let module R = CicReduction in
-  let module U = UriManager in
-  let module T = Tacticals in
    let (_,metasenv,_,_) = proof in
     let metano,context,ty = CicUtil.lookup_meta goal metasenv in
      match (R.whd context ty) with
@@ -363,4 +366,83 @@ let transitivity_tac ~term =
   ProofEngineTypes.mk_tactic (transitivity_tac ~term)
 ;;
 
+(* FG: subst tactic *********************************************************)
+
+(* FG: This should be replaced by T.try_tactic *)
+let try_tactic ~tactic =
+   let try_tactic status =
+      try PET.apply_tactic tactic status with
+         | PET.Fail _ -> PET.apply_tactic T.id_tac status
+   in
+   PET.mk_tactic try_tactic
+
+let rec lift_rewrite_tac ~context ~direction ~pattern equality =
+   let lift_rewrite_tac status =
+      let (proof, goal) = status in
+      let (_, metasenv, _, _) = proof in
+      let _, new_context, _ = CicUtil.lookup_meta goal metasenv in
+      let n = List.length new_context - List.length context in
+      let equality = if n > 0 then S.lift n equality else equality in
+      PET.apply_tactic (rewrite_tac ~direction ~pattern equality) status
+   in
+   PET.mk_tactic lift_rewrite_tac
+
+
+let msg0 = lazy "Subst: not found in context"
+let msg1 = lazy "Subst: not a simple equality"
+let msg2 = lazy "Subst: recursive equation" 
+
+let subst_tac ~hyp =
+   let hole = C.Implicit (Some `Hole) in
+   let subst_tac status =
+      let (proof, goal) = status in
+      let (_, metasenv, _, _) = proof in
+      let _, context, _ = CicUtil.lookup_meta goal metasenv in
+      let what = match PEH.get_rel context hyp with
+         | Some t -> t
+        | None   -> raise (PET.Fail msg0)
+      in
+      let ty, _ = TC.type_of_aux' metasenv context what CicUniv.empty_ugraph in
+      let direction, i, t = match ty with
+         | (C.Appl [(C.MutInd (uri, 0, [])); _; C.Rel i; t]) 
+           when LO.is_eq_URI uri -> `LeftToRight, i, t
+         | (C.Appl [(C.MutInd (uri, 0, [])); _; t; C.Rel i]) 
+           when LO.is_eq_URI uri -> `RightToLeft, i, t
+        | _ -> raise (PET.Fail msg1)
+      in    
+      let rewrite pattern =
+         let tactic = lift_rewrite_tac ~context ~direction ~pattern what in
+        try_tactic ~tactic
+      in
+      let var = match PEH.get_name context i with
+         | Some name -> name
+        | None      -> raise (PET.Fail msg0)   
+      in
+      if DTI.does_not_occur i t then () else raise (PET.Fail msg2);
+      let map self = function
+         | Some (C.Name s, _) when s <> self -> 
+            Some (rewrite (None, [(s, hole)], None))
+         | _                                 -> None
+      in
+      let rew_hips = HEL.list_rev_map_filter (map hyp) context in
+      let rew_concl = rewrite (None, [], Some hole) in
+      let clear = PESR.clear ~hyps:[hyp; var] in
+      let tactics = List.rev_append (rew_concl :: rew_hips) [clear] in
+      PET.apply_tactic (T.seq ~tactics) status
+   in
+   PET.mk_tactic subst_tac
 
+let subst_tac =
+   let subst hyp = try_tactic ~tactic:(subst_tac hyp) in
+   let map = function
+      | Some (C.Name s, _) -> Some (subst s)
+      | _                  -> None
+   in
+   let subst_tac status =
+      let (proof, goal) = status in
+      let (_, metasenv, _, _) = proof in
+      let _, context, _ = CicUtil.lookup_meta goal metasenv in
+      let tactics = HEL.list_rev_map_filter map context in
+      PET.apply_tactic (T.seq ~tactics) status
+   in
+   PET.mk_tactic subst_tac