この質問に対する答えは、他の場所で私に与えられました。GHC API はこれを行うことができます。ここに 2 つの関数があります。1 つはコンパイルしTarget.hs
、もう 1 つはアクセスします (モジュールTarget.accessMe
のソース コードがそこにある必要はありません)。Target
import GHC
import DynFlags
compile :: String -> IO SuccessFlag
compile name = defaultRunGhc $ do
dynflags <- getSessionDynFlags
let dynflags' = dynflags -- You can change various options here.
setSessionDynFlags dynflags'
-- (name) can be "Target.hs", "Target", etc.
target <- guessTarget name Nothing
addTarget target
load LoadAllTargets -- Runs something like "ghc --make".
これは、特定のモジュールをコンパイルし、コンパイルが成功したかどうかを返す関数です。defaultRunGhc
次のように定義されたヘルパー関数を使用します。
import GHC.Paths (libdir)
defaultRunGhc :: Ghc a -> IO a
defaultRunGhc = defaultErrorHandler defaultDynFlags . runGhc (Just libdir)
そして今、コンパイルされたモジュールから値をフェッチするための関数。モジュールのソース コードは、この時点で存在する必要はありません。
import Unsafe.Coerce (unsafeCoerce)
fetch :: String -> String -> IO Int -- Assumes we are fetching an Int value.
fetch name value = defaultRunGhc $ do
-- Again, you can change various options in dynflags here, as above.
dynflags <- getSessionDynFlags
let m = mkModule (thisPackage dynflags) (mkModuleName name)
setContext [] [(m, Nothing)] -- Use setContext [] [m] for GHC<7.
fetched <- compileExpr (name ++ "." ++ value) -- Fetching "Target.accessMe".
return (unsafeCoerce fetched :: Int)
以上です!