7

Following the GHC tutorial posted here and alterations to this code following the advice in a previous stack overflow question I asked, I have created a program which is able to compile and run a module in Test.hs with a function print to print a string to the screen:

import GHC
import GHC.Paths
import DynFlags
import Unsafe.Coerce

main :: IO ()
main =
    defaultErrorHandler defaultLogAction $ do
      func <- runGhc (Just libdir) $ do
        dflags <- getSessionDynFlags
        setSessionDynFlags dflags
        target <- guessTarget "Test.hs" Nothing
        addTarget target
        r <- load LoadAllTargets
        case r of
          Failed -> error "Compilation failed"
          Succeeded -> do
            m <- findModule (mkModuleName "Test") Nothing
            setContext [IIModule m]
            value <- compileExpr ("Test.print")
            do let value' = (unsafeCoerce value) :: String -> IO ()
               return value'
      func "Hello"
      return ()

The problem with this code, as noted in the comments, is that it only seems to work the first time you run it (When Test.hs has not yet been complied). If you attempt to run the code a second time, the following error appears:

mkTopLevEnv: not interpreted main:Test

I believe this has something to do with the fact that the code has already been compiled. If I delete the .hi and .o files and run the program again, the program runs correctly with the correct output. What am I missing? I am currently using ghc version 7.4.1

(Note: I have tried looking through the GHC API but could not find any references to mkTopLevEnv)

Community
  • 1
  • 1
Craig Innes
  • 1,573
  • 11
  • 23
  • 2
    As a workaround, you could get your program to delete the .hi and .o files itself if they exist! – AndrewC Oct 09 '12 at 06:01
  • I was considering this, but I would still be left with a big gap in the understanding of how the ghc api actually works – Craig Innes Oct 09 '12 at 08:13
  • Absolutely - it's an __ugly__ workaround. – AndrewC Oct 09 '12 at 09:34
  • 1
    Does this happen when you run it twice in fast succession? Does it happen when you wait at least two seconds, so the timestamps are definitely different? [here](http://www.haskell.org/pipermail/glasgow-haskell-users/2011-October/021009.html) Simon Marlow suggests replacing `guessTarget "Test.hs" Nothing` with `guessTarget "*Test.hs" Nothing`, on the grounds that it tells GHC not to load the `.o` file. [whole thread on a page via nabble](http://haskell.1045720.n5.nabble.com/mkTopLevEnv-not-interpreted-main-Main-td4861327.html) – AndrewC Oct 13 '12 at 15:31
  • Don't get your hopes up, though, because the bug is marked as [fixed](http://hackage.haskell.org/trac/ghc/ticket/5527), so it might not be your problem. However, if `"*Test.hs"` avoids loading the `.o` files, and the existence of the `.o` files is the problem, this workaround might yet work. – AndrewC Oct 13 '12 at 15:40

1 Answers1

2

Simon Marlow suggests here that replacing

guessTarget "Test.hs" Nothing

with

guessTarget "*Test.hs" Nothing

should avoid the error you're getting, on the grounds that it tells GHC not to load the .o file.

See the whole thread on a page via nabble

Of course, you could delete the .hi and .o files each time, but that's an ugly workaround.

AndrewC
  • 32,300
  • 7
  • 79
  • 115