@@ -101,6 +101,8 @@ module SAWScript.Proof
101
101
, tacticChange
102
102
, tacticSolve
103
103
, tacticExact
104
+ , tacticIntroHyps
105
+ , tacticRevertHyp
104
106
105
107
, Quantification (.. )
106
108
, predicateToProp
@@ -266,6 +268,34 @@ splitDisj sc (Prop p) =
266
268
t2 <- scPiList sc vars =<< scEqTrue sc p2
267
269
return (Just (Prop t1,Prop t2))
268
270
271
+ -- | Attempt to split an implication into a hypothesis and a conclusion
272
+ splitImpl :: SharedContext -> Prop -> IO (Maybe (Prop , Prop ))
273
+ splitImpl sc (Prop p)
274
+ | Just ( _ :*: h :*: c) <- (isGlobalDef " Prelude.implies" <@> return <@> return ) =<< asEqTrue p
275
+ = do h' <- scEqTrue sc h
276
+ c' <- scEqTrue sc c
277
+ return (Just (Prop h', Prop c'))
278
+
279
+ | Just ( _ :*: (_ :*: h) :*: c) <- (isGlobalDef " Prelude.or" <@> (isGlobalDef " Prelude.not" <@> return ) <@> return ) =<< asEqTrue p
280
+ = do h' <- scEqTrue sc h
281
+ c' <- scEqTrue sc c
282
+ return (Just (Prop h', Prop c'))
283
+
284
+ | Just ( _ :*: c :*: (_ :*: h)) <- (isGlobalDef " Prelude.or" <@> return <@> (isGlobalDef " Prelude.not" <@> return )) =<< asEqTrue p
285
+ = do h' <- scEqTrue sc h
286
+ c' <- scEqTrue sc c
287
+ return (Just (Prop h', Prop c'))
288
+
289
+ {- TODO? sequent normalization doesn't decompose arrows...
290
+
291
+ | Just (_nm, h, c ) <- asPi p
292
+ , looseVars c == emptyBitSet
293
+ = return (Just (Prop h, Prop c))
294
+ -}
295
+
296
+ | otherwise
297
+ = return Nothing
298
+
269
299
270
300
splitSequent :: SharedContext -> Sequent -> IO (Maybe (Sequent , Sequent ))
271
301
splitSequent sc sqt =
@@ -1813,6 +1843,45 @@ tacticIntro sc usernm = Tactic \goal ->
1813
1843
HypFocus _ _ -> fail " TODO: implement intro on hyps"
1814
1844
Unfocused -> fail " intro tactic: focus required"
1815
1845
1846
+
1847
+ tacticIntroHyps :: (F. MonadFail m , MonadIO m ) => SharedContext -> Integer -> Tactic m ()
1848
+ tacticIntroHyps sc n = Tactic \ goal ->
1849
+ case goalSequent goal of
1850
+ GoalFocusedSequent hs (FB gs1 g gs2) ->
1851
+ do (newhs, g') <- liftIO (loop n g)
1852
+ let sqt' = GoalFocusedSequent (hs ++ newhs) (FB gs1 g' gs2)
1853
+ let goal' = goal{ goalSequent = sqt' }
1854
+ return (() , mempty , [goal'], updateEvidence (NormalizeSequentEvidence sqt'))
1855
+ _ -> fail " goal_intro_hyps: conclusion focus required"
1856
+
1857
+ where
1858
+ loop i g
1859
+ | i <= 0 = return ([] ,g)
1860
+ | otherwise =
1861
+ splitImpl sc g >>= \ case
1862
+ Nothing -> fail " intro_hyps: could not find enough hypotheses to introduce"
1863
+ Just (h,g') ->
1864
+ do (hs,g'') <- loop (i- 1 ) g'
1865
+ return (h: hs, g'')
1866
+
1867
+ tacticRevertHyp :: (F. MonadFail m , MonadIO m ) => SharedContext -> Integer -> Tactic m ()
1868
+ tacticRevertHyp sc i = Tactic \ goal ->
1869
+ case goalSequent goal of
1870
+ GoalFocusedSequent hs (FB gs1 g gs2) ->
1871
+ case genericDrop i hs of
1872
+ (h: _) ->
1873
+ case (asEqTrue (unProp h), asEqTrue (unProp g)) of
1874
+ (Just h', Just g') ->
1875
+ do g'' <- liftIO (Prop <$> (scEqTrue sc =<< scImplies sc h' g'))
1876
+ let sqt' = GoalFocusedSequent hs (FB gs1 g'' gs2)
1877
+ let goal' = goal{ goalSequent = sqt' }
1878
+ return (() , mempty , [goal'], updateEvidence (NormalizeSequentEvidence sqt'))
1879
+
1880
+ _ -> fail " goal_revert_hyp: expected EqTrue props"
1881
+ _ -> fail " goal_revert_hyp: not enough hypotheses"
1882
+ _ -> fail " goal_revert_hyp: conclusion focus required"
1883
+
1884
+
1816
1885
{-
1817
1886
-- | Attempt to prove an implication goal by introducing a local assumption for
1818
1887
-- hypothesis. Return a @Theorem@ representing this local assumption.
@@ -1869,6 +1938,7 @@ tacticSplit sc = Tactic \gl ->
1869
1938
return (() , mempty , [g1,g2], splitEvidence)
1870
1939
Nothing -> fail " split tactic failed"
1871
1940
1941
+
1872
1942
tacticCut :: (F. MonadFail m , MonadIO m ) => SharedContext -> Prop -> Tactic m ()
1873
1943
tacticCut _sc p = Tactic \ gl ->
1874
1944
let sqt1 = addHypothesis p (goalSequent gl)
0 commit comments