ghc-lib-parser-ex 0.20200201.1.0 → 0.20200205.0.0
raw patch · 7 files changed
+220/−69 lines, 7 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Language.Haskell.GhclibParserEx.HsExtendInstances: HsExtendInstances :: a -> HsExtendInstances a
- Language.Haskell.GhclibParserEx.HsExtendInstances: [unextendInstances] :: HsExtendInstances a -> a
- Language.Haskell.GhclibParserEx.HsExtendInstances: astEq :: Data a => a -> a -> Bool
- Language.Haskell.GhclibParserEx.HsExtendInstances: astListEq :: Data a => [a] -> [a] -> Bool
- Language.Haskell.GhclibParserEx.HsExtendInstances: extendInstances :: a -> HsExtendInstances a
- Language.Haskell.GhclibParserEx.HsExtendInstances: instance Data.Data.Data a => GHC.Classes.Eq (Language.Haskell.GhclibParserEx.HsExtendInstances.HsExtendInstances a)
- Language.Haskell.GhclibParserEx.HsExtendInstances: instance Data.Data.Data a => GHC.Classes.Ord (Language.Haskell.GhclibParserEx.HsExtendInstances.HsExtendInstances a)
- Language.Haskell.GhclibParserEx.HsExtendInstances: instance Outputable.Outputable a => GHC.Show.Show (Language.Haskell.GhclibParserEx.HsExtendInstances.HsExtendInstances a)
- Language.Haskell.GhclibParserEx.HsExtendInstances: instance Outputable.Outputable a => Outputable.Outputable (Language.Haskell.GhclibParserEx.HsExtendInstances.HsExtendInstances a)
- Language.Haskell.GhclibParserEx.HsExtendInstances: newtype HsExtendInstances a
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: fromChar :: LHsExpr GhcPs -> Maybe Char
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: hasFieldsDotDot :: HsRecFields GhcPs (LHsExpr GhcPs) -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: isAnyApp :: LHsExpr GhcPs -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: isApp :: LHsExpr GhcPs -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: isDol :: LHsExpr GhcPs -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: isDot :: LHsExpr GhcPs -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: isDotApp :: LHsExpr GhcPs -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: isFieldPun :: LHsRecField GhcPs (LHsExpr GhcPs) -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: isFieldWildcard :: LHsRecField GhcPs (LHsExpr GhcPs) -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: isLCase :: LHsExpr GhcPs -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: isLambda :: LHsExpr GhcPs -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: isLexeme :: LHsExpr GhcPs -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: isMDo :: HsStmtContext Name -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: isOpApp :: LHsExpr GhcPs -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: isPar :: LHsExpr GhcPs -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: isParComp :: StmtLR GhcPs GhcPs (LHsExpr GhcPs) -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: isPrimLiteral :: HsLit GhcPs -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: isQuasiQuote :: LHsExpr GhcPs -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: isRecConstr :: LHsExpr GhcPs -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: isRecStmt :: StmtLR GhcPs GhcPs (LHsExpr GhcPs) -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: isRecUpdate :: LHsExpr GhcPs -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: isReturn :: LHsExpr GhcPs -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: isSection :: LHsExpr GhcPs -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: isSpliceDecl :: HsExpr GhcPs -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: isString :: HsLit GhcPs -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: isTag :: String -> LHsExpr GhcPs -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: isTupleSection :: HsTupArg GhcPs -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: isTypeApp :: LHsExpr GhcPs -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: isUnboxed :: Boxity -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: isVar :: LHsExpr GhcPs -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: isWHNF :: LHsExpr GhcPs -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: strToVar :: String -> LHsExpr GhcPs
+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr: varToStr :: LHsExpr GhcPs -> String
+ Language.Haskell.GhclibParserEx.GHC.Hs.ExtendInstances: HsExtendInstances :: a -> HsExtendInstances a
+ Language.Haskell.GhclibParserEx.GHC.Hs.ExtendInstances: [unextendInstances] :: HsExtendInstances a -> a
+ Language.Haskell.GhclibParserEx.GHC.Hs.ExtendInstances: astEq :: Data a => a -> a -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.ExtendInstances: astListEq :: Data a => [a] -> [a] -> Bool
+ Language.Haskell.GhclibParserEx.GHC.Hs.ExtendInstances: extendInstances :: a -> HsExtendInstances a
+ Language.Haskell.GhclibParserEx.GHC.Hs.ExtendInstances: instance Data.Data.Data a => GHC.Classes.Eq (Language.Haskell.GhclibParserEx.GHC.Hs.ExtendInstances.HsExtendInstances a)
+ Language.Haskell.GhclibParserEx.GHC.Hs.ExtendInstances: instance Data.Data.Data a => GHC.Classes.Ord (Language.Haskell.GhclibParserEx.GHC.Hs.ExtendInstances.HsExtendInstances a)
+ Language.Haskell.GhclibParserEx.GHC.Hs.ExtendInstances: instance Outputable.Outputable a => GHC.Show.Show (Language.Haskell.GhclibParserEx.GHC.Hs.ExtendInstances.HsExtendInstances a)
+ Language.Haskell.GhclibParserEx.GHC.Hs.ExtendInstances: instance Outputable.Outputable a => Outputable.Outputable (Language.Haskell.GhclibParserEx.GHC.Hs.ExtendInstances.HsExtendInstances a)
+ Language.Haskell.GhclibParserEx.GHC.Hs.ExtendInstances: newtype HsExtendInstances a
Files
- ChangeLog.md +8/−1
- ghc-lib-parser-ex.cabal +5/−4
- src/Language/Haskell/GhclibParserEx/Dump.hs +17/−13
- src/Language/Haskell/GhclibParserEx/GHC/Hs/Expr.hs +139/−0
- src/Language/Haskell/GhclibParserEx/GHC/Hs/ExtendInstances.hs +50/−0
- src/Language/Haskell/GhclibParserEx/HsExtendInstances.hs +0/−50
- test/Test.hs +1/−1
ChangeLog.md view
@@ -2,7 +2,14 @@ ## Unreleased changes -## 0.20200201 released 2020-02-01+## 8.8.4.0 released 2020-02-01+- New modules:+ - `Language.Haskell.GhclibparserEx.GHC.Hs.Expr`+- Moved modules:+ - `Language.Haskell.GhclibparserEx.HsExtendInstances` ->+ `Language.Haskell.GhclibparserEx.GHC.Hs.ExtendInstances`;++## 0.20200201.1.0 released 2020-02-01 - New modules: - `Language.Haskell.GhclibparserEx.HsExtendInstances`.
ghc-lib-parser-ex.cabal view
@@ -1,6 +1,6 @@ cabal-version: >= 1.18 name: ghc-lib-parser-ex-version: 0.20200201.1.0+version: 0.20200205.0.0 description: Please see the README on GitHub at <https://github.com/shayne-fletcher/ghc-lib-parser-ex#readme> homepage: https://github.com/shayne-fletcher/ghc-lib-parser-ex#readme bug-reports: https://github.com/shayne-fletcher/ghc-lib-parser-ex/issues@@ -30,12 +30,13 @@ library exposed-modules: Language.Haskell.GhclibParserEx.Config+ Language.Haskell.GhclibParserEx.Dump Language.Haskell.GhclibParserEx.DynFlags- Language.Haskell.GhclibParserEx.HsExtendInstances+ Language.Haskell.GhclibParserEx.Fixity+ Language.Haskell.GhclibParserEx.GHC.Hs.Expr+ Language.Haskell.GhclibParserEx.GHC.Hs.ExtendInstances Language.Haskell.GhclibParserEx.Parse Language.Haskell.GhclibParserEx.Outputable- Language.Haskell.GhclibParserEx.Dump- Language.Haskell.GhclibParserEx.Fixity other-modules: Paths_ghc_lib_parser_ex hs-source-dirs:
src/Language/Haskell/GhclibParserEx/Dump.hs view
@@ -1,19 +1,6 @@ -- Copyright (c) 2020, Shayne Fletcher. All rights reserved. -- SPDX-License-Identifier: BSD-3-Clause. {--Currently 'showAstData' is only available in ghc-lib. I intend to-move it to ghc-lib-parser. Then, we'll be able to get at it with-something like,-- #if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)- import GHC.Hs.Dump- #else- import HsDumpAst- #endif--The implementation is reproduced here until that time.--}-{- (c) The University of Glasgow 2006 (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 -}@@ -28,6 +15,21 @@ , BlankSrcSpan(..), ) where +#if !defined(MIN_VERSION_ghc_lib_parser)+-- Using native ghc.+# if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)+import GHC.Hs.Dump+# else+import HsDumpAst+# endif+#else+-- Using ghc-lib-parser. Recent versions will include+-- GHC.Hs.Dump (it got moved in from ghc-lib on 2020-02-05).+# if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)+import GHC.Hs.Dump+# else+-- For simplicity, just assume it's missing from 8.8 ghc-lib-parser+-- builds and reproduce the implementation. import Prelude as X hiding ((<>)) import Data.Data hiding (Fixity)@@ -233,3 +235,5 @@ -> (forall d1 d2. (Data d1, Data d2) => c (t d1 d2)) -> c a ext2 def ext = maybe def id (dataCast2 ext)+# endif+#endif
+ src/Language/Haskell/GhclibParserEx/GHC/Hs/Expr.hs view
@@ -0,0 +1,139 @@+-- Copyright (c) 2020, Shayne Fletcher. All rights reserved.+-- SPDX-License-Identifier: BSD-3-Clause.++{-# OPTIONS_GHC -Wno-missing-fields #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE LambdaCase #-}+#include "ghclib_api.h"++module Language.Haskell.GhclibParserEx.GHC.Hs.Expr(+ isTag, isDol, isDot, isReturn, isSection, isRecConstr, isRecUpdate,+ isVar, isPar, isApp, isOpApp, isAnyApp, isLexeme, isLambda, isQuasiQuote,+ isDotApp, isTypeApp, isWHNF, isLCase,+ isFieldPun, isRecStmt, isParComp, isMDo, isTupleSection, isString, isPrimLiteral,+ isSpliceDecl, isFieldWildcard, isUnboxed,+ hasFieldsDotDot,+ varToStr, strToVar,+ fromChar+ ) where++#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)+import GHC.Hs+#else+import HsSyn+#endif+import SrcLoc+import RdrName+import OccName+import Name+import BasicTypes+import TysWiredIn++#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)+noExt :: NoExtField+noExt = noExtField+#endif++-- 'True' if the provided expression is a variable with name 'tag'.+isTag :: String -> LHsExpr GhcPs -> Bool+isTag tag = \case (L _ (HsVar _ (L _ s))) -> occNameString (rdrNameOcc s) == tag; _ -> False++isDot, isDol, isReturn, isSection, isRecConstr, isRecUpdate,+ isVar, isPar, isApp, isOpApp, isAnyApp, isLexeme, isQuasiQuote,+ isLambda, isDotApp, isTypeApp, isWHNF, isLCase :: LHsExpr GhcPs -> Bool+isDol = isTag "$"+isDot = isTag "."+isReturn x = isTag "return" x || isTag "pure" x -- Allow both 'pure' and 'return' as they have the same semantics.+isSection = \case (L _ SectionL{}) -> True ; (L _ SectionR{}) -> True; _ -> False+isRecConstr = \case (L _ RecordCon{}) -> True; _ -> False+isRecUpdate = \case (L _ RecordUpd{}) -> True; _ -> False+isVar = \case (L _ HsVar{}) -> True; _ -> False+isPar = \case (L _ HsPar{}) -> True; _ -> False+isApp = \case (L _ HsApp{}) -> True; _ -> False+isOpApp = \case (L _ OpApp{}) -> True; _ -> False+isAnyApp x = isApp x || isOpApp x+isLexeme = \case (L _ HsVar{}) -> True; (L _ HsOverLit{}) -> True; (L _ HsLit{}) -> True; _ -> False+isLambda = \case (L _ HsLam{}) -> True; _ -> False+isQuasiQuote = \case (L _ (HsSpliceE _ HsQuasiQuote{})) -> True; _ -> False+isDotApp = \case (L _ (OpApp _ _ op _)) -> isDot op; _ -> False+isTypeApp = \case (L _ HsAppType{}) -> True; _ -> False+isWHNF = \case+ (L _ (HsVar _ (L _ x))) -> isRdrDataCon x+ (L _ (HsLit _ x)) -> case x of HsString{} -> False; HsInt{} -> False; HsRat{} -> False; _ -> True+ (L _ HsLam{}) -> True+ (L _ ExplicitTuple{}) -> True+ (L _ ExplicitList{}) -> True+ (L _ (HsPar _ x)) -> isWHNF x+ (L _ (ExprWithTySig _ x _)) -> isWHNF x+ -- Other (unknown) constructors may have bang patterns in them, so+ -- approximate.+ (L _ (HsApp _ (L _ (HsVar _ (L _ x))) _))+ | occNameString (rdrNameOcc x) `elem` ["Just", "Left", "Right"] -> True+ _ -> False+isLCase = \case (L _ HsLamCase{}) -> True; _ -> False++-- Field is punned e.g. '{foo}'.+isFieldPun :: LHsRecField GhcPs (LHsExpr GhcPs) -> Bool+isFieldPun = \case (L _ HsRecField {hsRecPun=True}) -> True; _ -> False++-- Contains a '..' as in 'Foo{..}'+hasFieldsDotDot :: HsRecFields GhcPs (LHsExpr GhcPs) -> Bool+hasFieldsDotDot = \case HsRecFields {rec_dotdot=Just _} -> True; _ -> False++isRecStmt :: StmtLR GhcPs GhcPs (LHsExpr GhcPs) -> Bool+isRecStmt = \case RecStmt{} -> True; _ -> False++isParComp :: StmtLR GhcPs GhcPs (LHsExpr GhcPs) -> Bool+isParComp = \case ParStmt{} -> True; _ -> False++isMDo :: HsStmtContext Name -> Bool+isMDo = \case MDoExpr -> True; _ -> False++isTupleSection :: HsTupArg GhcPs -> Bool+isTupleSection = \case Missing{} -> True; _ -> False++isString :: HsLit GhcPs -> Bool+isString = \case HsString{} -> True; _ -> False++isPrimLiteral :: HsLit GhcPs -> Bool+isPrimLiteral = \case+ HsCharPrim{} -> True+ HsStringPrim{} -> True+ HsIntPrim{} -> True+ HsWordPrim{} -> True+ HsInt64Prim{} -> True+ HsWord64Prim{} -> True+ HsFloatPrim{} -> True+ HsDoublePrim{} -> True+ _ -> False++isSpliceDecl :: HsExpr GhcPs -> Bool+isSpliceDecl = \case HsSpliceE{} -> True; _ -> False++-- Field has a '_' as in '{foo=_} or is punned e.g. '{foo}'.+isFieldWildcard :: LHsRecField GhcPs (LHsExpr GhcPs) -> Bool+isFieldWildcard = \case+#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)+ (L _ HsRecField {hsRecFieldArg=(L _ (HsUnboundVar _ s))}) -> occNameString s == "_"+#else+ (L _ HsRecField {hsRecFieldArg=(L _ (EWildPat _))}) -> True+#endif+ (L _ HsRecField {hsRecPun=True}) -> True+ (L _ HsRecField {}) -> False++isUnboxed :: Boxity -> Bool+isUnboxed = \case Unboxed -> True; _ -> False++varToStr :: LHsExpr GhcPs -> String+varToStr (L _ (HsVar _ (L _ n)))+ | n == consDataCon_RDR = ":"+ | n == nameRdrName nilDataConName = "[]"+ | n == nameRdrName (getName (tupleDataCon Boxed 0)) = "()"+ | otherwise = occNameString (rdrNameOcc n)+varToStr _ = ""++strToVar :: String -> LHsExpr GhcPs+strToVar x = noLoc $ HsVar noExt (noLoc $ mkRdrUnqual (mkVarOcc x))++fromChar :: LHsExpr GhcPs -> Maybe Char+fromChar = \case (L _ (HsLit _ (HsChar _ x))) -> Just x; _ -> Nothing
+ src/Language/Haskell/GhclibParserEx/GHC/Hs/ExtendInstances.hs view
@@ -0,0 +1,50 @@+-- Copyright (c) 2020, Shayne Fletcher. All rights reserved.+-- SPDX-License-Identifier: BSD-3-Clause.++{-# LANGUAGE GeneralizedNewtypeDeriving #-}++module Language.Haskell.GhclibParserEx.GHC.Hs.ExtendInstances (+ HsExtendInstances(..), extendInstances, astEq, astListEq)+where++-- At times, there are terms in Haskell syntax we work with that are+-- not in `Eq`, `Show` or `Ord` and we need them to be.++-- This work-around resorts to implementing Eq and Ord via+-- lexicographic string comparisons. As long as two different terms+-- never map to the same string, basing `Eq` and `Ord` on their string+-- representations rather than the terms themselves, leads to+-- identical results.++import Outputable+import Data.Data+import Data.Function++import Language.Haskell.GhclibParserEx.Dump++newtype HsExtendInstances a =+ HsExtendInstances { unextendInstances :: a }+ deriving Outputable++extendInstances :: a -> HsExtendInstances a+extendInstances = HsExtendInstances++-- Use 'showAstData'. This is preferable to 'ppr' in that trees that+-- only differ in arrangement due to fixities will produce differing+-- string representations.+toStr :: Data a => HsExtendInstances a -> String+toStr (HsExtendInstances e) =+ Outputable.showSDocUnsafe $ showAstData BlankSrcSpan e++instance Data a => Eq (HsExtendInstances a) where (==) a b = toStr a == toStr b+instance Data a => Ord (HsExtendInstances a) where compare = compare `on` toStr++astEq :: Data a => a -> a -> Bool+astEq a b = extendInstances a == extendInstances b++astListEq :: Data a => [a] -> [a] -> Bool+astListEq as bs = length as == length bs && all (uncurry astEq) (zip as bs)++-- Use 'ppr' for 'Show'.+instance Outputable a => Show (HsExtendInstances a) where+ show (HsExtendInstances e) = Outputable.showSDocUnsafe $ Outputable.ppr e
− src/Language/Haskell/GhclibParserEx/HsExtendInstances.hs
@@ -1,50 +0,0 @@--- Copyright (c) 2020, Shayne Fletcher. All rights reserved.--- SPDX-License-Identifier: BSD-3-Clause.--{-# LANGUAGE GeneralizedNewtypeDeriving #-}--module Language.Haskell.GhclibParserEx.HsExtendInstances (- HsExtendInstances(..), extendInstances, astEq, astListEq)-where---- At times, there are terms in Haskell syntax we work with that are--- not in `Eq`, `Show` or `Ord` and we need them to be.---- This work-around resorts to implementing Eq and Ord via--- lexicographic string comparisons. As long as two different terms--- never map to the same string, basing `Eq` and `Ord` on their string--- representations rather than the terms themselves, leads to--- identical results.--import Outputable-import Data.Data-import Data.Function--import Language.Haskell.GhclibParserEx.Dump--newtype HsExtendInstances a =- HsExtendInstances { unextendInstances :: a }- deriving Outputable--extendInstances :: a -> HsExtendInstances a-extendInstances = HsExtendInstances---- Use 'showAstData'. This is preferable to 'ppr' in that trees that--- only differ in arrangement due to fixities will produce differing--- string representations.-toStr :: Data a => HsExtendInstances a -> String-toStr (HsExtendInstances e) =- Outputable.showSDocUnsafe $ showAstData BlankSrcSpan e--instance Data a => Eq (HsExtendInstances a) where (==) a b = toStr a == toStr b-instance Data a => Ord (HsExtendInstances a) where compare = compare `on` toStr--astEq :: Data a => a -> a -> Bool-astEq a b = extendInstances a == extendInstances b--astListEq :: Data a => [a] -> [a] -> Bool-astListEq as bs = length as == length bs && all (uncurry astEq) (zip as bs)---- Use 'ppr' for 'Show'.-instance Outputable a => Show (HsExtendInstances a) where- show (HsExtendInstances e) = Outputable.showSDocUnsafe $ Outputable.ppr e
test/Test.hs view
@@ -15,10 +15,10 @@ import Language.Haskell.GhclibParserEx.Config import Language.Haskell.GhclibParserEx.DynFlags-import Language.Haskell.GhclibParserEx.HsExtendInstances import Language.Haskell.GhclibParserEx.Parse import Language.Haskell.GhclibParserEx.Dump import Language.Haskell.GhclibParserEx.Fixity+import Language.Haskell.GhclibParserEx.GHC.Hs.ExtendInstances #if defined (GHCLIB_API_811) || defined (GHCLIB_API_810) import GHC.Hs