简体   繁体   中英

How can I parse GHC core?

I am trying to parse ghc core code obtained from running ghc -c -ddump-simpl myfile.hs .

I know extcore and core libraries are my options.

I am looking for a simple example depicting the use of these libraries.

[EDIT] Parsing result should be a data structure from which it should be easy to trace different paths a function can take.

Consider a simple not function

not True = False
not False = True

GHC will turn this into case expressions (consider output from ghc -c -ddump-simple only). I am looking to parse this output of GHC core.

I think the easiest way is to forego these external Core libraries and just use GHC as a library directly. Based on this example from the Haskell wiki , we can make a simple function that turns a module into Core:

import GHC
import GHC.Paths (libdir)
import HscTypes (mg_binds)
import CoreSyn
import DynFlags
import Control.Monad ((<=<))

compileToCore :: String -> IO [CoreBind]
compileToCore modName = runGhc (Just libdir) $ do
    setSessionDynFlags =<< getSessionDynFlags
    target <- guessTarget (modName ++ ".hs") Nothing
    setTargets [target]
    load LoadAllTargets
    ds <- desugarModule <=< typecheckModule <=< parseModule <=< getModSummary $ mkModuleName modName
    return $ mg_binds . coreModule $ ds

Here's a silly example usage that processes its output to count the number of cases:

-- Silly example function that analyzes Core
countCases :: [CoreBind] -> Int
countCases = sum . map countBind
  where
    countBind (NonRec _ e) = countExpr e
    countBind (Rec bs) = sum . map (countExpr . snd) $ bs

    countExpr (Case e _ _ alts) = countExpr e + sum (map countAlt alts)
    countExpr (App f e) = countExpr f + countExpr e
    countExpr (Lam _ e) = countExpr e
    countExpr (Let b e) = countBind b + countExpr e
    countExpr (Cast e _) = countExpr e
    countExpr (Tick _ e) = countExpr e
    countExpr _ = 0

    countAlt (_, _, rhs) = 1 + countExpr rhs

Let's run it on your example:

main :: IO ()
main = do
   core <- compileToCore "MyNot"
   print $ countCases core

This outputs 2, as expected.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM