Dear GHCers,

I'm trying to refactor the types in GHC (working on HEAD). First of all, I want 
to parameterise HsExpr et al to be parametric in the type representation (to 
remove the PostTcType type, which can not be instantiated before the type 
checker).

I tried to do this with regular expressions, but that just becomes far too 
messy. Instead, I'm using GHC to refacter GHC. More precisely, I'm using the 
GHC API. I'm stuck now on a problem trying to load modules.

The build system resolves the directories in the GHC source tree, so I'm 
compensating for this by seeing which files I can find. To this end, I first 
build a name table by seeing what files I can find in the source tree:


type NameTable = Map (String,Bool) FilePath

listNames :: FilePath -> IO NameTable
listNames f = do
        putStrLn $ "Listing names of " ++ f
        cnt <- L.filter (not . \s -> "." `isSuffixOf` s || "." `isPrefixOf` s) 
`fmap` getDirectoryContents f
        (dirs,cnt') <- partitionM (doesDirectoryExist . ((f ++ "/")++)) cnt
        (fs,cnt'')  <- partitionM (doesFileExist . ((f ++ "/")++))      cnt'
        when (not $ L.null cnt'') (putStrLn $ "  !!  Objects in directory " ++ 
f ++ " neither dir or file: " ++ show cnt'')
        rec <- mconcat `fmap` mapM listNames (L.map ((f ++ "/")++) dirs)
        let res = M.fromList [ ((stripExt s, "-boot" `isSuffixOf` s), f ++ '/' 
: s) | s <- fs, any (`isSuffixOf` s) [".hs",".lhs","-boot"] ] `mappend` rec
        return res
        where
        stripExt = reverse . drop 1 . dropWhile (/= '.') . reverse

        partitionM :: Monad m => (a -> m Bool) -> [a] -> m ([a],[a])
        partitionM p = foldM (selectM p) ([],[]) . reverse

        selectM :: Monad m => (a -> m Bool) -> ([a], [a]) -> a -> m ([a], [a])
        selectM p ~(ts,fs) x = p x >>= \r -> return (if r then (x:ts,fs) else 
(ts,x:fs))


With this context, I can extend guessTarget from the GHC API. I first try and 
find a module that I'm looking for in my name table. If it doesn't exist, I use 
guessTarget:


myGuessTarget :: GhcMonad m => NameTable -> Bool -> String -> m Target
myGuessTarget tab boot name = maybe (guessTarget name Nothing) (return . 
template) $ M.lookup (name,boot) tab
        where
        template :: FilePath -> Target
        template f = Target {targetId = TargetFile f Nothing, 
targetAllowObjCode = False, targetContents = Nothing}


With this in place, I can finally try and find ModSummary-s with a preference 
for source files in the GHC source tree:


getModSum :: GhcMonad m => NameTable -> Bool -> String -> m ModSummary
getModSum tab boot n | trace ("ModSum: " ++ n) False = undefined
getModSum tab boot n = do
        dflags <- getSessionDynFlags
        let dflags' = (P.foldl xopt_set dflags [Opt_RankNTypes, Opt_Cpp, 
Opt_ImplicitPrelude, Opt_MagicHash, Opt_DeriveDataTypeable]) { includePaths
                = "/Users/holzensp/Documents/prog/Haskell/ghc/compiler/stage2"
                : "/Users/holzensp/Documents/prog/Haskell/ghc/compiler"
                : includePaths dflags' }
        setSessionDynFlags dflags'
        target <- trace "  * Guessing target" myGuessTarget tab boot n
        case targetId target of
                TargetFile _ _ -> trace ("  * Adding target (" ++ show target 
++ ")") $ addTarget target
                _ -> return () -- FIXME: Somehow, things that I don't have the 
source for, and that aren't a "home module base" should also be loaded
        trace "  * Loading modules" $ load $ LoadAllTargets
        trace "  * Getting summary" $ getModSummary $ mkModuleName n


The FIXME poses the problem. If I add the target, GHC panics when it comes to 
FastString.lhs, saying that "Data.Data" is a package module. I was pointed to 
lookupModuleInAllPackages by quicksilver on #ghc, but this gives me a 
PackageConfig, which I don't know how to load.

If I've not overlooked something obvious, I think this is a feature request for 
the GHC API. In general, the features in the API and the documentation thereof 
are very much geared towards mimicking the behaviour of the compiler pipeline. 
In my - very limited! - experience, the granularity of operations in the API 
seems very variable. Sometimes I'm doing a lot of nitty gritty work that makes 
me feel I must have overlooked an obvious function. Other times, I need to dig 
into the API source to copy-paste parts out of Very Large Functionality 
functions (like parseModule).

Any advice would be enormously appreciated.

Regards,
Philip





_______________________________________________
Cvs-ghc mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/cvs-ghc

Reply via email to