packages feed

grisette-0.13.0.1: test/Grisette/SymPrim/Prim/SerializationTests.hs

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}

module Grisette.SymPrim.Prim.SerializationTests (serializationTests) where

import Data.Data (Proxy (Proxy))
import Data.List.NonEmpty (NonEmpty ((:|)))
import Data.Serialize (Serialize, decode, encode)
import Grisette
  ( AlgReal,
    FPRoundingMode (RNE),
    IEEEFPConstants (fpNaN),
    Solvable (con),
    SymbolKind (ConstantKind),
    TypedSymbol,
    (-->),
    type (-->),
    type (=->) (TabularFun),
  )
import Grisette.Internal.SymPrim.BV (IntN, WordN)
import Grisette.Internal.SymPrim.FP (FP)
import Grisette.Internal.SymPrim.Prim.Term
  ( FPBinaryOp (FPMinimum),
    FPRoundingBinaryOp (FPAdd),
    FPRoundingUnaryOp (FPSqrt),
    FPTrait (FPIsNaN, FPIsNegativeInfinite),
    FPUnaryOp (FPAbs),
    FloatingUnaryOp (FloatingSin),
    Term,
    absNumTerm,
    addNumTerm,
    andBitsTerm,
    andTerm,
    applyTerm,
    bitCastOrTerm,
    bitCastTerm,
    bvConcatTerm,
    bvSelectTerm,
    bvsignExtendTerm,
    bvzeroExtendTerm,
    complementBitsTerm,
    conTerm,
    distinctTerm,
    divIntegralTerm,
    eqTerm,
    existsTerm,
    fdivTerm,
    floatingUnaryTerm,
    forallTerm,
    fpBinaryTerm,
    fpFMATerm,
    fpRoundingBinaryTerm,
    fpRoundingUnaryTerm,
    fpTraitTerm,
    fpUnaryTerm,
    fromFPOrTerm,
    fromIntegralTerm,
    iteTerm,
    leOrdTerm,
    ltOrdTerm,
    modIntegralTerm,
    negNumTerm,
    notTerm,
    orBitsTerm,
    orTerm,
    pevalFPTraitTerm,
    powerTerm,
    quotIntegralTerm,
    recipTerm,
    remIntegralTerm,
    rotateLeftTerm,
    rotateRightTerm,
    shiftLeftTerm,
    shiftRightTerm,
    signumNumTerm,
    ssymTerm,
    toFPTerm,
    xorBitsTerm,
  )
import Test.Framework (Test, testGroup)
import Test.Framework.Providers.HUnit (testCase)
import Test.HUnit ((@?=))

assertSerialization :: (Eq a, Show a, Serialize a) => a -> IO ()
assertSerialization x = decode (encode x) @?= Right x

