Skip to content

Instantly share code, notes, and snippets.

@worldsayshi
Forked from jhartikainen/DynLoad.hs
Last active February 25, 2022 15:01
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save worldsayshi/8853946 to your computer and use it in GitHub Desktop.
Save worldsayshi/8853946 to your computer and use it in GitHub Desktop.
Example for loading Haskell source code dynamically using the GHC api
-----------------------------------------------------------------------------
-- | 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
module DynTest where
aString = "Hello"
@worldsayshi
Copy link
Author

Also, look at the filepath argument to runGhc. Here I use libdir from the ghc-paths package.

@worldsayshi
Copy link
Author

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