{-# LANGUAGE TupleSections #-} import Data.Maybe import Data.Monoid (mconcat, mempty) import System.Exit import Control.Applicative ((<$>)) import Control.DeepSeq import Text.PrettyPrint.HughesPJ import CoreSyn import Var import System.Console.CmdArgs.Verbosity (whenLoud) import System.Console.CmdArgs.Default import qualified Language.Fixpoint.Config as FC import qualified Language.Haskell.Liquid.DiffCheck as DC import Language.Fixpoint.Misc import Language.Fixpoint.Interface import Language.Fixpoint.Types (sinfo) import Language.Haskell.Liquid.Types import Language.Haskell.Liquid.Errors import Language.Haskell.Liquid.CmdLine import Language.Haskell.Liquid.GhcInterface import Language.Haskell.Liquid.Constraint.Generate import Language.Haskell.Liquid.Constraint.ToFixpoint import Language.Haskell.Liquid.Constraint.Types import Language.Haskell.Liquid.TransformRec import Language.Haskell.Liquid.Annotate (mkOutput) main :: IO b main = do cfg0 <- getOpts res <- mconcat <$> mapM (checkOne cfg0) (files cfg0) let ecode = resultExit $ {- traceShow "RESULT" $ -} o_result res -- putStrLn $ "ExitCode: " ++ show ecode exitWith ecode checkOne :: Config -> FilePath -> IO (Output Doc) checkOne cfg0 t = getGhcInfo cfg0 t >>= either errOut (liquidOne t) where errOut r = exitWithResult cfg0 t $ mempty { o_result = r} liquidOne :: FilePath -> GhcInfo -> IO (Output Doc) liquidOne target info = do donePhase Loud "Extracted Core using GHC" let cfg = config $ spec info whenLoud $ do putStrLn "**** Config **************************************************" print cfg whenLoud $ do putStrLn $ showpp info putStrLn "*************** Original CoreBinds ***************************" putStrLn $ showpp (cbs info) let cbs' = transformScope (cbs info) whenLoud $ do donePhase Loud "transformRecExpr" putStrLn "*************** Transform Rec Expr CoreBinds *****************" putStrLn $ showpp cbs' putStrLn "*************** Slicing Out Unchanged CoreBinds *****************" dc <- prune cfg cbs' target info let cbs'' = maybe cbs' DC.newBinds dc let info' = maybe info (\z -> info {spec = DC.newSpec z}) dc let cgi = {-# SCC "generateConstraints" #-} generateConstraints $! info' {cbs = cbs''} cgi `deepseq` donePhase Loud "generateConstraints" out <- solveCs cfg target cgi info' dc donePhase Loud "solve" let out' = mconcat [maybe mempty DC.oldOutput dc, out] DC.saveResult target out' exitWithResult cfg target out' -- checkedNames :: Maybe DC.DiffCheck -> Maybe [Name.Name] checkedNames dc = concatMap names . DC.newBinds <$> dc where names (NonRec v _ ) = [showpp $ shvar v] names (Rec xs) = map (shvar . fst) xs shvar = showpp . varName -- prune :: Config -> [CoreBind] -> FilePath -> GhcInfo -> IO (Maybe Diff) prune cfg cbs target info | not (null vs) = return . Just $ DC.DC (DC.thin cbs vs) mempty sp | diffcheck cfg = DC.slice target cbs sp | otherwise = return Nothing where vs = tgtVars sp sp = spec info solveCs cfg target cgi info dc = do finfo <- cgInfoFInfo info cgi (r, sol) <- solve fx finfo let names = checkedNames dc let warns = logErrors cgi let annm = annotMap cgi let res = ferr sol r let out0 = mkOutput cfg res sol annm return $ out0 { o_vars = names } { o_errors = warns} { o_result = res } where fx = def { FC.solver = fromJust (smtsolver cfg) , FC.real = real cfg , FC.native = native cfg , FC.srcFile = target } ferr s r = fmap (tidyError s) $ result $ sinfo <$> r -- writeCGI tgt cgi = {-# SCC "ConsWrite" #-} writeFile (extFileName Cgi tgt) str -- where -- str = {-# SCC "PPcgi" #-} showpp cgi