serializationTests :: Test
serializationTests =
  testGroup
    "Serialization"
    [ testGroup
        "ConTerm"
        [ testCase "Bool" $ do
            assertSerialization $ conTerm True,
          testCase "Integer" $ do
            assertSerialization $ conTerm (1 :: Integer),
          testCase "IntN" $ do
            assertSerialization $ conTerm (42 :: IntN 8),
          testCase "WordN" $ do
            assertSerialization $ conTerm (42 :: WordN 8),
          testCase "FP" $ do
            assertSerialization $ conTerm (42 :: FP 8 24)
            let termNaN = conTerm (fpNaN :: FP 8 24)
            let decodedTerm =
                  decode (encode termNaN) ::
                    Either String (Term (FP 8 24))
            pevalFPTraitTerm FPIsNaN <$> decodedTerm @?= Right (conTerm True),
          testCase "FPRoundingMode" $ do
            assertSerialization $ conTerm RNE,
          testCase "AlgReal" $ do
            assertSerialization $ conTerm (1 / 8 :: AlgReal),
          testCase "TabularFun" $ do
            assertSerialization $ conTerm t1
            assertSerialization $ conTerm t2
            assertSerialization $ conTerm t3
            assertSerialization $ conTerm t4
            assertSerialization $ conTerm t5
            assertSerialization $ conTerm t6
            assertSerialization $ conTerm t7,
          testCase "GeneralFun" $ do
            assertSerialization $ conTerm g1
            assertSerialization $ conTerm g2
            assertSerialization $ conTerm g3
            assertSerialization $ conTerm g4
            assertSerialization $ conTerm g5
            assertSerialization $ conTerm g6
            assertSerialization $ conTerm g7
        ],
      testCase "SymTerm" $
        assertSerialization (ssymTerm "a" :: Term Bool),
      testCase "ForallTerm" $
        assertSerialization $
          forallTerm
            ("a" :: TypedSymbol 'ConstantKind Integer)
            (ssymTerm "b"),
      testCase "ExistsTerm" $
        assertSerialization $
          existsTerm
            ("a" :: TypedSymbol 'ConstantKind Integer)
            (ssymTerm "b"),
      testCase "NotTerm" $ assertSerialization $ notTerm (ssymTerm "a"),
      testCase "AndTerm" $
        assertSerialization $
          andTerm (ssymTerm "a") (ssymTerm "b"),
      testCase "OrTerm" $
        assertSerialization $
          orTerm (ssymTerm "a") (ssymTerm "b"),
      testCase "EqTerm" $
        assertSerialization $
          eqTerm (ssymTerm "a" :: Term Integer) (ssymTerm "b"),
      testCase "DistinctTerm" $
        assertSerialization $
          distinctTerm $
            (ssymTerm "a" :: Term Integer) :| [ssymTerm "b", ssymTerm "c"],
      testCase "ITETerm" $
        assertSerialization $
          iteTerm (ssymTerm "a") (ssymTerm "b" :: Term Integer) (ssymTerm "c"),
      testCase "AddNumTerm" $
        assertSerialization $
          addNumTerm (ssymTerm "a" :: Term Integer) (ssymTerm "b"),
      testCase "NegNumTerm" $
        assertSerialization $
          negNumTerm (ssymTerm "a" :: Term Integer),
      testCase "MulNumTerm" $
        assertSerialization $
          addNumTerm (ssymTerm "a" :: Term Integer) (ssymTerm "b"),
      testCase "AbsNumTerm" $
        assertSerialization $
          absNumTerm (ssymTerm "a" :: Term Integer),
      testCase "SignumNumTerm" $
        assertSerialization $
          signumNumTerm (ssymTerm "a" :: Term Integer),
      testCase "ltOrdTerm" $
        assertSerialization $
          ltOrdTerm (ssymTerm "a" :: Term Integer) (ssymTerm "b"),
      testCase "leOrdTerm" $
        assertSerialization $
          leOrdTerm (ssymTerm "a" :: Term Integer) (ssymTerm "b"),
      testCase "andBitsTerm" $
        assertSerialization $
          andBitsTerm (ssymTerm "a" :: Term (WordN 8)) (ssymTerm "b"),
      testCase "orBitsTerm" $
        assertSerialization $
          orBitsTerm (ssymTerm "a" :: Term (WordN 8)) (ssymTerm "b"),
      testCase "xorBitsTerm" $
        assertSerialization $
          xorBitsTerm (ssymTerm "a" :: Term (WordN 8)) (ssymTerm "b"),
      testCase "complementBitsTerm" $
        assertSerialization $
          complementBitsTerm (ssymTerm "a" :: Term (WordN 8)),
      testCase "shiftLeftTerm" $
        assertSerialization $
          shiftLeftTerm (ssymTerm "a" :: Term (WordN 8)) (ssymTerm "b"),
      testCase "shiftRightTerm" $
        assertSerialization $
          shiftRightTerm (ssymTerm "a" :: Term (WordN 8)) (ssymTerm "b"),
      testCase "rotateLeftTerm" $
        assertSerialization $
          rotateLeftTerm (ssymTerm "a" :: Term (WordN 8)) (ssymTerm "b"),
      testCase "rotateRightTerm" $
        assertSerialization $
          rotateRightTerm (ssymTerm "a" :: Term (WordN 8)) (ssymTerm "b"),
      testCase "bitCastTerm" $ do
        assertSerialization
          (bitCastTerm (ssymTerm "a" :: Term Bool) :: Term (WordN 1))
        assertSerialization
          (bitCastTerm (ssymTerm "a" :: Term Bool) :: Term (IntN 1))
        assertSerialization
          (bitCastTerm (ssymTerm "a" :: Term (WordN 1)) :: Term Bool)
        assertSerialization
          (bitCastTerm (ssymTerm "a" :: Term (IntN 1)) :: Term Bool)
        assertSerialization
          (bitCastTerm (ssymTerm "a" :: Term (WordN 8)) :: Term (FP 2 6))
        assertSerialization
          (bitCastTerm (ssymTerm "a" :: Term (WordN 8)) :: Term (IntN 8))
        assertSerialization
          (bitCastTerm (ssymTerm "a" :: Term (IntN 8)) :: Term (FP 2 6)),
      testCase "bitCastOrTerm" $ do
        assertSerialization
          ( bitCastOrTerm
              (ssymTerm "d" :: Term (WordN 8))
              (ssymTerm "a" :: Term (FP 2 6))
          )
        assertSerialization
          ( bitCastOrTerm
              (ssymTerm "d" :: Term (IntN 8))
              (ssymTerm "a" :: Term (FP 2 6))
          ),
      testCase "bvConcatTerm" $
        assertSerialization $
          bvConcatTerm
            (ssymTerm "d" :: Term (WordN 8))
            (ssymTerm "a" :: Term (WordN 8)),
      testCase "bvSelectTerm" $
        assertSerialization $
          bvSelectTerm
            (Proxy @2)
            (Proxy @3)
            (ssymTerm "b" :: Term (WordN 8)),
      testCase "bvExtendTerm" $ do
        assertSerialization $
          bvsignExtendTerm
            (Proxy @16)
            (ssymTerm "b" :: Term (WordN 8))
        assertSerialization $
          bvzeroExtendTerm
            (Proxy @16)
            (ssymTerm "b" :: Term (WordN 8)),
      testCase "applyTerm" $ do
        assertSerialization $
          applyTerm (ssymTerm "a" :: Term (Integer =-> Integer)) (ssymTerm "b")
        assertSerialization $
          applyTerm (ssymTerm "a" :: Term (Integer --> Integer)) (ssymTerm "b"),
      testCase "divIntegralTerm" $
        assertSerialization $
          divIntegralTerm (ssymTerm "a" :: Term Integer) (ssymTerm "b"),
      testCase "modIntegralTerm" $
        assertSerialization $
          modIntegralTerm (ssymTerm "a" :: Term Integer) (ssymTerm "b"),
      testCase "quotIntegralTerm" $
        assertSerialization $
          quotIntegralTerm (ssymTerm "a" :: Term Integer) (ssymTerm "b"),
      testCase "remIntegralTerm" $
        assertSerialization $
          remIntegralTerm (ssymTerm "a" :: Term Integer) (ssymTerm "b"),
      testCase "fpTraitTerm" $
        assertSerialization $
          fpTraitTerm FPIsNegativeInfinite (ssymTerm "a" :: Term (FP 2 6)),
      testCase "fdivTerm" $
        assertSerialization $
          fdivTerm (ssymTerm "a" :: Term (FP 2 6)) (ssymTerm "b"),
      testCase "recipTerm" $
        assertSerialization $
          recipTerm (ssymTerm "a" :: Term (FP 2 6)),
      testCase "floatingUnaryTerm" $
        assertSerialization $
          floatingUnaryTerm FloatingSin (ssymTerm "a" :: Term (FP 2 6)),
      testCase "powerTerm" $
        assertSerialization $
          powerTerm (ssymTerm "a" :: Term (FP 2 6)) (ssymTerm "b"),
      testCase "fpUnaryTerm" $
        assertSerialization $
          fpUnaryTerm FPAbs (ssymTerm "a" :: Term (FP 2 6)),
      testCase "fpBinaryTerm" $
        assertSerialization $
          fpBinaryTerm FPMinimum (ssymTerm "a" :: Term (FP 2 6)) (ssymTerm "b"),
      testCase "fpRoundingUnaryTerm" $
        assertSerialization $
          fpRoundingUnaryTerm
            FPSqrt
            (ssymTerm "a")
            (ssymTerm "b" :: Term (FP 2 6)),
      testCase "fpRoundingBinaryTerm" $
        assertSerialization $
          fpRoundingBinaryTerm
            FPAdd
            (ssymTerm "a")
            (ssymTerm "b" :: Term (FP 2 6))
            (ssymTerm "c"),
      testCase "fpFMATerm" $
        assertSerialization $
          fpFMATerm
            (ssymTerm "a")
            (ssymTerm "b" :: Term (FP 2 6))
            (ssymTerm "c")
            (ssymTerm "d"),
      testCase "fromIntegralTerm" $ do
        assertSerialization
          (fromIntegralTerm (ssymTerm "a" :: Term Integer) :: Term Integer)
        assertSerialization
          (fromIntegralTerm (ssymTerm "a" :: Term Integer) :: Term AlgReal)
        assertSerialization
          (fromIntegralTerm (ssymTerm "a" :: Term Integer) :: Term (WordN 8))
        assertSerialization
          (fromIntegralTerm (ssymTerm "a" :: Term Integer) :: Term (IntN 8))
        assertSerialization
          (fromIntegralTerm (ssymTerm "a" :: Term Integer) :: Term (FP 8 24))
        assertSerialization
          (fromIntegralTerm (ssymTerm "a" :: Term (WordN 8)) :: Term Integer)
        assertSerialization
          (fromIntegralTerm (ssymTerm "a" :: Term (WordN 8)) :: Term AlgReal)
        assertSerialization
          (fromIntegralTerm (ssymTerm "a" :: Term (WordN 8)) :: Term (WordN 8))
        assertSerialization
          (fromIntegralTerm (ssymTerm "a" :: Term (WordN 8)) :: Term (IntN 8))
        assertSerialization
          (fromIntegralTerm (ssymTerm "a" :: Term (WordN 8)) :: Term (FP 8 24))
        assertSerialization
          (fromIntegralTerm (ssymTerm "a" :: Term (IntN 8)) :: Term Integer)
        assertSerialization
          (fromIntegralTerm (ssymTerm "a" :: Term (IntN 8)) :: Term AlgReal)
        assertSerialization
          (fromIntegralTerm (ssymTerm "a" :: Term (IntN 8)) :: Term (WordN 8))
        assertSerialization
          (fromIntegralTerm (ssymTerm "a" :: Term (IntN 8)) :: Term (IntN 8))
        assertSerialization
          (fromIntegralTerm (ssymTerm "a" :: Term (IntN 8)) :: Term (FP 8 24)),
      testCase "fromFPOrTerm" $ do
        assertSerialization
          ( fromFPOrTerm
              (ssymTerm "a" :: Term Integer)
              (ssymTerm "r")
              (ssymTerm "b" :: Term (FP 8 24))
          )
        assertSerialization
          ( fromFPOrTerm
              (ssymTerm "a" :: Term AlgReal)
              (ssymTerm "r")
              (ssymTerm "b" :: Term (FP 8 24))
          )
        assertSerialization
          ( fromFPOrTerm
              (ssymTerm "a" :: Term (WordN 8))
              (ssymTerm "r")
              (ssymTerm "b" :: Term (FP 8 24))
          )
        assertSerialization
          ( fromFPOrTerm
              (ssymTerm "a" :: Term (IntN 8))
              (ssymTerm "r")
              (ssymTerm "b" :: Term (FP 8 24))
          )
        assertSerialization
          ( fromFPOrTerm
              (ssymTerm "a" :: Term (FP 11 53))
              (ssymTerm "r")
              (ssymTerm "b" :: Term (FP 8 24))
          ),
      testCase "toFPTerm" $ do
        assertSerialization
          ( toFPTerm
              (ssymTerm "r")
              (ssymTerm "a" :: Term Integer) ::
              Term (FP 8 24)
          )
        assertSerialization
          ( toFPTerm
              (ssymTerm "r")
              (ssymTerm "a" :: Term AlgReal) ::
              Term (FP 8 24)
          )
        assertSerialization
          ( toFPTerm
              (ssymTerm "r")
              (ssymTerm "a" :: Term (WordN 8)) ::
              Term (FP 8 24)
          )
        assertSerialization
          ( toFPTerm
              (ssymTerm "r")
              (ssymTerm "a" :: Term (IntN 8)) ::
              Term (FP 8 24)
          )
        assertSerialization
          ( toFPTerm
              (ssymTerm "r")
              (ssymTerm "a" :: Term (FP 11 53)) ::
              Term (FP 8 24)
          )
    ]

t1 :: Integer =-> Integer
t1 = TabularFun [(1, 2), (2, 3)] 4

t1' :: Integer =-> Integer
t1' = TabularFun [(1, 2), (22, 3)] 4

t2 :: Integer =-> Integer =-> Integer
t2 = TabularFun [(1, t1)] t1'

t2' :: Integer =-> Integer =-> Integer
t2' = TabularFun [(2, t1)] t1'

t3 :: Integer =-> Integer =-> Integer =-> Integer
t3 = TabularFun [(2, t2)] t2'

t3' :: Integer =-> Integer =-> Integer =-> Integer
t3' = TabularFun [(3, t2)] t2'

t4 :: Integer =-> Integer =-> Integer =-> Integer =-> Integer
t4 = TabularFun [(3, t3)] t3'

t4' :: Integer =-> Integer =-> Integer =-> Integer =-> Integer
t4' = TabularFun [(4, t3)] t3'

t5 :: Integer =-> Integer =-> Integer =-> Integer =-> Integer =-> Integer
t5 = TabularFun [(4, t4)] t4'

t5' :: Integer =-> Integer =-> Integer =-> Integer =-> Integer =-> Integer
t5' = TabularFun [(5, t4)] t4'

t6 ::
  Integer
    =-> Integer
    =-> Integer
    =-> Integer
    =-> Integer
    =-> Integer
    =-> Integer
t6 = TabularFun [(5, t5)] t5'

t6' ::
  Integer
    =-> Integer
    =-> Integer
    =-> Integer
    =-> Integer
    =-> Integer
    =-> Integer
t6' = TabularFun [(6, t5)] t5'

t7 ::
  Integer
    =-> Integer
    =-> Integer
    =-> Integer
    =-> Integer
    =-> Integer
    =-> Integer
    =-> Integer
t7 = TabularFun [(6, t6)] t6'

g1 :: Integer --> Integer
g1 = "a" --> "a" + "b" + "c" + "d" + "e" + "f" + "g"

g2 :: Integer --> Integer --> Integer
g2 = "b" --> con g1

g3 :: Integer --> Integer --> Integer --> Integer
g3 = "c" --> con g2

g4 :: Integer --> Integer --> Integer --> Integer --> Integer
g4 = "d" --> con g3

g5 :: Integer --> Integer --> Integer --> Integer --> Integer --> Integer
g5 = "e" --> con g4

g6 ::
  Integer
    --> Integer
    --> Integer
    --> Integer
    --> Integer
    --> Integer
    --> Integer
g6 = "f" --> con g5

g7 ::
  Integer
    --> Integer
    --> Integer
    --> Integer
    --> Integer
    --> Integer
    --> Integer
    --> Integer
g7 = "g" --> con g6