PyF 0.7.1.0 → 0.7.2.0
raw patch · 7 files changed
+171/−15 lines, 7 filesdep ~basedep ~haskell-src-metadep ~template-haskellPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: base, haskell-src-meta, template-haskell
API changes (from Hackage documentation)
+ PyF.Internal.Extensions: thExtToMetaExt :: Extension -> Maybe Extension
- PyF.Internal.PythonSyntax: parseGenericFormatString :: (Char, Char) -> Parser [Item]
+ PyF.Internal.PythonSyntax: parseGenericFormatString :: [Extension] -> (Char, Char) -> Parser [Item]
- PyF.Internal.PythonSyntax: parsePythonFormatString :: Parser [Item]
+ PyF.Internal.PythonSyntax: parsePythonFormatString :: [Extension] -> Parser [Item]
Files
- ChangeLog.md +4/−0
- PyF.cabal +5/−3
- src/PyF/Internal/Extensions.hs +128/−0
- src/PyF/Internal/PythonSyntax.hs +16/−10
- src/PyF/Internal/QQ.hs +7/−2
- test/Spec.hs +8/−0
- test/SpecFail.hs +3/−0
ChangeLog.md view
@@ -1,5 +1,9 @@ # Revision history for PyF +## 0.7.2.0 -- 2019-02-27++- Fixed: PyF now uses the same haskell extensions as the one used by the current haskell file to parse sub expressions.+ ## 0.7.1.0 -- 2019-02-11 - Fixed: PyF was wrongly ignoring everything located after a non-doubled closing delimiter.
PyF.cabal view
@@ -1,5 +1,5 @@ name: PyF-version: 0.7.1.0+version: 0.7.2.0 synopsis: Quasiquotations for a python like interpolated string formater description: Quasiquotations for a python like interpolated string formater. license: BSD3@@ -16,6 +16,7 @@ PyF PyF.Internal.PythonSyntax PyF.Internal.QQ+ PyF.Internal.Extensions PyF.Formatters build-depends: base >= 4.9 && < 5.0@@ -26,8 +27,9 @@ , text >= 0.11 && < 1.3 , containers >= 0.5 && < 0.7 - --- , haskell-src-meta+ -- haskell-src-meta < 0.8.2 does not correctly handle TypeApplication+ -- That's not critical for PyF, so you can ignore this bound if needed+ , haskell-src-meta >= 0.8.2 , haskell-src-exts hs-source-dirs: src ghc-options: -Wall
+ src/PyF/Internal/Extensions.hs view
@@ -0,0 +1,128 @@+module PyF.Internal.Extensions+ ( thExtToMetaExt+ ) where++import qualified Language.Haskell.Exts.Extension as Exts+import qualified Language.Haskell.TH as TH+++-- | Associate a template haskell extension to an haskell-src-ext extension+thExtToMetaExt :: TH.Extension -> Maybe Exts.Extension+thExtToMetaExt e = Exts.EnableExtension <$> case e of+ TH.Cpp -> Just Exts.CPP -- LOL, different case ;)+ TH.OverlappingInstances -> Just Exts.OverlappingInstances+ TH.UndecidableInstances -> Just Exts.UndecidableInstances+ TH.IncoherentInstances -> Just Exts.IncoherentInstances+ TH.MonomorphismRestriction -> Just Exts.MonomorphismRestriction+ TH.MonoPatBinds -> Just Exts.MonoPatBinds+ TH.MonoLocalBinds -> Just Exts.MonoLocalBinds+ TH.RelaxedPolyRec -> Just Exts.RelaxedPolyRec+ TH.ExtendedDefaultRules -> Just Exts.ExtendedDefaultRules+ TH.ForeignFunctionInterface -> Just Exts.ForeignFunctionInterface+ TH.UnliftedFFITypes -> Just Exts.UnliftedFFITypes+ TH.InterruptibleFFI -> Just Exts.InterruptibleFFI+ TH.CApiFFI -> Just Exts.CApiFFI+ TH.GHCForeignImportPrim -> Just Exts.GHCForeignImportPrim+ TH.JavaScriptFFI -> Just Exts.JavaScriptFFI+ TH.ParallelArrays -> Just Exts.ParallelArrays+ TH.Arrows -> Just Exts.Arrows+ TH.TemplateHaskell -> Just Exts.TemplateHaskell+ TH.QuasiQuotes -> Just Exts.QuasiQuotes+ TH.ImplicitParams -> Just Exts.ImplicitParams+ TH.ImplicitPrelude -> Just Exts.ImplicitPrelude+ TH.ScopedTypeVariables -> Just Exts.ScopedTypeVariables+ TH.UnboxedSums -> Just Exts.UnboxedSums+ TH.BangPatterns -> Just Exts.BangPatterns+ TH.TypeFamilies -> Just Exts.TypeFamilies+ TH.TypeFamilyDependencies -> Just Exts.TypeFamilyDependencies+ TH.OverloadedStrings -> Just Exts.OverloadedStrings+ TH.DisambiguateRecordFields -> Just Exts.DisambiguateRecordFields+ TH.RecordWildCards -> Just Exts.RecordWildCards+ TH.RecordPuns -> Just Exts.RecordPuns+ TH.ViewPatterns -> Just Exts.ViewPatterns+ TH.GADTs -> Just Exts.GADTs+ TH.NPlusKPatterns -> Just Exts.NPlusKPatterns+ TH.DoAndIfThenElse -> Just Exts.DoAndIfThenElse+ TH.RebindableSyntax -> Just Exts.RebindableSyntax+ TH.ConstraintKinds -> Just Exts.ConstraintKinds+ TH.PolyKinds -> Just Exts.PolyKinds+ TH.DataKinds -> Just Exts.DataKinds+ TH.InstanceSigs -> Just Exts.InstanceSigs+ TH.StandaloneDeriving -> Just Exts.StandaloneDeriving+ TH.DeriveDataTypeable -> Just Exts.DeriveDataTypeable+ TH.DeriveFunctor -> Just Exts.DeriveFunctor+ TH.DeriveTraversable -> Just Exts.DeriveTraversable+ TH.DeriveFoldable -> Just Exts.DeriveFoldable+ TH.DeriveGeneric -> Just Exts.DeriveGeneric+ TH.DefaultSignatures -> Just Exts.DefaultSignatures+ TH.DeriveAnyClass -> Just Exts.DeriveAnyClass+ TH.DerivingStrategies -> Just Exts.DerivingStrategies+ TH.TypeSynonymInstances -> Just Exts.TypeSynonymInstances+ TH.FlexibleContexts -> Just Exts.FlexibleContexts+ TH.FlexibleInstances -> Just Exts.FlexibleInstances+ TH.ConstrainedClassMethods -> Just Exts.ConstrainedClassMethods+ TH.MultiParamTypeClasses -> Just Exts.MultiParamTypeClasses+ TH.FunctionalDependencies -> Just Exts.FunctionalDependencies+ TH.UnicodeSyntax -> Just Exts.UnicodeSyntax+ TH.ExistentialQuantification -> Just Exts.ExistentialQuantification+ TH.MagicHash -> Just Exts.MagicHash+ TH.EmptyDataDecls -> Just Exts.EmptyDataDecls+ TH.KindSignatures -> Just Exts.KindSignatures+ TH.RoleAnnotations -> Just Exts.RoleAnnotations+ TH.ParallelListComp -> Just Exts.ParallelListComp+ TH.TransformListComp -> Just Exts.TransformListComp+ TH.GeneralizedNewtypeDeriving -> Just Exts.GeneralizedNewtypeDeriving+ TH.RecursiveDo -> Just Exts.RecursiveDo+ TH.PostfixOperators -> Just Exts.PostfixOperators+ TH.TupleSections -> Just Exts.TupleSections+ TH.PatternGuards -> Just Exts.PatternGuards+ TH.LiberalTypeSynonyms -> Just Exts.LiberalTypeSynonyms+ TH.RankNTypes -> Just Exts.RankNTypes+ TH.ImpredicativeTypes -> Just Exts.ImpredicativeTypes+ TH.TypeOperators -> Just Exts.TypeOperators+ TH.ExplicitNamespaces -> Just Exts.ExplicitNamespaces+ TH.PackageImports -> Just Exts.PackageImports+ TH.ExplicitForAll -> Just Exts.ExplicitForAll+ TH.DatatypeContexts -> Just Exts.DatatypeContexts+ TH.NondecreasingIndentation -> Just Exts.NondecreasingIndentation+ TH.LambdaCase -> Just Exts.LambdaCase+ TH.MultiWayIf -> Just Exts.MultiWayIf+ TH.BinaryLiterals -> Just Exts.BinaryLiterals+ TH.OverloadedLabels -> Just Exts.OverloadedLabels+ TH.EmptyCase -> Just Exts.EmptyCase+ TH.PatternSynonyms -> Just Exts.PatternSynonyms+ TH.PartialTypeSignatures -> Just Exts.PartialTypeSignatures+ TH.NamedWildCards -> Just Exts.NamedWildCards+ TH.TypeApplications -> Just Exts.TypeApplications++ -- Theses extensions have no associated extensions in haskell-src-exts+ TH.UndecidableSuperClasses -> Nothing+ TH.TemplateHaskellQuotes -> Nothing+ TH.AllowAmbiguousTypes -> Nothing+ TH.UnboxedTuples -> Nothing+ TH.TypeInType -> Nothing+ TH.OverloadedLists -> Nothing+ TH.NumDecimals -> Nothing+ TH.GADTSyntax -> Nothing+ TH.BlockArguments -> Nothing+ TH.ApplicativeDo -> Nothing+ TH.AutoDeriveTypeable -> Nothing+ TH.DeriveLift -> Nothing+ TH.DerivingVia -> Nothing+ TH.NullaryTypeClasses -> Nothing+ TH.MonadComprehensions -> Nothing+ TH.AlternativeLayoutRule -> Nothing+ TH.AlternativeLayoutRuleTransitional -> Nothing+ TH.RelaxedLayout -> Nothing+ TH.TraditionalRecordSyntax -> Nothing+ TH.NegativeLiterals -> Nothing+ TH.HexFloatLiterals -> Nothing+ TH.DuplicateRecordFields -> Nothing+ TH.StaticPointers -> Nothing+ TH.Strict -> Nothing+ TH.StrictData -> Nothing+ TH.MonadFailDesugaring -> Nothing+ TH.EmptyDataDeriving -> Nothing+ TH.NumericUnderscores -> Nothing+ TH.QuantifiedConstraints -> Nothing+ TH.StarIsType -> Nothing
src/PyF/Internal/PythonSyntax.hs view
@@ -35,6 +35,7 @@ import qualified Data.Set as Set -- For fancyFailure import qualified Language.Haskell.Meta.Syntax.Translate as SyntaxTranslate import qualified Language.Haskell.Exts.Parser as ParseExp+import qualified Language.Haskell.Exts.Extension as ParseExtension import qualified Language.Haskell.Exts.SrcLoc as SrcLoc import PyF.Formatters @@ -80,11 +81,11 @@ (FixedF (Precision 2) NormalForm Minus) Nothing))] -}-parsePythonFormatString :: Parser [Item]-parsePythonFormatString = parseGenericFormatString ('{', '}')+parsePythonFormatString :: [ParseExtension.Extension] -> Parser [Item]+parsePythonFormatString exts = parseGenericFormatString exts ('{', '}') -parseGenericFormatString :: (Char, Char) -> Parser [Item]-parseGenericFormatString delimiters = many ((Raw "\\" <$ "\\\\") <|> (Raw "" <$ "\\\n") <|> rawString delimiters <|> escapedParenthesis delimiters <|> replacementField delimiters) <* eof+parseGenericFormatString :: [ParseExtension.Extension] -> (Char, Char) -> Parser [Item]+parseGenericFormatString exts delimiters = many ((Raw "\\" <$ "\\\\") <|> (Raw "" <$ "\\\n") <|> rawString delimiters <|> escapedParenthesis delimiters <|> replacementField exts delimiters) <* eof rawString :: (Char, Char) -> Parser Item rawString (openingChar,closingChar) = Raw . escapeChars <$> some (noneOf ([openingChar, closingChar]))@@ -103,10 +104,10 @@ [] -> "" ((c, xs):_) -> c : escapeChars xs -replacementField :: (Char, Char) -> Parser Item-replacementField (charOpening, charClosing) = do+replacementField :: [ParseExtension.Extension] -> (Char, Char) -> Parser Item+replacementField exts (charOpening, charClosing) = do _ <- char charOpening- expr <- evalExpr (many (noneOf (charClosing:":" :: [Char])))+ expr <- evalExpr exts (many (noneOf (charClosing:":" :: [Char]))) fmt <- optional $ do _ <- char ':' format_spec@@ -178,11 +179,16 @@ fancyFailure (Set.singleton (ErrorFail err)) -evalExpr :: Parser String -> Parser Exp-evalExpr exprParser = do+evalExpr :: [ParseExtension.Extension] -> Parser String -> Parser Exp+evalExpr exts exprParser = do offset <- getOffset s <- exprParser- case SyntaxTranslate.toExp <$> ParseExp.parseExp s of++ -- Setup the parser using the provided list of extensions+ -- Which are detected by template haskell at splice position+ let parseMode = ParseExp.defaultParseMode { ParseExp.extensions = exts }++ case SyntaxTranslate.toExp <$> ParseExp.parseExpWithMode parseMode s of ParseExp.ParseOk expr -> pure expr ParseExp.ParseFailed (SrcLoc.SrcLoc _name' line col) err -> do let
src/PyF/Internal/QQ.hs view
@@ -34,9 +34,11 @@ import qualified Data.Word as Word import qualified Data.Int as Int import Numeric.Natural-+import qualified Data.Maybe import PyF.Internal.PythonSyntax+import PyF.Internal.Extensions+ import qualified PyF.Formatters as Formatters import PyF.Formatters (AnyAlign(..)) import Data.Proxy@@ -47,7 +49,10 @@ toExp:: (Char, Char) -> String -> Q Exp toExp delimiters s = do filename <- loc_filename <$> location- case parse (parseGenericFormatString delimiters) filename s of++ exts <- Data.Maybe.mapMaybe thExtToMetaExt <$> extsEnabled++ case parse (parseGenericFormatString exts delimiters) filename s of Left err -> do err' <- overrideErrorForFile filename err fail (errorBundlePretty err')
test/Spec.hs view
@@ -3,6 +3,8 @@ {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE ExtendedDefaultRules #-} {-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE BinaryLiterals #-} import Test.Hspec @@ -214,3 +216,9 @@ - b \ |] `shouldBe` "\\\n- a\n- b\n"++ describe "language extensions" $ do+ it "parses @Int" $ do+ [f|hello {show @Int 10}|] `shouldBe` "hello 10"+ it "parses BinaryLiterals" $ do+ [f|hello {0b1111}|] `shouldBe` "hello 15"
test/SpecFail.hs view
@@ -175,3 +175,6 @@ describe "non-doubled delimiters" $ do failCompile "hello } world" failCompile "hello { world"++ describe "fail is not enabled extension" $ do+ failCompile "{0b0001}"