PageRenderTime 56ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/testsuite/tests/plugins/simple-plugin/Simple/Plugin.hs

http://github.com/ghc/ghc
Haskell | 86 lines | 66 code | 16 blank | 4 comment | 3 complexity | ea682a689dd923f472e9f57add645df6 MD5 | raw file
Possible License(s): MIT, BSD-3-Clause, GPL-3.0
  1. {-# LANGUAGE TemplateHaskell #-}
  2. module Simple.Plugin(plugin) where
  3. import GHC.Types.Unique.FM
  4. import GHC.Plugins
  5. import qualified GHC.Utils.Error
  6. -- For annotation tests
  7. import Simple.DataStructures
  8. import Control.Monad
  9. import Data.Monoid hiding (Alt)
  10. import Data.Dynamic
  11. import qualified Language.Haskell.TH as TH
  12. plugin :: Plugin
  13. plugin = defaultPlugin {
  14. installCoreToDos = install,
  15. pluginRecompile = purePlugin
  16. }
  17. install :: [CommandLineOption] -> [CoreToDo] -> CoreM [CoreToDo]
  18. install options todos = do
  19. putMsgS $ "Simple Plugin Passes Queried"
  20. putMsgS $ "Got options: " ++ unwords options
  21. -- Create some actual passes to continue the test.
  22. return $ CoreDoPluginPass "Main pass" mainPass
  23. : todos
  24. findNameBinds :: String -> [CoreBind] -> First Name
  25. findNameBinds target = mconcat . map (findNameBind target)
  26. findNameBind :: String -> CoreBind -> First Name
  27. findNameBind target (NonRec b e) = findNameBndr target b
  28. findNameBind target (Rec bes) = mconcat (map (findNameBndr target . fst) bes)
  29. findNameBndr :: String -> CoreBndr -> First Name
  30. findNameBndr target b
  31. = if getOccString (varName b) == target
  32. then First (Just (varName b))
  33. else First Nothing
  34. mainPass :: ModGuts -> CoreM ModGuts
  35. mainPass guts = do
  36. putMsgS "Simple Plugin Pass Run"
  37. (_, anns) <- getAnnotations deserializeWithData guts :: CoreM (ModuleEnv [ReplaceWith], NameEnv [ReplaceWith])
  38. -- Var's have the same uniques as their names. Making a cast from NameEnv to VarEnv safe.
  39. let anns' = unsafeCastUFMKey anns :: VarEnv [ReplaceWith]
  40. bindsOnlyPass (mapM (changeBind anns' Nothing)) guts
  41. changeBind :: VarEnv [ReplaceWith] -> Maybe String -> CoreBind -> CoreM CoreBind
  42. changeBind anns mb_replacement (NonRec b e) = changeBindPr anns mb_replacement b e >>= (return . uncurry NonRec)
  43. changeBind anns mb_replacement (Rec bes) = liftM Rec $ mapM (uncurry (changeBindPr anns mb_replacement)) bes
  44. changeBindPr :: VarEnv [ReplaceWith] -> Maybe String -> CoreBndr -> CoreExpr -> CoreM (CoreBndr, CoreExpr)
  45. changeBindPr anns mb_replacement b e = do
  46. case lookupWithDefaultUFM anns [] b of
  47. [] -> do
  48. e' <- changeExpr anns mb_replacement e
  49. return (b, e')
  50. [ReplaceWith replace_string] -> do
  51. e' <- changeExpr anns (Just replace_string) e
  52. return (b, e')
  53. _ -> do dflags <- getDynFlags
  54. error ("Too many change_anns on one binder:" ++ showPpr dflags b)
  55. changeExpr :: VarEnv [ReplaceWith] -> Maybe String -> CoreExpr -> CoreM CoreExpr
  56. changeExpr anns mb_replacement e = let go = changeExpr anns mb_replacement in case e of
  57. Lit (LitString _) -> case mb_replacement of
  58. Nothing -> return e
  59. Just replacement -> do
  60. putMsgS "Performing Replacement"
  61. return $ Lit (LitString (bytesFS (mkFastString replacement)))
  62. App e1 e2 -> liftM2 App (go e1) (go e2)
  63. Lam b e -> liftM (Lam b) (go e)
  64. Let bind e -> liftM2 Let (changeBind anns mb_replacement bind) (go e)
  65. Case e b ty alts -> liftM4 Case (go e) (return b) (return ty) (mapM (changeAlt anns mb_replacement) alts)
  66. Cast e coerce -> liftM2 Cast (go e) (return coerce)
  67. Tick t e -> liftM (Tick t) (go e)
  68. _ -> return e
  69. changeAlt :: VarEnv [ReplaceWith] -> Maybe String -> CoreAlt -> CoreM CoreAlt
  70. changeAlt anns mb_replacement (Alt con bs e) = liftM (\e' -> Alt con bs e') (changeExpr anns mb_replacement e)