如何测试GHC插件?

问题描述 投票:13回答:1

最近版本的GHC有一个新的“插件”功能,你可以编写普通的Haskell代码,像往常一样编译它,然后将它插入到编译器中,这样它就可以摆弄GHC的内部状态。

哪个很酷。然而,有一个小障碍:为了做到这一点,插件必须已经编译(似乎很明显)并在包DB中注册为包!

一旦插件完成,这很好;打包并把它放在Hackage上供所有人享用。但是,在尝试开发包装时,您如何解决这个问题呢?编辑 - 编译 - 执行循环在每次编辑时如何工作,您必须手动取消注册旧包,构建新包并注册它?

基本上,在尝试开发插件时,是否有某种方法可以支持这一要求?

haskell ghc
1个回答
4
投票

如果你正在使用Cabal,它应该为你管理一切:

my-plugin.cabal
cabal-version: 2.4
name: my-plugin
version: 1.0.0.0

library
  build-depends: base ^>= 4.12.0.0
               , ghc ^>= 8.6.1
  hs-source-dirs: src
  exposed-modules: MyPlugin

-- could also be an internal library, executable, etc
test-suite test-plugin
  type: exitcode-stdio-1.0
  -- the dependency on my-plugin is everything, placing it
  -- in the package DB of the GHC compiling this test
  build-depends: base, my-plugin
  hs-source-dirs: test
  ghc-options: -fplugin=MyPlugin
  main-is: Main.hs
src/MyPlugin.hs
module MyPlugin(plugin) where
import GhcPlugins
-- this is an example plugin from the manual
-- it prints the names of the non-recursive bindings in each module

plugin :: Plugin
plugin = defaultPlugin {
  installCoreToDos = install
  }

install :: [CommandLineOption] -> [CoreToDo] -> CoreM [CoreToDo]
install _ todo = do
  return (CoreDoPluginPass "Say name" pass : todo)

pass :: ModGuts -> CoreM ModGuts
pass guts = do dflags <- getDynFlags
               bindsOnlyPass (mapM (printBind dflags)) guts
  where printBind :: DynFlags -> CoreBind -> CoreM CoreBind
        printBind dflags bndr@(NonRec b _) = do
          putMsgS $ "Non-recursive binding named " ++ showSDoc dflags (ppr b)
          return bndr
        printBind _ bndr = return bndr
test/Main.hs
module Main where
import Numeric.Natural
import Prelude hiding (even, odd)

-- printed
x :: Int
x = 5

-- not printed
fixObvious :: (a -> a) -> a
fixObvious f = f (fixObvious f)

-- printed
fixSubtle :: (a -> a) -> a
fixSubtle f = let x = f x in x

-- neither printed
even, odd :: Natural -> Bool
even 0 = True
even n = odd (n - 1)
odd 0 = False
odd n = even (n - 1)

-- printed
main :: IO ()
main = return ()
-- if the plugin were more interesting, you may want to test that any
-- modified definitions act like you expect them to
© www.soinside.com 2019 - 2024. All rights reserved.