src/HOL/Tools/LSC/LazySmallCheck.hs
author bulwahn
Fri, 11 Mar 2011 10:37:35 +0100
changeset 41905 e2611bc96022
child 41908 3bd9a21366d2
permissions -rw-r--r--
adding files for prototype of lazysmallcheck
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
41905
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
     1
module LazySmallCheck where {
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
     2
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
     3
import Monad;
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
     4
import Control.Exception;
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
     5
import System.IO;
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
     6
import System.Exit;
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
     7
import Code;
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
     8
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
     9
type Pos = [Integer];
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    10
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    11
-- Term refinement
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    12
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    13
new :: Pos -> [[Type]] -> [Term];
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    14
new p ps = [ Ctr c (zipWith (\i t -> Var (p++[i]) t) [0..] ts)
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    15
           | (c, ts) <- zip [0..] ps ];
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    16
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    17
refine :: Term -> Pos -> [Term];
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    18
refine (Var p (SumOfProd ss)) [] = new p ss;
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    19
refine (Ctr c xs) p = map (Ctr c) (refineList xs p);
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    20
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    21
refineList :: [Term] -> Pos -> [[Term]];
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    22
refineList xs (i:is) = let (ls, x:rs) = splitAt (fromInteger i) xs in [ls ++ y:rs | y <- refine x is];
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    23
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    24
-- Find total instantiations of a partial value
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    25
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    26
total :: Term -> [Term];
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    27
total (Ctr c xs) = [Ctr c ys | ys <- mapM total xs];
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    28
total (Var p (SumOfProd ss)) = [y | x <- new p ss, y <- total x];
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    29
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    30
-- Answers
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    31
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    32
answer :: a -> (a -> IO b) -> (Pos -> IO b) -> IO b;
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    33
answer a known unknown =
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    34
  try (evaluate a) >>= (\res ->
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    35
     case res of
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    36
       Right b -> known b
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    37
       Left (ErrorCall ('\0':p)) -> unknown (map (toInteger . fromEnum) p)
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    38
       Left e -> throw e);
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    39
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    40
-- Refute
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    41
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    42
str_of_list [] = "[]";
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    43
str_of_list (x:xs) = "(" ++ x ++ " :: " ++ str_of_list xs ++ ")";
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    44
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    45
report :: Result -> [Term] -> IO Integer;
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    46
report r xs = putStrLn ("SOME (" ++ (str_of_list $ zipWith ($) (showArgs r) $ head [ys | ys <- mapM total xs]) ++ ")") >> hFlush stdout >> exitWith ExitSuccess;
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    47
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    48
eval :: Bool -> (Bool -> IO a) -> (Pos -> IO a) -> IO a;
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    49
eval p k u = answer p (\p -> answer p k u) u;
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    50
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    51
ref :: Result -> [Term] -> IO Integer;
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    52
ref r xs = eval (apply_fun r xs) (\res -> if res then return 1 else report r xs) (\p -> sumMapM (ref r) 1 (refineList xs p));
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    53
          
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    54
refute :: Result -> IO Integer;
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    55
refute r = ref r (args r);
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    56
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    57
sumMapM :: (a -> IO Integer) -> Integer -> [a] -> IO Integer;
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    58
sumMapM f n [] = return n;
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    59
sumMapM f n (a:as) = seq n (do m <- f a ; sumMapM f (n+m) as);
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    60
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    61
-- Testable
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    62
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    63
instance Show Typerep where {
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    64
  show (Typerepa c ts) = "Type (\"" ++ c ++ "\", " ++ show ts ++ ")";
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    65
};
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    66
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    67
instance Show Terma where {
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    68
  show (Const c t) = "Const (\"" ++ c ++ "\", " ++ show t ++ ")";
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    69
  show (App s t) = "(" ++ show s ++ ") $ (" ++ show t ++ ")";
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    70
  show (Abs s ty t) = "Abs (\"" ++ s ++ "\", " ++ show ty ++ ", " ++ show t ++ ")";  
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    71
};
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    72
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    73
data Result =
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    74
  Result { args     :: [Term]
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    75
         , showArgs :: [Term -> String]
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    76
         , apply_fun    :: [Term] -> Bool
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    77
         };
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    78
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    79
data P = P (Integer -> Integer -> Result);
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    80
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    81
run :: Testable a => ([Term] -> a) -> Integer -> Integer -> Result;
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    82
run a = let P f = property a in f;
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    83
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    84
class Testable a where {
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    85
  property :: ([Term] -> a) -> P;
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    86
};
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    87
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    88
instance Testable Bool where {
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    89
  property app = P $ \n d -> Result [] [] (app . reverse);
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    90
};
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    91
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    92
instance (Term_of a, Serial a, Testable b) => Testable (a -> b) where {
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    93
  property f = P $ \n d ->
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    94
    let C t c = series d
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    95
        c' = conv c
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    96
        r = run (\(x:xs) -> f xs (c' x)) (n+1) d
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    97
    in  r { args = Var [n] t : args r, showArgs = (show . term_of . c') : showArgs r };
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    98
};
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
    99
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
   100
-- Top-level interface
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
   101
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
   102
depthCheck :: Testable a => Integer -> a -> IO ();
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
   103
depthCheck d p =
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
   104
  (refute $ run (const p) 0 d) >>= (\n -> putStrLn $ "OK, required " ++ show n ++ " tests at depth " ++ show d);
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
   105
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
   106
smallCheck :: Testable a => Integer -> a -> IO ();
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
   107
smallCheck d p = mapM_ (`depthCheck` p) [0..d] >> putStrLn ("NONE");
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
   108
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
   109
}
e2611bc96022 adding files for prototype of lazysmallcheck
bulwahn
parents:
diff changeset
   110