liquidhaskell-0.8.0.2: scripts/CountBinders.hs
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeSynonymInstances #-}
module Main where
import Control.Applicative
import Data.Function
import Data.Generics
import Data.List
import System.Environment
import Text.Printf
import CoreMonad
import CoreSyn
import DynFlags
import GHC
import GHC.Paths
import HscTypes
import qualified Outputable as Out
import Type
import Var
import Language.Haskell.Liquid.GhcMisc
import Language.Haskell.Liquid.Misc
getCoreBinds :: FilePath -> IO [CoreBind]
getCoreBinds target = runGhc (Just libdir) $ do
addTarget =<< guessTarget target Nothing
flags <- getSessionDynFlags
inc <- liftIO getIncludeDir
setSessionDynFlags $ updateDynFlags flags [inc]
load LoadAllTargets
modGraph <- getModuleGraph
case find ((== target) . msHsFilePath) modGraph of
Just modSummary -> do
mod_guts <- coreModule <$> (desugarModule =<< typecheckModule =<< parseModule modSummary)
return $! mg_binds mod_guts
Nothing -> error "Ghc Interface: Unable to get GhcModGuts"
updateDynFlags :: DynFlags -> [FilePath] -> DynFlags
updateDynFlags df ps
= df { importPaths = ps ++ importPaths df
, libraryPaths = ps ++ libraryPaths df
, profAuto = ProfAutoCalls
, ghcLink = NoLink
, hscTarget = HscInterpreted
, ghcMode = CompManager
} `xopt_set` Opt_MagicHash
`dopt_set` Opt_ImplicitImportQualified
allBinders :: [CoreBind] -> [CoreBind]
allBinders cbs = cbs ++ map bind (concatMap (listify isBinder) cbs)
where
bind (Let x _) = x
isBinder (Let _ _) = True
isBinder _ = False
recsAndFuns :: [CoreBind] -> ([Var],[Var],[Var])
recsAndFuns binds = (recs,recfuns,funs)
where
recs = [v | Rec bs <- binds, (v,_) <- bs]
recfuns = filter isFun recs
-- GHC does transforms recursive functions (at least with tyvars)
-- into a let binding that quantifies over the tyvar followed by a
-- letrec that defines the function, e.g.
-- let foo = \ @a -> { letrec foo = ... in foo }
-- but we don't want to count foo as rec and nonrec
funs = nubBy ((==) `on` getOccName)
$ [v | NonRec v _ <- binds, isFun v]
++ recfuns
isFun = isFunTy . snd . splitForAllTys . varType
main :: IO ()
main = do
target <- head <$> getArgs
binds <- allBinders <$> getCoreBinds target
let (recs,recfuns,funs) = recsAndFuns binds
printf "funs: %d\n" (length funs)
printf "recs: %d\n" (length recs)
printf "recsFuns: %d\n" (length recfuns)
instance Show CoreBind where
show = showPpr
instance Show (Expr CoreBndr) where
show = showPpr