2013-04-05 16 views
11

che sto cercando di caricare ed eseguire il modulo in modo dinamico,ghc 7.4.2, in modo dinamico chiamando moduli

Qui di seguito è il mio codice

TestModule.hs

module TestModule 
     where 

evaluate = "Hello !!!" 

Invoke.hs

module Invoke 
     where 

import GHC 
import DynFlags 
import GHC.Paths (libdir) 
import Unsafe.Coerce (unsafeCoerce) 
import Data.Dynamic 

execFnGhc :: String -> String -> Ghc a 
execFnGhc modname fn = do 
     mod <- findModule (mkModuleName modname) Nothing 
     --setContext [IIModule mod] 
     GHC.setContext [ GHC.IIDecl $ (GHC.simpleImportDecl . GHC.mkModuleName $ modname) {GHC.ideclQualified = True} ] 
     value <- compileExpr (modname ++ "." ++ fn) 
     let value' = (unsafeCoerce value) :: a 
     return value' 

Main2.hs

import GHC.Paths (libdir) 
import GHC 
import Invoke 
-- import TestModule 

main :: IO() 
main = runGhc (Just libdir) $ do 
         str <- execFnGhc "TestModule" "evaluate" 
         return str 

Quando provo a fare funzionare il programma che mi mostra sotto l'errore

[[email protected] mypproj]# ./Main2 
Main2: <command line>: module is not loaded: `TestModule' (./TestModule.hs) 

Non so cosa mi manca, qualcuno può per favore aiutarmi a risolvere questo errore

+0

Non ne so molto, ma sembra che tu possa farlo molto più facilmente con i [plugin] (http: //hackage.haskell. pacchetto org/package/plugins). – Almanildo

risposta

1

Il mio pensiero sarebbe il problema ha qualcosa fare con il tuo percorso, e che il programma si interrompa silenziosamente quando non può caricare "TestModule", quindi si lamenta che il modulo non è caricato. Hai provato a usare execFnGhc con un modulo che è già stato caricato e hai provato a caricare un modulo che è in GHC in modo naturale, come Text.Parsec, quindi eseguendo qualcosa in esso?

Mi metterei alla prova, ma non vedo una libreria GHC.Paths ovunque: /.

+0

Ho provato la lunghezza dell'elenco, str <- execFnGhc "Data.List" "length [1,2,3]", ma lancia eccezioni come "Main: Main: panic! (L''impossibile' è successo) (versione GHC 7.4.2 per x86_64-unknown-linux): \t nessuno stato pacchetto ancora: lo chiamano GHC.setSessionDynFlags prega di segnalare questo come un bug GHC: http://www.haskell.org/ghc/reportabug " – Xinus

+0

Dalla errore, sembra che prima di poter usare execFnGhc, è necessario impostare "flag di sessione" per GHC. Prova a guardare il tipo di GHC.setSessionFlags e forse vedere se "GHC.getSessionFlags" esiste; sembra che GHC abbia bisogno di più informazioni prima di poter chiamare le cose. –

0

Stavo leggendo il codice sorgente GHC relativo recentemente e sembra che findModule non funzioni sui moduli locali (TestModule.hs nel tuo caso) a meno che non siano già stati caricati. (Funziona su moduli in pacchetti remoti, tuttavia.)

Per fare stile GHCi il caricamento dinamico di moduli compilati, la soluzione migliore è quella di utilizzare addTarget e load. Come è stato menzionato nei commenti, è necessario anche inizializzare i flag dinamici di sessione. Ecco una versione funzionante del codice:

module Invoke 
     where 

import GHC 
import DynFlags 
import GHC.Paths (libdir) 
import Unsafe.Coerce (unsafeCoerce) 
import Data.Dynamic 

execFnGhc :: String -> String -> Ghc String 
execFnGhc modname fn = do 
     dflags <- getDynFlags 
     setSessionDynFlags dflags 
     let target = Target (TargetModule (mkModuleName modname)) True Nothing 
     addTarget target 
     load (LoadUpTo (mkModuleName modname)) 
     mod <- findModule (mkModuleName modname) Nothing 
     GHC.setContext [ GHC.IIDecl $ (GHC.simpleImportDecl . GHC.mkModuleName $ modname) {GHC.ideclQualified = True} ] 
     value <- compileExpr (modname ++ "." ++ fn) 
     let value' = (unsafeCoerce value) :: String 
     return value' 

Quali sono i parametri di Target? Il primo è il nome del modulo; il secondo è se dobbiamo o non dobbiamo caricare il codice oggetto o interpretare sempre il modulo; l'ultimo è un buffer di stringa opzionale che è possibile utilizzare per sovrascrivere il codice sorgente nel file effettivo (è Nothing perché non è necessario.)

Come ho capito? Ho esaminato il codice che GHCi utilizza per implementare questo codice sorgente GHC, nonché lo compiler/main/GHC.hs. Ho trovato questo è il modo più affidabile per capire come ottenere l'API GHC per fare ciò che vuoi.

Confondere? L'API GHC non è stata progettata tanto quanto ...