twee-2.7.1: test/Common.hs
-- Common code used by the rest of the tests.
{-# LANGUAGE FlexibleInstances, ScopedTypeVariables, DeriveGeneric, DeriveAnyClass #-}
module Common where
import Data.Intern
import Twee.Base
import Twee.Constraints
import Twee.Equation
import Twee.Utils
import qualified Twee.KBO as KBO
import Control.Monad
import Data.Hashable
import Data.List
import Data.Maybe
import Data.Typeable
import GHC.Generics
import Test.QuickCheck hiding (Function)
import Text.Printf
import Data.Binary.Sharing
data Func = Min | Skolem Int | F Int Integer deriving (Eq, Ord, Generic, Hashable, Binary)
instance Show Func where
show Min = "m"
show (Skolem n) = printf "sk%d" n
show (F x y) = printf "f%d_%d" x y
instance Pretty Func where
pPrint Min = text "m"
pPrint (Skolem m) = text "sk" <#> int m
pPrint (F 3 _) = text "a"
pPrint (F 4 _) = text "b"
pPrint (F 5 _) = text "zero"
pPrint (F 6 _) = text "plus"
pPrint (F 7 _) = text "times"
pPrint (F f _) = text "f" <#> int f
instance PrettyTerm Func
instance Arbitrary (Subst Func) where
arbitrary = fmap fromJust (fmap listToSubst (liftM2 zip (fmap nub arbitrary) (infiniteListOf arbitrary)))
instance Arbitrary Func where
arbitrary =
frequency
[(10, F <$> choose (0, 2) <*> choose (1, 3)),
(2, Skolem <$> choose (0, 2)),
(1, return Min)]
instance Minimal Func where
minimal = intern Min
skolem n = intern (Skolem n)
instance KBO.Sized Func where
size (F _ n) = n
size _ = 1
instance Weighted Func where
weight (F _ n) = fromIntegral n
weight _ = 1
instance KBO.ArgWeighted Func where argWeight _ = 1
class Arity f where
arity :: f -> Int
instance Arity Func where
arity (F 0 _) = 0
arity (F 1 _) = 1
arity (F 2 _) = 2
arity (F 3 _) = 0 -- a
arity (F 4 _) = 0 -- b
arity (F 5 _) = 0 -- zero
arity (F 6 _) = 2 -- plus
arity (F 7 _) = 2 -- times
arity _ = 0
instance EqualsBonus Func
instance Arbitrary Var where arbitrary = fmap V (choose (0, 3))
instance (Hashable f, Eq f, Typeable f, Arbitrary f, Arity f) => Arbitrary (Sym f) where
arbitrary = fmap intern arbitrary
instance (Hashable f, Eq f, Typeable f, Arbitrary f, Arity f) => Arbitrary (Term f) where
arbitrary =
sized $ \n ->
oneof $
[ build <$> var <$> arbitrary ] ++
[ do { f <- arbitrary; build <$> app (Sym f) <$> vectorOf (arity f) (resize ((n-1) `div` arity f) arbitrary :: Gen (Term f)) } | n > 0 ]
shrink (App f ts0) =
ts ++ (build <$> app f <$> shrinkOne ts)
where
ts = unpack ts0
shrinkOne [] = []
shrinkOne (x:xs) =
[ y:xs | y <- shrink x ] ++
[ x:ys | ys <- shrinkOne xs ]
shrink _ = []
instance (Hashable f, Eq f, Typeable f, Arbitrary f, Arity f) => Arbitrary (TermList f) where
arbitrary = buildList <$> listOf (arbitrary :: Gen (Term f))
shrink = map buildList . shrink . unpack
data Pair f = Pair (Term f) (Term f) deriving Show
instance (Hashable f, Eq f, Typeable f, Arbitrary f, Arity f) => Arbitrary (Pair f) where
arbitrary = liftM2 Pair arbitrary arbitrary
shrink (Pair x y) =
[ Pair x' y | x' <- shrink x ] ++
[ Pair x y' | y' <- shrink y ] ++
[ Pair x' y' | x' <- shrink x, y' <- shrink y ]
instance (Hashable f, Eq f, Typeable f, Arbitrary f, Arity f) => Arbitrary (Equation f) where
arbitrary = do
Pair t u <- arbitrary
return (t :=: u)
shrink (t :=: u) = [t' :=: u' | Pair t' u' <- shrink (Pair t u)]
instance Ordered Func where
lessIn = KBO.lessIn
lessEq = KBO.lessEq
lessEqSkolem = KBO.lessEqSkolem
instance Function f => Arbitrary (Model f) where
arbitrary = fmap (modelFromOrder . map Variable . nub) arbitrary
shrink = weakenModel
genSubst :: [Var] -> Gen (Subst Func)
genSubst xs = do
let xs' = usort xs
ts <- sequence [arbitrary | _ <- xs']
let Just sub = listToSubst (zip xs' ts)
return sub