@@ -72,6 +72,7 @@ import Verifier.SAW.SATQuery
72
72
import Verifier.SAW.SCTypeCheck hiding (TypedTerm )
73
73
import qualified Verifier.SAW.SCTypeCheck as TC (TypedTerm (.. ))
74
74
import Verifier.SAW.Recognizer
75
+ import Verifier.SAW.Prelude (scEq )
75
76
import Verifier.SAW.SharedTerm
76
77
import Verifier.SAW.TypedTerm
77
78
import qualified Verifier.SAW.Simulator.Concrete as Concrete
@@ -636,6 +637,58 @@ extract_uninterp unints opaques tt =
636
637
pure (tt', replList)
637
638
638
639
640
+ congruence_for :: TypedTerm -> TopLevel TypedTerm
641
+ congruence_for tt =
642
+ do sc <- getSharedContext
643
+ congTm <- io $ build_congruence sc (ttTerm tt)
644
+ io $ mkTypedTerm sc congTm
645
+
646
+ -- | Given an input term, construct another term that
647
+ -- represents a congruence law for that term.
648
+ -- This term will be a Curry-Howard style theorem statement
649
+ -- that can be dispatched to solvers, and should have
650
+ -- type "Prop".
651
+ --
652
+ -- This will only work for terms that represent non-dependent
653
+ -- functions.
654
+ build_congruence :: SharedContext -> Term -> IO Term
655
+ build_congruence sc tm =
656
+ do ty <- scTypeOf sc tm
657
+ case asPiList ty of
658
+ ([] ,_) -> fail " congruence_for: Term is not a function"
659
+ (pis, body) ->
660
+ if looseVars body == emptyBitSet then
661
+ loop pis []
662
+ else
663
+ fail " congruence_for: cannot build congruence for dependent functions"
664
+ where
665
+ loop ((nm,tp): pis) vars =
666
+ if looseVars tp == emptyBitSet then
667
+ do l <- scFreshEC sc (nm <> " _1" ) tp
668
+ r <- scFreshEC sc (nm <> " _2" ) tp
669
+ loop pis ((l,r): vars)
670
+ else
671
+ fail " congruence_for: cannot build congruence for dependent functions"
672
+
673
+ loop [] vars =
674
+ do lvars <- mapM (scExtCns sc . fst ) (reverse vars)
675
+ rvars <- mapM (scExtCns sc . snd ) (reverse vars)
676
+ let allVars = concat [ [l,r] | (l,r) <- reverse vars ]
677
+
678
+ basel <- scApplyAll sc tm lvars
679
+ baser <- scApplyAll sc tm rvars
680
+ baseeq <- scEqTrue sc =<< scEq sc basel baser
681
+
682
+ let f x (l,r) =
683
+ do l' <- scExtCns sc l
684
+ r' <- scExtCns sc r
685
+ eq <- scEqTrue sc =<< scEq sc l' r'
686
+ scFun sc eq x
687
+ finalEq <- foldM f baseeq vars
688
+
689
+ scGeneralizeExts sc allVars finalEq
690
+
691
+
639
692
filterCryTerms :: SharedContext -> [Term ] -> IO [TypedTerm ]
640
693
filterCryTerms sc = loop
641
694
where
@@ -1201,6 +1254,11 @@ abstractSymbolicPrim (TypedTerm _ t) = do
1201
1254
bindAllExts :: SharedContext -> Term -> IO Term
1202
1255
bindAllExts sc body = scAbstractExts sc (getAllExts body) body
1203
1256
1257
+ term_apply :: TypedTerm -> [TypedTerm ] -> TopLevel TypedTerm
1258
+ term_apply fn args =
1259
+ do sc <- getSharedContext
1260
+ io $ applyTypedTerms sc fn args
1261
+
1204
1262
lambda :: TypedTerm -> TypedTerm -> TopLevel TypedTerm
1205
1263
lambda x = lambdas [x]
1206
1264
@@ -1464,6 +1522,44 @@ eval_size s =
1464
1522
Right _ -> fail " eval_size: not a numeric type"
1465
1523
_ -> fail " eval_size: unsupported polymorphic type"
1466
1524
1525
+ int_to_term :: Int -> TopLevel TypedTerm
1526
+ int_to_term i
1527
+ | i < 0 =
1528
+ do sc <- getSharedContext
1529
+ tm <- io (scNat sc (fromInteger (negate (toInteger i))))
1530
+ tm' <- io (scIntNeg sc =<< scNatToInt sc tm)
1531
+ io (mkTypedTerm sc tm')
1532
+ | otherwise =
1533
+ do sc <- getSharedContext
1534
+ tm <- io (scNat sc (fromIntegral i))
1535
+ tm' <- io (scNatToInt sc tm)
1536
+ io (mkTypedTerm sc tm')
1537
+
1538
+ nat_to_term :: Int -> TopLevel TypedTerm
1539
+ nat_to_term i
1540
+ | i >= 0 =
1541
+ do sc <- getSharedContext
1542
+ tm <- io $ scNat sc (fromIntegral i)
1543
+ io $ mkTypedTerm sc tm
1544
+
1545
+ | otherwise =
1546
+ fail (" nat_to_term: negative value " ++ show i)
1547
+
1548
+
1549
+ size_to_term :: C. Schema -> TopLevel TypedTerm
1550
+ size_to_term s =
1551
+ do sc <- getSharedContext
1552
+ tm <- io $ case s of
1553
+ C. Forall [] [] t ->
1554
+ case C. evalType mempty t of
1555
+ Left (C. Nat x) | x >= 0 ->
1556
+ scCtorApp sc " Cryptol.TCNum" =<< sequence [scNat sc (fromInteger x)]
1557
+ Left C. Inf -> scCtorApp sc " Cryptol.TCInf" []
1558
+ _ -> fail " size_to_term: not a numeric type"
1559
+ _ -> fail " size_to_term: unsupported polymorphic type"
1560
+
1561
+ return (TypedTerm (TypedTermKind C. KNum ) tm)
1562
+
1467
1563
nthPrim :: [a ] -> Int -> TopLevel a
1468
1564
nthPrim [] _ = fail " nth: index too large"
1469
1565
nthPrim (x : _) 0 = return x
0 commit comments