GHC API:查找范围

时间:2017-03-10 21:27:42

标签: function haskell types ghc

我试图列出(打印)给定模块范围内的所有函数(及其类型)。

例如,我有这个模块:

{-# 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]]

当然,这只是我需要的数据的一半。

1 个答案:

答案 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,您将获得NothingName),当名称引用某个函数时,TyThing将为{{1}其中AnId i是您正在寻找的东西。 Id只是一个带有类型的名称。 然后,您可以使用varType获取类型。

你可能会争辩说所有这些类型都会让这个问题变得更加困难,但是他们使我能够在不查看代码且没有文档的情况下弄清楚我需要做什么。