module ThmTactics where import Lookup import Tactics import Tacticals import Kernel import Tree import Core_datatype import DerivedRules import Goals import Vtslib import Type_defs import Parse import X_interface import Edlib import Globals import Tags -- partain import Sub_Core1 import Sub_Core2 import Sub_Core3 import Sub_Core4 import Unparse import Attributes {- rewrite_tac = Tactic "Rewrite" rewrite_input rewrite_subgoal beta_tac = Tactic "Beta" beta_input beta_subgoal eta_tac = Tactic "Eta" eta_input eta_subgoal recurse_tac = Tactic "Recurse" recurse_input recurse_subgoal -} {- create_name s i dc@(Symbol_dec t attL) = case get_att Name_Style attL of SOME _ -> (dc,i) NONE -> (Symbol_dec t attL' , i+1) where nm = Name (s ++ nprimes i) att = set_att Name_Style (Symbol_Name nm) attL' = att : attL create_name s i dc@(Axiom_dec t attL) = case get_att Name_Style attL of SOME _ -> (dc,i) NONE -> (Axiom_dec t attL' , i+1) where nm = Name (s ++ nprimes i) att = set_att Name_Style (Symbol_Name nm) attL' = att : attL -} create_name s i (Decpair dc1 dc2 attL) = (Decpair dc1' dc2' attL, i3) where (dc1',i2) = create_name s i dc1 (dc2',i3) = create_name s i2 dc2 create_name s i dc = (dc,i) --nprimes i = take i ( repeat '\39' ) {- (******************************************************************************) (* complete_thm *) (* *) (* ô *) (* --------- Complete (ø : ô) *) (* *) (******************************************************************************) -} complete_tac = Tactic "Complete" complete_thm_input complete_thm complete_thm gst sg lt (SOME [dv]) (ThmSpec itm) = if not (is_valid_Thm th ) then Bad mesg else if eq_trm th_itm itm then Ok ([], complete_thm_valid th) else Bad ("Derivation does not prove given goal\n" ++ "proves: " ++ unparse_trm sg ps th_itm ) where ps = fetch_ps gst th = parse_Thm sg ps dv ( TH_Err mesg ) = th ( th_itm , _ ) = internal_Thm th complete_thm _ _ _ _ _ = Bad "Goal is not a theorem" complete_thm_valid th [] = SOME (ThmDone th) complete_thm_valid _ _ = NONE complete_thm_input lt gst (ThmSpec tm) = x_form True form /./ exp where exp NONE = reTurn NONE exp ( SOME [OutText s]) = reTurn ( SOME [s] ) form = [InComment "Complete Theorem", InMultiText "Derivation" ""] {- (******************************************************************************) (* gen_subgoal *) (* *) (* ±ë.ô *) (* ------------ Gen *) (* ë, Ûë] ô *) (* *) (******************************************************************************) -} gen_tac = OrdTactic "Gen" null_arg_fn gen_subgoal gen_subgoal gst sg lt args (ThmSpec (Binder Forall dc tm _ _)) = Ok (subgoals, [lt,lt], rwL, gen_valid sg ) where (dc',_) = create_name "xxx" 0 dc subgoals = [DecSpec dc', ThmSpec tm] rwL = [True, False] -- ltL = [lt, extend_lookup_table true dc' lt] gen_subgoal _ _ _ _ _ = Bad "Cannot apply tactic to given goal" gen_valid sg dnL rwL = case (dnL, rwL) of ([SOME (DecDone dc), SOME (ThmDone th)],_) -> (rwL,[sg,extend dc sg],SOME (ThmDone (generalise th))) ([SOME (DecDone dc), NONE], [true,_]) -> ([True,True],[sg,extend dc sg],NONE) _ -> (rwL,[sg,sg],NONE) {- (******************************************************************************) (* disch_subgoal *) (* *) (* [ë] ¶ ô *) (* -------------- Dischage *) (* ë, ÛkÝ t *) (******************************************************************************) -} disch_tac = OrdTactic "Disch" null_arg_fn disch_subgoal disch_subgoal gst sg lt args (ThmSpec (Binder Imp dc tm _ _)) = Ok (subgoals, [lt,lt], rwL, disch_valid sg) where (dc',_) = create_name "hhh" 0 dc subgoals = [DecSpec dc', ThmSpec tm] rwL = [True, False] disch_subgoal _ _ _ _ _ = Bad "Cannot apply 'Disch' to specified goal" disch_valid sg dnL rwL = case (dnL, rwL) of ([SOME (DecDone dc), SOME (ThmDone th)],_) -> (rwL,[sg,extend dc sg],SOME (ThmDone (discharge th))) ([SOME (DecDone dc), NONE], [true,_]) -> ([True,True],[sg,extend dc sg],NONE) _ -> (rwL,[sg,sg],NONE) {- (******************************************************************************) (* conj_subgoal *) (* *) (* æ ³ ù *) (* ----- Conjunction *) (* æ, ù *) (******************************************************************************) -} conj_tac = Tactic "Conjunction" null_arg_fn conj_subgoal conj_subgoal gst sg lt args (ThmSpec (Binary' And tm1 tm2 _ _)) = Ok ([ThmSpec tm1, ThmSpec tm2], conj_valid) conj_subgoal _ _ _ _ _ = Bad "cannot apply tactic to specified goal" conj_valid [SOME (ThmDone th1), SOME (ThmDone th2)] = SOME (ThmDone (conj th1 th2)) conj_valid _ = NONE {- (******************************************************************************) (* disj_subgoal *) (* *) (* c *) (* --------- Disjunction (ø : a´b) give either ø or a´b *) (* a¶c, b¶c *) (******************************************************************************) -} disj_tac = Tactic "Disjunction" disj_input disj_subgoal disj_subgoal gst sg lt (SOME args) (ThmSpec tm) = case args of ["Derivation", dv] -> if is_valid_Thm th then case internal_Thm th of (Binary' Or tm1 tm2 _ _ , _) -> Ok ([ThmSpec tm4, ThmSpec tm5], disj_dv_valid th) where dc1 = Axiom_dec tm1 [] dc2 = Axiom_dec tm2 [] tm3 = shift_trm [] 1 tm tm4 = Binder Imp dc1 tm3 [] [] tm5 = Binder Imp dc2 tm3 [] [] _ -> Bad "Goal is not a disjunction" else Bad mesg where ps = fetch_ps gst th = parse_Thm sg ps dv ( TH_Err mesg ) = th ["Specification",tm_rep] -> parse_trm sg ps tm_rep ||| exp where exp tm6@(Binary' Or tm1 tm2 _ _) = Ok ([ThmSpec tm4, ThmSpec tm5, ThmSpec tm6], disj_tm_valid) where dc1 = Axiom_dec tm1 [] dc2 = Axiom_dec tm2 [] tm3 = shift_trm [] 1 tm tm4 = Binder Imp dc1 tm3 [] [] tm5 = Binder Imp dc2 tm3 [] [] exp _ = Bad "Specification is not a disjunction" ps = fetch_ps gst _ -> Bad "No selection" disj_subgoal _ _ _ _ _ = Bad "Cannot apply 'disjunction'" disj_dv_valid th [SOME (ThmDone th1), SOME (ThmDone th2)] = SOME (ThmDone (disj th th1 th2)) disj_dv_valid _ _ = NONE disj_tm_valid [SOME (ThmDone th1), SOME (ThmDone th2), SOME (ThmDone th3)] = SOME (ThmDone (disj th3 th1 th2)) disj_tm_valid _ = NONE disj_input lt gst _ = x_form True form /./ exp where exp NONE = reTurn NONE exp ( SOME [OutRadio s1,OutText s2] ) = reTurn ( SOME [s1,s2] ) form = [InComment "Disjunction", InRadio "Argument Type" 0 ["Derivation","Specification"], InMultiText "" ""] {- (******************************************************************************) (* reflex_subgoal *) (* *) (* ô = ô *) (* ----- Reflex *) (* *) (******************************************************************************) -} reflex_tac = Tactic "Reflex" null_arg_fn reflex_subgoal reflex_subgoal gst sg lt args (ThmSpec (Binary' Eq' tm1 tm2 _ _)) | eq_trm tm1 tm2 = Ok ([], reflex_valid (reflex (trm_to_Trm sg tm1))) | otherwise = Bad "Terms not equal" reflex_subgoal _ _ _ _ _ = Bad "cannot apply 'reflex' to specified goal" reflex_valid th [] = SOME (ThmDone th) reflex_valid _ _ = NONE {- {- (******************************************************************************) (* rewrite_subgoal *) (* *) (* P[a]i *) (* ----- Rewrite (ø : a = b) supply either ø or a=b *) (* P[b]i *) (* *) (******************************************************************************) -} rewrite_subgoal gst sg lt (SOME [index,spec,spec_type]) (ThmSpec tm) = case spec_type of "Derivation" -> case internal_Thm th of (Binary' Eq' tm2 tm3 _ _ ,_) | eq_trm tm1 tm2 -> Ok ([ThmSpec tm4], rewrite_th_valid iL th) where tm4 = replace_trm tm tm3 iL | otherwise -> Bad "LHS does not match subgoal" _ -> Bad "Theorem not an equality" where iL = parse_index index (tm1,dcL) = select_trm tm iL sg1 = foldl ext_Sg sg dcL ps = fetch_ps gst th = parse_Thm sg ps spec "Specification" -> case parse_trm sg spec of -- add ps to parse th_tm@(Binary' Eq' tm2 tm3 _ _) | eq_trm tm1 tm2 -> Ok ([ThmSpec tm4, ThmSpec th_tm], rewrite_tm_valid iL) where tm4 = replace_trm tm tm3 iL | otherwise -> Bad "LHS does not match subgoal" _ -> Bad "Term not an equality" where iL = parse_index index (tm1,dcL) = select_trm tm iL sg1 = foldl ext_sg (internal_Sgn sg) dcL ps = fetch_ps gst rewrite_th_valid iL th [SOME (ThmDone th1)] = SOME (ThmDone (subterm_rw th1 (symmetry th) iL)) rewrite_tm_valid iL [SOME (ThmDone th1), SOME (ThmDone th2)] = SOME (ThmDone (subterm_rw th1 (symmetry th2) iL)) rewrite_input gst lt (ThmSpec tm) = error "rewrite_input not implemented" {- = x_form True form /./ exp where exp NONE -> reTurn NONE exp ( SOME [OutSubterm s1,OutText s2,OutRadio s3] ) = reTurn ( SOME [s1,s2,s3] ) exp _ = return_err "Unexected arguments returned" attL = get_attributes gst (s,data) = unparse_trm_data ust1 tm form = [InComment "Rewrite", InSubterm s data, InMultiText "Rewrite Theorem" "", InRadio "Type of Input " 0 ["Derivation","Specification"]] -} parse_index inp = case next_tk inp of (SOME tk, inp1) -> read tk : parse_index inp1 (NONE, _) -> [] ext_Sg sg dc = extend (dec_to_Dec sg dc) sg ext_sg sg dc = Extend dc sg [] -} induction_tac= Tactic "Induction" null_arg_fn ind_subgoal ind_subgoal gst sg lt args (ThmSpec (Binder Forall dc tm _ attL)) = Ok ( gL , ind_valid ind_thm pL ) where tm1 = Binder Lambda dc tm [] attL ( Symbol_dec st attL ) = dc (i,j,spec,dcL,parmL) = get_datatype_info (internal_Sgn sg) st specL = map (trm_to_Trm sg) spec ind_thm = foldl specialise (induction (constructor sg i j 0)) specL (Binder _ dec tm2 _ _ , _) = internal_Thm ind_thm (spec_thm,pL) = find_betas (subst_trm dec tm2 tm1) gL = map ThmSpec (reduce_ind spec_thm) ++ [TrmSpec tm1] ind_subgoal _ _ _ _ _ = Bad "Goal is not universally quantified" reduce_ind (Binder Imp dc tm _ _) = typ_of_dec dc : reduce_ind (shift_trm [] (-1) tm) reduce_ind _ = [] ind_valid th pL dnL = SOME (ThmDone (foldl mp th1 dnL1)) where i = length dnL - 1 dnL1 = take i dnL SOME (TrmDone tm) = head (drop i dnL) th1 = rep_beta (specialise th tm) pL mp th1 (SOME (ThmDone th2)) = modus_ponens th1 th2 axiom_tac = Tactic "Axiom" axiom_arg_fn axiom_subgoal axiom_arg_fn gst lt (ThmSpec tm) = x_form True form /./ exp where exp NONE = reTurn NONE exp ( SOME [OutText s] ) = reTurn ( SOME [s] ) form = [InComment "Tactic: Axiom", InSingleText "Name Of Axiom" ""] axiom_subgoal gst sg lt (SOME [name]) obj = case lookup_name sg name of SOME (Sym i j _ _) -> if ( is_valid_Thm app_axiom ) then Ok ([], axiom_valid app_axiom ) else Bad ("Axiom: " ++ show i ++ " " ++ show j) where app_axiom = axiom sg i j _ -> Bad ("No Such Axiom Name: " ++ name) axiom_subgoal _ _ _ _ _ = Bad "Hmm: it's failed, no name supplied perhaps?" axiom_valid th [] = SOME (ThmDone th) axiom_valid _ _ = NONE hyp_tac = Tactic "Hyp" null_arg_fn find_hyp find_hyp gst sg lt NONE (ThmSpec tm) = case filter (find_match tm) hyps of [] -> Bad "Can't find match" (th : _) -> Ok ([], axiom_valid th) where hyps = get_hyp_from_sgn sg (internal_Sgn sg) 0 find_hyp _ _ _ _ _ = Bad "goal is not a theorem specification" get_hyp_from_sgn sg (Empty _) i = [] get_hyp_from_sgn sg (Extend dc isg _) i = l ++ get_hyp_from_sgn sg isg (i + 1) where (_, l) = get_hyp_from_dec sg dc i 0 get_hyp_from_sgn sg _ i = [] get_hyp_from_dec sg (Axiom_dec _ _ ) i j = (j, [axiom sg i j]) get_hyp_from_dec sg (Def _ _ _) i j = (j, [axiom sg i j]) get_hyp_from_dec sg (Decpair dc1 dc2 _) i j = (j'', l ++ l') where (j', l) = get_hyp_from_dec sg dc1 i (j+1) (j'',l') = get_hyp_from_dec sg dc2 i (j' + 1) get_hyp_from_dec _ _ _ j = (j, []) find_match tm th = eq_trm tm tm' where (tm',_) = internal_Thm th {- (******************************************************************************) (* eq_subgoal *) (* *) (* a=b *) (* --------- *) (* a¶b b¶a *) (******************************************************************************) -} eq_tac = Tactic "Eq" null_arg_fn eq_subgoal eq_subgoal gst sg lt args (ThmSpec (Binary' Eq' itm1 itm2 _ _)) = if eq_trm ty1 ty2 && eq_trm ty1 (Constant Bool' [] []) then Ok ([ThmSpec tm3, ThmSpec tm4],eq_valid gst lt sg tm1 tm2) else Bad "Equality not on booleans" where dc1 = Axiom_dec itm1 [] dc2 = Axiom_dec itm2 [] tm3 = Binder Imp dc1 (shift_trm [] 1 itm2) [] [] tm4 = Binder Imp dc2 (shift_trm [] 1 itm1) [] [] tm1 = trm_to_Trm sg itm1 tm2 = trm_to_Trm sg itm2 (ty1,_,_) = internal_Trm (typ_of_Trm tm1) (ty2,_,_) = internal_Trm (typ_of_Trm tm2) eq_subgoal _ _ _ _ _ = Bad "Cannot apply tactic to given goal" eq_valid gst lt sg tm1 tm2 [SOME (ThmDone th1), SOME (ThmDone th2)] = SOME (ThmDone th6) where inp = "\186(\177a:bool.\177b:bool.(a\182b)\182(b\182a)\182(a=b))" ps = fetch_ps gst eq_th = parse_Thm sg ps inp th3 = specialise eq_th tm1 th4 = specialise th3 tm2 th5 = modus_ponens th4 th1 th6 = modus_ponens th5 th2 eq_valid _ _ _ _ _ _ = NONE {- (******************************************************************************) (* or_subgoal *) (* *) (* a ³ b *) (* ------- *) (* µ a ¶ b *) (******************************************************************************) -} or_tac = Tactic "Or" null_arg_fn or_subgoal or_subgoal gst sg lt NONE (ThmSpec (Binary' Or tm1 tm2 _ _)) = Ok ([ThmSpec tm3], or_valid gst lt sg tM1 tM2) where dc = Axiom_dec (Unary Not tm1 [] []) [] tm3 = Binder Imp dc (shift_trm [] 1 tm2) [] [] tM1 = trm_to_Trm sg tm1 tM2 = trm_to_Trm sg tm2 or_subgoal _ _ _ _ _ = Bad "Goal is not a disjunction" or_valid gst lt sg tm1 tm2 [SOME (ThmDone th)] = SOME (ThmDone th2) where inp = "\186(\177a:bool.\177b:bool.(\181a\182b)=(a\180b))" ps = fetch_ps gst or_th = parse_Thm sg ps inp th1 = specialise (specialise or_th tm1) tm2 th2 = subterm_rw th th1 [] or_valid _ _ _ _ _ _ = NONE {- (******************************************************************************) (* not_subgoal *) (* *) (* µ µ a *) (* ------- *) (* a *) (******************************************************************************) -} not_tac = Tactic "Not" null_arg_fn not_subgoal not_subgoal gst sg lt NONE (ThmSpec (Unary Not (Unary Not tm1 _ _) _ _)) = Ok ([ThmSpec tm1], not_valid gst lt sg tM1) where tM1 = trm_to_Trm sg tm1 not_subgoal _ _ _ _ _ = Bad "cannot apply 'Not' to given goal" not_valid gst lt sg tm1 [SOME (ThmDone th)] = SOME (ThmDone th2) where inp = "\186(\177a:bool.a=\181\181a)" ps = fetch_ps gst not_th = parse_Thm sg ps inp th1 = specialise not_th tm1 th2 = subterm_rw th th1 [] not_valid _ _ _ _ _ = NONE {- (******************************************************************************) (* lemma-subgoal *) (* *) (* a *) (* ------------ b *) (* b ¶ a, b *) (******************************************************************************) -} lemma_tac = Tactic "Lemma" lemma_input lemma_subgoal lemma_subgoal gst sg lt (SOME [nm,spec]) (ThmSpec tm) = parse_trm sg ps spec ||| exp where ps = fetch_ps gst exp lemma = Ok ( [g1,g2], lemma_valid ) where g1 = ThmSpec (Binder Imp dc tm' [] []) where rnm = Name nm dc = Axiom_dec lemma [sym_nm rnm] tm' = shift_trm [] 1 tm g2 = ThmSpec lemma lemma_subgoal _ _ _ _ _ = Bad "Goal is not a theorem specification" lemma_valid [SOME (ThmDone th1), SOME (ThmDone th2)] = SOME (ThmDone (modus_ponens th1 th2)) lemma_valid _ = NONE lemma_input gst lt (ThmSpec tm) = x_form True form /./ exp where exp NONE = reTurn NONE exp ( SOME [OutText s1,OutText s2] ) = reTurn ( SOME [s1,s2] ) form = [InComment "Add lemma", InSingleText "Name " "", InMultiText "Lemma" ""] {- rw_input str gst lt (ThmSpec tm) = error "re_input not implemented" {- = x_form True form /./ exp where` exp NONE = reTurn NONE exp ( SOME [OutSubterm s] ) = reTurn ( SOME [s] ) exp _ = return_err "Unexected arguments returned" attL = get_attributes gst ust = get_default_us gst val ust1 = U.set_defaults (U.set_lookup_table ust lt) attL val (s,data) = unparse_trm_data ust1 tm form = [InComment str, InSubterm s data] -} beta_subgoal gst sg lt (SOME [index]) (ThmSpec tm) = Ok ( [ ThmSpec tm3 ] , beta_valid th iL ) where iL = parse_index index (App (Binder Lambda dc tm1 _ _) tm2 _ _ ,dcL) = select_trm tm iL tm3 = replace_trm tm (subst_trm dc tm1 tm2) iL th = reflex (trm_to_Trm sg tm) beta_valid th iL [SOME (ThmDone th')] = SOME (ThmDone (subterm_rw th' (beta_rw th (0:iL)) [])) beta_valid _ _ _ = NONE beta_input = rw_input "â Rewrite" {- fun eta_subgoal gst sg lt (SOME [index]) (ThmSpec tm) = let val iL = parse_index (strings_to_input [index]) val (Binder(Lambda,dc,App (tm1,Sym(0,0,_,_),_,_),_,_),dcL) = select_trm tm iL in if occurs 0 tm1 then fail "Not è-reducducable" else let val tm3 = replace_trm tm (shift_trm [] ~1 tm1) iL val th = reflex (trm_to_Trm sg tm) in ( [ ThmSpec tm3 ] , eta_valid th iL ) end end and eta_valid th iL [SOME (ThmDone th')] = SOME (ThmDone (subterm_rw th' (eta_rw th (0::iL)) [])) val eta_input = rw_input "è Rewrite" -} {- fun recurse_subgoal gst sg lt (SOME [index]) (ThmSpec tm) = let val iL = parse_index (strings_to_input [index]) val (App (Recurse _,_,_,_),dcL) = select_trm tm iL val th = recurse_rw (reflex (trm_to_Trm sg tm)) (0::iL) val (Binary' (Eq',tm3,_,_,_), _) = internal_Thm th in ( [ ThmSpec tm3 ] , recurse_valid th ) end and recurse_valid th [SOME (ThmDone th')] = SOME (ThmDone (subterm_rw th' th [])) val recurse_input = rw_input "Recurse Rewrite" -} -} taut_tac = Tactic "Taut" null_arg_fn taut_subgoal taut_subgoal gst sg lt _ (ThmSpec tm) = if is_valid_Thm th then Ok ( [] , taut_valid th ) else Bad mesg where th = taut (trm_to_Trm sg tm) ( TH_Err mesg ) = th taut_subgoal _ _ _ _ _ = Bad "goal is not a theorem specification" taut_valid th [] = SOME (ThmDone th) taut_valid _ _ = NONE {- (******************************************************************************) (* exists_subgoal *) (* *) (* p *) (* ------ ø : ²x.q *) (* ±x.q¶p *) (******************************************************************************) -} exists_elim_tac = Tactic "ExistsElim" exists_elim_input exists_elim_subgoal exists_elim_subgoal gst sg lt (SOME [s1,"Derivation"]) (ThmSpec tm) = parse_Thm_M sg ps s1 ||| exp where ps = fetch_ps gst exp th = Ok ( [ ThmSpec tm''' ] , exists_elim_valid th ) where (Binder Exists dc tm' _ _ ,_) = internal_Thm th tm'' = Binder Imp (Axiom_dec tm' [])(shift_trm [] 2 tm) [] [] tm''' = Binder Forall dc tm'' [] [] exists_elim_subgoal gst sg lt (SOME [s1,"Specification"]) (ThmSpec tm) = parse_trm sg ps s1 ||| exp where ps = fetch_ps gst exp tm1@(Binder Exists dc tm' _ _) = Ok ( [ ThmSpec tm''', ThmSpec tm1 ] , exists_elim_valid' ) where tm'' = Binder Imp (Axiom_dec tm' []) (shift_trm [] 2 tm) [] [] tm''' = Binder Forall dc tm'' [] [] exp _ = Bad "term is not an existential" exists_elim_subgoal _ _ _ _ _ = Bad "Invalid application of 'ExistsElim'" exists_elim_valid th' [SOME (ThmDone th)] = SOME (ThmDone (exists_elim th' th)) exists_elim_valid _ _ = NONE exists_elim_valid' [SOME (ThmDone th1), SOME (ThmDone th2)] = SOME (ThmDone (exists_elim th1 th2)) exists_elim_valid' _ = NONE exists_elim_input gst lt (ThmSpec tm) = x_form True form /./ exp where exp ( SOME [OutText s1,OutRadio s2] ) = reTurn ( SOME [s1,s2] ) exp _ = reTurn NONE form = [InComment "Exists Elimination", InMultiText "Existential Object" "", InRadio "Type of Object" 0 ["Derivation","Specification"]] strip split_tac auto_tac = repeat_tac (snd (lift_tactic reflex_tac) `orelse` snd (lift_tactic hyp_tac) `orelse` -- snd (lift_tactic taut_tac) `orelse` snd (lift_ordtactic gen_tac) `orelse` snd (lift_ordtactic disch_tac) `orelse` snd (lift_tactic conj_tac) `orelse` snd (lift_tactic or_tac) `orelse` snd (lift_tactic not_tac) `orelse` snd (lift_tactic eq_tac) `orelse` snd (lift_tactic auto_tac) ) -- `orelse` -- snd (lift_ordtactic split_tac) ) triv auto_tac = snd (lift_tactic reflex_tac) `orelse` snd (lift_tactic hyp_tac) `orelse` snd (lift_tactic auto_tac) `orelse` snd (lift_tactic taut_tac) `orelse` ( \ trst -> reTurn trst )