2013-04-05 2 views
11

Я пытаюсь загрузить и выполнить модуль динамически,GHC 7.4.2, Динамически вызова модулей

Ниже мой код

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 

Когда я пытаюсь запустить программу, показать мне ниже ошибки

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

Не уверен, что мне не хватает, Может кто-то пожалуйста, помогите мне решить эту ошибку

+0

Я не знаю много об этом, но похоже, что вы можете сделать это намного проще с помощью [плагинов] (http: //hackage.haskell. org/package/plugins). – Almanildo

ответ

1

Моя мысль была бы проблема есть что-то делать это с вашим путем и что программа молчает, когда не может загрузить «TestModule», а затем жалуется, что модуль не загружен. Пробовали ли вы использовать execFnGhc с уже загруженным модулем и попробовали ли вы загружать модуль, который находится в GHC, например, Text.Parsec, а затем что-то что-то в нем делать?

Я бы испытал себя, но я не вижу библиотеки GHC.Paths где угодно: /.

+0

Я пробовал длину списка, str <- execFnGhc «Data.List» «length [1,2,3]», но он выбрасывает исключение как «Main: Main: panic! (Произошло« невозможное ») (версия GHC 7.4.2 для x86_64-неизвестно-Linux): \t нет состояния пакета еще: не называйте GHC.setSessionDynFlags Пожалуйста, сообщите об этом как об ошибке GHC: http://www.haskell.org/ghc/reportabug " – Xinus

+0

из ошибка, похоже, прежде чем вы сможете использовать execFnGhc, вам нужно установить «флаги сеанса» для GHC. Попробуйте взглянуть на тип GHC.setSessionFlags и, возможно, видеть, существует ли «GHC.getSessionFlags»; похоже, что GHC нуждается в дополнительной информации, прежде чем она сможет называть вещи. –

0

Недавно я читал соответствующий исходный код GHC, и похоже, что findModule не работает с локальными модулями (TestModule.hs в вашем случае), если они уже не были загружены. (Однако он работает с модулями в удаленных пакетах.)

Чтобы сделать динамическую загрузку скомпилированных модулей в стиле GHCi, лучше всего использовать addTarget и load. Как уже упоминалось в комментариях, вам также необходимо инициализировать динамические флаги сессии. Вот рабочая версия вашего кода:

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' 

Каковы параметры Target? Первое - это имя модуля; второй - это то, нужно ли нам разрешать загружать объектный код или всегда интерпретировать модуль; последний - необязательный строковый буфер, который вы могли бы использовать для переопределения исходного кода в фактическом файле (это Nothing, потому что нам это не нужно.)

Как я понял это? Я просмотрел код, который GHCi использует для реализации этого в исходном коде GHC, а также compiler/main/GHC.hs. Я нашел, что это самый надежный способ выяснить, как заставить GHC API делать то, что вы хотите.

Confusing? API GHC не был так сконструирован как accreted ...

Смежные вопросы