module Vectorise.Monad.Base (
VResult(..),
VM(..),
liftDs,
cantVectorise,
maybeCantVectorise,
maybeCantVectoriseM,
emitVt, traceVt, dumpOptVt, dumpVt,
noV, traceNoV,
ensureV, traceEnsureV,
onlyIfV,
tryV, tryErrV,
maybeV, traceMaybeV,
orElseV, orElseErrV,
fixV,
) where
import Vectorise.Builtins
import Vectorise.Env
import DsMonad
import TcRnMonad
import ErrUtils
import Outputable
import DynFlags
import StaticFlags
import Control.Monad
import System.IO (stderr)
data VResult a
= Yes GlobalEnv LocalEnv a
| No SDoc
newtype VM a
= VM { runVM :: Builtins -> GlobalEnv -> LocalEnv -> DsM (VResult a) }
instance Monad VM where
return x = VM $ \_ genv lenv -> return (Yes genv lenv x)
VM p >>= f = VM $ \bi genv lenv -> do
r <- p bi genv lenv
case r of
Yes genv' lenv' x -> runVM (f x) bi genv' lenv'
No reason -> return $ No reason
instance Applicative VM where
pure = return
(<*>) = ap
instance Functor VM where
fmap = liftM
instance MonadIO VM where
liftIO = liftDs . liftIO
liftDs :: DsM a -> VM a
liftDs p = VM $ \_ genv lenv -> do { x <- p; return (Yes genv lenv x) }
cantVectorise :: String -> SDoc -> a
cantVectorise s d = pgmError
. showSDoc
$ vcat [text "*** Vectorisation error ***",
nest 4 $ sep [text s, nest 4 d]]
maybeCantVectorise :: String -> SDoc -> Maybe a -> a
maybeCantVectorise s d Nothing = cantVectorise s d
maybeCantVectorise _ _ (Just x) = x
maybeCantVectoriseM :: Monad m => String -> SDoc -> m (Maybe a) -> m a
maybeCantVectoriseM s d p
= do
r <- p
case r of
Just x -> return x
Nothing -> cantVectorise s d
emitVt :: String -> SDoc -> VM ()
emitVt herald doc
= liftDs $
liftIO . printForUser stderr alwaysQualify $
hang (text herald) 2 doc
traceVt :: String -> SDoc -> VM ()
traceVt herald doc
| 1 <= opt_TraceLevel = liftDs $
traceOptIf Opt_D_dump_vt_trace $
hang (text herald) 2 doc
| otherwise = return ()
dumpOptVt :: DynFlag -> String -> SDoc -> VM ()
dumpOptVt flag header doc
= do { b <- liftDs $ doptM flag
; if b
then dumpVt header doc
else return ()
}
dumpVt :: String -> SDoc -> VM ()
dumpVt header doc
= do { unqual <- liftDs mkPrintUnqualifiedDs
; liftIO $ printForUser stderr unqual (mkDumpDoc header doc)
}
noV :: SDoc -> VM a
noV reason = VM $ \_ _ _ -> return $ No reason
traceNoV :: String -> SDoc -> VM a
traceNoV s d = pprTrace s d $ noV d
ensureV :: SDoc -> Bool -> VM ()
ensureV reason False = noV reason
ensureV _reason True = return ()
traceEnsureV :: String -> SDoc -> Bool -> VM ()
traceEnsureV s d False = traceNoV s d
traceEnsureV _ _ True = return ()
onlyIfV :: SDoc -> Bool -> VM a -> VM a
onlyIfV reason b p = ensureV reason b >> p
tryErrV :: VM a -> VM (Maybe a)
tryErrV (VM p) = VM $ \bi genv lenv ->
do
r <- p bi genv lenv
case r of
Yes genv' lenv' x -> return (Yes genv' lenv' (Just x))
No reason -> do { unqual <- mkPrintUnqualifiedDs
; liftIO $
printForUser stderr unqual $
text "Warning: vectorisation failure:" <+> reason
; return (Yes genv lenv Nothing)
}
tryV :: VM a -> VM (Maybe a)
tryV (VM p) = VM $ \bi genv lenv ->
do
r <- p bi genv lenv
case r of
Yes genv' lenv' x -> return (Yes genv' lenv' (Just x))
No _reason -> return (Yes genv lenv Nothing)
maybeV :: SDoc -> VM (Maybe a) -> VM a
maybeV reason p = maybe (noV reason) return =<< p
traceMaybeV :: String -> SDoc -> VM (Maybe a) -> VM a
traceMaybeV s d p = maybe (traceNoV s d) return =<< p
orElseErrV :: VM a -> VM a -> VM a
orElseErrV p q = maybe q return =<< tryErrV p
orElseV :: VM a -> VM a -> VM a
orElseV p q = maybe q return =<< tryV p
fixV :: (a -> VM a) -> VM a
fixV f = VM (\bi genv lenv -> fixDs $ \r -> runVM (f (unYes r)) bi genv lenv )
where
unYes (Yes _ _ x) = x
unYes (No reason) = pprPanic "Vectorise.Monad.Base.fixV: no result" reason