@@ -92,6 +92,7 @@ module SAWScript.Proof
92
92
, withFirstGoal
93
93
, tacticIntro
94
94
, tacticApply
95
+ , tacticApplyHyp
95
96
, tacticSplit
96
97
, tacticCut
97
98
, tacticTrivial
@@ -101,6 +102,8 @@ module SAWScript.Proof
101
102
, tacticExact
102
103
, tacticIntroHyps
103
104
, tacticRevertHyp
105
+ , tacticInsert
106
+ , tacticSpecializeHyp
104
107
105
108
, Quantification (.. )
106
109
, predicateToProp
@@ -324,7 +327,13 @@ splitSequent sc sqt =
324
327
return (Just ( HypFocusedSequent (FB hs1 x (hs2 ++ [b])) gs
325
328
, HypFocusedSequent (FB hs1 y (hs2 ++ [nb])) gs
326
329
))
327
- Nothing -> return Nothing
330
+ Nothing ->
331
+ splitImpl sc h >>= \ case
332
+ Just (x, y) ->
333
+ return (Just ( HypFocusedSequent (FB hs1 y hs2) gs
334
+ , GoalFocusedSequent (hs1 ++ [h] ++ hs2) (FB gs x [] )
335
+ ))
336
+ Nothing -> return Nothing
328
337
329
338
UnfocusedSequent _ _ -> fail " split tactic: focus required"
330
339
@@ -857,11 +866,13 @@ data Evidence
857
866
-- current goal.
858
867
| ApplyEvidence ! Theorem ! [Either Term Evidence ]
859
868
860
- -- | This type of evidence is used to prove an implication. The included
861
- -- proposition must match the hypothesis of the goal, and the included
862
- -- evidence must match the conclusion of the goal. The proposition is
863
- -- allowed to appear inside the evidence as a local assumption.
864
- -- | AssumeEvidence TheoremNonce Prop Evidence
869
+ -- | This type of evidence is produced when a local hypothesis is applied
870
+ -- via backward reasoning to prove a goal. Pi-quantified variables
871
+ -- of the hypothesis may be specialized either by giving an explicit @Term@ to
872
+ -- instantiate the variable, or by giving @Evidence@ for @Prop@ hypotheses.
873
+ -- After specializing the given @Theorem@ the result must match the
874
+ -- current goal.
875
+ | ApplyHypEvidence Integer ! [Either Term Evidence ]
865
876
866
877
-- | This type of evidence is used to prove a universally-quantified statement.
867
878
| IntroEvidence ! (ExtCns Term ) ! Evidence
@@ -971,6 +982,14 @@ cutEvidence :: Prop -> [Evidence] -> IO Evidence
971
982
cutEvidence p [e1,e2] = pure (CutEvidence p e1 e2)
972
983
cutEvidence _ _ = fail " cutEvidence: expected two evidence values"
973
984
985
+ insertEvidence :: Theorem -> [Evidence ] -> IO Evidence
986
+ insertEvidence thm [e] = pure (CutEvidence (_thmProp thm) e (ApplyEvidence thm [] ))
987
+ insertEvidence _ _ = fail " insertEvidence: expected one evidence value"
988
+
989
+ specializeHypEvidence :: Integer -> Prop -> [Term ] -> [Evidence ] -> IO Evidence
990
+ specializeHypEvidence n h ts [e] = pure (CutEvidence h e (ApplyHypEvidence n (map Left ts)))
991
+ specializeHypEvidence _ _ _ _ = fail " specializeHypEvidence: expected one evidence value"
992
+
974
993
structuralEvidence :: Sequent -> Evidence -> Evidence
975
994
structuralEvidence _sqt (StructuralEvidence sqt' e) = StructuralEvidence sqt' e
976
995
structuralEvidence sqt e = StructuralEvidence sqt e
@@ -1033,16 +1052,17 @@ constructTheorem sc db p e loc ploc rsn elapsed =
1033
1052
-- of the given theorem.
1034
1053
specializeTheorem :: SharedContext -> TheoremDB -> Pos -> Text -> Theorem -> [Term ] -> IO Theorem
1035
1054
specializeTheorem _sc _db _loc _rsn thm [] = return thm
1036
- specializeTheorem sc db loc rsn thm ts0 =
1037
- do let p0 = unProp (_thmProp thm)
1038
- res <- TC. runTCM (loop p0 ts0) sc Nothing []
1055
+ specializeTheorem sc db loc rsn thm ts =
1056
+ do res <- specializeProp sc (_thmProp thm) ts
1039
1057
case res of
1040
1058
Left err -> fail (unlines ([" specialize_theorem: failed to specialize" ] ++ TC. prettyTCError err))
1041
1059
Right p' ->
1042
- constructTheorem sc db ( Prop p') (ApplyEvidence thm (map Left ts0 )) loc Nothing rsn 0
1060
+ constructTheorem sc db p' (ApplyEvidence thm (map Left ts )) loc Nothing rsn 0
1043
1061
1062
+ specializeProp :: SharedContext -> Prop -> [Term ] -> IO (Either TC. TCError Prop )
1063
+ specializeProp sc (Prop p0) ts0 = TC. runTCM (loop p0 ts0) sc Nothing []
1044
1064
where
1045
- loop p [] = return p
1065
+ loop p [] = return ( Prop p)
1046
1066
loop p (t: ts) =
1047
1067
do prop <- liftIO (scSort sc propSort)
1048
1068
t' <- TC. typeInferComplete t
@@ -1388,6 +1408,29 @@ checkEvidence sc = \e p -> do nenv <- scGetNamingEnv sc
1388
1408
d2 <- check nenv e2 sqt2
1389
1409
return (d1 <> d2)
1390
1410
1411
+ ApplyHypEvidence n es ->
1412
+ case sqt of
1413
+ GoalFocusedSequent hs (FB gs1 g gs2) ->
1414
+ case genericDrop n hs of
1415
+ (h: _) ->
1416
+ do (d,sy,p') <- checkApply nenv (\ g' -> GoalFocusedSequent hs (FB gs1 g' gs2)) h es
1417
+ ok <- scConvertible sc False (unProp g) p'
1418
+ unless ok $ fail $ unlines
1419
+ [ " Apply evidence does not match the required proposition"
1420
+ , showTerm (unProp g)
1421
+ , showTerm p'
1422
+ ]
1423
+ return (d, sy)
1424
+
1425
+ _ -> fail $ unlines $
1426
+ [ " Not enough hypotheses in apply hypothesis: " ++ show n
1427
+ , prettySequent defaultPPOpts nenv sqt
1428
+ ]
1429
+ _ -> fail $ unlines $
1430
+ [ " Apply hypothesis evidence requires a goal-focused sequent."
1431
+ , prettySequent defaultPPOpts nenv sqt
1432
+ ]
1433
+
1391
1434
ApplyEvidence thm es ->
1392
1435
case sequentState sqt of
1393
1436
GoalFocus p mkSqt ->
@@ -1532,7 +1575,7 @@ finishProof sc db conclProp ps@(ProofState gs (concl,loc,ploc,rsn) stats _ check
1532
1575
(deps,sy) <- checkEvidence sc e' conclProp
1533
1576
n <- freshNonce globalNonceGenerator
1534
1577
end <- getCurrentTime
1535
- thm <- (if recordThm then recordTheorem db else return )
1578
+ thm <- (if recordThm then recordTheorem db else return )
1536
1579
Theorem
1537
1580
{ _thmProp = conclProp
1538
1581
, _thmStats = stats
@@ -1814,6 +1857,37 @@ tacticRevertHyp sc i = Tactic \goal ->
1814
1857
_ -> fail " goal_revert_hyp: conclusion focus required"
1815
1858
1816
1859
1860
+ -- | Attempt to prove a goal by applying a local hypothesis. Any hypotheses of
1861
+ -- the applied proposition will generate additional subgoals.
1862
+ tacticApplyHyp :: (F. MonadFail m , MonadIO m ) => SharedContext -> Integer -> Tactic m ()
1863
+ tacticApplyHyp sc n = Tactic \ goal ->
1864
+ case goalSequent goal of
1865
+ UnfocusedSequent {} -> fail " apply hyp tactic: focus required"
1866
+ HypFocusedSequent {} -> fail " apply hyp tactic: cannot apply in a hypothesis"
1867
+ GoalFocusedSequent hs (FB gs1 g gs2) ->
1868
+ case genericDrop n hs of
1869
+ (h: _) ->
1870
+ liftIO (goalApply sc h g) >>= \ case
1871
+ Nothing -> fail " apply hyp tactic: no match"
1872
+ Just newterms ->
1873
+ let newgoals =
1874
+ [ goal{ goalSequent = GoalFocusedSequent hs (FB gs1 p gs2)
1875
+ , goalType = goalType goal ++ " .subgoal" ++ show i
1876
+ }
1877
+ | Right p <- newterms
1878
+ | i <- [0 :: Integer ]
1879
+ ] in
1880
+ return (() , mempty , newgoals, \ es -> ApplyHypEvidence n <$> processEvidence newterms es)
1881
+ _ -> fail " apply hyp tactic: not enough hypotheses"
1882
+
1883
+ where
1884
+ processEvidence :: [Either Term Prop ] -> [Evidence ] -> IO [Either Term Evidence ]
1885
+ processEvidence (Left tm : xs) es = (Left tm : ) <$> processEvidence xs es
1886
+ processEvidence (Right _ : xs) (e: es) = (Right e : ) <$> processEvidence xs es
1887
+ processEvidence [] [] = pure []
1888
+ processEvidence _ _ = fail " apply hyp tactic failed: evidence mismatch"
1889
+
1890
+
1817
1891
-- | Attempt to prove a goal by applying the given theorem. Any hypotheses of
1818
1892
-- the theorem will generate additional subgoals.
1819
1893
tacticApply :: (F. MonadFail m , MonadIO m ) => SharedContext -> Theorem -> Tactic m ()
@@ -1851,6 +1925,27 @@ tacticSplit sc = Tactic \gl ->
1851
1925
Nothing -> fail " split tactic failed"
1852
1926
1853
1927
1928
+ tacticSpecializeHyp ::
1929
+ (F. MonadFail m , MonadIO m ) => SharedContext -> [Term ] -> Tactic m ()
1930
+ tacticSpecializeHyp sc ts = Tactic \ gl ->
1931
+ case goalSequent gl of
1932
+ HypFocusedSequent (FB hs1 h hs2) gs ->
1933
+ do res <- liftIO (specializeProp sc h ts)
1934
+ case res of
1935
+ Left err ->
1936
+ fail (unlines ([" specialize_hyp tactic: failed to specialize" ] ++ TC. prettyTCError err))
1937
+ Right h' ->
1938
+ do let gl' = gl{ goalSequent = HypFocusedSequent (FB hs1 h (hs2++ [h'])) gs }
1939
+ return (() , mempty , [gl'], specializeHypEvidence (genericLength hs1) h' ts)
1940
+ _ -> fail " specialize_hyp tactic failed: requires hypothesis focus"
1941
+
1942
+
1943
+ tacticInsert :: (F. MonadFail m , MonadIO m ) => SharedContext -> Theorem -> Tactic m ()
1944
+ tacticInsert _sc thm = Tactic \ gl ->
1945
+ let sqt = addHypothesis (_thmProp thm) (goalSequent gl)
1946
+ gl' = gl{ goalSequent = sqt }
1947
+ in return (() , mempty , [gl'], insertEvidence thm)
1948
+
1854
1949
tacticCut :: (F. MonadFail m , MonadIO m ) => SharedContext -> Prop -> Tactic m ()
1855
1950
tacticCut _sc p = Tactic \ gl ->
1856
1951
let sqt1 = addHypothesis p (goalSequent gl)
0 commit comments