packages feed

record-dot-preprocessor 0.2.7 → 0.2.8

raw patch · 8 files changed

+88/−15 lines, 8 filesdep ~ghc

Dependency ranges changed: ghc

Files

CHANGES.txt view
@@ -1,5 +1,8 @@ Changelog for record-dot-preprocessor +0.2.8, released 2021-02-21+    Support GHC 9.0+    #38, make the preprocessor avoid quasi quotes 0.2.7, released 2020-10-02     #29, deal with records containing type families in field types 0.2.6, released 2020-08-12
LICENSE view
@@ -1,4 +1,4 @@-Copyright Neil Mitchell 2018-2020.+Copyright Neil Mitchell 2018-2021.  Licensed under either of: 
README.md view
@@ -1,4 +1,4 @@-# record-dot-preprocessor [![Hackage version](https://img.shields.io/hackage/v/record-dot-preprocessor.svg?label=Hackage)](https://hackage.haskell.org/package/record-dot-preprocessor) [![Stackage version](https://www.stackage.org/package/record-dot-preprocessor/badge/nightly?label=Stackage)](https://www.stackage.org/package/record-dot-preprocessor) [![Build status](https://img.shields.io/travis/ndmitchell/record-dot-preprocessor/master.svg?label=Build)](https://travis-ci.org/ndmitchell/record-dot-preprocessor)+# record-dot-preprocessor [![Hackage version](https://img.shields.io/hackage/v/record-dot-preprocessor.svg?label=Hackage)](https://hackage.haskell.org/package/record-dot-preprocessor) [![Stackage version](https://www.stackage.org/package/record-dot-preprocessor/badge/nightly?label=Stackage)](https://www.stackage.org/package/record-dot-preprocessor) [![Build status](https://img.shields.io/github/workflow/status/ndmitchell/record-dot-preprocessor/ci.svg)](https://github.com/ndmitchell/record-dot-preprocessor/actions)  In almost every programming language `a.b` will get the `b` field from the `a` data type, and many different data types can have a `b` field. The reason this feature is ubiquitous is because it's _useful_. This feature has been [proposed for Haskell](https://github.com/ghc-proposals/ghc-proposals/pull/282) as `RecordDotSyntax`. The `record-dot-preprocessor` brings this feature to Haskell today. Some examples: @@ -20,9 +20,9 @@ First install `record-dot-preprocessor` with either `stack install record-dot-preprocessor` or `cabal update && cabal install record-dot-preprocessor`. Then at the top of the file add:  * Either: `{-# OPTIONS_GHC -F -pgmF=record-dot-preprocessor #-}` for the preprocessor.-* Or: `{-# OPTIONS_GHC -fplugin=RecordDotPreprocessor #-}` and `{-# LANGUAGE DuplicateRecordFields, TypeApplications, FlexibleContexts, DataKinds, MultiParamTypeClasses, TypeSynonymInstances, FlexibleInstances #-}` for the GHC plugin.+* Or: `{-# OPTIONS_GHC -fplugin=RecordDotPreprocessor #-}` and `{-# LANGUAGE DuplicateRecordFields, TypeApplications, FlexibleContexts, DataKinds, MultiParamTypeClasses, TypeSynonymInstances, FlexibleInstances, UndecidableInstances, GADTs #-}` for the GHC plugin. -The GHC plugin only runs on GHC 8.6 or higher, [doesn't work on Windows](https://gitlab.haskell.org/ghc/ghc/issues/16405) and has much better error messages. In contrast, the preprocessor runs everywhere and has more features.+The GHC plugin only runs on GHC 8.6 or higher, [has some issues on Windows](https://gitlab.haskell.org/ghc/ghc/issues/16405) and has much better error messages. In contrast, the preprocessor runs everywhere and has more features.  You must make sure that the `OPTIONS_GHC` is applied both to the file _where your records are defined_, and _where the record syntax is used_. The resulting program will require the [`record-hasfield` library](https://hackage.haskell.org/package/record-hasfield). 
examples/Both.hs view
@@ -180,7 +180,7 @@ -- --------------------------------------------------------------------- -- Deal with kind signatures -data UserF (f :: * -> *) = UserF { userf_name :: String }+data UserF (f :: T.Type -> T.Type) = UserF { userf_name :: String }  test7 :: IO () test7 = do
plugin/Compat.hs view
@@ -5,7 +5,14 @@ module Compat(module Compat) where  import GHC+#if __GLASGOW_HASKELL__ < 900 import BasicTypes+import TcEvidence+#else+import GHC.Types.Basic+import GHC.Unit.Types+import GHC.Parser.Annotation+#endif #if __GLASGOW_HASKELL__ < 810 import HsSyn as Compat #else@@ -26,11 +33,32 @@ noE = noExtField #endif +realSrcLoc :: SrcLoc -> Maybe RealSrcLoc+#if __GLASGOW_HASKELL__ < 811+realSrcLoc (RealSrcLoc x) = Just x+#else+realSrcLoc (RealSrcLoc x _) = Just x+#endif+realSrcLoc _ = Nothing++#if __GLASGOW_HASKELL__ >= 900+hsLTyVarBndrToType :: LHsTyVarBndr flag (GhcPass p) -> LHsType (GhcPass p)+hsLTyVarBndrToType x = noL $ HsTyVar noE NotPromoted $ noL $ hsLTyVarName x+#endif+ --------------------------------------------------------------------- -- COMMON SIGNATURES +#if __GLASGOW_HASKELL__ < 811+type Module = HsModule GhcPs+#else+type Module = HsModule+#endif+ mkAppType :: LHsExpr GhcPs -> LHsType GhcPs -> LHsExpr GhcPs mkTypeAnn :: LHsExpr GhcPs -> LHsType GhcPs -> LHsExpr GhcPs+mkFunTy :: LHsType GhcPs -> LHsType GhcPs -> LHsType GhcPs+newFunBind :: Located RdrName -> MatchGroup GhcPs (LHsExpr GhcPs) -> HsBind GhcPs  #if __GLASGOW_HASKELL__ < 807 @@ -46,7 +74,21 @@  #endif +#if __GLASGOW_HASKELL__ < 811 +-- GHC 8.10 and below+mkFunTy a b = noL $ HsFunTy noE a b+newFunBind a b = FunBind noE a b WpHole []++#else++-- GHC 9.0+mkFunTy a b = noL $ HsFunTy noE (HsUnrestrictedArrow NormalSyntax) a b+newFunBind a b = FunBind noE a b []++#endif++ #if __GLASGOW_HASKELL__ < 807  -- GHC 8.6@@ -76,9 +118,16 @@ qualifiedImplicitImport x = noL $ ImportDecl noE NoSourceText (noL x) Nothing False False     True {- qualified -} True {- implicit -} Nothing Nothing -#else+#elif __GLASGOW_HASKELL__ < 811 +-- GHC 8.10 qualifiedImplicitImport x = noL $ ImportDecl noE NoSourceText (noL x) Nothing False False+    QualifiedPost {- qualified -} True {- implicit -} Nothing Nothing++#else++-- GHC 9.0+qualifiedImplicitImport x = noL $ ImportDecl noE NoSourceText (noL x) Nothing NotBoot False     QualifiedPost {- qualified -} True {- implicit -} Nothing Nothing  #endif
plugin/RecordDotPreprocessor.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE RecordWildCards, ViewPatterns, NamedFieldPuns, OverloadedStrings #-} {- HLINT ignore "Use camelCase" -} @@ -8,13 +9,22 @@ import Data.List.Extra import Data.Tuple.Extra import Compat-import Bag import qualified GHC+#if __GLASGOW_HASKELL__ < 900+import Bag import qualified GhcPlugins as GHC import qualified PrelNames as GHC import SrcLoc-import TcEvidence+#else+import GHC.Data.Bag+import qualified GHC.Driver.Plugins as GHC+import qualified GHC.Driver.Types as GHC+import qualified GHC.Builtin.Names as GHC+import qualified GHC.Plugins as GHC+import GHC.Types.SrcLoc+#endif + --------------------------------------------------------------------- -- PLUGIN WRAPPER @@ -43,7 +53,7 @@ var_dot = GHC.mkRdrUnqual $ GHC.mkVarOcc "."  -onModule :: HsModule GhcPs -> HsModule GhcPs+onModule :: Module -> Module onModule x = x { hsmodImports = onImports $ hsmodImports x                , hsmodDecls = concatMap onDecl $ hsmodDecls x                }@@ -71,7 +81,7 @@         typ = noL $ makeEqQualTy field (unLoc . typ')          has :: LHsBindLR GhcPs GhcPs-        has = noL $ FunBind noE (noL var_hasField) (mg1 eqn) WpHole []+        has = noL $ newFunBind (noL var_hasField) (mg1 eqn)             where                 eqn = Match                     { m_ext     = noE@@ -88,7 +98,7 @@                 update = RecordUpd noE (noL $ GHC.HsVar noE $ noL vR)                     [noL $ HsRecField (noL (Unambiguous noE (rdrNameFieldOcc selector))) (noL $ GHC.HsVar noE $ noL vX) False]                 get = mkApp-                    (mkParen $ mkTypeAnn (noL $ GHC.HsVar noE $ rdrNameFieldOcc selector) (noL $ HsFunTy noE (noL record) (noL field)))+                    (mkParen $ mkTypeAnn (noL $ GHC.HsVar noE $ rdrNameFieldOcc selector) (mkFunTy (noL record) (noL field)))                     (noL $ GHC.HsVar noE $ noL vR)          mg1 :: Match GhcPs (LHsExpr GhcPs) -> MatchGroup GhcPs (LHsExpr GhcPs)@@ -224,7 +234,7 @@  -- | Are the end of a and the start of b next to each other, no white space adjacentBy :: Int -> Located a -> Located b -> Bool-adjacentBy i (L (srcSpanEnd -> RealSrcLoc a) _) (L (srcSpanStart -> RealSrcLoc b) _) =+adjacentBy i (L (realSrcLoc . srcSpanEnd -> Just a) _) (L (realSrcLoc . srcSpanStart -> Just b) _) =     srcLocFile a == srcLocFile b &&     srcLocLine a == srcLocLine b &&     srcLocCol a + i == srcLocCol b
preprocessor/Edit.hs view
@@ -54,6 +54,14 @@ isCtor (Item x) = any isUpper $ take 1 $ lexeme x isCtor _ = False +-- | This test does not check that the @quoter@ name is a qualified identifier,+-- instead relying on lack of whitespace in the opener and existence of a paired+-- closed (@|]@)+isQuasiQuotation :: PL -> Bool+isQuasiQuotation (Paren (L "[") inner@(Item qq : Item (L "|") : _) (L "]"))+    | Item close@(L "|") <- last inner = null (whitespace qq) && null (whitespace close)+isQuasiQuotation _ = False+ isField (x:_) = x == '_' || isLower x isField _ = False @@ -95,6 +103,9 @@   editLoop :: [PL] -> [PL]++--  Leave quasiquotations alone+editLoop (p : ps) | isQuasiQuotation p = p : editLoop ps  -- | a.b.c ==> getField @'(b,c) a editLoop (NoW e : (spanFields -> (fields@(_:_), whitespace, rest)))
record-dot-preprocessor.cabal view
@@ -1,14 +1,14 @@ cabal-version:      >= 1.18 build-type:         Simple name:               record-dot-preprocessor-version:            0.2.7+version:            0.2.8 license:            BSD3 x-license:          BSD-3-Clause OR Apache-2.0 license-file:       LICENSE category:           Development author:             Neil Mitchell <ndmitchell@gmail.com> maintainer:         Neil Mitchell <ndmitchell@gmail.com>-copyright:          Neil Mitchell 2018-2020+copyright:          Neil Mitchell 2018-2021 synopsis:           Preprocessor to allow record.field syntax description:     In almost every programming language @a.b@ will get the @b@ field from the @a@ data type, and many different data types can have a @b@ field.@@ -19,7 +19,7 @@ extra-doc-files:     README.md     CHANGES.txt-tested-with:        GHC==8.10, GHC==8.8, GHC==8.6, GHC==8.4+tested-with:        GHC==9.0, GHC==8.10, GHC==8.8, GHC==8.6 extra-source-files:     examples/Both.hs     examples/Both2.hs