Как небольшая часть более крупного университетского проекта, мне нужно написать то, что по сути является чрезвычайно сырой IDE. Идея состоит в том, чтобы получить ввод из текстового поля gtk, обработать эту строку, как если бы она была в файле .hs, и выполнить внутри нее функцию.
Мой основной подход заключался в использовании GHC API для компиляции и оценки тестовой функции. Мне уже удалось получить игрушечный пример, работающий на компиляцию из файла .hs. Тип данных Target GHC имел необязательный конструктор для получения цели из StringBuffer, поэтому я решил попробовать изменить свой код, чтобы заставить его работать из String Buffer:
compileText :: SourceView -> IO ()
compileText tview = do
txtBuff <- textViewGetBuffer tview
startIt <- textBufferGetStartIter txtBuff
endIt <- textBufferGetEndIter txtBuff
compTime <- getClockTime
srcString <- textBufferGetText txtBuff startIt endIt False
defaultErrorHandler defaultLogAction $ do
func <- runGhc (Just libdir) $ do
dflags <- getSessionDynFlags
setSessionDynFlags dflags
addTarget $ haskellFileFromText srcString compTime
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 ()
haskellFileFromText :: String -> ClockTime -> GHC.Target
haskellFileFromText codeStr cTime = GHC.Target (TargetModule (mkModuleName "Test")) False (Just ((stringToStringBuffer codeStr), cTime))
В это время в текстовом поле находился следующий код:
module Test (Test.print) where
print :: String -> IO ()
print x = putStrLn x
Однако, похоже, это не работает. Я получаю сообщение об ошибке:
textEdit: panic! (the 'impossible' happened)
(GHC version 7.4.1 for x86_64-unknown-linux):
Could not find module `Test'
Use -v to see a list of the files searched for.
Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug
Что я делаю неправильно? Я чувствую, что совершенно неправильно понимаю, как работает этот код.
Альтернативой этому методу, который был предложен мне, является использование чего-то вроде подсказки или mueval для оценки текста в текстовом поле. Казалось бы, это работает нормально, если я просто хочу оценить одну функцию изолированно, но будет ли это масштабироваться, если я хочу оценить функцию, которая зависит от контекста запуска 4 других функций, определенных в том же исходном файле?
hint
? Это не просто анализатор выражений — он ближе к GHCi, с загрузкой модулей и всем остальным. - person C. A. McCann   schedule 09.01.2013