--
-- (c) Susumu Katayama
--
\begin{code}
module MagicHaskeller(
module TH, module Typeable,
ProgramGenerator,
ProgGen, ProgGenSF, ProgGenSFIORef,
p, setPrimitives, mkPG, mkPGSF, setPG,
mkMemo, mkMemoSF,
mkPG075, mkMemo075,
mkPGOpt,
mkPGX, mkPGXOpt,
mkPGXOpts, updatePGXOpts, updatePGXOptsFilt,
Options, Opt(..), options, MemoType(..),
mkPGIO, mkPGXOptIO,
#ifdef HASKELLSRC
load, f,
#endif
setDepth,
setTimeout, unsetTimeout,
define, Everything, Filter, Every, EveryIO,
findOne, printOne, printAll, printAllF, io2pred,
filterFirst, filterFirstF, filterThen, filterThenF, fp,
getEverything, everything, everythingM, everythingIO, unifyable, matching, getEverythingF, everythingF, unifyableF, matchingF, everyACE,
everyF,
stripEvery,
pprs, pprsIO, pprsIOn, lengths, lengthsIO, lengthsIOn, lengthsIOnLn, printQ,
Primitive, HValue(HV),
#ifdef PAR
fpartialParIO, mapParIO,
#endif
unsafeCoerce#, exprToTHExp, trToTHType, printAny, p1, Filtrable, zipAppend, mapIO, fpIO, fIO, fpartial, fpartialIO, ftotalIO, etup, mkCurriedDecls
) where
import Data.Generics(everywhere, mkT, Data)
import Data.Array.IArray
import MagicHaskeller.CoreLang
import Language.Haskell.TH as TH
#ifdef HASKELLSRC
import MagicHaskeller.ReadHsType(readHsTypeSigs)
#endif
import MagicHaskeller.TyConLib
import qualified Data.Map as Map
import Data.Char
import Control.Monad(mplus)
import MagicHaskeller.Types as Types
import MagicHaskeller.T10(mergesortWithBy)
import MagicHaskeller.ProgGen(ProgGen(PG))
import MagicHaskeller.ProgGenSF(ProgGenSF, PGSF)
import MagicHaskeller.ProgGenSFIORef(ProgGenSFIORef, PGSFIOR)
import MagicHaskeller.ProgramGenerator
import MagicHaskeller.Options(Opt(..), options)
import Control.Monad.Search.Combinatorial
import Data.Typeable as Typeable
import System.IO.Unsafe(unsafePerformIO)
import Data.IORef
import GHC.Exts(unsafeCoerce#)
import System.IO
#ifdef TFRANDOM
import System.Random.TF(seedTFGen,TFGen)
#else
import System.Random(mkStdGen,StdGen)
#endif
import MagicHaskeller.MHTH
import MagicHaskeller.TimeOut
import MagicHaskeller.ReadTHType
import MagicHaskeller.ReadTypeRep(trToType, trToTHType)
import MagicHaskeller.MyDynamic
import qualified MagicHaskeller.PolyDynamic as PD
import MagicHaskeller.Expression
import MagicHaskeller.Classify
import MagicHaskeller.ClassifyDM(filterDM)
import MagicHaskeller.Classification(unsafeRandomTestFilter, Filtrable)
import MagicHaskeller.Instantiate(mkRandTrie)
import MagicHaskeller.MemoToFiles(MemoType(..))
import Data.List(genericLength, transpose)
import MagicHaskeller.DebMT(interleaveActions)
#ifdef PAR
import Control.Monad.Par.IO
import Control.Monad.Par.Class
import Control.Monad.IO.Class(liftIO)
#endif
import Control.Concurrent.MVar
import Control.Concurrent
import Debug.Trace
\end{code}
\begin{code}
mkCurriedDecls :: String -> ExpQ -> ExpQ -> DecsQ
mkCurriedDecls tag funq eq = do e <- eq
fun <- funq
case e of TupE es -> fmap concat $ mapM (mcd fun) es
_ -> mcd fun e
where mcd :: Exp -> Exp -> DecsQ
mcd fun v@(VarE name) = let nb = nameBase name
in return [ValD (VarP $ mkName $ nb++tag) (NormalB (AppE fun v)) []]
define :: TH.Name -> String -> TH.ExpQ -> TH.Q [TH.Dec]
define mn name pq = pq >>= \prims ->
return [ SigD (mkName ("memo"++name)) (ConT mn),
ValD (VarP (mkName ("memo"++name))) (NormalB (AppE (VarE (mkName "mkPG")) prims
)) [],
SigD (mkName ("every"++name)) (ConT (mkName "Everything")),
ValD (VarP (mkName ("every"++name))) (NormalB (VarE (mkName "everything") `AppE` VarE (mkName ("memo"++name)))) [],
SigD (mkName ("filter"++name)) (ConT (mkName "Filter")),
ValD (VarP (mkName ("filter"++name))) (NormalB ((VarE (mkName "flip") `AppE` VarE (mkName "filterThen")) `AppE` VarE (mkName ("every"++name)))) [] ]
type Every a = [[(TH.Exp,a)]]
type EveryIO a = Int
-> IO [(TH.Exp, a)]
type Everything = forall a. Typeable a => Every a
type Filter = forall a. Typeable a => (a->Bool) -> IO (Every a)
p :: TH.ExpQ
-> TH.ExpQ
p eq = eq >>= \e -> case e of TupE es -> (return . ListE) =<< (mapM p1 es)
_ -> (return . ListE . return) =<< p1 e
p1 :: TH.Exp -> TH.ExpQ
p1 (SigE e ty) = p1' (SigE e $ useArrowT ty) e ty
p1 e@(ConE name) = do
#if __GLASGOW_HASKELL__ < 800
DataConI _ ty _ _ <- reify name
#else
DataConI _ ty _ <- reify name
#endif
p1' e e ty
p1 e@(VarE name) = do
#if __GLASGOW_HASKELL__ < 800
VarI _ ty _ _ <- reify name
#else
VarI _ ty _ <- reify name
#endif
p1' e e ty
p1 e = [| (HV (unsafeCoerce# $(return e)), $(expToExpExp e), trToTHType (typeOf $(return e))) |]
p1' se e ty = [| (HV (unsafeCoerce# $(return se)), $(expToExpExp e), $(typeToExpType ty)) |]
useArrowT :: TH.Type -> TH.Type
useArrowT = everywhere (mkT uAT)
uAT (ConT name) | nameBase name == "(->)" = ArrowT
uAT t = t
primitivesp :: TyConLib -> [[Primitive]] -> [[Typed [CoreExpr]]]
primitivesp tcl pss = dynamicsp (map (map (primitiveToDynamic tcl)) pss)
dynamicsp :: [[PD.Dynamic]] -> [[Typed [CoreExpr]]]
dynamicsp pss
= let ixs = scanl (+) 0 $ map genericLength pss
in zipWith (\ix -> mergesortWithBy (\(x:::t) (y:::_) -> (x++y):::t) (\(_:::t) (_:::u) -> compare t u) .
zipWith (\ n d -> [if expIsAConstr $ PD.dynExp d then PrimCon n else Primitive n] ::: toCxt (numCxts $ PD.dynExp d) (PD.dynType d)) [ix..]) ixs pss
filtTCEsss :: Common -> Int -> [[Typed [CoreExpr]]] -> [[Typed [CoreExpr]]]
filtTCEsss cmn depth = tMxAEsToTCEsss depth . map (filtTMxAEs cmn) . tMxCEsToTMxAEs (reducer cmn) . tCEsssToTMxCEs
tCEsssToTMxCEs :: [[Typed [CoreExpr]]] -> [Typed (Matrix CoreExpr)]
tCEsssToTMxCEs = mergesortWithBy (\(x:::t) (y:::_) -> (x `mplus` y):::t) (\(_:::t) (_:::u) -> compare t u) .
concat .
zipWith (\d ts -> map (fmap (\ces -> Mx $ replicate d [] ++ ces : repeat [])) ts) [0..]
tMxCEsToTMxAEs :: (CoreExpr->Dynamic) -> [Typed (Matrix CoreExpr)] -> [Typed (Matrix AnnExpr)]
tMxCEsToTMxAEs reduce = map (fmap (fmap (toAnnExpr reduce)))
filtTMxAEs :: Common -> Typed (Matrix AnnExpr) -> Typed (Matrix AnnExpr)
filtTMxAEs cmn (m ::: ty) = fromDB (MagicHaskeller.ClassifyDM.filterDM cmn ty (fromMx m)) ::: ty
tMxAEsToTCEsss :: Expression e => Int -> [Typed (Matrix e)] -> [[Typed [CoreExpr]]]
tMxAEsToTCEsss dep tmxaes = map (filter (not . null . typee)) $ transpose [ [ map toCE aes ::: ty | aes <- take dep aess ] | Mx aess ::: ty <- tmxaes ]
expIsAConstr (ConE _) = True
expIsAConstr (LitE _) = True
expIsAConstr (ListE _) = True
expIsAConstr (TupE _) = True
expIsAConstr (AppE e _) = expIsAConstr e
expIsAConstr (InfixE _ (ConE _) _) = True
expIsAConstr _ = False
numCxts (VarE nm) = case nameBase nm of 'b':'y':d:'_':_ | isDigit d -> digitToInt d
'-':'-':xs@('#':_) -> length $ takeWhile (=='#') xs
_ -> 0
numCxts _ = 0
toCxt 0 t = t
toCxt n (t :-> u) = t :=> toCxt (n1) u
primitivesc :: TyConLib -> [Primitive] -> [Typed [CoreExpr]]
primitivesc tcl ps = dynamicsc (map (primitiveToDynamic tcl) ps)
dynamicsc :: [PD.Dynamic] -> [Typed [CoreExpr]]
dynamicsc ps = mergesortWithBy (\(x:::t) (y:::_) -> (x++y):::t) (\(_:::t) (_:::u) -> compare t u) $
map (\ dyn -> [Context $ Dict dyn] ::: PD.dynType dyn) ps
mkPG :: ProgramGenerator pg => [Primitive] -> pg
mkPG = mkPGX [] . (:[])
mkPGX :: ProgramGenerator pg => [Primitive] -> [[Primitive]] -> pg
mkPGX = mkPG' True
mkMemo :: ProgramGenerator pg => [Primitive] -> pg
mkMemo = mkPG' False [] . (:[])
mkPG' :: ProgramGenerator pg => Bool -> [Primitive] -> [[Primitive]] -> pg
mkPG' cont classes tups = case mkCommon options{contain=cont} totals totals depths of cmn -> mkTrie cmn (primitivesc (tcl cmn) classes) (primitivesp (tcl cmn) tups)
where totals = concat tups ++ classes
depths = mkDepths tups ++ map (const 0) classes
mkPGSF,mkMemoSF :: ProgramGenerator pg =>
#ifdef TFRANDOM
TFGen
#else
StdGen
#endif
-> [Int]
-> [Primitive]
-> [Primitive]
-> [Primitive] -> pg
mkPGSF = mkPGSF' True
mkMemoSF = mkPGSF' False
mkPGSF' cont gen nrnds classes optups tups = mkPGOpt (options{primopt = Just [optups], contain = cont, stdgen = gen, nrands = nrnds}) classes tups
mkPG075 :: ProgramGenerator pg => [Primitive] -> [Primitive] -> pg
mkPG075 = mkPGOpt (options{primopt = Nothing, contain = True, guess = True})
mkMemo075 :: ProgramGenerator pg => [Primitive] -> [Primitive] -> pg
mkMemo075 = mkPGOpt (options{primopt = Nothing, contain = False, guess = True})
mkPGOpt :: ProgramGenerator pg => Options -> [Primitive] -> [Primitive] -> pg
mkPGOpt opt classes prims = mkPGXOpt opt classes [] [prims] []
mkPGXOpt :: ProgramGenerator pg => Options -> [Primitive] -> [(Primitive,Primitive)] -> [[Primitive]] -> [[(Primitive,Primitive)]] -> pg
mkPGXOpt = mkPGXOpts mkTrieOpt
mkPGIO :: ProgramGeneratorIO pg => [Primitive] -> [Primitive] -> IO pg
mkPGIO classes prims = mkPGXOptIO options classes [] [prims] []
mkPGXOptIO :: ProgramGeneratorIO pg => Options -> [Primitive] -> [(Primitive,Primitive)] -> [[Primitive]] -> [[(Primitive,Primitive)]] -> IO pg
mkPGXOptIO = mkPGXOpts mkTrieOptIO
mkPGXOpts :: (Common -> [Typed [CoreExpr]] -> [[Typed [CoreExpr]]] -> [[Typed [CoreExpr]]] -> a)
-> Options -> [Primitive] -> [(Primitive,Primitive)] -> [[Primitive]] -> [[(Primitive,Primitive)]] -> a
mkPGXOpts mkt opt classes partclasses prims partprims
= let cmn = initCommon opt (classes ++ concat prims ++ map fst (partclasses ++ concat partprims))
ptd = primitiveToDynamic (tcl cmn)
in updatePGXOpts mkt (primopt opt)
[ ptd cl | cl <- classes ]
[ (ptd tot, ptd part) | (tot, part) <- partclasses ]
[ [ ptd p | p <- ps ] | ps <- prims ]
[ [ (ptd tot, ptd part) | (tot, part) <- pps ] | pps <- partprims ]
cmn
updatePGXOpts :: (Common -> [Typed [CoreExpr]] -> [[Typed [CoreExpr]]] -> [[Typed [CoreExpr]]] -> a)
-> Maybe [[Primitive]] -> [PD.Dynamic] -> [(PD.Dynamic,PD.Dynamic)] -> [[PD.Dynamic]] -> [[(PD.Dynamic,PD.Dynamic)]] -> Common -> a
updatePGXOpts = uPGXO (const dynamicsp)
updatePGXOptsFilt :: Int -> (Common -> [Typed [CoreExpr]] -> [[Typed [CoreExpr]]] -> [[Typed [CoreExpr]]] -> a)
-> Maybe [[Primitive]] -> [PD.Dynamic] -> [(PD.Dynamic,PD.Dynamic)] -> [[PD.Dynamic]] -> [[(PD.Dynamic,PD.Dynamic)]] -> Common -> a
updatePGXOptsFilt dep = uPGXO (\cmn dynss ->
filtTCEsss cmn dep $ dynamicsp dynss)
uPGXO :: (Common -> [[PD.Dynamic]] -> [[Typed [CoreExpr]]]) ->
(Common -> [Typed [CoreExpr]] -> [[Typed [CoreExpr]]] -> [[Typed [CoreExpr]]] -> a)
-> Maybe [[Primitive]] -> [PD.Dynamic] -> [(PD.Dynamic,PD.Dynamic)] -> [[PD.Dynamic]] -> [[(PD.Dynamic,PD.Dynamic)]] -> Common -> a
uPGXO dyp mkt mbpo classes partclasses prims partprims c = case updateCommon (concat totalss ++ totalclss) (concat partialss ++ partialclss) (mkDepths totalss ++ map (const 0) totalclss) c of cmn -> mkt cmn (dynamicsc totalclss) (alt cmn) (dyp cmn totalss)
where alt cmn = case mbpo of Nothing -> dyp cmn totalss
Just po -> primitivesp (tcl c) po
(tot, part) = unzip $ map unzip partprims
totalss = zipAppend prims tot
partialss = zipAppend prims part
(totc,partc)= unzip partclasses
totalclss = classes ++ totc
partialclss = classes ++ partc
mkDepths :: [[a]] -> [Int]
mkDepths = concat . zipWith (\i xs -> map (const i) xs) [0..]
setPG :: ProgGen -> IO ()
setPG = writeIORef refmemodeb
setPrimitives :: [Primitive] -> [Primitive] -> IO ()
setPrimitives classes tups = do PG (_,_,_,cmn) <- readIORef refmemodeb
setPG $ mkPGOpt ((opt cmn){primopt=Nothing}) classes tups
zipAppend :: [[a]] -> [[a]] -> [[a]]
zipAppend [] yss = yss
zipAppend xss [] = xss
zipAppend (xs:xss) (ys:yss) = (xs++ys) : zipAppend xss yss
#ifdef HASKELLSRC
load :: FilePath
-> TH.ExpQ
load fp = do str <- runIO $ readFile fp
f str
f :: String -> TH.ExpQ
f = p . return . readHsTypeSigs
#endif
setTimeout :: Int
-> IO ()
setTimeout n = do pto <- newPTO n
PG (x,y,z,cmn) <- readIORef refmemodeb
writeIORef refmemodeb $ PG (x,y,z,cmn{opt = (opt cmn){timeout=Just pto}})
unsetTimeout :: IO ()
unsetTimeout = do PG (x,y,z,cmn) <- readIORef refmemodeb
writeIORef refmemodeb $ PG (x,y,z,cmn{opt = (opt cmn){timeout=Nothing}})
setDepth :: Int
-> IO ()
setDepth d = do PG (x,y,z,cmn) <- readIORef refmemodeb
writeIORef refmemodeb $ PG (x,y,z,cmn{opt = (opt cmn){memodepth=d}})
refmemodeb :: IORef ProgGen
refmemodeb = unsafePerformIO (newIORef defaultMD)
defaultMD = mkPG [] :: ProgGen
trsToTCL :: [TypeRep] -> TyConLib
trsToTCL trs
= (Map.fromListWith (\new old -> old) [ tup | k <- [0..7], tup <- tcsByK ! k ], tcsByK)
where tnsByK :: Array Types.Kind [TypeName]
tnsByK = accumArray (flip (:)) [] (0,7) ( trsToTCstrs trs )
tcsByK :: Array Types.Kind [(TypeName,Types.TyCon)]
tcsByK = listArray (0,7) [ tnsToTCs (tnsByK ! k) | k <- [0..7] ]
tnsToTCs :: [TypeName] -> [(TypeName,Types.TyCon)]
tnsToTCs tns = zipWith (\ i tn -> (tn, i)) [0..] tns
trsToTCstrs :: [TypeRep] -> [(Int, String)]
trsToTCstrs [] = []
trsToTCstrs (tr:ts) = case splitTyConApp tr of (tc,trs) -> (length trs, tyConName tc) : trsToTCstrs (trs++ts)
getEverything :: Typeable a =>
Bool
-> IO (Every a)
getEverything withAbsents = do
memodeb <- readIORef refmemodeb
return (everything memodeb withAbsents)
getEverythingF :: Typeable a =>
Bool
-> IO (Every a)
getEverythingF withAbsents = do
memodeb <- readIORef refmemodeb
return (everythingF memodeb withAbsents)
everything, everythingF :: (ProgramGenerator pg, Typeable a) =>
pg
-> Bool
-> Every a
everything memodeb = et undefined memodeb (mxExprToEvery "MagicHaskeller.everything: type mismatch" memodeb)
everythingF memodeb = et undefined memodeb (mxExprFiltEvery "MagicHaskeller.everythingF: type mismatch" memodeb)
everyACE :: (ProgramGenerator pg, Typeable a) =>
pg
-> Bool
-> [[(CoreExpr,a)]]
everyACE memodeb = et undefined memodeb (mxExprToACE "MagicHaskeller.everyACE: type mismatch" memodeb)
et :: (ProgramGenerator pg, Typeable a) =>
a
-> pg
-> (Types.Type -> Matrix AnnExpr -> Matrix (e,a))
-> Bool
-> [[(e,a)]]
et dmy memodeb filt withAbsents = unMx $ filt ty $ matchPs withAbsents ty memodeb
where ty = trToType (extractTCL memodeb) (typeOf dmy)
noFilter :: ProgramGenerator pg => pg -> Types.Type -> a -> a
noFilter _m _t = id
matchPs True = matchingPrograms
matchPs False = matchingProgramsWOAbsents
mxExprToEvery :: (Expression e, Search m, WithCommon pg, Typeable a) => String -> pg -> Types.Type -> m e -> m (Exp, a)
mxExprToEvery msg memodeb _ = fmap (unwrapAE (extractVL memodeb) msg memodeb . toAnnExpr (reducer $ extractCommon memodeb))
mxExprFiltEvery :: (Expression e, FiltrableBF m, WithCommon pg, Typeable a) => String -> pg -> Types.Type -> m e -> m (Exp, a)
mxExprFiltEvery msg memodeb ty = fmap (unwrapAE (extractVL memodeb) msg memodeb) . randomTestFilter memodeb ty . mxExpr memodeb
mxExpr memodeb = fmap (toAnnExpr (reducer $ extractCommon memodeb))
mxExprToACE :: (Expression e, Search m, WithCommon pg, Typeable a) => String -> pg -> Types.Type -> m e -> m (CoreExpr, a)
mxExprToACE msg memodeb _ = fmap (unwrapToCE msg memodeb . toAnnExpr (reducer $ extractCommon memodeb))
unwrapAE :: (WithCommon pg, Typeable a) => VarLib -> String -> pg -> AnnExpr -> (Exp, a)
unwrapAE vl msg memodeb (AE e dyn) = (exprToTHExp vl e, fromDyn tcl dyn (error msg))
where tcl = extractTCL memodeb
unwrapToCE :: (WithCommon pg, Typeable a) => String -> pg -> AnnExpr -> (CoreExpr, a)
unwrapToCE msg memodeb ae@(AE e dyn) = (e, fromDyn tcl dyn (error msg))
where tcl = extractTCL memodeb
etup :: (ProgramGenerator pg, Typeable a) =>
a
-> pg
-> Bool
-> [[((Exp,a), (Exp,a))]]
etup dmy memodeb withAbsents
= unMx
$ fmap (\e -> (unwrapAE (vl cmn) "MagicHaskeller.etup: type mismatch" memodeb $ toAnnExpr (execute (opt cmn) (vl cmn)) e,
unwrapAE (pvl cmn) "MagicHaskeller.etup: type mismatch" memodeb $ toAnnExpr (execute (opt cmn) (pvl cmn)) $ toCE e))
$ matchPs withAbsents ty memodeb
where ty = trToType (extractTCL memodeb) (typeOf dmy)
cmn = extractCommon memodeb
everythingM :: (ProgramGenerator pg, Typeable a, Monad m, Functor m) =>
pg
-> Bool
-> Int
-> m [(TH.Exp, a)]
everythingM = eM undefined
eM :: (ProgramGenerator pg, Typeable a, Monad m, Functor m) =>
a
-> pg
-> Bool
-> Int
-> m [(TH.Exp, a)]
eM dmy memodeb withAbsents = result
where tcl = extractTCL memodeb
ty = trToType tcl $ typeOf dmy
result = unRcT $ mxExprToEvery "MagicHaskeller.everythingM: type mismatch" memodeb undefined $ matchPs withAbsents ty memodeb
everythingIO :: (ProgramGeneratorIO pg, Typeable a) =>
pg
-> EveryIO a
everythingIO = eIO undefined
eIO :: (ProgramGeneratorIO pg, Typeable a) =>
a
-> pg
-> EveryIO a
eIO dmy memodeb = result
where tcl = extractTCL memodeb
ty = trToType tcl $ typeOf dmy
result = unRcT $ mxExprToEvery "MagicHaskeller.everythingIO: type mismatch" memodeb undefined $ matchingProgramsIO ty memodeb
strip :: m (Every a) -> a
strip = undefined
stripEvery :: Every a -> a
stripEvery = head . map snd . concat
unifyable, matching, unifyableF, matchingF :: ProgramGenerator pg =>
pg
-> TH.Type
-> [[TH.Exp]]
unifyable memodeb tht = unMx $ genExps noFilter unifyingPrograms memodeb tht
matching memodeb tht = unMx $ genExps noFilter matchingPrograms memodeb tht
unifyableF memodeb tht = unMx $ genExps randomTestFilter unifyingPrograms memodeb tht
matchingF memodeb tht = unMx $ genExps randomTestFilter matchingPrograms memodeb tht
genExps filt rawGenProgs memodeb tht
= case thTypeToType (extractTCL memodeb) tht of
ty -> fmap (exprToTHExp (extractVL memodeb) . toCE) $
filt memodeb ty $ fmap (toAnnExpr (reducer $ extractCommon memodeb)) (rawGenProgs ty memodeb)
findOne :: Typeable a =>
Bool
-> (a->Bool) -> TH.Exp
findOne withAbsents pred = unsafePerformIO $ findDo (\e _ -> return e) withAbsents pred
printOne :: Typeable a =>
Bool
-> (a->Bool) -> IO TH.Exp
printOne withAbsents pred = do
expr <- findDo (\e _ -> return e) withAbsents pred
putStrLn $ pprintUC expr
return expr
printAll, printAny :: Typeable a =>
Bool
-> (a->Bool) -> IO ()
printAny = printAll
printAll = findDo (\e r -> putStrLn (pprintUC e) >> r)
printAllF :: (Typeable a, Filtrable a) =>
Bool
-> (a->Bool) -> IO ()
printAllF withAbsents pred = do
et <- getEverything withAbsents
fet <- filterThenF pred et
pprs fet
findDo :: Typeable a =>
(TH.Exp -> IO b -> IO b)
-> Bool
-> (a->Bool) -> IO b
findDo op withAbsents pred = do
et <- getEverything withAbsents
md <- readIORef refmemodeb
let mpto = timeout $ opt $ extractCommon md
fp mpto (concat et)
where fp mpto ((e,a):ts) = do
result <- maybeWithTO seq mpto (return (pred a))
case result of Just True -> e `op` fp mpto ts
Just False -> fp mpto ts
Nothing -> hPutStrLn stderr ("timeout on "++pprintUC e) >> fp mpto ts
filterFirst :: Typeable a =>
Bool
-> (a->Bool) -> IO (Every a)
filterFirst withAbsents pred = do
et <- getEverything withAbsents
filterThen pred et
filterFirstF :: (Typeable a, Filtrable a) =>
Bool
-> (a->Bool) -> IO (Every a)
filterFirstF withAbsents pred = do
et <- getEverything withAbsents
filterThenF pred et
filterThenF pred et = do
fd <- filterThen pred et
memodeb <- readIORef refmemodeb
let o = opt $ extractCommon memodeb
return $ everyF o fd
everyF :: (Typeable a, Filtrable a) =>
Opt b
-> [[(e,a)]] -> [[(e,a)]]
everyF o = unMx . unsafeRandomTestFilter (timeout o) (fcnrand o) . Mx
filterThen :: Typeable a => (a->Bool) -> Every a -> IO (Every a)
filterThen pred ts = do md <- readIORef refmemodeb
let mpto = timeout $ opt $ extractCommon md
return (map (fp mpto pred) ts)
fp :: Typeable a => Maybe Int -> (a->Bool) -> [(Exp, a)] -> [(Exp, a)]
fp mpto pred = filter (\ (_,a) -> unsafePerformIO (maybeWithTO seq mpto (return (pred a))) == Just True)
fpartial :: Typeable a => Maybe Int -> (a->Bool) -> [((Exp, a),(Exp,a))] -> [(Exp, a)]
fpartial mpto pred ts = [ t | Just t <- map (fpart mpto pred) ts ]
fpart mpto pred (ea@(_,a),eap@(_,ap))
= case unsafePerformIO (maybeWithTO seq mpto (return $! (pred ap))) of
Just True -> Just eap
Just False -> Nothing
Nothing -> case unsafePerformIO (maybeWithTO seq mpto (return $!(pred a))) of
Just True -> Just ea
_ -> Nothing
fpartialIO :: Typeable a => Maybe Int -> (a->Bool) -> [((e, a),(e,a))] -> IO [(e, a)]
fpartialIO mpto pred ts = filterIO (fpartIO mpto pred) ts
filterIO :: Typeable a => (t -> IO (Maybe (e,a))) -> [t] -> IO [(e,a)]
filterIO filt ts = do mbs <- interleaveActions $ map filt ts
return [ tup | Just tup <- mbs ]
#ifdef PAR
fpartialParIO :: Typeable a => Maybe Int -> (a->Bool) -> [((e, a),(e,a))] -> ParIO [(e, a)]
fpartialParIO mpto pred ts = do mbs <- mapParIO (liftIO . fpartIO mpto pred) ts
return [ tup | Just tup <- mbs ]
#endif
fpartIO :: Typeable a => Maybe Int -> (a->Bool) -> ((e, a),(e,a)) -> IO (Maybe (e, a))
fpartIO mpto pred (ea, eap@(_,ap))
= do mbb <- maybeWithTO seq mpto $ return $! pred ap
case mbb of
Just True -> return $ Just eap
Just False -> return Nothing
Nothing -> ftotIO mpto pred ea
ftotalIO :: Typeable a => Maybe Int -> (a->Bool) -> [(e, a)] -> IO [(e, a)]
ftotalIO mpto pred ts = filterIO (ftotIO mpto pred) ts
ftotIO :: Typeable a => Maybe Int -> (a->Bool) -> (e,a) -> IO (Maybe (e, a))
ftotIO mpto pred (ea@(_,a))
= do mbb <- maybeWithTO seq mpto $ return $! pred a
case mbb of
Just True -> return $ Just ea
_ -> return Nothing
fpIO :: Typeable a => Maybe Int -> (a->Bool) -> [((Exp, a),(Exp,a))] -> IO [(Exp, a)]
fpIO mpto pred ts = do mbs <- sequence $ zipWith (fIO mpto pred) ts [0..]
return [ tup | Just tup <- mbs ]
fIO :: Typeable a => Maybe Int -> (a->Bool) -> ((Exp, a),(Exp,a)) -> Int -> IO (Maybe (Exp, a))
fIO mpto pred (ea@(e,a),eap@(_,ap)) i
= do hPutStrLn stderr (shows i " trying "++pprint e)
mbb <- maybeWithTO seq mpto $ return $! pred a
case mbb of
Just True -> return $ Just ea
_ -> return Nothing
mapIO :: (a -> IO b) -> [a] -> IO [b]
mapIO f xs = mapM (spawnIO . f) xs >>= mapM takeMVar
spawnIO :: IO a -> IO (MVar a)
spawnIO a = do
mv <- newEmptyMVar
forkIO (a >>= \v -> v `seq` putMVar mv v)
return mv
#ifdef PAR
mapParIO :: (a -> ParIO b) -> [a] -> ParIO [b]
mapParIO f as = mapM (spawn_ . f) as >>= mapM get
#endif
io2pred :: Eq b => [(a,b)] -> ((a->b)->Bool)
io2pred ios f = all (\(a,b) -> f a == b) ios
pprs :: Every a -> IO ()
pprs = mapM_ (putStrLn . pprintUC . fst) . concat
pprsIO :: EveryIO a -> IO ()
pprsIO eio = mapM_ (\d -> eio d >>= mapM_ (putStrLn . pprintUC . fst)) [0..]
pprsIOn :: Int -> EveryIO a -> IO ()
pprsIOn depth eio = mapM_ (\d -> eio d >>= mapM_ (putStrLn . pprintUC . fst)) [0..depth1]
pprintUC :: (Ppr a, Data a) => a -> String
pprintUC = pprint . everywhere (mkT unqCons)
unqCons :: Name -> Name
unqCons n | show n == show '(:) = mkName ":"
| otherwise = n
lengths :: Every a -> IO ()
lengths = print . map length
lengthsIO :: EveryIO a -> IO ()
lengthsIO eio = mapM_ (\d -> eio d >>= putStr . (' ':) . show . length) [0..]
lengthsIOn, lengthsIOnLn :: Int -> EveryIO a -> IO ()
lengthsIOn depth eio = mapM_ (\d -> eio d >>= putStr . (' ':) . show . length) [0..depth1]
lengthsIOnLn depth eio = lengthsIOn depth eio >> putStrLn ""
printQ :: (Ppr a, Data a) => Q a -> IO ()
printQ q = runQ q >>= putStrLn . pprintUC
\end{code}