Skip to content

Commit 552cffb

Browse files
committed
dhall-json: implement --type mode for encoding type as json
1 parent 5e50f14 commit 552cffb

File tree

4 files changed

+63
-10
lines changed

4 files changed

+63
-10
lines changed

dhall-json/dhall-to-json/Main.hs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import Control.Applicative (optional, (<|>))
88
import Control.Exception (SomeException)
99
import Data.Aeson (Value)
1010
import Data.Version (showVersion)
11-
import Dhall.JSON (Conversion, SpecialDoubleMode (..))
11+
import Dhall.JSON (Conversion, SpecialDoubleMode (..), EncodeTarget)
1212
import Options.Applicative (Parser, ParserInfo)
1313

1414
import qualified Control.Exception
@@ -31,6 +31,7 @@ data Options
3131
, pretty :: Bool
3232
, omission :: Value -> Value
3333
, conversion :: Conversion
34+
, encodeTarget :: EncodeTarget
3435
, approximateSpecialDoubles :: Bool
3536
, file :: Maybe FilePath
3637
, output :: Maybe FilePath
@@ -44,6 +45,7 @@ parseOptions =
4445
<*> parsePretty
4546
<*> Dhall.JSON.parsePreservationAndOmission
4647
<*> Dhall.JSON.parseConversion
48+
<*> Dhall.JSON.parseEncodeTarget
4749
<*> parseApproximateSpecialDoubles
4850
<*> optional parseFile
4951
<*> optional parseOutput
@@ -150,7 +152,7 @@ main = do
150152
Nothing -> Text.IO.getContents
151153
Just path -> Text.IO.readFile path
152154

153-
json <- omission <$> explaining (Dhall.JSON.codeToValue conversion specialDoubleMode file text)
155+
json <- omission <$> explaining (Dhall.JSON.codeToValue conversion specialDoubleMode encodeTarget file text)
154156

155157
let write =
156158
case output of

