packages feed

hedn 0.2.0.1 → 0.3.0.0

raw patch · 11 files changed

+122/−71 lines, 11 filesdep ~basedep ~megaparsecPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base, megaparsec

API changes (from Hackage documentation)

+ Data.EDN.Class.Parser: parserError :: String -> Parser a
- Data.EDN: decodeText :: (FromEDN a, Monad m) => String -> Text -> m a
+ Data.EDN: decodeText :: FromEDN a => String -> Text -> Either String a
- Data.EDN: fromEDN :: (FromEDN a, Monad m) => TaggedValue -> m a
+ Data.EDN: fromEDN :: FromEDN a => TaggedValue -> Either String a
- Data.EDN: parseText :: Monad m => String -> Text -> m TaggedValue
+ Data.EDN: parseText :: String -> Text -> Either String TaggedValue
- Data.EDN.AST.Parser: parseText :: Monad m => String -> Text -> m TaggedValue
+ Data.EDN.AST.Parser: parseText :: String -> Text -> Either String TaggedValue
- Data.EDN.Class: fromEDN :: (FromEDN a, Monad m) => TaggedValue -> m a
+ Data.EDN.Class: fromEDN :: FromEDN a => TaggedValue -> Either String a
- Data.EDN.Class: mapGetP :: Monad m => TaggedValue -> (TaggedValue -> m a) -> EDNMap -> m a
+ Data.EDN.Class: mapGetP :: TaggedValue -> (TaggedValue -> Parser a) -> EDNMap -> Parser a
- Data.EDN.Class.Parser: parseM :: Monad m => (a -> Parser b) -> a -> m b
+ Data.EDN.Class.Parser: parseM :: MonadFail m => (a -> Parser b) -> a -> m b

Files

