packages feed

dhall-json 1.1.0 → 1.2.0

raw patch · 4 files changed

+510/−59 lines, 4 filesdep +insert-ordered-containersdep +optparse-applicativedep −optparse-genericdep ~dhallPVP ok

version bump matches the API change (PVP)

Dependencies added: insert-ordered-containers, optparse-applicative

Dependencies removed: optparse-generic

Dependency ranges changed: dhall

API changes (from Hackage documentation)

+ Dhall.JSON: Conversion :: Text -> Text -> Conversion
+ Dhall.JSON: NoConversion :: Conversion
+ Dhall.JSON: [mapKey] :: Conversion -> Text
+ Dhall.JSON: [mapValue] :: Conversion -> Text
+ Dhall.JSON: convertToHomogeneousMaps :: Conversion -> Expr s X -> Expr s X
+ Dhall.JSON: data Conversion
+ Dhall.JSON: parseConversion :: Parser Conversion
- Dhall.JSON: codeToValue :: Text -> Text -> IO Value
+ Dhall.JSON: codeToValue :: Conversion -> Text -> Text -> IO Value

Files

dhall-json.cabal view
@@ -1,5 +1,5 @@ Name: dhall-json-Version: 1.1.0+Version: 1.2.0 Cabal-Version: >=1.8.0.2 Build-Type: Simple Tested-With: GHC == 7.10.2, GHC == 8.0.1@@ -29,11 +29,13 @@ Library     Hs-Source-Dirs: src     Build-Depends:-        base                 >= 4.8.0.0  && < 5   ,-        aeson                >= 1.0.0.0  && < 1.4 ,-        dhall                >= 1.11.0   && < 1.14,-        text                 >= 0.11.1.0 && < 1.3 ,-        unordered-containers                < 0.3+        base                      >= 4.8.0.0  && < 5   ,+        aeson                     >= 1.0.0.0  && < 1.4 ,+        dhall                     >= 1.14.0   && < 1.15,+        insert-ordered-containers                < 1.14,+        optparse-applicative      >= 0.14.0.0 && < 0.15,+        text                      >= 0.11.1.0 && < 1.3 ,+        unordered-containers                     < 0.3     Exposed-Modules: Dhall.JSON     GHC-Options: -Wall @@ -41,13 +43,13 @@     Hs-Source-Dirs: dhall-to-json     Main-Is: Main.hs     Build-Depends:-        base                                  ,-        aeson                                 ,-        aeson-pretty                    < 0.9 ,-        bytestring                      < 0.11,-        dhall                                 ,-        dhall-json                            ,-        optparse-generic >= 1.1.1    && < 1.4 ,+        base                       ,+        aeson                      ,+        aeson-pretty         < 0.9 ,+        bytestring           < 0.11,+        dhall                      ,+        dhall-json                 ,+        optparse-applicative       ,         text     GHC-Options: -Wall @@ -59,7 +61,7 @@         bytestring                      < 0.11,         dhall                                 ,         dhall-json                            ,-        optparse-generic >= 1.1.1    && < 1.4 ,+        optparse-applicative                  ,         yaml             >= 0.5.0    && < 0.9 ,         text     GHC-Options: -Wall
dhall-to-json/Main.hs view
@@ -1,14 +1,13 @@-{-# LANGUAGE DataKinds         #-}-{-# LANGUAGE DeriveAnyClass    #-}-{-# LANGUAGE DeriveGeneric     #-}-{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ApplicativeDo     #-} {-# LANGUAGE RecordWildCards   #-}-{-# LANGUAGE TypeOperators     #-}+{-# LANGUAGE OverloadedStrings #-}  module Main where  import Control.Exception (SomeException)-import Options.Generic (Generic, ParseRecord, type (<?>))+import Data.Monoid ((<>))+import Dhall.JSON (Conversion)+import Options.Applicative (Parser, ParserInfo)  import qualified Control.Exception import qualified Data.Aeson@@ -19,32 +18,72 @@ import qualified Dhall import qualified Dhall.JSON import qualified GHC.IO.Encoding-import qualified Options.Generic+import qualified Options.Applicative import qualified System.Exit import qualified System.IO  data Options = Options-    { explain  :: Bool <?> "Explain error messages in detail"-    , pretty   :: Bool <?> "Pretty print generated JSON"-    , omitNull :: Bool <?> "Omit record fields that are null"-    } deriving (Generic, ParseRecord)+    { explain    :: Bool+    , pretty     :: Bool+    , omitNull   :: Bool+    , conversion :: Conversion+    } +parseOptions :: Parser Options+parseOptions = Options.Applicative.helper <*> do+    explain    <- parseExplain+    pretty     <- parsePretty+    omitNull   <- parseOmitNull+    conversion <- Dhall.JSON.parseConversion+    return (Options {..})+  where+    parseExplain =+        Options.Applicative.switch+            (   Options.Applicative.long "explain"+            <>  Options.Applicative.help "Explain error messages in detail"+            )++    parsePretty =+        Options.Applicative.switch+            (   Options.Applicative.long "pretty"+            <>  Options.Applicative.help "Pretty print generated JSON"+            )++    parseOmitNull =+        Options.Applicative.switch+            (   Options.Applicative.long "omitNull"+            <>  Options.Applicative.help "Omit record fields that are null"+            )++parserInfo :: ParserInfo Options+parserInfo =+    Options.Applicative.info+        parseOptions+        (   Options.Applicative.fullDesc+        <>  Options.Applicative.progDesc "Compile Dhall to JSON"+        )+ main :: IO ()-main = handle $ do+main = do     GHC.IO.Encoding.setLocaleEncoding GHC.IO.Encoding.utf8-    Options {..} <- Options.Generic.getRecord "Compile Dhall to JSON" -    let encode       = if   Options.Generic.unHelpful pretty-                       then Data.Aeson.Encode.Pretty.encodePretty-                       else Data.Aeson.encode-        explaining   = if Options.Generic.unHelpful explain  then Dhall.detailed      else id-        omittingNull = if Options.Generic.unHelpful omitNull then Dhall.JSON.omitNull else id+    Options {..} <- Options.Applicative.execParser parserInfo -    stdin <- Data.Text.IO.getContents+    handle $ do+        let encode =+                if pretty+                then Data.Aeson.Encode.Pretty.encodePretty+                else Data.Aeson.encode -    json  <- omittingNull <$> explaining (Dhall.JSON.codeToValue "(stdin)" stdin)+        let explaining = if explain then Dhall.detailed else id -    Data.ByteString.Char8.putStrLn $ Data.ByteString.Lazy.toStrict $ encode json +        let omittingNull = if omitNull then Dhall.JSON.omitNull else id++        stdin <- Data.Text.IO.getContents++        json <- omittingNull <$> explaining (Dhall.JSON.codeToValue conversion "(stdin)" stdin)++        Data.ByteString.Char8.putStrLn $ Data.ByteString.Lazy.toStrict $ encode json  handle :: IO a -> IO a handle = Control.Exception.handle handler
dhall-to-yaml/Main.hs view
@@ -1,14 +1,13 @@-{-# LANGUAGE DataKinds         #-}-{-# LANGUAGE DeriveAnyClass    #-}-{-# LANGUAGE DeriveGeneric     #-}+{-# LANGUAGE ApplicativeDo     #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards   #-}-{-# LANGUAGE TypeOperators     #-}  module Main where  import Control.Exception (SomeException)-import Options.Generic (Generic, ParseRecord, type (<?>))+import Data.Monoid ((<>))+import Dhall.JSON (Conversion)+import Options.Applicative (Parser, ParserInfo)  import qualified Control.Exception import qualified Data.ByteString@@ -17,28 +16,59 @@ import qualified Dhall import qualified Dhall.JSON import qualified GHC.IO.Encoding-import qualified Options.Generic+import qualified Options.Applicative import qualified System.Exit import qualified System.IO  data Options = Options-    { explain  :: Bool <?> "Explain error messages in detail"-    , omitNull :: Bool <?> "Omit record fields that are null"-    } deriving (Generic, ParseRecord)+    { explain    :: Bool+    , omitNull   :: Bool+    , conversion :: Conversion+    } +parseOptions :: Parser Options+parseOptions = Options.Applicative.helper <*> do+    explain    <- parseExplain+    omitNull   <- parseOmitNull+    conversion <- Dhall.JSON.parseConversion+    return (Options {..})+  where+    parseExplain =+        Options.Applicative.switch+            (   Options.Applicative.long "explain"+            <>  Options.Applicative.help "Explain error messages in detail"+            )++    parseOmitNull =+        Options.Applicative.switch+            (   Options.Applicative.long "omitNull"+            <>  Options.Applicative.help "Omit record fields that are null"+            )++parserInfo :: ParserInfo Options+parserInfo =+    Options.Applicative.info+        parseOptions+        (   Options.Applicative.fullDesc+        <>  Options.Applicative.progDesc "Compile Dhall to YAML"+        )+ main :: IO ()-main = handle $ do+main = do     GHC.IO.Encoding.setLocaleEncoding GHC.IO.Encoding.utf8-    Options{..} <- Options.Generic.getRecord "Compile Dhall to JSON" -    let explaining   = if Options.Generic.unHelpful explain  then Dhall.detailed      else id-        omittingNull = if Options.Generic.unHelpful omitNull then Dhall.JSON.omitNull else id+    Options {..} <- Options.Applicative.execParser parserInfo -    stdin <- Data.Text.IO.getContents+    handle $ do+        let explaining = if explain then Dhall.detailed else id -    json  <- omittingNull <$> explaining (Dhall.JSON.codeToValue "(stdin)" stdin)+        let omittingNull = if omitNull then Dhall.JSON.omitNull else id -    Data.ByteString.putStr $ Data.Yaml.encode json +        stdin <- Data.Text.IO.getContents++        json <- omittingNull <$> explaining (Dhall.JSON.codeToValue conversion "(stdin)" stdin)++        Data.ByteString.putStr $ Data.Yaml.encode json   handle :: IO a -> IO a handle = Control.Exception.handle handler
src/Dhall/JSON.hs view
@@ -1,5 +1,7 @@+{-# LANGUAGE ApplicativeDo      #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE OverloadedStrings  #-}+{-# LANGUAGE RecordWildCards    #-}  {-| This library only exports a single `dhallToJSON` function for translating a     Dhall syntax tree to a JSON syntax tree (i.e. a `Value`) for the @aeson@@@ -100,21 +102,30 @@     -- * Dhall to JSON       dhallToJSON     , omitNull+    , Conversion(..)+    , convertToHomogeneousMaps+    , parseConversion     , codeToValue      -- * Exceptions     , CompileError(..)     ) where +import Control.Applicative (empty, (<|>))+import Control.Monad (guard) import Control.Exception (Exception, throwIO) import Data.Aeson (Value(..)) import Data.Monoid ((<>))+import Data.Text.Lazy (Text) import Data.Typeable (Typeable) import Dhall.Core (Expr) import Dhall.TypeCheck (X)+import Options.Applicative (Parser)  import qualified Data.Aeson+import qualified Data.Foldable import qualified Data.HashMap.Strict+import qualified Data.HashMap.Strict.InsOrd import qualified Data.Text import qualified Data.Text.Lazy import qualified Data.Text.Lazy.Builder@@ -122,6 +133,7 @@ import qualified Dhall.Import import qualified Dhall.Parser import qualified Dhall.TypeCheck+import qualified Options.Applicative  {-| This is the exception type for errors that might arise when translating     Dhall to JSON@@ -197,6 +209,369 @@ omitNull Null =     Null +{-| Specify whether or not to convert association lists of type+    @List { mapKey: Text, mapValue : v }@ to records+-}+data Conversion+    = NoConversion+    | Conversion { mapKey :: Text, mapValue :: Text }++{-| Convert association lists to homogeneous maps++    This converts an association list of the form:++    > [ { mapKey = k0, mapValue = v0 }, { mapKey = k1, mapValue = v1 } ]++    ... to a record of the form:++    > { k0 = v0, k1 = v1 }+-}+convertToHomogeneousMaps :: Conversion -> Expr s X -> Expr s X+convertToHomogeneousMaps NoConversion e0 = e0+convertToHomogeneousMaps (Conversion {..}) e0 = loop (Dhall.Core.normalize e0)+  where+    loop e = case e of+        Dhall.Core.Const a ->+            Dhall.Core.Const a++        Dhall.Core.Var v ->+            Dhall.Core.Var v++        Dhall.Core.Lam a b c ->+            Dhall.Core.Lam a b' c'+          where+            b' = loop b+            c' = loop c++        Dhall.Core.Pi a b c ->+            Dhall.Core.Pi a b' c'+          where+            b' = loop b+            c' = loop c++        Dhall.Core.App a b ->+            Dhall.Core.App a' b'+          where+            a' = loop a+            b' = loop b++        Dhall.Core.Let a b c d ->+            Dhall.Core.Let a b' c' d'+          where+            b' = fmap loop b+            c' =      loop c+            d' =      loop d++        Dhall.Core.Annot a b ->+            Dhall.Core.Annot a' b'+          where+            a' = loop a+            b' = loop b++        Dhall.Core.Bool ->+            Dhall.Core.Bool++        Dhall.Core.BoolLit a ->+            Dhall.Core.BoolLit a++        Dhall.Core.BoolAnd a b ->+            Dhall.Core.BoolAnd a' b'+          where+            a' = loop a+            b' = loop b++        Dhall.Core.BoolOr a b ->+            Dhall.Core.BoolOr a' b'+          where+            a' = loop a+            b' = loop b++        Dhall.Core.BoolEQ a b ->+            Dhall.Core.BoolEQ a' b'+          where+            a' = loop a+            b' = loop b++        Dhall.Core.BoolNE a b ->+            Dhall.Core.BoolNE a' b'+          where+            a' = loop a+            b' = loop b++        Dhall.Core.BoolIf a b c ->+            Dhall.Core.BoolIf a' b' c'+          where+            a' = loop a+            b' = loop b+            c' = loop c++        Dhall.Core.Natural ->+            Dhall.Core.Natural++        Dhall.Core.NaturalLit a ->+            Dhall.Core.NaturalLit a++        Dhall.Core.NaturalFold ->+            Dhall.Core.NaturalFold++        Dhall.Core.NaturalBuild ->+            Dhall.Core.NaturalBuild++        Dhall.Core.NaturalIsZero ->+            Dhall.Core.NaturalIsZero++        Dhall.Core.NaturalEven ->+            Dhall.Core.NaturalEven++        Dhall.Core.NaturalOdd ->+            Dhall.Core.NaturalOdd++        Dhall.Core.NaturalToInteger ->+            Dhall.Core.NaturalToInteger++        Dhall.Core.NaturalShow ->+            Dhall.Core.NaturalShow++        Dhall.Core.NaturalPlus a b ->+            Dhall.Core.NaturalPlus a' b'+          where+            a' = loop a+            b' = loop b++        Dhall.Core.NaturalTimes a b ->+            Dhall.Core.NaturalTimes a' b'+          where+            a' = loop a+            b' = loop b++        Dhall.Core.Integer ->+            Dhall.Core.Integer++        Dhall.Core.IntegerLit a ->+            Dhall.Core.IntegerLit a++        Dhall.Core.IntegerShow ->+            Dhall.Core.IntegerShow++        Dhall.Core.Double ->+            Dhall.Core.Double++        Dhall.Core.DoubleLit a ->+            Dhall.Core.DoubleLit a++        Dhall.Core.DoubleShow ->+            Dhall.Core.DoubleShow++        Dhall.Core.Text ->+            Dhall.Core.Text++        Dhall.Core.TextLit (Dhall.Core.Chunks a b) ->+            Dhall.Core.TextLit (Dhall.Core.Chunks a' b)+          where+            a' = fmap (fmap loop) a++        Dhall.Core.TextAppend a b ->+            Dhall.Core.TextAppend a' b'+          where+            a' = loop a+            b' = loop b++        Dhall.Core.List ->+            Dhall.Core.List++        Dhall.Core.ListLit a b ->+            case transform of+                Just c  -> c+                Nothing -> Dhall.Core.ListLit a' b'+          where+            elements = Data.Foldable.toList b++            toKeyValue :: Expr s X -> Maybe (Text, Expr s X)+            toKeyValue (Dhall.Core.RecordLit m) = do+                guard (Data.HashMap.Strict.InsOrd.size m == 2)++                key   <- Data.HashMap.Strict.InsOrd.lookup mapKey   m+                value <- Data.HashMap.Strict.InsOrd.lookup mapValue m++                keyText <- case key of+                    Dhall.Core.TextLit (Dhall.Core.Chunks [] keyText) ->+                        return keyText++                    _ ->+                        empty++                return (Data.Text.Lazy.Builder.toLazyText keyText, value)+            toKeyValue _ = do+                empty++            transform =+                case elements of+                    [] ->+                        case a of+                            Just (Dhall.Core.Record m) -> do+                                guard (Data.HashMap.Strict.InsOrd.size m == 2)+                                guard (Data.HashMap.Strict.InsOrd.member mapKey   m)+                                guard (Data.HashMap.Strict.InsOrd.member mapValue m)+                                return (Dhall.Core.RecordLit Data.HashMap.Strict.InsOrd.empty)+                            _ -> do+                                empty++                    _  -> do+                        keyValues <- traverse toKeyValue elements++                        let recordLiteral =+                                Data.HashMap.Strict.InsOrd.fromList keyValues++                        return (Dhall.Core.RecordLit recordLiteral)++            a' = fmap loop a+            b' = fmap loop b++        Dhall.Core.ListAppend a b ->+            Dhall.Core.ListAppend a' b'+          where+            a' = loop a+            b' = loop b++        Dhall.Core.ListBuild ->+            Dhall.Core.ListBuild++        Dhall.Core.ListFold ->+            Dhall.Core.ListFold++        Dhall.Core.ListLength ->+            Dhall.Core.ListLength++        Dhall.Core.ListHead ->+            Dhall.Core.ListHead++        Dhall.Core.ListLast ->+            Dhall.Core.ListLast++        Dhall.Core.ListIndexed ->+            Dhall.Core.ListIndexed++        Dhall.Core.ListReverse ->+            Dhall.Core.ListReverse++        Dhall.Core.Optional ->+            Dhall.Core.Optional++        Dhall.Core.OptionalLit a b ->+            Dhall.Core.OptionalLit a' b'+          where+            a' =      loop a+            b' = fmap loop b++        Dhall.Core.OptionalFold ->+            Dhall.Core.OptionalFold++        Dhall.Core.OptionalBuild ->+            Dhall.Core.OptionalBuild++        Dhall.Core.Record a ->+            Dhall.Core.Record a'+          where+            a' = fmap loop a++        Dhall.Core.RecordLit a ->+            Dhall.Core.RecordLit a'+          where+            a' = fmap loop a++        Dhall.Core.Union a ->+            Dhall.Core.Union a'+          where+            a' = fmap loop a++        Dhall.Core.UnionLit a b c ->+            Dhall.Core.UnionLit a b' c'+          where+            b' =      loop b+            c' = fmap loop c++        Dhall.Core.Combine a b ->+            Dhall.Core.Combine a' b'+          where+            a' = loop a+            b' = loop b++        Dhall.Core.CombineTypes a b ->+            Dhall.Core.CombineTypes a' b'+          where+            a' = loop a+            b' = loop b++        Dhall.Core.Prefer a b ->+            Dhall.Core.Prefer a' b'+          where+            a' = loop a+            b' = loop b++        Dhall.Core.Merge a b c ->+            Dhall.Core.Merge a' b' c'+          where+            a' =      loop a+            b' =      loop b+            c' = fmap loop c++        Dhall.Core.Constructors a ->+            Dhall.Core.Constructors a'+          where+            a' = loop a++        Dhall.Core.Field a b ->+            Dhall.Core.Field a' b+          where+            a' = loop a++        Dhall.Core.Project a b ->+            Dhall.Core.Project a' b+          where+            a' = loop a++        Dhall.Core.Note a b ->+            Dhall.Core.Note a b'+          where+            b' = loop b++        Dhall.Core.Embed a ->+            Dhall.Core.Embed a++parseConversion :: Parser Conversion+parseConversion =+        conversion+    <|> noConversion+  where+    conversion = do+        mapKey   <- parseKeyField+        mapValue <- parseValueField+        return (Conversion {..})+      where+        parseKeyField =+            Options.Applicative.strOption+                (   Options.Applicative.long "key"+                <>  Options.Applicative.help "Reserved key field name for association lists"+                <>  Options.Applicative.value "mapKey"+                <>  Options.Applicative.showDefaultWith Data.Text.Lazy.unpack+                )++        parseValueField =+            Options.Applicative.strOption+                (   Options.Applicative.long "value"+                <>  Options.Applicative.help "Reserved value field name for association lists"+                <>  Options.Applicative.value "mapValue"+                <>  Options.Applicative.showDefaultWith Data.Text.Lazy.unpack+                )++    noConversion =+        Options.Applicative.flag'+            NoConversion+            (   Options.Applicative.long "noMaps"+            <>  Options.Applicative.help "Disable conversion of association lists to homogeneous maps"+            )++ {-| Convert a piece of Text carrying a Dhall inscription to an equivalent JSON Value  >>> :set -XOverloadedStrings@@ -205,19 +580,24 @@ >>> Object (fromList [("a",Number 1.0)]) -} codeToValue-  :: Data.Text.Text  -- ^ Describe the input for the sake of error location.+  :: Conversion+  -> Data.Text.Text  -- ^ Describe the input for the sake of error location.   -> Data.Text.Text  -- ^ Input text.   -> IO Value-codeToValue name code = do-    expr <- case Dhall.Parser.exprFromText (Data.Text.unpack name) (Data.Text.Lazy.fromStrict code) of-      Left  err  -> Control.Exception.throwIO err-      Right expr -> return expr+codeToValue conversion name code = do+    parsedExpression <- case Dhall.Parser.exprFromText (Data.Text.unpack name) (Data.Text.Lazy.fromStrict code) of+      Left  err              -> Control.Exception.throwIO err+      Right parsedExpression -> return parsedExpression -    expr' <- Dhall.Import.load expr-    case Dhall.TypeCheck.typeOf expr' of+    resolvedExpression <- Dhall.Import.load parsedExpression++    case Dhall.TypeCheck.typeOf resolvedExpression  of       Left  err -> Control.Exception.throwIO err       Right _   -> return () -    case dhallToJSON expr' of+    let convertedExpression =+            convertToHomogeneousMaps conversion resolvedExpression++    case dhallToJSON convertedExpression of       Left  err  -> Control.Exception.throwIO err       Right json -> return json