-
-
Save worldsayshi/8853946 to your computer and use it in GitHub Desktop.
Example for loading Haskell source code dynamically using the GHC api
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
----------------------------------------------------------------------------- | |
-- | Example for loading Haskell source code dynamically using the GHC api | |
-- Tested on ghc 7.4.2 | |
-- | |
-- Useful links: | |
-- GHC api: | |
-- http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/GHC.html | |
-- Wiki: | |
-- http://www.haskell.org/haskellwiki/GHC/As_a_library | |
----------------------------------------------------------------------------- | |
module DynLoad where | |
import GHC | |
import GhcMonad (liftIO) | |
import GHC.Paths (libdir) | |
import Name (getOccString) | |
import Data.Dynamic (fromDyn) | |
-- | List all exports of this module | |
-- and evaluate a symbol from a module DynTest | |
main = | |
runGhc (Just libdir) $ do | |
putString ":::Display exports of modules:::" | |
modSums <- initSession ["DynLoad","DynTest"] | |
let thisModSum = head modSums | |
exports <- listExports thisModSum | |
mapM_ putString exports | |
putString ":::Evaluate a name from module DynTest:::" | |
importDecl_RdrName <- parseImportDecl "import DynTest as D" | |
setContext [IIDecl importDecl_RdrName] | |
dynVal <- dynCompileExpr "D.aString" | |
liftIO $ print $ (fromDyn dynVal "nope-nothing") | |
-- | Init interactive session and load modules | |
initSession modStrNames = do | |
dflags <- getSessionDynFlags | |
setSessionDynFlags $ dflags { | |
hscTarget = HscInterpreted | |
, ghcLink = LinkInMemory | |
} | |
targets <- mapM | |
(\modStrName -> do | |
putString modStrName | |
target <- guessTarget ("*"++modStrName++".hs") Nothing | |
return target | |
) modStrNames | |
setTargets targets | |
load LoadAllTargets | |
modSums <- mapM | |
(\modStrName -> do | |
putString modStrName | |
modSum <- getModSummary $ mkModuleName modStrName | |
return $ ms_mod modSum | |
) modStrNames | |
return modSums | |
-- | List exported names of this or a sibling module | |
listExports mod = do | |
maybeModInfo <- getModuleInfo mod | |
case maybeModInfo of | |
(Just modInfo) -> do | |
let expNames = modInfoExports modInfo | |
expStrNames = map getOccString expNames | |
return expStrNames | |
_ -> return [] | |
-- | Util for printing | |
putString = liftIO . putStrLn |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module DynTest where | |
aString = "Hello" |
Here's ghc (api) docs (somewhat hard to google):
http://www.haskell.org/platform/doc/2013.2.0.0/ghc-api/GHC.html
Completely rewritten. Cleaner now. Tested on ghc 7.4.2
Is there a way to get it to load a module given an absolute path to that module?
Not sure, haven't tried anything like that. You might want to try setting the importPaths
dynflag in the setSessionDynFlags
call above to import modules at other paths.
Disclaimer: It was quite a while since I worked with this problem.
Here's one way of doing it: replace guessTarget ("*"++modStrName++".hs")
above with guessTarget ("/full/path/to/my/source/Foobar.hs")
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Compiled but untested atm.