module QuickSpec.Explore where
import QuickSpec.Explore.Polymorphic
import QuickSpec.Testing
import QuickSpec.Pruning
import QuickSpec.Term
import QuickSpec.Type
import QuickSpec.Utils
import QuickSpec.Prop
import QuickSpec.Terminal
import Control.Monad
import Control.Monad.Trans.Class
import Control.Monad.Trans.State.Strict
import Text.Printf
moreTerms :: (Ord a, Apply (Term f), Sized f, Typed f) => Universe -> [f] -> (Term f -> a) -> [[Term f]] -> [Term f]
moreTerms univ funs measure tss =
sortBy' measure $
atomic ++
[ unPoly v
| i <- [0..n],
t <- uss !! i,
u <- uss !! (ni),
Just v <- [tryApply (poly t) (poly u)],
unPoly v `usefulForUniverse` univ ]
where
n = length tss
atomic =
[App f [] | f <- funs, size f == n] ++
[Var (V typeVar 0) | n == 1]
uss = tss ++ [atomic]
quickSpec ::
(Ord measure, Ord fun, Ord norm, Sized fun, Typed fun, Ord result, Apply (Term fun), PrettyTerm fun,
MonadPruner (Term fun) norm m, MonadTester testcase (Term fun) m, MonadTerminal m) =>
(Prop (Term fun) -> m ()) ->
(Term fun -> measure) ->
(Term fun -> testcase -> result) ->
Int -> Universe -> [fun] -> m ()
quickSpec present measure eval maxSize univ funs = do
let
state0 = initialState univ (\t -> size t <= 5) eval
loop m n _ | m > n = return ()
loop m n tss = do
putStatus (printf "enumerating terms of size %d" m)
let
ts = moreTerms univ funs measure tss
total = length ts
consider (i, t) = do
putStatus (printf "testing terms of size %d: %d/%d" m i total)
res <- explore t
putStatus (printf "testing terms of size %d: %d/%d" m i total)
lift $ mapM_ present (result_props res)
case res of
Accepted _ -> return True
Rejected _ -> return False
us <- map snd <$> filterM consider (zip [1 :: Int ..] ts)
clearStatus
loop (m+1) n (tss ++ [us])
evalStateT (loop 0 maxSize []) state0