haskell runtime evaluation ghc ghc-api

Evaluación de las declaraciones/expresiones de Haskell utilizando la API de GHC



runtime evaluation (3)

Buen trabajo haciendo funcionar la API. Les puedo contar un poco sobre cómo funciona el generador de código.

GHC utiliza el ensamblador del sistema para crear un archivo .o. Si no hay una opción disponible para que GHC se limpie después de sí misma, debe presentar una solicitud de función contra la API, utilizando el rastreador de errores en http://hackage.haskell.org/trac/ghc/newticket?type=feature+request . Para presentar la solicitud, deberá registrar una cuenta.

Al utilizar el generador de códigos estándar, no podrá evitar por completo la E / S de archivos, solo porque GHC delega el trabajo de crear un código de objeto reubicable en el ensamblador. Existe un back-end experimental basado en LLVM que podría hacer todo en la memoria, pero me sorprendería si estuviera disponible en cualquier versión anterior a 6.13. Sin embargo, podría valer la pena preguntar en la lista de desarrolladores de GHC.

Para una herramienta que estoy escribiendo ( http://hackage.haskell.org/package/explore ) necesito una forma de leer las definiciones de la función de haskell en tiempo de ejecución, aplicarlas a los valores de mi herramienta y recuperar los resultados de su aplicación .

¿Puede alguien darme un ejemplo muy básico utilizando la API de GHC (6.10.4 o 6.12.1)?

definición de función de ejemplo para leer desde un archivo en tiempo de ejecución:

f x = 10**(4/1102*x - 1)

salida esperada del programa

--mapM_ print $ map f [428, 410, 389] 3.577165388142748 3.077536885227335 2.5821307011665815

!!¡¡ACTUALIZAR!!
Publiqué una respuesta rápida, pero crea un archivo de objeto en el directorio de ejecución, cualquier sugerencia para evitar esto y evitar todo archivo de E / S es bienvenido. También quiero ver una versión que haga todo en la memoria: el usuario proporciona la definición de la función en una GUI, por ejemplo, y la compilación / evaluación no crea ningún archivo de objeto.


Utilice hint . Es un envoltorio similar a GHCi alrededor de la API de GHC que no es muy difícil de usar.

Si quieres un ejemplo de su uso, lo usé en mi proyecto Yogurt .


adaptado de: http://www.bluishcoder.co.nz/2008/11/dynamic-compilation-and-loading-of.html

f.hs:

module Func (Func.f) where f :: Double -> Double f x = 10**(4/1102*x - 1)

main.hs:

import GHC import GHC.Paths import DynFlags import Unsafe.Coerce import Control.Monad main :: IO () main = defaultErrorHandler defaultDynFlags $ do func <- runGhc (Just libdir) $ do dflags <- getSessionDynFlags setSessionDynFlags dflags target <- guessTarget "f.hs" Nothing addTarget target r <- load LoadAllTargets case r of Failed -> error "Compilation failed" Succeeded -> do m <- findModule (mkModuleName "Func") Nothing setContext [] [m] value <- compileExpr ("Func.f") do let value'' = (unsafeCoerce value) :: Double -> Double return value'' let f = func mapM_ print $ map f [428, 410, 389] return ()