(* Copyright (C) 2002, HELM Team. * * This file is part of HELM, an Hypertextual, Electronic * Library of Mathematics, developed at the Computer Science * Department, University of Bologna, Italy. * * HELM is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * HELM is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HELM; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * For details, see the HELM World-Wide-Web page, * http://cs.unibo.it/helm/. *) module C = Cic module DT = DiscriminationTactics module DTI = DoubleTypeInference module ET = EqualityTactics module HEL = HExtlib module LO = LibraryObjects module PEH = ProofEngineHelpers module PESR = ProofEngineStructuralRules module PET = ProofEngineTypes module RT = ReductionTactics module S = CicSubstitution module T = Tacticals module TC = CicTypeChecker let 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 = S.lift n equality in PET.apply_tactic (ET.rewrite_tac ~direction ~pattern equality []) status in PET.mk_tactic lift_rewrite_tac let lift_destruct_tac ~context ~what = let lift_destruct_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 what = S.lift n what in PET.apply_tactic (DT.destruct_tac ~term:what) status in PET.mk_tactic lift_destruct_tac let msg0 = lazy "Subst: not found in context" let msg1 = lazy "Subst: not an erasable equation" let msg2 = lazy "Subst: recursive equation" let msg3 = lazy "Subst: no progress" let rec subst_tac ~try_tactic ~hyp = let hole = C.Implicit (Some `Hole) in let meta = C.Implicit None in let rec ind = function | C.MutInd _ -> true | C.Appl (t :: tl) -> ind t | _ -> false in let rec constr = function | C.MutConstruct _ -> true | C.Appl (t :: tl) -> constr t | _ -> false 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 subst_g direction i t = 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 List.rev_append (rew_concl :: rew_hips) [clear] in let destruct_g () = [lift_destruct_tac ~context ~what; PESR.clear ~hyps:[hyp]] in let whd_g () = let whd_pattern = C.Appl [meta; hole; hole; hole] in let pattern = None, [hyp, whd_pattern], None in [RT.whd_tac ~pattern; subst_tac ~try_tactic ~hyp] in let tactics = match ty with | (C.Appl [(C.MutInd (uri, 0, [])); _; C.Rel i; t]) when LO.is_eq_URI uri -> subst_g `LeftToRight i t | (C.Appl [(C.MutInd (uri, 0, [])); _; t; C.Rel i]) when LO.is_eq_URI uri -> subst_g `RightToLeft i t | (C.Appl [(C.MutInd (uri, 0, [])); t; t1; t2]) when LO.is_eq_URI uri && ind t && constr t1 && constr t2 -> destruct_g () | (C.Appl [(C.MutInd (uri, 0, [])); _; t1; t2]) when LO.is_eq_URI uri -> whd_g () | _ -> raise (PET.Fail msg1) in PET.apply_tactic (T.seq ~tactics) status in PET.mk_tactic subst_tac let subst_tac = let subst_tac status = let progress = ref false in let try_tactic ~tactic = let try_tactic status = try let result = PET.apply_tactic tactic status in progress := true; result with | PET.Fail _ -> PET.apply_tactic T.id_tac status in PET.mk_tactic try_tactic in let subst hyp = try_tactic ~tactic:(subst_tac ~try_tactic ~hyp) in let map = function | Some (C.Name s, _) -> Some (subst s) | _ -> None in 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 let result = PET.apply_tactic (T.seq ~tactics) status in if !progress then result else raise (PET.Fail msg3) in PET.mk_tactic subst_tac let try_tac tactic = T.try_tactic ~tactic let then_tac start continuation = T.then_ ~start ~continuation let subst_tac = let tactic = T.repeat_tactic ~tactic:subst_tac in T.try_tactic ~tactic