ghc-lib-parser-ex 8.8.2 → 8.8.3.0
raw patch · 9 files changed
+235/−128 lines, 9 filesdep ~tastyPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: tasty
API changes (from Hackage documentation)
- Language.Haskell.GhclibParserEx.Parse: fakeLlvmConfig :: (LlvmTargets, LlvmPasses)
- Language.Haskell.GhclibParserEx.Parse: fakeSettings :: Settings
- Language.Haskell.GhclibParserEx.Parse: parseExpr :: String -> DynFlags -> ParseResult (LHsExpr GhcPs)
- Language.Haskell.GhclibParserEx.Parse: parsePragmasIntoDynFlags :: DynFlags -> FilePath -> String -> IO (Either String DynFlags)
+ Language.Haskell.GhclibParserEx.Config: fakeLlvmConfig :: (LlvmTargets, LlvmPasses)
+ Language.Haskell.GhclibParserEx.Config: fakeSettings :: Settings
+ Language.Haskell.GhclibParserEx.DynFlags: parsePragmasIntoDynFlags :: DynFlags -> ([Extension], [Extension]) -> FilePath -> String -> IO (Either String DynFlags)
+ Language.Haskell.GhclibParserEx.Parse: parseBackpack :: String -> DynFlags -> ParseResult [LHsUnit PackageName]
+ Language.Haskell.GhclibParserEx.Parse: parseExpression :: String -> DynFlags -> ParseResult (LHsExpr GhcPs)
+ Language.Haskell.GhclibParserEx.Parse: parseHeader :: String -> DynFlags -> ParseResult (Located (HsModule GhcPs))
+ Language.Haskell.GhclibParserEx.Parse: parseIdentifier :: String -> DynFlags -> ParseResult (Located RdrName)
+ Language.Haskell.GhclibParserEx.Parse: parseModule :: String -> DynFlags -> ParseResult (Located (HsModule GhcPs))
+ Language.Haskell.GhclibParserEx.Parse: parsePattern :: String -> DynFlags -> ParseResult (LPat GhcPs)
+ Language.Haskell.GhclibParserEx.Parse: parseSignature :: String -> DynFlags -> ParseResult (Located (HsModule GhcPs))
+ Language.Haskell.GhclibParserEx.Parse: parseStatement :: String -> DynFlags -> ParseResult (LStmt GhcPs (LHsExpr GhcPs))
+ Language.Haskell.GhclibParserEx.Parse: parseStmt :: String -> DynFlags -> ParseResult (Maybe (LStmt GhcPs (LHsExpr GhcPs)))
+ Language.Haskell.GhclibParserEx.Parse: parseType :: String -> DynFlags -> ParseResult (LHsType GhcPs)
+ Language.Haskell.GhclibParserEx.Parse: parseTypeSignature :: String -> DynFlags -> ParseResult (LHsDecl GhcPs)
Files
- ChangeLog.md +9/−1
- README.md +12/−7
- cbits/ghclib_api.h +1/−1
- ghc-lib-parser-ex.cabal +8/−6
- src/Language/Haskell/GhclibParserEx/Config.hs +75/−0
- src/Language/Haskell/GhclibParserEx/DynFlags.hs +32/−0
- src/Language/Haskell/GhclibParserEx/Fixity.hs +2/−2
- src/Language/Haskell/GhclibParserEx/Parse.hs +52/−91
- test/Test.hs +44/−20
ChangeLog.md view
@@ -1,3 +1,11 @@ # Changelog for ghc-lib-parser-ex -## 8.8.1.20191204, released 2020-01-18+## 8.8.3.0 released 2020-01-25+- Change in versioning scheme;+- New modules:+ - `Language.Haskell.GhclibParserEx.Config`+ - `Language.Haskell.GhclibParserEx.DynFlags`+- `parsePragmasIntoDynFlags` signature change.++## 8.8.1.20191204, 8.8.2, 0.20200102 released 2020-01-18+- First releases
README.md view
@@ -6,22 +6,27 @@ ## Using `ghc-lib-parser-ex` -The package `ghc-lib-parser-ex` is available on [Hackage](https://hackage.haskell.org/) e.g. `cabal install ghc-lib-parser-ex`. There are two release streams within the `ghc-lib-parser-ex` name (tracking released `ghc-lib-parser` versions exactly):+Package `ghc-lib-parser-ex` is on [Hackage](https://hackage.haskell.org/package/ghc-lib-parser-ex) e.g. `cabal install ghc-lib-parser-ex`. Like `ghc-lib-parser`, there are two release streams within the `ghc-lib-parser-ex` name. -* Version 8.10.1 will be the `ghc-lib-parser-ex` for use against `ghc-lib-parser-8.10.1`(or the released GHC 8.10.1);-* Version 0.20190204 is for use against [`ghc-lib-parser-0.20190204`](http://hackage.haskell.org/package/ghc-lib-0.20190204).+Version numbers are of the form α.β.γ.δ where α.β corresponds to a GHC series and γ.δ are the major and minor parts of the `ghc-lib-ex-parser` package release. Examples:+* Version 8.10.1.3 is compatible with any `ghc-lib-parser-8.10.*` (or `ghc-8.10.*`) package;+* Version 0.20190204.2.0 is compatible with [`ghc-lib-parser-0.20190204`](http://hackage.haskell.org/package/ghc-lib-0.20190204). -### Building `ghc-lib-parser-ex`+The major part γ of the release number indicates an interface breaking change from the previous release. The minor part δ indicates a non-interface breaking change from the previous release. -You can build with `stack build` and test with `stack test`. You can also produce `ghc-lib-parser-ex` package distributions by executing the CI script (which incidentally builds everything and runs the tests).+## Building `ghc-lib-parser-ex`++You can build with `stack build` and test with `stack test`. Produce `ghc-lib-parser-ex` package distributions by executing the CI script: ```bash # Setup git clone git@github.com:shayne-fletcher/ghc-lib-parser-ex.git cd ghc-lib-parser-ex stack runhaskell --package extra --package optparse-applicative CI.hs ```-Run `stack runhaskell --package extra --package optparse-applicative CI.hs -- --help` for more configurability options.+Run `stack runhaskell --package extra --package optparse-applicative CI.hs -- --help` for more options. -## Releasing `ghc-lib` (notes for maintainers)+To run [`hlint`](https://github.com/ndmitchell/hlint) on this repository, `hlint --cpp-include cbits --cpp-define GHCLIB_API_XXX .` (where `XXX` at this time is one of `808`, `810` or `811`).++## Releasing `ghc-lib-parser-ex` (notes for maintainers) Build `ghc-lib-parser-ex` using the [above instructions](#building-ghc-lib-parser-ex) and upload the resulting `.tar.gz` files to [Hackage](https://hackage.haskell.org/upload).
cbits/ghclib_api.h view
@@ -6,7 +6,7 @@ #if !defined(GHCLIB_API_H) # define GHCLIB_API_H -# if !defined(GHCLIB_API_811) && !defined(GHCLIBAPI_810) && !defined(GHCLIB_API_808)+# if !defined(GHCLIB_API_811) && !defined(GHCLIB_API_810) && !defined(GHCLIB_API_808) # if defined(MIN_VERSION_ghc_lib_parser) # if !MIN_VERSION_ghc_lib_parser(1, 0, 0) # define GHCLIB_API_811
ghc-lib-parser-ex.cabal view
@@ -1,6 +1,6 @@ cabal-version: >= 1.18 name: ghc-lib-parser-ex-version: 8.8.2+version: 8.8.3.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@@ -12,11 +12,11 @@ category: Development synopsis: Algorithms on GHC parse trees build-type: Simple+tested-with: GHC==8.8.1, GHC==8.6.5, GHC==8.4.4 extra-source-files: README.md ChangeLog.md-extra-source-files:- cbits/ghclib_api.h+ cbits/ghclib_api.h source-repository head type: git@@ -29,6 +29,8 @@ library exposed-modules:+ Language.Haskell.GhclibParserEx.Config+ Language.Haskell.GhclibParserEx.DynFlags Language.Haskell.GhclibParserEx.Parse Language.Haskell.GhclibParserEx.Outputable Language.Haskell.GhclibParserEx.Dump@@ -47,7 +49,7 @@ ghc-boot-th else build-depends:- ghc-lib-parser+ ghc-lib-parser include-dirs: cbits install-includes:@@ -67,7 +69,7 @@ ghc-options: -threaded -rtsopts -with-rtsopts=-N build-depends: base >=4.7 && <5- , tasty >= 1.2.3+ , tasty >= 1.2 , tasty-hunit >= 0.10.0 , directory >= 1.3.3 , filepath >= 1.4.2@@ -79,5 +81,5 @@ ghc-boot-th else build-depends:- ghc-lib-parser+ ghc-lib-parser default-language: Haskell2010
+ src/Language/Haskell/GhclibParserEx/Config.hs view
@@ -0,0 +1,75 @@+-- Copyright (c) 2020, Shayne Fletcher. All rights reserved.+-- SPDX-License-Identifier: BSD-3-Clause.++{-# OPTIONS_GHC -Wno-missing-fields #-}+{-# LANGUAGE CPP #-}+#include "ghclib_api.h"++module Language.Haskell.GhclibParserEx.Config(+ fakeSettings+ , fakeLlvmConfig+ )+ where++import Config+import DynFlags+import Fingerprint++#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)+import GHC.Platform+import ToolSettings+#else+import Platform+#endif++fakeSettings :: Settings+fakeSettings = Settings+#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)+ { sGhcNameVersion=ghcNameVersion+ , sFileSettings=fileSettings+ , sTargetPlatform=platform+ , sPlatformMisc=platformMisc+ , sPlatformConstants=platformConstants+ , sToolSettings=toolSettings+ }+#else+ { sTargetPlatform=platform+ , sPlatformConstants=platformConstants+ , sProjectVersion=cProjectVersion+ , sProgramName="ghc"+ , sOpt_P_fingerprint=fingerprint0+ }+#endif+ where+#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)+ toolSettings = ToolSettings {+ toolSettings_opt_P_fingerprint=fingerprint0+ }+ fileSettings = FileSettings {}+ platformMisc = PlatformMisc {}+ ghcNameVersion =+ GhcNameVersion{ghcNameVersion_programName="ghc"+ ,ghcNameVersion_projectVersion=cProjectVersion+ }+#endif+ platform =+ Platform{+#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)+ platformWordSize = PW8+ , platformMini = PlatformMini {platformMini_arch=ArchUnknown, platformMini_os=OSUnknown}+#else+ platformWordSize=8+ , platformOS=OSUnknown+#endif+ , platformUnregisterised=True+ }+ platformConstants =+ PlatformConstants{pc_DYNAMIC_BY_DEFAULT=False,pc_WORD_SIZE=8}++#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)+fakeLlvmConfig :: LlvmConfig+fakeLlvmConfig = LlvmConfig [] []+#else+fakeLlvmConfig :: (LlvmTargets, LlvmPasses)+fakeLlvmConfig = ([], [])+#endif
+ src/Language/Haskell/GhclibParserEx/DynFlags.hs view
@@ -0,0 +1,32 @@+-- Copyright (c) 2020, Shayne Fletcher. All rights reserved.+-- SPDX-License-Identifier: BSD-3-Clause.++module Language.Haskell.GhclibParserEx.DynFlags(+ parsePragmasIntoDynFlags+ ) where++import DynFlags+import Panic+import HeaderInfo+import StringBuffer+import HscTypes+import GHC.LanguageExtensions.Type+import Data.List++parsePragmasIntoDynFlags :: DynFlags+ -> ([Extension], [Extension])+ -> FilePath+ -> String+ -> IO (Either String DynFlags)+parsePragmasIntoDynFlags flags (enable, disable) file str =+ catchErrors $ do+ let opts = getOptions flags (stringToStringBuffer str) file+ (flags, _, _) <- parseDynamicFilePragma flags opts+ let flags' = foldl' xopt_set flags enable+ let flags'' = foldl' xopt_unset flags' disable+ return $ Right (flags'' `gopt_set` Opt_KeepRawTokenStream)+ where+ catchErrors :: IO (Either String DynFlags) -> IO (Either String DynFlags)+ catchErrors act = handleGhcException reportErr+ (handleSourceError reportErr act)+ reportErr e = return $ Left (show e)
src/Language/Haskell/GhclibParserEx/Fixity.hs view
@@ -67,7 +67,7 @@ #if defined (GHCLIB_API_811) || defined (GHCLIB_API_810) | associate_right = ConPatIn op1 (InfixCon p11 (L loc (mkConOpPat fs op2 fix2 p12 p2))) #else- | associate_right = let new_p = mkConOpPat fs op2 fix2 p12 p2 in ConPatIn op1 (InfixCon p11 (cL loc new_p))+ | associate_right = ConPatIn op1 (InfixCon p11 (cL loc (mkConOpPat fs op2 fix2 p12 p2))) #endif | otherwise = ConPatIn op2 (InfixCon p1 p2) where@@ -109,7 +109,7 @@ getIdent (unLoc -> HsVar _ (L _ n)) = occNameString . rdrNameOcc $ n getIdent _ = error "Must be HsVar" --- If there are no fixities provided, give 'baseFixities.+-- If there are no fixities, give 'baseFixities'. getFixities :: [(String, Fixity)] -> [(String, Fixity)] getFixities fixities = if null fixities then baseFixities else fixities
src/Language/Haskell/GhclibParserEx/Parse.hs view
@@ -6,14 +6,21 @@ #include "ghclib_api.h" module Language.Haskell.GhclibParserEx.Parse(- parse- , parseExpr+ parseFile+ , parseModule+ , parseSignature , parseImport+ , parseStatement+ , parseBackpack , parseDeclaration- , parseFile- , parsePragmasIntoDynFlags- , fakeSettings- , fakeLlvmConfig+ , parseExpression+ , parsePattern+ , parseTypeSignature+ , parseStmt+ , parseIdentifier+ , parseType+ , parseHeader+ , parse ) where @@ -23,76 +30,15 @@ #else import HsSyn #endif-import Config import DynFlags import StringBuffer-import Fingerprint import Lexer import qualified Parser import FastString import SrcLoc-import Panic-import HscTypes-import HeaderInfo--#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)-import GHC.Platform-import ToolSettings-#else-import Platform-#endif--fakeSettings :: Settings-fakeSettings = Settings-#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)- { sGhcNameVersion=ghcNameVersion- , sFileSettings=fileSettings- , sTargetPlatform=platform- , sPlatformMisc=platformMisc- , sPlatformConstants=platformConstants- , sToolSettings=toolSettings- }-#else- { sTargetPlatform=platform- , sPlatformConstants=platformConstants- , sProjectVersion=cProjectVersion- , sProgramName="ghc"- , sOpt_P_fingerprint=fingerprint0- }-#endif- where-#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)- toolSettings = ToolSettings {- toolSettings_opt_P_fingerprint=fingerprint0- }- fileSettings = FileSettings {}- platformMisc = PlatformMisc {}- ghcNameVersion =- GhcNameVersion{ghcNameVersion_programName="ghc"- ,ghcNameVersion_projectVersion=cProjectVersion- }-#endif- platform =- Platform{-#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)- platformWordSize = PW8- , platformMini = PlatformMini {platformMini_arch=ArchUnknown, platformMini_os=OSUnknown}-#else- platformWordSize=8- , platformOS=OSUnknown-#endif- , platformUnregisterised=True- }- platformConstants =- PlatformConstants{pc_DYNAMIC_BY_DEFAULT=False,pc_WORD_SIZE=8}--#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810)-fakeLlvmConfig :: LlvmConfig-fakeLlvmConfig = LlvmConfig [] []-#else-fakeLlvmConfig :: (LlvmTargets, LlvmPasses)-fakeLlvmConfig = ([], [])-#endif+import BkpSyn+import PackageConfig+import RdrName parse :: P a -> String -> DynFlags -> ParseResult a parse p str flags =@@ -102,19 +48,49 @@ buffer = stringToStringBuffer str parseState = mkPState flags buffer location -#if defined (GHCLIB_API_811)-parseExpr :: String -> DynFlags -> ParseResult RdrHsSyn.ECP-#else-parseExpr :: String -> DynFlags -> ParseResult (LHsExpr GhcPs)-#endif-parseExpr = parse Parser.parseExpression+parseModule :: String -> DynFlags -> ParseResult (Located (HsModule GhcPs))+parseModule = parse Parser.parseModule +parseSignature :: String -> DynFlags -> ParseResult (Located (HsModule GhcPs))+parseSignature = parse Parser.parseSignature+ parseImport :: String -> DynFlags -> ParseResult (LImportDecl GhcPs) parseImport = parse Parser.parseImport +parseStatement :: String -> DynFlags -> ParseResult (LStmt GhcPs (LHsExpr GhcPs))+parseStatement = parse Parser.parseStatement++parseBackpack :: String -> DynFlags -> ParseResult [LHsUnit PackageName]+parseBackpack = parse Parser.parseBackpack+ parseDeclaration :: String -> DynFlags -> ParseResult (LHsDecl GhcPs) parseDeclaration = parse Parser.parseDeclaration +#if defined (GHCLIB_API_811)+parseExpression :: String -> DynFlags -> ParseResult RdrHsSyn.ECP+#else+parseExpression :: String -> DynFlags -> ParseResult (LHsExpr GhcPs)+#endif+parseExpression = parse Parser.parseExpression++parsePattern :: String -> DynFlags -> ParseResult (LPat GhcPs)+parsePattern = parse Parser.parsePattern++parseTypeSignature :: String -> DynFlags -> ParseResult (LHsDecl GhcPs)+parseTypeSignature = parse Parser.parseTypeSignature++parseStmt :: String -> DynFlags -> ParseResult (Maybe (LStmt GhcPs (LHsExpr GhcPs)))+parseStmt = parse Parser.parseStmt++parseIdentifier :: String -> DynFlags -> ParseResult (Located RdrName)+parseIdentifier = parse Parser.parseIdentifier++parseType :: String -> DynFlags -> ParseResult (LHsType GhcPs)+parseType = parse Parser.parseType++parseHeader :: String -> DynFlags -> ParseResult (Located (HsModule GhcPs))+parseHeader = parse Parser.parseHeader+ #if defined (GHC_API_811) parseFile :: String -> DynFlags@@ -132,18 +108,3 @@ location = mkRealSrcLoc (mkFastString filename) 1 1 buffer = stringToStringBuffer str parseState = mkPState flags buffer location--parsePragmasIntoDynFlags :: DynFlags- -> FilePath- -> String- -> IO (Either String DynFlags)-parsePragmasIntoDynFlags flags file str =- catchErrors $ do- let opts = getOptions flags (stringToStringBuffer str) file- (flags, _, _) <- parseDynamicFilePragma flags opts- return $ Right (flags `gopt_set` Opt_KeepRawTokenStream)- where- catchErrors :: IO (Either String DynFlags) -> IO (Either String DynFlags)- catchErrors act = handleGhcException reportErr- (handleSourceError reportErr act)- reportErr e = return $ Left (show e)
test/Test.hs view
@@ -13,20 +13,20 @@ import System.IO.Extra import Control.Monad +import Language.Haskell.GhclibParserEx.Config+import Language.Haskell.GhclibParserEx.DynFlags import Language.Haskell.GhclibParserEx.Parse import Language.Haskell.GhclibParserEx.Dump import Language.Haskell.GhclibParserEx.Fixity #if defined (GHCLIB_API_811) || defined (GHCLIB_API_810) import GHC.Hs-#else-import HsSyn+import RdrHsSyn #endif import DynFlags import Lexer import Outputable import ErrUtils-import RdrHsSyn #if defined (GHCLIB_API_808) import Bag #endif@@ -55,36 +55,56 @@ parseTests :: TestTree parseTests = testGroup "Parse tests" [- testCase "Expression" $ do- let flags = defaultDynFlags fakeSettings fakeLlvmConfig+ testCase "Module" $ chkParseResult report flags $- parseExpr "unfoldr $ listToMaybe . concatMap reads . tails" flags- , testCase "Import" $ do- let flags = defaultDynFlags fakeSettings fakeLlvmConfig+ parseModule (unlines+ [ "module Foo (readMany) where"+ , "import Data.List"+ , "import Data.Maybe"+ , "readMany = unfoldr $ listToMaybe . concatMap reads . tails"+ ]) flags+ , testCase "Signature" $ chkParseResult report flags $+ parseSignature (unlines+ [ "signature Str where"+ , "data Str"+ , "empty :: Str"+ , "append :: Str -> Str -> Str"+ ]) flags+ , testCase "Import" $+ chkParseResult report flags $ parseImport "import qualified \"foo-lib\" Foo as Bar hiding ((<.>))" flags- , testCase "Declaration" $ do- let flags = defaultDynFlags fakeSettings fakeLlvmConfig+ , testCase "Statement" $ chkParseResult report flags $- parseDeclaration (- unlines [- "fact :: Int -> Int"- , "fact n = if n <= 1 then 1 else n * fact (n - 1)"- ]) flags+ parseStatement "Foo foo <- bar" flags+ , testCase "Backpack" $+ chkParseResult report flags $+ parseBackpack (unlines+ [ "unit main where"+ , " module Main where"+ , " main = putStrLn \"Hello world!\""+ ]) flags+ , testCase "Expression" $+ chkParseResult report flags $+ parseExpression "unfoldr $ listToMaybe . concatMap reads . tails" flags+ , testCase "Declaration" $+ chkParseResult report flags $+ parseDeclaration "fact n = if n <= 1 then 1 else n * fact (n - 1)" flags , testCase "File" $ do foo <- makeFile "Foo.hs" $ unlines- [ "module Foo (readMany) where"+ ["{-# LANGUAGE ScopedTypeVariables #-}"+ , "module Foo (readMany) where" , "import Data.List" , "import Data.Maybe" , "readMany = unfoldr $ listToMaybe . concatMap reads . tails" ] s <- readFile' foo- parsePragmasIntoDynFlags (defaultDynFlags fakeSettings fakeLlvmConfig) foo s >>= \case+ parsePragmasIntoDynFlags flags ([], []) foo s >>= \case Left msg -> assertFailure msg- Right flags ->- chkParseResult report flags $ parseFile foo (flags `gopt_set` Opt_KeepRawTokenStream) s+ Right flags -> chkParseResult report flags $ parseFile foo flags s ] where+ flags = unsafeGlobalDynFlags report flags msgs = concat [ showSDoc flags msg | msg <- pprErrMsgBagWithLoc msgs ] fixityTests :: TestTree@@ -92,8 +112,12 @@ [ testCase "Expression" $ do let flags = defaultDynFlags fakeSettings fakeLlvmConfig- case parseExpr "1 + 2 * 3" flags of+ case parseExpression "1 + 2 * 3" flags of+#if defined (GHCLIB_API_811) || defined (GHCLIB_API_810) POk s e ->+#else+ POk _ e ->+#endif #if defined (GHCLIB_API_811) || defined (GHCLIB_API_810) case unP (runECP_P e >>= \e -> return e) s :: ParseResult (LHsExpr GhcPs) of POk _ e ->