@@ -42,10 +42,8 @@ module SAWScript.Proof
42
42
, Evidence (.. )
43
43
, checkEvidence
44
44
45
- , ProofGoal (.. )
46
- , withFirstGoal
47
-
48
45
, Tactic
46
+ , withFirstGoal
49
47
, tacticIntro
50
48
, tacticCut
51
49
, tacticAssume
@@ -57,16 +55,18 @@ module SAWScript.Proof
57
55
, tacticSolve
58
56
59
57
, Quantification (.. )
60
- , makeProofGoal
61
58
, predicateToProp
62
59
, propToPredicate
63
60
64
61
, ProofState
65
62
, psTimeout
66
63
, psGoals
67
64
, setProofTimeout
65
+ , ProofGoal (.. )
68
66
, startProof
69
67
, finishProof
68
+
69
+ , predicateToSATQuery
70
70
) where
71
71
72
72
import qualified Control.Monad.Fail as F
@@ -411,47 +411,32 @@ data ProofGoal =
411
411
data Quantification = Existential | Universal
412
412
deriving Eq
413
413
414
- -- | Construct a 'ProofGoal' from a term of type @Bool@, or a function
415
- -- of any arity with a boolean result type. Any function arguments are
416
- -- treated as quantified variables. If the 'Quantification' argument
417
- -- is 'Existential', then the predicate is negated and turned into a
418
- -- universally-quantified goal.
419
- makeProofGoal ::
420
- SharedContext ->
421
- Quantification ->
422
- Int {- goal number -} ->
423
- String {- goal type -} ->
424
- String {- goal name -} ->
425
- Term {- goal predicate -} ->
426
- IO ProofGoal
427
- makeProofGoal sc quant gnum gtype gname t =
428
- do t' <- predicateToProp sc quant [] t
429
- return (ProofGoal gnum gtype gname t')
430
-
431
414
-- | Convert a term with a function type of any arity into a pi type.
432
415
-- Negate the term if the result type is @Bool@ and the quantification
433
416
-- is 'Existential'.
434
- predicateToProp :: SharedContext -> Quantification -> [Term ] -> Term -> IO Prop
435
- predicateToProp sc quant env t =
436
- case asLambda t of
437
- Just (x, ty, body) ->
438
- do Prop body' <- predicateToProp sc quant (ty : env) body
439
- Prop <$> scPi sc x ty body'
440
- Nothing ->
441
- do (argTs, resT) <- asPiList <$> scTypeOf' sc env t
442
- let toPi [] t0 =
443
- case asBoolType resT of
444
- Nothing -> return t0 -- TODO: check quantification
445
- Just () ->
446
- case quant of
447
- Universal -> scEqTrue sc t0
448
- Existential -> scEqTrue sc =<< scNot sc t0
449
- toPi ((x, xT) : tys) t0 =
450
- do t1 <- incVars sc 0 1 t0
451
- t2 <- scApply sc t1 =<< scLocalVar sc 0
452
- t3 <- toPi tys t2
453
- scPi sc x xT t3
454
- Prop <$> toPi argTs t
417
+ predicateToProp :: SharedContext -> Quantification -> Term -> IO Prop
418
+ predicateToProp sc quant = loop []
419
+ where
420
+ loop env t =
421
+ case asLambda t of
422
+ Just (x, ty, body) ->
423
+ do Prop body' <- loop (ty : env) body
424
+ Prop <$> scPi sc x ty body'
425
+ Nothing ->
426
+ do (argTs, resT) <- asPiList <$> scTypeOf' sc env t
427
+ let toPi [] t0 =
428
+ case asBoolType resT of
429
+ Nothing -> return t0 -- TODO: check quantification TODO2: should this just be an error?
430
+ Just () ->
431
+ case quant of
432
+ Universal -> scEqTrue sc t0
433
+ Existential -> scEqTrue sc =<< scNot sc t0
434
+ toPi ((x, xT) : tys) t0 =
435
+ do t1 <- incVars sc 0 1 t0
436
+ t2 <- scApply sc t1 =<< scLocalVar sc 0
437
+ t3 <- toPi tys t2
438
+ scPi sc x xT t3
439
+ Prop <$> toPi argTs t
455
440
456
441
-- | Turn a pi type with an @EqTrue@ result into a lambda term with a
457
442
-- boolean result type. This function exists to interface the new
@@ -683,6 +668,42 @@ withFirstGoal f =
683
668
evidenceCont (e: es2)
684
669
return (x, ProofState (gs' <> gs) concl (stats <> stats') timeout evidenceCont')
685
670
671
+ predicateToSATQuery :: SharedContext -> Set VarIndex -> Term -> IO SATQuery
672
+ predicateToSATQuery sc unintSet tm0 =
673
+ do (initVars, abstractVars) <- filterFirstOrderVars mempty mempty (getAllExts tm0)
674
+ (finalVars, tm') <- processTerm initVars tm0
675
+ return SATQuery
676
+ { satVariables = finalVars
677
+ , satUninterp = Set. union unintSet abstractVars
678
+ , satAsserts = [tm']
679
+ }
680
+ where
681
+ filterFirstOrderVars fovars absvars [] = pure (fovars, absvars)
682
+ filterFirstOrderVars fovars absvars (e: es) =
683
+ runMaybeT (asFirstOrderTypeMaybe sc (ecType e)) >>= \ case
684
+ Nothing -> filterFirstOrderVars fovars (Set. insert (ecVarIndex e) absvars) es
685
+ Just fot -> filterFirstOrderVars (Map. insert e fot fovars) absvars es
686
+
687
+ processTerm vars tm =
688
+ case asLambda tm of
689
+ Just (lnm,tp,body) ->
690
+ do fot <- asFirstOrderType sc tp
691
+ ec <- scFreshEC sc (Text. unpack lnm) tp
692
+ etm <- scExtCns sc ec
693
+ body' <- instantiateVar sc 0 etm body
694
+ processTerm (Map. insert ec fot vars) body'
695
+
696
+ -- TODO: check that the type is a boolean
697
+ Nothing ->
698
+ do ty <- scTypeOf sc tm
699
+ ok <- scConvertible sc True ty =<< scBoolType sc
700
+ unless ok $ fail $ unlines
701
+ [ " predicateToSATQuery: expected boolean result but got:"
702
+ , showTerm ty
703
+ , showTerm tm0
704
+ ]
705
+ return (vars, tm)
706
+
686
707
-- | Given a proposition, compute a SAT query which will prove the proposition
687
708
-- iff the SAT query is unsatisfiable.
688
709
propToSATQuery :: SharedContext -> Set VarIndex -> Prop -> IO SATQuery
@@ -710,7 +731,7 @@ propToSATQuery sc unintSet prop =
710
731
, looseVars body == emptyBitSet ->
711
732
do processTerm vars (x: xs) body
712
733
713
- -- TODO? Allow first-order hypotheses...
734
+ -- TODO? Allow universal hypotheses...
714
735
715
736
| otherwise ->
716
737
do fot <- asFirstOrderType sc tp
@@ -749,6 +770,7 @@ goalApply sc rule goal = applyFirst (asPiLists (unProp rule))
749
770
mkNewGoals mts args
750
771
mkNewGoals _ _ = return []
751
772
newgoalterms <- mkNewGoals inst' (reverse ruleArgs)
773
+ -- TODO, change the "ty" field to list the hypotheses?
752
774
let newgoals = reverse [ goal { goalProp = t } | t <- newgoalterms ]
753
775
return (Just newgoals)
754
776
0 commit comments