@@ -59,13 +59,14 @@ import SAWScript.Prover.MRSolver.Term
59
59
-- | The context in which a failure occurred
60
60
data FailCtx
61
61
= FailCtxRefines NormComp NormComp
62
+ | FailCtxCoIndHyp CoIndHyp
62
63
| FailCtxMNF Term
63
64
deriving Show
64
65
65
66
-- | That's MR. Failure to you
66
67
data MRFailure
67
68
= TermsNotRel Bool Term Term
68
- | TypesNotEq Type Type
69
+ | TypesNotRel Bool Type Type
69
70
| CompsDoNotRefine NormComp NormComp
70
71
| ReturnNotError Term
71
72
| FunsNotEq FunName FunName
@@ -89,6 +90,9 @@ data MRFailure
89
90
pattern TermsNotEq :: Term -> Term -> MRFailure
90
91
pattern TermsNotEq t1 t2 = TermsNotRel False t1 t2
91
92
93
+ pattern TypesNotEq :: Type -> Type -> MRFailure
94
+ pattern TypesNotEq t1 t2 = TypesNotRel False t1 t2
95
+
92
96
-- | Remove the context from a 'MRFailure', i.e. remove all applications of the
93
97
-- 'MRFailureLocalVar' and 'MRFailureCtx' constructors
94
98
mrFailureWithoutCtx :: MRFailure -> MRFailure
@@ -118,6 +122,9 @@ instance PrettyInCtx FailCtx where
118
122
prettyInCtx (FailCtxRefines m1 m2) =
119
123
group <$> nest 2 <$>
120
124
ppWithPrefixSep " When proving refinement:" m1 " |=" m2
125
+ prettyInCtx (FailCtxCoIndHyp hyp) =
126
+ group <$> nest 2 <$>
127
+ ppWithPrefix " When doing co-induction with hypothesis:" hyp
121
128
prettyInCtx (FailCtxMNF t) =
122
129
group <$> nest 2 <$> vsepM [return " When normalizing computation:" ,
123
130
prettyInCtx t]
@@ -127,8 +134,10 @@ instance PrettyInCtx MRFailure where
127
134
ppWithPrefixSep " Could not prove terms equal:" t1 " and" t2
128
135
prettyInCtx (TermsNotRel True t1 t2) =
129
136
ppWithPrefixSep " Could not prove terms heterogeneously related:" t1 " and" t2
130
- prettyInCtx (TypesNotEq tp1 tp2) =
137
+ prettyInCtx (TypesNotRel False tp1 tp2) =
131
138
ppWithPrefixSep " Types not equal:" tp1 " and" tp2
139
+ prettyInCtx (TypesNotRel True tp1 tp2) =
140
+ ppWithPrefixSep " Types not heterogeneously related:" tp1 " and" tp2
132
141
prettyInCtx (CompsDoNotRefine m1 m2) =
133
142
ppWithPrefixSep " Could not prove refinement: " m1 " |=" m2
134
143
prettyInCtx (ReturnNotError t) =
@@ -236,6 +245,28 @@ coIndHypArg :: CoIndHyp -> Either Int Int -> Term
236
245
coIndHypArg hyp (Left i) = (coIndHypLHS hyp) !! i
237
246
coIndHypArg hyp (Right i) = (coIndHypRHS hyp) !! i
238
247
248
+ -- | Set the @i@th argument on either the left- or right-hand side of a
249
+ -- coinductive hypothesis to the given value
250
+ coIndHypSetArg :: CoIndHyp -> Either Int Int -> Term -> CoIndHyp
251
+ coIndHypSetArg hyp@ (CoIndHyp {.. }) (Left i) x =
252
+ hyp { coIndHypLHS = take i coIndHypLHS ++ x : drop (i+ 1 ) coIndHypLHS }
253
+ coIndHypSetArg hyp@ (CoIndHyp {.. }) (Right i) x =
254
+ hyp { coIndHypRHS = take i coIndHypRHS ++ x : drop (i+ 1 ) coIndHypRHS }
255
+
256
+ -- | Set all of the arguments in the given list to the given value in a
257
+ -- coinductive hypothesis, using 'coIndHypSetArg'
258
+ coIndHypSetArgs :: CoIndHyp -> [Either Int Int ] -> Term -> CoIndHyp
259
+ coIndHypSetArgs hyp specs x =
260
+ foldl' (\ hyp' spec -> coIndHypSetArg hyp' spec x) hyp specs
261
+
262
+ -- | Add a variable to the context of a coinductive hypothesis, returning the
263
+ -- updated coinductive hypothesis and a 'Term' which is the new variable
264
+ coIndHypWithVar :: CoIndHyp -> LocalName -> Type -> MRM (CoIndHyp , Term )
265
+ coIndHypWithVar (CoIndHyp ctx f1 f2 args1 args2 invar1 invar2) nm (Type tp) =
266
+ do var <- liftSC1 scLocalVar 0
267
+ (args1', args2') <- liftTermLike 0 1 (args1, args2)
268
+ return (CoIndHyp (ctx ++ [(nm,tp)]) f1 f2 args1' args2' invar1 invar2, var)
269
+
239
270
-- | A map from pairs of function names to co-inductive hypotheses over those
240
271
-- names
241
272
type CoIndHyps = Map (FunName , FunName ) CoIndHyp
@@ -440,6 +471,59 @@ liftSC5 :: (SharedContext -> a -> b -> c -> d -> e -> IO f) ->
440
471
liftSC5 f a b c d e = mrSC >>= \ sc -> liftIO (f sc a b c d e)
441
472
442
473
474
+ ----------------------------------------------------------------------
475
+ -- * Relating Types Heterogeneously
476
+ ----------------------------------------------------------------------
477
+
478
+ -- | A datatype encapsulating all the way in which we consider two types to
479
+ -- be heterogeneously related: either one is a @Num@ and the other is a @Nat@,
480
+ -- one is a @BVVec@ and the other is a non-@BVVec@ vector (of the same length,
481
+ -- this is checked in 'matchHet'), or both sides are pairs (whose components
482
+ -- are respectively heterogeneously related, this recursion must be done where
483
+ -- 'matchHet' is used, see 'typesHetRelated', for example)
484
+ data HetRelated = HetBVNum Natural
485
+ | HetNumBV Natural
486
+ | HetBVVecVec (Term , Term , Term ) (Term , Term )
487
+ | HetVecBVVec (Term , Term ) (Term , Term , Term )
488
+ | HetPair (Term , Term ) (Term , Term )
489
+
490
+ -- | Check to see if the given types match one of the cases of 'HetRelated'
491
+ matchHet :: Term -> Term -> MRM (Maybe HetRelated )
492
+ matchHet (asBitvectorType -> Just n)
493
+ (asDataType -> Just (primName -> " Cryptol.Num" , _)) =
494
+ return $ Just $ HetBVNum n
495
+ matchHet (asDataType -> Just (primName -> " Cryptol.Num" , _))
496
+ (asBitvectorType -> Just n) =
497
+ return $ Just $ HetNumBV n
498
+ matchHet (asBVVecType -> Just (n, len, a))
499
+ (asNonBVVecVectorType -> Just (m, a')) =
500
+ do m' <- mrBvToNat n len
501
+ ms_are_eq <- mrConvertible m' m
502
+ return $ if ms_are_eq then Just $ HetBVVecVec (n, len, a) (m, a')
503
+ else Nothing
504
+ matchHet (asNonBVVecVectorType -> Just (m, a'))
505
+ (asBVVecType -> Just (n, len, a)) =
506
+ do m' <- mrBvToNat n len
507
+ ms_are_eq <- mrConvertible m' m
508
+ return $ if ms_are_eq then Just $ HetVecBVVec (m, a') (n, len, a)
509
+ else Nothing
510
+ matchHet (asPairType -> Just (tpL1, tpR1))
511
+ (asPairType -> Just (tpL2, tpR2)) =
512
+ return $ Just $ HetPair (tpL1, tpR1) (tpL2, tpR2)
513
+ matchHet _ _ = return $ Nothing
514
+
515
+ -- | Return true iff the given types are heterogeneously related
516
+ typesHetRelated :: Term -> Term -> MRM Bool
517
+ typesHetRelated tp1 tp2 = matchHet tp1 tp2 >>= \ case
518
+ Just (HetBVNum _) -> return True
519
+ Just (HetNumBV _) -> return True
520
+ Just (HetBVVecVec (_, _, a) (_, a')) -> typesHetRelated a a'
521
+ Just (HetVecBVVec (_, a') (_, _, a)) -> typesHetRelated a' a
522
+ Just (HetPair (tpL1, tpR1) (tpL2, tpR2)) ->
523
+ (&&) <$> typesHetRelated tpL1 tpL2 <*> typesHetRelated tpR1 tpR2
524
+ Nothing -> mrConvertible tp1 tp2
525
+
526
+
443
527
----------------------------------------------------------------------
444
528
-- * Functions for Building Terms
445
529
----------------------------------------------------------------------
@@ -504,6 +588,10 @@ funNameType (GlobalName gd projs) =
504
588
mrApplyAll :: Term -> [Term ] -> MRM Term
505
589
mrApplyAll f args = liftSC2 scApplyAllBeta f args
506
590
591
+ -- | Apply a 'Term' to a single argument and beta-reduce in Mr. Monad
592
+ mrApply :: Term -> Term -> MRM Term
593
+ mrApply f arg = mrApplyAll f [arg]
594
+
507
595
-- | Like 'scBvNat', but if given a bitvector literal it is converted to a
508
596
-- natural number literal
509
597
mrBvToNat :: Term -> Term -> MRM Term
@@ -566,6 +654,18 @@ uniquifyNames (nm:nms) nms_other =
566
654
let nm' = uniquifyName nm nms_other in
567
655
nm' : uniquifyNames nms (nm' : nms_other)
568
656
657
+ -- | Build a lambda term with the lifting (in the sense of 'incVars') of an
658
+ -- MR Solver term
659
+ mrLambdaLift :: TermLike tm => [(LocalName ,Term )] -> tm ->
660
+ ([Term ] -> tm -> MRM Term ) -> MRM Term
661
+ mrLambdaLift [] t f = f [] t
662
+ mrLambdaLift ctx t f =
663
+ do nms <- uniquifyNames (map fst ctx) <$> map fst <$> mrUVars
664
+ let ctx' = zipWith (\ nm (_,tp) -> (nm,tp)) nms ctx
665
+ vars <- reverse <$> mapM (liftSC1 scLocalVar) [0 .. length ctx - 1 ]
666
+ t' <- liftTermLike 0 (length ctx) t
667
+ f vars t' >>= liftSC2 scLambdaList ctx'
668
+
569
669
-- | Run a MR Solver computation in a context extended with a universal
570
670
-- variable, which is passed as a 'Term' to the sub-computation. Note that any
571
671
-- assumptions made in the sub-computation will be lost when it completes.
@@ -728,6 +828,11 @@ mrCallsFun f = memoFixTermFun $ \recurse t -> case t of
728
828
(unwrapTermF -> tf) ->
729
829
foldM (\ b t' -> if b then return b else recurse t') False tf
730
830
831
+
832
+ ----------------------------------------------------------------------
833
+ -- * Monadic Operations on Mr. Solver State
834
+ ----------------------------------------------------------------------
835
+
731
836
-- | Make a fresh 'MRVar' of a given type, which must be closed, i.e., have no
732
837
-- free uvars
733
838
mrFreshVar :: LocalName -> Term -> MRM MRVar
@@ -1002,6 +1107,11 @@ mrFunAssumpRHSAsNormComp (OpaqueFunAssump f args) =
1002
1107
FunBind f args <$> CompFunReturn <$> Type <$> mrFunOutType f args
1003
1108
mrFunAssumpRHSAsNormComp (RewriteFunAssump rhs) = return rhs
1004
1109
1110
+
1111
+ ----------------------------------------------------------------------
1112
+ -- * Functions for Debug Output
1113
+ ----------------------------------------------------------------------
1114
+
1005
1115
-- | Print a 'String' if the debug level is at least the supplied 'Int'
1006
1116
debugPrint :: Int -> String -> MRM ()
1007
1117
debugPrint i str =
0 commit comments