module Tip.Compile (compileHaskellFile) where
import Tip.Calls
import Tip.Dicts (inlineDicts)
import Tip.GHCUtils
import Tip.Params
import Tip.ParseDSL
import Tip.GHCScope
import Tip.Unfoldings
import Data.List.Split (splitOn)
import Control.Monad
import Data.List
import Data.Maybe
import qualified Data.Foldable as F
import System.FilePath
import CoreMonad (liftIO)
import CoreSyn
import CoreSyn (flattenBinds)
import DynFlags
import GHC
import GHC.Paths
import HscTypes
import SimplCore
import Var
import VarSet
#if __GLASGOW_HASKELL__ < 708
import StaticFlags
#endif
compileHaskellFile :: Params -> IO [Var]
compileHaskellFile params@Params{..} = do
runGhc (Just libdir) $ do
dflags0 <- getSessionDynFlags
let dflags =
#if __GLASGOW_HASKELL__ >= 708
updateWays $
addWay' WayThreaded $
#endif
dflags0 { ghcMode = CompManager
, optLevel = 0
, profAuto = NoProfAuto
, importPaths = include ++ includePaths dflags0 ++ ["."]
}
`wopt_unset` Opt_WarnOverlappingPatterns
#if __GLASGOW_HASKELL__ >= 708
`gopt_unset` Opt_IgnoreInterfacePragmas
`gopt_unset` Opt_OmitInterfacePragmas
`gopt_set` Opt_ExposeAllUnfoldings
`gopt_set` Opt_BuildDynamicToo
#else
`dopt_unset` Opt_IgnoreInterfacePragmas
`dopt_unset` Opt_OmitInterfacePragmas
`dopt_set` Opt_ExposeAllUnfoldings
#endif
_ <- setSessionDynFlags dflags
let file_with_ext = replaceExtension file ".hs"
target <- guessTarget file_with_ext Nothing
addTarget target
r <- load LoadAllTargets
when (failed r) $ error "Compilation failed!"
mod_graph <- getModuleGraph
let mod_sum = findModuleSum file_with_ext mod_graph
p <- parseModule mod_sum
t <- typecheckModule p
d <- desugarModule t
let modguts = dm_core_module d
let binds = fixUnfoldings (inlineDicts (flattenBinds (mg_binds modguts)))
let fix_id :: Id -> Id
fix_id = fixId binds
liftIO $ when (PrintCore `elem` flags) $
putStrLn ("Tip.Compile, PrintCore:\n" ++ showOutputable binds)
setContext $
[ IIDecl (simpleImportDecl (moduleName (ms_mod mod_sum)))
, IIDecl (qualifiedImport "GHC.Types")
, IIDecl (qualifiedImport "GHC.Base")
, IIDecl (qualifiedImport "Prelude")
]
++ map (IIDecl . unLoc) (ms_textual_imps mod_sum)
ids_in_scope <- getIdsInScope fix_id
let only' :: [String]
only' = concatMap (splitOn ",") only
props :: [Var]
props =
[ fix_id i
| i <- ids_in_scope
, varWithPropType i
, not (varInTip i)
, null only || varToString i `elem` only'
]
when (PrintProps `elem` flags)
(liftIO (putStrLn ("Tip.Compile, PrintProps:\n" ++ showOutputable props)))
extra_ids <- extraIds params props
return (props `union` extra_ids)
findModuleSum :: FilePath -> [ModSummary] -> ModSummary
findModuleSum file
= fromMaybe (error $ "Cannot find module " ++ file)
. find (maybe False (== file) . summaryHsFile)
summaryHsFile :: ModSummary -> Maybe FilePath
summaryHsFile = ml_hs_file . ms_location
parseToId :: String -> Ghc Id
parseToId s = do
t <- lookupString s
case mapMaybe thingToId t of
[] -> error $ s ++ " not in scope!"
[x] -> return x
xs -> error $ s ++ " in scope as too many things: " ++ showOutputable xs
extraIds :: Params -> [Var] -> Ghc [Var]
extraIds p@Params{..} prop_ids = do
extra_ids <- mapM parseToId (concatMap (splitOn ",") extra)
let trans_ids :: VarSet
trans_ids = unionVarSets $
map (transCalls With) (prop_ids ++ extra_ids)
let ids = varSetElems $ filterVarSet (\ x -> not (varInTip x || varWithPropType x) && not (hasClass (varType x)))
trans_ids
let in_scope = inScope . varToString
ids_in_scope <- filterM in_scope ids
liftIO $ when (PrintExtraIds `elem` flags) $ do
putStrLn "Tip.Compile, PrintExtraIds:"
let out :: String -> [Id] -> IO ()
out lbl os = putStrLn $ lbl ++ " =\n " ++ showOutputable [ (o) | o <- os ]
#define OUT(i) out "i" (i)
OUT(prop_ids)
OUT(extra_ids)
OUT(ids)
OUT(ids_in_scope)
#undef OUT
return ids_in_scope
qualifiedImport :: String -> ImportDecl name
qualifiedImport = qualifiedImportDecl . mkModuleName
qualifiedImportDecl :: ModuleName -> ImportDecl name
qualifiedImportDecl m = (simpleImportDecl m) { ideclQualified = True }