CHANGELOG.md view
@@ -3,6 +3,22 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [0.3.0.0] - 2019-09-29++### Added++- GHC 8.8 support++### Removed++- GHC 8.0 (Stackage LTS < 11) aren't supported due to upstream changes.+  You can still find a package version combination that'll work for you.++### Changed++- AST Parser `parseText` and EDN `decodeText` no longer rely on MonadFail+  and work in `Either String` instead.+ ## [0.2.0.1] - 2019-02-18  ### Changed@@ -61,6 +77,7 @@  - Use utf8-string parsing for unicode literals. +[0.3.0.0]: https://gitlab.com/dpwiz/hedn/tree/v0.3.0.0 [0.2.0.1]: https://gitlab.com/dpwiz/hedn/tree/v0.2.0.1 [0.2.0.0]: https://gitlab.com/dpwiz/hedn/tree/0.2.0.0 [0.1.9.1]: https://gitlab.com/dpwiz/hedn/tree/0.1.9.1
README.md view
@@ -38,8 +38,7 @@  main = do   edn <- Text.readFile "example.edn"-  value <- EDN.parseText "example.edn" edn-  print value+  either error print $ EDN.parseText "example.edn" edn ```  ```haskell
− example.edn
@@ -1,12 +0,0 @@-(#haskell/edn example/kitchensink ; tagged symbol- nil ; ugh..- \space ; character- "dynamic \"typing\"" ; string- {:numbers ; keyword-  [42 ; integer-   42.0 ; floating-  ] ; Vector-  :bools-  #{true false} ; Set- } ; Map-) ; List
hedn.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 3422cbfa0f065b597c1a18d7b765dcd6ddddbea6b62aceab67212f90c480a468+-- hash: 51ffeea2c9239d08c2d1e746437afcd12120103d004da5308747b27a697dcd05  name:           hedn-version:        0.2.0.1+version:        0.3.0.0 synopsis:       EDN parsing and encoding description:    A EDN parsing and encoding library.                 .@@ -18,13 +18,12 @@ copyright:      (c) 2019 Alexander Bondarenko license:        BSD3 license-file:   LICENSE-tested-with:    GHC==8.0.1, GHC==8.2.2, GHC==8.4.4, GHC==8.6.3+tested-with:    GHC==8.2.2, GHC==8.4.4, GHC==8.6.3, GHC==8.8.1 build-type:     Simple extra-source-files:     CHANGELOG.md     LICENSE     README.md-    example.edn  source-repository head   type: git@@ -48,7 +47,7 @@       lib   ghc-options: -Wall   build-depends:-      base >=4.9 && <4.13+      base >=4.9 && <4.14     , containers >=0.5.7 && <0.7     , deepseq >=1.4 && <2     , deriving-compat >=0.3.6 && <0.6@@ -77,9 +76,9 @@       tests   ghc-options: -Wall   build-depends:-      base >=4.9 && <4.13+      base >=4.9 && <4.14     , containers >=0.5.7 && <0.7-    , hedgehog >=0.6 && <0.7+    , hedgehog >=0.6 && <2     , hedn >=0.2 && <1     , megaparsec >=7.0 && <8     , text >=1.2 && <2
lib/Data/EDN.hs view
@@ -61,10 +61,10 @@  -- | Decode EDN document into AST and parse value using its 'FromEDN' instance. decodeText-  :: (FromEDN a, Monad m)+  :: (FromEDN a)   => String -- ^ Source name, for megaparsec error reports             -- e.g. @/path/to/file.edn@ or @<stdin>@   -> Text   -- ^ EDN document body-  -> m a+  -> Either String a decodeText sourceName source =   parseText sourceName source >>= fromEDN
lib/Data/EDN/AST/Parser.hs view
@@ -42,17 +42,13 @@ import qualified Data.EDN.AST.Types as EDN  parseText-  :: Monad m-  => String -- ^ Source name, for megaparsec error reports+  :: String -- ^ Source name, for megaparsec error reports             -- e.g. @/path/to/file.edn@ or @<stdin>@   -> Text   -- ^ EDN document body-  -> m TaggedValue-parseText sourceName source =-  case P.parse parseDoc sourceName source of-    Right tv ->-      pure tv-    Left err ->-      fail (P.errorBundlePretty err)+  -> Either String TaggedValue+parseText sourceName =+  either (Left . P.errorBundlePretty) Right .+    P.parse parseDoc sourceName  parseDoc :: Parser TaggedValue parseDoc = do
lib/Data/EDN/Class.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP                  #-} {-# LANGUAGE FlexibleInstances    #-} {-# LANGUAGE LambdaCase           #-} {-# LANGUAGE OverloadedLists      #-}@@ -39,7 +40,10 @@  import Control.Applicative ((<|>)) import Data.Map (Map)+#if MIN_VERSION_base(4,12,0)+#else import Data.Semigroup ((<>))+#endif import Data.Set (Set) import Data.Text (Text) import Data.Time (UTCTime, defaultTimeLocale, formatTime, parseTimeM)@@ -169,7 +173,7 @@       | tagNS' == tagNS && tag == tag' ->           p v       | otherwise ->-          fail . Text.unpack $ mconcat+          DP.parserError . Text.unpack $ mconcat             [ "unexpected tag. "             , "expecting: #"             , nsToText tagNS' tag'@@ -177,7 +181,7 @@             , nsToText tagNS tag             ]     _ ->-      fail "expected tagged value"+      DP.parserError "expected tagged value"  withNoTag :: (EDN.Value -> DP.Parser a) -> EDN.TaggedValue -> DP.Parser a withNoTag p tv =@@ -185,7 +189,7 @@     EDN.NoTag v ->       p v     EDN.Tagged tagNS tag _v ->-      fail $ "no tag expected, got #" <> Text.unpack (nsToText tagNS tag)+      DP.parserError $ "no tag expected, got #" <> Text.unpack (nsToText tagNS tag)  withNil :: DP.Parser a -> EDN.Value -> DP.Parser a withNil p = \case@@ -329,8 +333,8 @@   {-# INLINE parseEDNv #-}  -- | Apply appropriate parsers for a value to decode AST.-fromEDN :: (FromEDN a, Monad m) => EDN.TaggedValue -> m a-fromEDN = DP.parseM parseEDN+fromEDN :: (FromEDN a) => EDN.TaggedValue -> Either String a+fromEDN = DP.parseEither parseEDN  instance FromEDN EDN.TaggedValue where   parseEDN = pure@@ -339,7 +343,7 @@   parseEDNv = pure  instance FromEDN Void where-  parseEDN = fail "absurd"+  parseEDN _ = DP.parserError "unable to construct Void value"  instance FromEDN () where   parseEDNv = withNil $ pure ()@@ -387,7 +391,7 @@ vecGet ix v =   case v Vector.!? ix of     Nothing ->-      fail $ unwords+      DP.parserError $ unwords         [ "expected vector with at least"         , show (succ ix)         , "elements"@@ -407,17 +411,16 @@  -- | Get a value from 'EDN.EDNMap' and apply a parser to it mapGetP-  :: Monad m-  => EDN.TaggedValue          -- ^ Map key-  -> (EDN.TaggedValue -> m a) -- ^ Parser to apply to a value-  -> EDN.EDNMap               -- ^ Map with EDN keys and values-  -> m a+  :: EDN.TaggedValue                  -- ^ Map key+  -> (EDN.TaggedValue -> DP.Parser a) -- ^ Parser to apply to a value+  -> EDN.EDNMap                       -- ^ Map with EDN keys and values+  -> DP.Parser a mapGetP key inner m =   case Map.lookup key m of     Just tv ->       inner tv     Nothing ->-      fail . Text.unpack $ "key not found: " <> renderText key+      DP.parserError . Text.unpack $ "key not found: " <> renderText key  -- | Get a value from 'EDN.EDNMap' for a 'EDN.Keyword' key. mapGetKeyword :: FromEDN a => Text -> EDN.EDNMap -> DP.Parser a@@ -445,21 +448,21 @@     [a, b] ->       (,) <$> parseEDN a <*> parseEDN b     _ ->-      fail "vector of size 2 expected"+      DP.parserError "vector of size 2 expected"  instance (FromEDN a, FromEDN b, FromEDN c) => FromEDN (a, b, c) where   parseEDNv = withVec $ \case     [a, b, c] ->       (,,) <$> parseEDN a <*> parseEDN b <*> parseEDN c     _ ->-      fail "vector of size 3 expected"+      DP.parserError "vector of size 3 expected"  instance (FromEDN a, FromEDN b, FromEDN c, FromEDN d) => FromEDN (a, b, c, d) where   parseEDNv = withVec $ \case     [a, b, c, d] ->       (,,,) <$> parseEDN a <*> parseEDN b <*> parseEDN c <*> parseEDN d     _ ->-      fail "vector of size 3 expected"+      DP.parserError "vector of size 3 expected"  instance FromEDN UTCTime where   parseEDN tv = parseTaggedUTCTime tv <|> parseUntaggedUTCTime tv@@ -483,7 +486,7 @@       parseUUID t =         case UUID.fromText t of           Nothing ->-            fail "invalid UUID string"+            DP.parserError "invalid UUID string"           Just uuid ->             pure uuid 
lib/Data/EDN/Class/Parser.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE RankNTypes #-}  -- | Generic continuation-based parser@@ -10,6 +11,7 @@   , Failure   , Expected   , Label+  , parserError   ) where  import Control.Applicative (Alternative(..))@@ -20,7 +22,7 @@ import qualified Data.List as List  -- | Run a 'Parser' reporting to arbitrary 'Monad' with 'fail'.-parseM :: Monad m => (a -> Parser b) -> a -> m b+parseM :: Fail.MonadFail m => (a -> Parser b) -> a -> m b parseM p v = runParser (p v) (unexpected fail) pure  -- | Run a 'Parser' reporting to an 'Either'.@@ -95,9 +97,7 @@   {-# INLINE (<|>) #-}  instance Fail.MonadFail Parser where-  fail msg =-    Parser $ \kf _ks ->-      kf mempty msg+  fail = parserError   {-# INLINE fail #-}  instance Monad Parser where@@ -112,8 +112,11 @@   return = pure   {-# INLINE return #-} +#if MIN_VERSION_base(4,12,0)+#else   fail = Fail.fail   {-# INLINE fail #-}+#endif  instance MonadPlus Parser where   mzero = fail "mzero"@@ -131,3 +134,8 @@    mappend = (<>)   {-# INLINE mappend #-}++parserError :: String -> Parser a+parserError msg = Parser $ \kf _ks ->+  kf mempty msg+{-# INLINE parserError #-}
lib/Data/EDN/QQ.hs view
@@ -39,9 +39,13 @@ edn :: QuasiQuoter edn = ednQQ $ \str -> do   src <- fmap loc_filename qLocation-  tv <- parseText src (Text.pack str)-  lift tv +  case parseText src (Text.pack str) of+    Right val ->+      lift val+    Left err ->+      error err+ -- | Quasiquoter for untagged 'Value' wrapped in a List. -- -- @@@ -52,9 +56,16 @@ ednList :: QuasiQuoter ednList = ednQQ $ \str -> do   src <- fmap loc_filename qLocation-  NoTag tv <- parseText src $ "(" <> Text.pack str <> ")"-  lift tv+  let doc = "(" <> Text.pack str <> ")" +  case parseText src doc of+    Right (NoTag tv) ->+      lift tv+    Right Tagged{} ->+      error "unexpected tagged value"+    Left err ->+      error err+ -- | Quasiquoter for untagged 'Value' wrapped in a Vec. -- -- @@@ -65,9 +76,16 @@ ednVec :: QuasiQuoter ednVec = ednQQ $ \str -> do   src <- fmap loc_filename qLocation-  NoTag tv <- parseText src $ "[" <> Text.pack str <> "]"-  lift tv+  let doc = "[" <> Text.pack str <> "]" +  case parseText src doc of+    Right (NoTag tv) ->+      lift tv+    Right Tagged{} ->+      error "unexpected tagged value"+    Left err ->+      error err+ -- | Quasiquoter for untagged 'Value' wrapped in a Set. -- -- @@@ -78,9 +96,16 @@ ednSet :: QuasiQuoter ednSet = ednQQ $ \str -> do   src <- fmap loc_filename qLocation-  NoTag tv <- parseText src $ "#{" <> Text.pack str <> "}"-  lift tv+  let doc = "#{" <> Text.pack str <> "}" +  case parseText src doc of+    Right (NoTag tv) ->+      lift tv+    Right Tagged{} ->+      error "unexpected tagged value"+    Left err ->+      error err+ -- | Quasiquoter for untagged 'Value' wrapped in a Map. -- -- @@@ -91,9 +116,16 @@ ednMap :: QuasiQuoter ednMap = ednQQ $ \str -> do   src <- fmap loc_filename qLocation-  NoTag tv <- parseText src $ "{" <> Text.pack str <> "}"-  lift tv+  let doc = "{" <> Text.pack str <> "}" +  case parseText src doc of+    Right (NoTag tv) ->+      lift tv+    Right Tagged{} ->+      error "unexpected tagged value"+    Left err ->+      error err+ -- | Specializable QuasiQuoter for compile-time decoding. -- -- > ednPerson = fromEDN @Person@@ -104,8 +136,11 @@ fromEDN :: forall a. (Lift a, FromEDN a) => QuasiQuoter fromEDN = ednQQ $ \str -> do   src <- fmap loc_filename qLocation-  val <- decodeText src (Text.pack str) :: Q a-  lift val+  case decodeText src (Text.pack str) of+    Left err ->+      error err+    Right (val :: a) ->+      lift val  ednQQ :: (String -> Q Exp) -> QuasiQuoter ednQQ qexp = QuasiQuoter
tests/Data/EDN/AST/Test.hs view
@@ -30,14 +30,14 @@  prop_regr_empty_containers :: Property prop_regr_empty_containers = withTests 1 . property $ do-  emptyList <- EDN.parseText "<regr_empty_containers>" "( )"+  emptyList <- either fail pure $ EDN.parseText "<regr_empty_containers>" "( )"   emptyList === EDN.NoTag (EDN.List mempty) -  emptyVec <- EDN.parseText "<regr_empty_containers>" "[ ]"+  emptyVec <- either fail pure $ EDN.parseText "<regr_empty_containers>" "[ ]"   emptyVec === EDN.NoTag (EDN.Vec mempty) -  emptySet <- EDN.parseText "<regr_empty_containers>" "#{ }"+  emptySet <- either fail pure $ EDN.parseText "<regr_empty_containers>" "#{ }"   emptySet === EDN.NoTag (EDN.Set mempty) -  emptyMap <- EDN.parseText "<regr_empty_containers>" "{ }"+  emptyMap <- either fail pure $ EDN.parseText "<regr_empty_containers>" "{ }"   emptyMap === EDN.NoTag (EDN.Map mempty)
tests/Data/EDN/Class/Test.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-}@@ -34,7 +35,7 @@  codecExample :: forall a. (ToEDN a, FromEDN a, Eq a, Show a) => Text -> a -> Example codecExample encoded value = withTests 1 . property $ do-  tripping value toEDN (fromEDN :: EDN.TaggedValue -> Either String a)+  tripping value toEDN fromEDN   EDN.renderText (toEDN value) === encoded  -- * Atomic types@@ -136,7 +137,11 @@  prop_tagged_utctime :: Example prop_tagged_utctime = codecExample+#if MIN_VERSION_time(1,9,3)+  "#inst \"1985-04-12T23:20:50.52UTC\""+#else   "#inst \"1985-04-12T23:20:50.52Z\""+#endif   (parseTimeOrError     False     defaultTimeLocale@@ -179,5 +184,6 @@  prop_unexpected :: Property prop_unexpected = property $ do-  uuid <- EDN.decodeText "Test.hs:184" "#uuid \"f81d4fae-7dec-11d0-a765-00a0c91e6bf6\""+  uuid <- either fail pure $+    EDN.decodeText "Test.hs:184" "#uuid \"f81d4fae-7dec-11d0-a765-00a0c91e6bf6\""   uuid === (read "f81d4fae-7dec-11d0-a765-00a0c91e6bf6" :: UUID)