2017-06-24 5 views
6

Je suis en train d'extraire la représentation STG d'une source Haskell comme String via Outputable, mais il semble que coreToStgArgs est panicing avec la décharge suivante:Extracting STG de Haskell Source

[email protected] ~/Desktop/hue $ runhaskell test.hs 
[foo :: forall a. Num a => a -> a 
[GblId, Arity=2, Caf=NoCafRefs, Str=DmdType] = 
    \r srt:SRT:[] [$dNum a1] + $dNum a1 a1;, 
bar :: Int -> Int 
[GblId,test.hs: test.hs: panic! (the 'impossible' happened) 
    (GHC version 7.10.3 for x86_64-unknown-linux): 
    coreToStgArgs I# 3 

Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug 

Voici le fichier FooBar.hs que je veux extraire:

module FooBar where 

foo a = a + a 

bar :: Int -> Int 
bar b = b + 3 

Voici la source de test.hs que je:

import CoreToStg 
import GHC 
import GHC.Paths 
import Outputable 
import StgSyn 

mkDynFlags :: IO DynFlags 
mkDynFlags = runGhc (Just libdir) getSessionDynFlags 

mkSTG :: FilePath -> FilePath -> IO [StgBinding] 
mkSTG proj src = do 
    dflags <- mkDynFlags 
    ghc_core <- runGhc (Just libdir) $ do 
     setSessionDynFlags (dflags {importPaths = [proj]}) 
     compileToCoreSimplified src 
     -- compileToCoreModule src 
    coreToStg dflags (cm_module ghc_core) (cm_binds ghc_core) 

mkIOStr :: (Outputable a) => a -> IO String 
mkIOStr obj = do 
    dflags <- mkDynFlags 
    let ppr_str = showPpr dflags obj 
    return ppr_str 

main :: IO() 
main = do 
    let proj = "/home/user/Desktop/hue" 
    let src = proj ++ "/FooBar.hs" 
    res <- mkIOStr =<< mkSTG proj src 
    putStrLn res 

Il semble que quelqu'un plusieurs années avant moi a rencontré un problème similaire:

https://ghc.haskell.org/trac/ghc/ticket/7159

Cependant, je ne sais pas ce qui est arrivé depuis. Je ne sais pas non plus si c'est la bonne façon d'extraire le STG d'une source arbitraire Haskell, donc s'il y a de meilleures alternatives qui fonctionnent, j'aimerais en entendre parler.

EDIT: traduction STG apparaît réussie pour le programme suivant où bar b = b + 3 est changé en bar b = 3:

module FooBar where 

foo a = a + a 

bar :: Int -> Int 
bar b = 3 

En fait, à première vue, les choses semblent fonctionner si le noyau Haskell induit ne force pas opérations primitives à effectuer. Par exemple bar b = 3 + 9 échoue.

+1

Le bug que vous avez lié à dit "* Ce n'est pas un bug après tout.Je devais utiliser 'CorePrep.corePrepPgm' avant d'essayer d'utiliser' CoreToStg.coreToStg'. *". – melpomene

+0

Ah, ça marche après un peu de lutte :) Merci! –

+0

Vous devriez publier le code de travail en guise de réponse. – melpomene

Répondre

1

Un grand merci à melpomene pour souligner quelque chose que j'ai manqué dans la documentation.

Voici la source du test.hs modifié qui fonctionne:

import CorePrep 
import CoreToStg 
import GHC 
import GHC.Paths 
import GhcMonad 
import HscTypes 
import Outputable 
import StgSyn 
import System.IO 

mkSTG :: FilePath -> FilePath -> IO [StgBinding] 
mkSTG proj src = runGhc (Just libdir) $ do 
     env <- getSession 
     dflags <- getSessionDynFlags 
     setSessionDynFlags (dflags {importPaths = [proj]}) 
     target <- guessTarget src Nothing 
     setTargets [target] 
     load LoadAllTargets 

     mod_graph <- getModuleGraph 
     let mod_sum = head mod_graph -- This is bad practice 
     pmod <- parseModule mod_sum 
     tmod <- typecheckModule pmod 
     dmod <- desugarModule tmod 
     let guts = coreModule dmod 
     let loc = ms_location mod_sum 
     let binds = mg_binds guts 
     let tcs = mg_tcs guts 
     prep <- liftIO $ corePrepPgm env loc binds tcs 
     liftIO $ coreToStg dflags (mg_module guts) prep 

mkIOStr :: (Outputable a) => a -> IO String 
mkIOStr obj = do 
    dflags <- runGhc (Just libdir) getSessionDynFlags 
    let ppr_str = showPpr dflags obj 
    return ppr_str 

main :: IO() 
main = do 
    let proj = "/home/celery/Desktop/hue" 
    let src = proj ++ "/FooBar.hs" 
    res <- mkIOStr =<< mkSTG proj src 
    putStrLn res 

Je ne sais pas quelle est la meilleure façon de récupérer un ModSummary (et donc le ModuleName) d'un Target est, mais je ne me souviens vaguement c'est le premier élément du ModuleGraph, qui est défini comme type ModuleGraph = [ModSummary].

La signature de type pour corePrepPgm est également différent entre GHC 7 et 8:

https://downloads.haskell.org/~ghc/7.10.1/docs/html/libraries/ghc-7.10.1/CorePrep.html

https://downloads.haskell.org/~ghc/latest/docs/html/libraries/ghc-8.0.1/CorePrep.html

suggestions d'amélioration sont bienvenus :)

EDIT: J'ai trouvé exemples de contre-exemples à cela - le head d'un ModuleGraph n'est pas alwa ys la cible. Ma solution actuelle consiste à voir si un ModSummary dans le ModuleGraph contient un emplacement qui correspond à celui de l'emplacement du fichier source initial.

+0

"- C'est une mauvaise pratique" - en effet, mais l'API GHC est remplie d'accidents historiques (comme représenter une liste non vide avec le type '[]') qui parfois vous force à faire de "mauvaises" choses. Alors ne vous sentez pas trop mal à ce sujet! – user2407038