[Haskell-cafe] hint / ghc api and reloading modules

Evan Laforge qdunkan at gmail.com
Sat May 31 13:46:00 EDT 2008


I'm using "hint", but since it's basically a thin wrapper around the
GHC API, this is probably a GHC api question too.  Maybe this should
go to cvs-ghc?  Let me know and I'll go subscribe over there.

It's my impression from the documentation that I should be able to
load a module interpreted, make changes to it, and then reload it.
This is, after all what ghci does.  It's also my impression that the
other imported modules should be loaded as object files, if the .hi
and .o exist, since this is also what ghci does.

However, if I load a module and run code like so (using hint):

    GHC.loadModules ["Cmd.LanguageEnviron"]
    GHC.setTopLevelModules ["Cmd.LanguageEnviron"]
    GHC.setImports ["Prelude"]
    cmd_func <- GHC.interpret (mangle_code text) (GHC.as :: LangType)

It works fine until I change LanguageEnviron.  If I make a change to a
function, I don't see my changes in the output, as if the session is
only getting partially reset.  If I insert a syntax error, then I do
see it, so it is recompiling the file in some way.  However, if I
*rename* the function and call it with the new name, I get a
GhcException:

During interactive linking, GHCi couldn't find the following symbol:
  ... etc.

So I examined the code in hint for loadModules and the code in
ghci/InteractiveUI.hs:/loadModule, and they do look like they're doing
basically the same things, except a call to rts_revertCAFs, which I
called too just for good measure but it didn't help (I can't find its
source anywhere, but the ghci docs imply it's optional, so I suspect
it's a red herring).

Here's a condensed summary of what hint is doing:
-- reset
GHC.setContext session [] []
GHC.setTargets session []
GHC.load session GHC.LoadAllTargets
-- rts_revertCAFs

-- load
targets <- mapM (\f -> GHC.guessTarget f Nothing) fs
GHC.setTargets session targets
GHC.load session GHC.LoadAllTargets

-- interpret
let expr_typesig = "($expr) :: xyz"
expr_val <- GHC.compileExpr session expr_typesig
return (GHC.Exts.unsafeCorce# expr_val :: a)

-- GHC.compileExpr
maybe_stuff <- hscStmt hsc_env ("let __cmCompileExpr = "++expr)
([n],[hv]) <- (unsafeCoerce# hval) :: IO [HValue]
return (Just hv)


and then ghci does:
-- load
GHC.setTargets session []
GHC.load session LoadAllTargets

targets <- io (mapM (uncurry GHC.guessTarget) files')
GHC.setTargets session targets
GHC.load session LoadAllTargets

rts_revertCAFs
putStrLn "Ok, modules loaded: $modules"

-- interpret
GHC.runStmt session stmt step

-- GHC.runStmt
Just (ids, hval) <- hscStmt hsc_env' expr
coerce hval to (IO [HValue]) and run it carefully


So it *looks* like I'm doing basically the same thing as ghci...
except obviously I'm not because ghci reloads modules without any
trouble.  Before I go start trying to make hint even more identical to
ghci, is there anything obviously wrong here that I'm doing?


More information about the Haskell-Cafe mailing list