dhall-json/src/Dhall/JSON.hs

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,8 @@ module Dhall.JSON (
201201
, omitNull
202202
, omitEmpty
203203
, parsePreservationAndOmission
204+
, EncodeTarget(..)
205+
, parseEncodeTarget
204206
, Conversion(..)
205207
, defaultConversion
206208
, convertToHomogeneousMaps
@@ -592,6 +594,32 @@ dhallToJSON e0 = loop (Core.alphaNormalize (Core.normalize e0))
592594
outer _ = Left (Unsupported e)
593595

594596
outer value
597+
598+
-- Schemas
599+
Core.Bool -> return (Aeson.String "Bool")
600+
Core.Natural -> return (Aeson.String "Natural")
601+
Core.Bytes -> return (Aeson.String "Bytes")
602+
Core.Integer -> return (Aeson.String "Integer")
603+
Core.Double -> return (Aeson.String "Double")
604+
Core.Text -> return (Aeson.String "Text")
605+
Core.Date -> return (Aeson.String "Date")
606+
Core.Time -> return (Aeson.String "Time")
607+
Core.TimeZone -> return (Aeson.String "TimeZone")
608+
Core.App Core.List t -> do
609+
t' <- loop t
610+
return $ Aeson.Object [("type", Aeson.String "List"), ("element", t')]
611+
Core.App Core.Optional t -> do
612+
t' <- loop t
613+
return $ Aeson.Object [("type", Aeson.String "Optional"), ("element", t')]
614+
Core.Record a -> do
615+
a' <- traverse (loop . Core.recordFieldValue) a
616+
return $ Aeson.Object [("type", Aeson.String "Record"), ("fields", Aeson.toJSON (Dhall.Map.toMap a')) ]
617+
Core.Union a -> do
618+
let go Nothing = return $ Aeson.Object []
619+
go (Just t) = loop t
620+
a' <- traverse go a
621+
return $ Aeson.Object [("type", Aeson.String "Union"), ("choices", Aeson.toJSON (Dhall.Map.toMap a')) ]
622+
595623
_ -> Left (Unsupported e)
596624

597625
getContents :: Expr s Void -> Maybe (Text, Maybe (Expr s Void))
@@ -692,6 +720,22 @@ parseNullPreservation =
692720
parsePreservationAndOmission :: Parser (Value -> Value)
693721
parsePreservationAndOmission = parseOmission <|> parseNullPreservation
694722

723+
724+
{-| Specify whether to encode data or type as JSON (default data) -}
725+
data EncodeTarget
726+
= EncodeData
727+
| EncodeType
728+
729+
parseEncodeTarget :: Parser EncodeTarget
730+
parseEncodeTarget =
731+
Options.Applicative.flag'
732+
EncodeType
733+
( Options.Applicative.long "type"
734+
<> Options.Applicative.help "Encode the type of the input expression instead of the value"
735+
)
736+
<|> pure EncodeData
737+
738+
695739
{-| Specify whether or not to convert association lists of type
696740
@List { mapKey: Text, mapValue : v }@ to records
697741
-}
@@ -1198,24 +1242,26 @@ handleSpecialDoubles specialDoubleMode =
11981242
codeToValue
11991243
:: Conversion
12001244
-> SpecialDoubleMode
1245+
-> EncodeTarget
12011246
-> Maybe FilePath -- ^ The source file path. If no path is given, imports
12021247
-- are resolved relative to the current directory.
12031248
-> Text -- ^ Input text.
12041249
-> IO Value
1205-
codeToValue conversion specialDoubleMode mFilePath code = do
1206-
fmap snd (codeToHeaderAndValue conversion specialDoubleMode mFilePath code)
1250+
codeToValue conversion specialDoubleMode encodeTarget mFilePath code = do
1251+
fmap snd (codeToHeaderAndValue conversion specialDoubleMode encodeTarget mFilePath code)
12071252

12081253
{-| This is like `codeToValue`, except also returning a `Header` that is a
12091254
valid YAML comment derived from the original Dhall code's `Header`
12101255
-}
12111256
codeToHeaderAndValue
12121257
:: Conversion
12131258
-> SpecialDoubleMode
1259+
-> EncodeTarget
12141260
-> Maybe FilePath -- ^ The source file path. If no path is given, imports
12151261
-- are resolved relative to the current directory.
12161262
-> Text -- ^ Input text.
12171263
-> IO (Header, Value)
1218-
codeToHeaderAndValue conversion specialDoubleMode mFilePath code = do
1264+
codeToHeaderAndValue conversion specialDoubleMode encodeTarget mFilePath code = do
12191265
(Header header, parsedExpression) <- Core.throws (Dhall.Parser.exprAndHeaderFromText (fromMaybe "(input)" mFilePath) code)
12201266

12211267
let adapt line =
@@ -1231,10 +1277,15 @@ codeToHeaderAndValue conversion specialDoubleMode mFilePath code = do
12311277

12321278
resolvedExpression <- Dhall.Import.loadRelativeTo rootDirectory UseSemanticCache parsedExpression
12331279

1234-
_ <- Core.throws (Dhall.TypeCheck.typeOf resolvedExpression)
1280+
t <- Core.throws (Dhall.TypeCheck.typeOf resolvedExpression)
1281+
1282+
let resolvedExpression' =
1283+
case encodeTarget of
1284+
EncodeData -> resolvedExpression
1285+
EncodeType -> t
12351286

12361287
let convertedExpression =
1237-
convertToHomogeneousMaps conversion resolvedExpression
1288+
convertToHomogeneousMaps conversion resolvedExpression'
12381289

12391290
specialDoubleExpression <- Core.throws (handleSpecialDoubles specialDoubleMode convertedExpression)
12401291

dhall-json/src/Dhall/JSON/Yaml.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ dhallToYaml Options{..} mFilePath code = do
9090

9191
let adapt (header, value) = (header, omission value)
9292

93-
(Header comment, json) <- adapt <$> explaining (Dhall.JSON.codeToHeaderAndValue conversion UseYAMLEncoding mFilePath code)
93+
(Header comment, json) <- adapt <$> explaining (Dhall.JSON.codeToHeaderAndValue conversion UseYAMLEncoding Dhall.JSON.EncodeData mFilePath code)
9494

9595
let suffix
9696
| preserveHeader = Data.Text.Encoding.encodeUtf8 comment

dhall-yaml/src/Dhall/Yaml.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ module Dhall.Yaml
1212
import Data.ByteString (ByteString)
1313
import Data.ByteString.Lazy (toStrict)
1414
import Data.Text (Text)
15-
import Dhall.JSON (SpecialDoubleMode (..), codeToHeaderAndValue)
15+
import Dhall.JSON (SpecialDoubleMode (..), codeToHeaderAndValue, EncodeTarget(EncodeData))
1616
import Dhall.JSON.Yaml (Options (..))
1717
import Dhall.Parser (Header (..))
1818

@@ -44,7 +44,7 @@ dhallToYaml Options{..} mFilePath code = do
4444

4545
let adapt (header, value) = (header, omission value)
4646

47-
(Header comment, json) <- adapt <$> explaining (codeToHeaderAndValue conversion UseYAMLEncoding mFilePath code)
47+
(Header comment, json) <- adapt <$> explaining (codeToHeaderAndValue conversion UseYAMLEncoding EncodeData mFilePath code)
4848

4949
let suffix
5050
| preserveHeader = Data.Text.Encoding.encodeUtf8 comment

0 commit comments

Comments
 (0)