我试图列出(打印)给定模块范围内的所有函数(及其类型)。
例如,我有这个模块:
{-# LANGUAGE NoImplicitPrelude #-}
module Reverse where
import Prelude ((==), String)
myString :: String
myString = "string"
我尝试使用GHC API(8.0.2),但我似乎无法找到我要查找的信息存储位置。 我已经设法使用以下代码查找范围内的所有函数(但不是它们的类型):
import Data.IORef
import DynFlags
import GHC
import GHC.LanguageExtensions
import GHC.Paths (libdir)
import HscTypes
import NameEnv
import OccName
import Outputable
import RdrName
import TcRnTypes
main = runGhc (Just libdir) $ do
liftIO $ print sets
dflags <- getSessionDynFlags
let compdflags =
(foldl xopt_set dflags [Cpp, ImplicitPrelude, MagicHash])
setSessionDynFlags compdflags
target <- guessTarget "Reverse.hs" Nothing
setTargets [target]
load LoadAllTargets
modSum <- getModSummary $ mkModuleName "Reverse"
parsedModule <- parseModule modSum
tmod <- typecheckModule parsedModule
let (tcenv, moddets) = tm_internals_ tmod
printO $ map (map gre_name) $ occEnvElts $ tcg_rdr_env tcenv
printO
:: (GhcMonad m, Outputable a)
=> a -> m ()
printO a = do
dfs <- getProgramDynFlags
liftIO $ putStrLn $ showPpr dfs a
我得到了这个输出:
[[String], [==], [myString]]
当然,这只是我需要的数据的一半。
答案 0 :(得分:2)
GHC API相当令人困惑,您必须习惯许多缩写,类型同义词和样式异构代码库,但是应该可以找到范围内所有内容的名称和类型。 否则GHC无法告诉你,如果你打错了,你的功能不在范围内。
实际上,一旦您对模块进行了类型检查,就可以获得所有相关信息。
首先,您需要函数的所有Name
,这些代码可以获得:
parsedModule <- parseModule modSum
tmod <- typecheckModule parsedModule
let (tcenv, moddets) = tm_internals_ tmod
let names = concatMap (map gre_name) $ occEnvElts $ tcg_rdr_env tcenv
然后,您需要使用lookupName
查找Names
以获取TyThing
。
如果找不到Maybe TyThing
,您将获得Nothing
(Name
),当名称引用某个函数时,TyThing
将为{{1}其中AnId i
是您正在寻找的东西。
Id
只是一个带有类型的名称。
然后,您可以使用varType
获取类型。
你可能会争辩说所有这些类型都会让这个问题变得更加困难,但是他们使我能够在不查看代码且没有文档的情况下弄清楚我需要做什么。