/hareview/keep/HaskellGhcParser.hs

https://github.com/RefactoringTools/HaRe · Haskell · 294 lines · 102 code · 58 blank · 134 comment · 3 complexity · 07506c8397fa8c4eb0fb25fc7bb5eaa5 MD5 · raw file

  1. {-# LANGUAGE ScopedTypeVariables #-}
  2. module HaskellGhcParser where
  3. -- container
  4. import Data.Tree (Tree(Node,rootLabel),drawTree)
  5. -- syb
  6. import Data.Generics (Data)
  7. -- base
  8. import Unsafe.Coerce (unsafeCoerce)
  9. import Data.Generics
  10. import qualified Data.Generics.Schemes as SYB
  11. import qualified Data.Generics.Aliases as SYB
  12. import qualified GHC.SYB.Utils as SYB
  13. import qualified Bag as GHC
  14. import qualified DynFlags as GHC
  15. import qualified ErrUtils as GHC
  16. import qualified FastString as GHC
  17. import qualified GHC
  18. import qualified GHC.Paths as GHC
  19. import qualified MonadUtils as GHC
  20. import qualified NameSet as GHC
  21. import qualified OccName as GHC
  22. import qualified Outputable as GHC
  23. import qualified SrcLoc as GHC
  24. import qualified Var as GHC
  25. import GHC.Paths ( libdir )
  26. import System.IO.Unsafe
  27. -- local imports
  28. import Language.Astview.Parser as Astview
  29. import Language.Astview.DataTree
  30. import Data.Tree (Tree(Node,rootLabel))
  31. import Language.Haskell.Exts (parseFileContents)
  32. import Language.Haskell.Exts.Parser (ParseResult(ParseOk))
  33. import Language.Haskell.Exts.Syntax (Module)
  34. import Data.List
  35. haskellghc = Parser "Haskell" [".hs"] buildTreeHaskellGhc
  36. buildTreeHaskellGhc :: String -> Tree String
  37. buildTreeHaskellGhc s = case parseHaskellGhc s of
  38. Right ast -> flat $ data2treeGhc (ast::GHC.Located (GHC.HsModule GHC.RdrName))
  39. -- Right ast -> flat $ data2tree (ast::GHC.Located (GHC.HsModule GHC.RdrName))
  40. Left ParseError -> Node "ParseError" []
  41. -- parseHaskellGhc :: (Data a) => String -> Either ParseError a
  42. parseHaskellGhc :: String -> Either ParseError (GHC.Located (GHC.HsModule GHC.RdrName))
  43. parseHaskellGhc s = case (foo s) of
  44. -- Right (_,p) -> unsafeCoerce $ Right p
  45. Right (_,p) -> Right p
  46. Left err -> Left ParseError
  47. -- | Trealise Data to Tree (from SYB 2, sec. 3.4 )
  48. -- bearing in mind the GHC parser stage holes
  49. data2treeGhc :: Data a => a -> Tree String
  50. data2treeGhc = data2treeGhcStaged SYB.Parser 0
  51. -- data2treeGhc = data2tree
  52. -- | Generic Data-based show, with special cases for GHC Ast types,
  53. -- and simplistic indentation-based layout (the 'Int' parameter);
  54. -- showing abstract types abstractly and avoiding known potholes
  55. -- (based on the 'Stage' that generated the Ast)
  56. -- data2treeGhcStaged stage n = const (Node "foo" [])
  57. {-
  58. data2treeGhcStaged :: Data a => SYB.Stage -> a -> Tree String
  59. -- showData :: Data a => Stage -> Int -> a -> String
  60. data2treeGhcStaged stage n =
  61. {- generic
  62. `ext1Q` list
  63. `extQ` string
  64. `extQ` fastString
  65. `extQ` srcSpan
  66. `extQ` name `extQ` occName `extQ` moduleName `extQ` var `extQ` dataCon
  67. `extQ` bagName `extQ` bagRdrName `extQ` bagVar
  68. -}
  69. {- (gdefault n)
  70. `ext1Q` -}
  71. 'mkQ' (nameSet stage n)
  72. {-
  73. `extQ` postTcType `extQ` -}
  74. -- fixity n
  75. {-
  76. `extQ` gdefault
  77. -}
  78. where -- generic :: Data a => a -> Tree String
  79. -- generic t = Node "(" ++ showConstr (toConstr t)
  80. -- ++ space (concat (intersperse " " (gmapQ (data2treeGhcStaged stage (n+1)) t))) ++ ")"
  81. -- space "" = ""
  82. -- space s = ' ':s
  83. -- gdefault :: Data a => SYB.Stage -> a -> Tree String
  84. -- gdefault :: Data a => a -> Tree String
  85. gdefault x = Node (showConstr $ toConstr x) (gmapQ (data2treeGhcStaged stage) x)
  86. -- nameSet x
  87. nameSet stage x
  88. | stage `elem` [SYB.Parser,SYB.TypeChecker]
  89. = const ( Node "{!NameSet placeholder here!}" []) -- :: GHC.NameSet -> Tree String
  90. | otherwise
  91. -- = const (Node (showConstr $ toConstr x) (gmapQ (data2treeGhcStaged stage) x)) :: GHC.NameSet -> Tree String
  92. = const ( Node "{!NameSet placeholder here!}" []) -- :: GHC.NameSet -> Tree String
  93. postTcType | stage<SYB.TypeChecker = const (Node "{!type placeholder here?!}" []) :: GHC.PostTcType -> Tree String
  94. -- | otherwise = GHC.showSDoc . GHC.ppr :: GHC.Type -> Tree String
  95. | otherwise = const (Node "{!type placeholder here!}" []) :: GHC.Type -> Tree String
  96. fixity | stage<SYB.Renamer = const (Node "{!fixity placeholder here?!}" []) :: GHC.Fixity -> Tree String
  97. | otherwise = const (Node ("{Fixity: ") []) :: GHC.Fixity -> Tree String
  98. -- | otherwise = const (Node (("{Fixity: "++) . (++"}") . GHC.showSDoc . GHC.ppr) []) :: GHC.Fixity -> Tree String
  99. -}
  100. {-
  101. -- | Generic Data-based show, with special cases for GHC Ast types,
  102. -- and simplistic indentation-based layout (the 'Int' parameter);
  103. -- showing abstract types abstractly and avoiding known potholes
  104. -- (based on the 'Stage' that generated the Ast)
  105. data2treeGhcStaged :: Data a => SYB.Stage -> a -> Tree String
  106. -- showData :: Data a => Stage -> Int -> a -> String
  107. data2treeGhcStaged stage n =
  108. generic `ext1Q` list `extQ` string `extQ` fastString `extQ` srcSpan
  109. `extQ` name `extQ` occName `extQ` moduleName `extQ` var `extQ` dataCon
  110. `extQ` bagName `extQ` bagRdrName `extQ` bagVar `extQ` nameSet
  111. `extQ` postTcType `extQ` fixity
  112. where generic :: Data a => a -> String
  113. generic t = indent n ++ "(" ++ showConstr (toConstr t)
  114. ++ space (concat (intersperse " " (gmapQ (data2treeGhcStaged stage (n+1)) t))) ++ ")"
  115. space "" = ""
  116. space s = ' ':s
  117. indent n = "\n" ++ replicate n ' '
  118. string = show :: String -> String
  119. fastString = ("{FastString: "++) . (++"}") . show :: GHC.FastString -> String
  120. list l = indent n ++ "["
  121. ++ concat (intersperse "," (map (data2treeGhc stage (n+1)) l)) ++ "]"
  122. name = ("{Name: "++) . (++"}") . GHC.showSDoc . GHC.ppr :: GHC.Name -> String
  123. occName = ("{OccName: "++) . (++"}") . GHC.occNameString
  124. moduleName = ("{ModuleName: "++) . (++"}") . GHC.showSDoc . GHC.ppr :: GHC.ModuleName -> String
  125. srcSpan = ("{"++) . (++"}") . GHC.showSDoc . GHC.ppr :: GHC.SrcSpan -> String
  126. var = ("{Var: "++) . (++"}") . GHC.showSDoc . GHC.ppr :: GHC.Var -> String
  127. dataCon = ("{DataCon: "++) . (++"}") . GHC.showSDoc . GHC.ppr :: GHC.DataCon -> String
  128. bagRdrName:: GHC.Bag (GHC.Located (GHC.HsBind GHC.RdrName)) -> String
  129. bagRdrName = ("{Bag(Located (HsBind RdrName)): "++) . (++"}") . list . GHC.bagToList
  130. bagName :: GHC.Bag (GHC.Located (GHC.HsBind GHC.Name)) -> String
  131. bagName = ("{Bag(Located (HsBind Name)): "++) . (++"}") . list . GHC.bagToList
  132. bagVar :: GHC.Bag (GHC.Located (GHC.HsBind GHC.Var)) -> String
  133. bagVar = ("{Bag(Located (HsBind Var)): "++) . (++"}") . list . GHC.bagToList
  134. nameSet | stage `elem` [SYB.Parser,SYB.TypeChecker]
  135. = const ("{!NameSet placeholder here!}") :: GHC.NameSet -> String
  136. | otherwise
  137. = ("{NameSet: "++) . (++"}") . list . GHC.nameSetToList
  138. postTcType | stage<SYB.TypeChecker = const "{!type placeholder here?!}" :: GHC.PostTcType -> String
  139. | otherwise = GHC.showSDoc . GHC.ppr :: GHC.Type -> String
  140. fixity | stage<SYB.Renamer = const "{!fixity placeholder here?!}" :: GHC.Fixity -> String
  141. | otherwise = ("{Fixity: "++) . (++"}") . GHC.showSDoc . GHC.ppr :: GHC.Fixity -> String
  142. -}
  143. -- ---------------------------------------------------------------------
  144. -- | Generic Data-based show, with special cases for GHC Ast types,
  145. -- and simplistic indentation-based layout (the 'Int' parameter);
  146. -- showing abstract types abstractly and avoiding known potholes
  147. -- (based on the 'Stage' that generated the Ast)
  148. data2treeGhcStaged :: Data a => SYB.Stage -> Int -> a -> Tree String
  149. -- data2treeGhcStaged' :: Data a => SYB.Stage -> Int -> a -> String
  150. data2treeGhcStaged stage n =
  151. generic `ext1Q` list
  152. `extQ` string
  153. -- `extQ` fastString
  154. -- `extQ` gname
  155. -- `extQ` occName
  156. -- `extQ` moduleName
  157. -- `extQ` srcSpan
  158. -- `extQ` var
  159. -- `extQ` dataCon
  160. -- `extQ` bagName `extQ` bagRdrName `extQ` bagVar
  161. `extQ` nameSet
  162. `extQ` postTcType
  163. `extQ` fixity
  164. where generic :: Data a => a -> Tree String
  165. generic t = Node ("T:" ++ (showConstr (toConstr t))) (gmapQ (data2treeGhcStaged stage (n+1)) t)
  166. space "" = ""
  167. space s = ' ':s
  168. -- indent n' = "\n" ++ replicate n' ' '
  169. indent n' = ""
  170. -- string = show :: String -> String
  171. string = const (Node ("show t") []) :: String -> Tree String
  172. -- fastString = ("{FastString: "++) . (++"}") . show :: GHC.FastString -> String
  173. -- list l = indent n ++ "["
  174. -- ++ concat (intersperse "," (map (data2treeGhcStaged' stage (n+1)) l)) ++ "]"
  175. -- list l = Node (indent n ++ "["
  176. -- ++ concat (intersperse "," ["a","b"]{- (map (data2treeGhcStaged' stage (n+1)) l) -}) ++ "]") []
  177. list l = Node "list" ((map (data2treeGhcStaged stage (n+1)) l))
  178. -- gname = ("{Name: "++) . (++"}") . GHC.showSDoc . GHC.ppr :: GHC.Name -> String
  179. -- occName = ("{OccName: "++) . (++"}") . GHC.occNameString
  180. -- moduleName = ("{ModuleName: "++) . (++"}") . GHC.showSDoc . GHC.ppr :: GHC.ModuleName -> String
  181. -- srcSpan = ("{"++) . (++"}") . GHC.showSDoc . GHC.ppr :: GHC.SrcSpan -> String
  182. -- var = ("{Var: "++) . (++"}") . GHC.showSDoc . GHC.ppr :: GHC.Var -> String
  183. -- dataCon = ("{DataCon: "++) . (++"}") . GHC.showSDoc . GHC.ppr :: GHC.DataCon -> String
  184. {-
  185. bagRdrName:: GHC.Bag (GHC.Located (GHC.HsBind GHC.RdrName)) -> String
  186. bagRdrName = ("{Bag(Located (HsBind RdrName)): "++) . (++"}") . list . GHC.bagToList
  187. bagName :: GHC.Bag (GHC.Located (GHC.HsBind GHC.Name)) -> String
  188. bagName = ("{Bag(Located (HsBind Name)): "++) . (++"}") . list . GHC.bagToList
  189. bagVar :: GHC.Bag (GHC.Located (GHC.HsBind GHC.Var)) -> String
  190. bagVar = ("{Bag(Located (HsBind Var)): "++) . (++"}") . list . GHC.bagToList
  191. -}
  192. nameSet | stage `elem` [SYB.Parser,SYB.TypeChecker]
  193. = const (Node ("{!NameSet placeholder here!}") []) :: GHC.NameSet -> Tree String
  194. postTcType | stage<SYB.TypeChecker = const (Node "{!type placeholder here?!}" []) :: GHC.PostTcType -> Tree String
  195. fixity | stage<SYB.Renamer = const (Node "{!fixity placeholder here?!}" []) :: GHC.Fixity -> Tree String
  196. -- ---------------------------------------------------------------------
  197. parseHaskellGhc' ::
  198. String
  199. -> Either
  200. ParseError
  201. (GHC.WarningMessages, GHC.Located (GHC.HsModule GHC.RdrName))
  202. parseHaskellGhc' s = case (foo s) of
  203. Right p -> Right p
  204. Left err -> Left ParseError
  205. foo s = do
  206. res <- unsafePerformIO $ parseSourceFile s
  207. return res
  208. parseSourceFile ::
  209. String
  210. -> IO
  211. (Either
  212. GHC.ErrorMessages
  213. (GHC.WarningMessages, GHC.Located (GHC.HsModule GHC.RdrName)))
  214. parseSourceFile s =
  215. GHC.defaultErrorHandler GHC.defaultLogAction $ do
  216. GHC.runGhc (Just GHC.libdir) $ do
  217. dflags <- GHC.getSessionDynFlags
  218. let dflags' = foldl GHC.xopt_set dflags
  219. [GHC.Opt_Cpp, GHC.Opt_ImplicitPrelude, GHC.Opt_MagicHash]
  220. GHC.setSessionDynFlags dflags
  221. let result = GHC.parser s dflags' "filename.hs"
  222. -- -> Either ErrorMessages (WarningMessages, Located (HsModule RdrName))
  223. return result
  224. -- ---------------------------------------------------------------------
  225. -- | A simple test function to launch parsers from ghci.
  226. -- When this works, astview should work too.
  227. testParser :: Parser -> String -> IO ()
  228. testParser p s = putStrLn $ drawTree $ (tree p) s
  229. tsrc = "main = putStrLn \"Hello World\""
  230. t = testParser haskellghc tsrc
  231. p = putStrLn $ SYB.showData SYB.Parser 2 (parseHaskellGhc tsrc)