Skip to content

Commit 3b14346

Browse files
committed
Add a few new tactics for introducing and reverting hypotheses
in sequents.
1 parent 6aff5ef commit 3b14346

File tree

3 files changed

+90
-0
lines changed

3 files changed

+90
-0
lines changed

src/SAWScript/Builtins.hs

+10
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,16 @@ goal_exact tm =
828828
do sc <- SV.scriptTopLevel getSharedContext
829829
execTactic (tacticExact sc (ttTerm tm))
830830

831+
goal_intro_hyps :: Integer -> ProofScript ()
832+
goal_intro_hyps n =
833+
do sc <- SV.scriptTopLevel getSharedContext
834+
execTactic (tacticIntroHyps sc n)
835+
836+
goal_revert_hyp :: Integer -> ProofScript ()
837+
goal_revert_hyp i =
838+
do sc <- SV.scriptTopLevel getSharedContext
839+
execTactic (tacticRevertHyp sc i)
840+
831841
{-
832842
goal_assume :: ProofScript Theorem
833843
goal_assume =

src/SAWScript/Interpreter.hs

+10
Original file line numberDiff line numberDiff line change
@@ -1696,6 +1696,16 @@ primitives = Map.fromList
16961696
, "This will succeed if the type of the given term matches the current goal."
16971697
]
16981698

1699+
, prim "goal_intro_hyps" "Int -> ProofScript ()"
1700+
(pureVal goal_intro_hyps)
1701+
Experimental
1702+
[ "TODO "]
1703+
1704+
, prim "goal_revert_hyp" "Int -> ProofScript ()"
1705+
(pureVal goal_revert_hyp)
1706+
Experimental
1707+
[ "TODO "]
1708+
16991709
{-
17001710
, prim "goal_assume" "ProofScript Theorem"
17011711
(pureVal goal_assume)

src/SAWScript/Proof.hs

+70
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ module SAWScript.Proof
101101
, tacticChange
102102
, tacticSolve
103103
, tacticExact
104+
, tacticIntroHyps
105+
, tacticRevertHyp
104106

105107
, Quantification(..)
106108
, predicateToProp
@@ -266,6 +268,34 @@ splitDisj sc (Prop p) =
266268
t2 <- scPiList sc vars =<< scEqTrue sc p2
267269
return (Just (Prop t1,Prop t2))
268270

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+
269299

270300
splitSequent :: SharedContext -> Sequent -> IO (Maybe (Sequent, Sequent))
271301
splitSequent sc sqt =
@@ -1813,6 +1843,45 @@ tacticIntro sc usernm = Tactic \goal ->
18131843
HypFocus _ _ -> fail "TODO: implement intro on hyps"
18141844
Unfocused -> fail "intro tactic: focus required"
18151845

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+
18161885
{-
18171886
-- | Attempt to prove an implication goal by introducing a local assumption for
18181887
-- hypothesis. Return a @Theorem@ representing this local assumption.
@@ -1869,6 +1938,7 @@ tacticSplit sc = Tactic \gl ->
18691938
return ((), mempty, [g1,g2], splitEvidence)
18701939
Nothing -> fail "split tactic failed"
18711940

1941+
18721942
tacticCut :: (F.MonadFail m, MonadIO m) => SharedContext -> Prop -> Tactic m ()
18731943
tacticCut _sc p = Tactic \gl ->
18741944
let sqt1 = addHypothesis p (goalSequent gl)

0 commit comments

Comments
 (0)