Skip to content

Commit cd60fc2

Browse files
authored
dhall-toml: Add support for Prelude.Map.Type (#2549)
Fixes #2509 This adds `dhall-to-toml` and `toml-to-dhall` support for the `Prelude.Map.Type` type which is translated to and from TOML tables.
1 parent c8fbc37 commit cd60fc2

12 files changed

+93
-35
lines changed

dhall-toml/src/Dhall/DhallToToml.hs

Lines changed: 48 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
{-# LANGUAGE ApplicativeDo #-}
2-
{-# LANGUAGE PatternSynonyms #-}
3-
{-# LANGUAGE RecordWildCards #-}
1+
{-# LANGUAGE ApplicativeDo #-}
2+
{-# LANGUAGE PatternSynonyms #-}
3+
{-# LANGUAGE RecordWildCards #-}
4+
{-# LANGUAGE OverloadedLists #-}
5+
{-# LANGUAGE OverloadedStrings #-}
6+
{-# LANGUAGE ViewPatterns #-}
47

58
{-| This module exports the `dhallToToml` function for translating a
69
Dhall syntax tree to a TOML syntax tree (`TOML`) for the @tomland@
@@ -81,6 +84,11 @@
8184
> [r.nested]
8285
> c = 3
8386
87+
… and @Prelude.Map.Type@ also translates to a TOML table:
88+
89+
> $ dhall-to-toml <<< '[ { mapKey = "foo", mapValue = 1 } ]'
90+
> foo = 1
91+
8492
Dhall unions translate to the wrapped value, or a string if the alternative is empty:
8593
8694
> $ dhall-to-toml <<< '{ u = < A | B >.A }'
@@ -248,9 +256,21 @@ pattern UnionApp x <- Core.App (Core.Field (Core.Union _) _) x
248256
assertRecordLit
249257
:: Expr Void Void
250258
-> Either CompileError (Map Text (Core.RecordField Void Void))
251-
assertRecordLit (Core.RecordLit r) = Right r
252-
assertRecordLit (UnionApp x) = assertRecordLit x
253-
assertRecordLit e = Left $ NotARecord e
259+
assertRecordLit (Core.RecordLit r) =
260+
Right r
261+
assertRecordLit (UnionApp x) =
262+
assertRecordLit x
263+
assertRecordLit (Core.ListLit _ expressions)
264+
| Just keyValues <- traverse toKeyValue (toList expressions) =
265+
Right (Map.fromList keyValues)
266+
where
267+
toKeyValue
268+
(Core.RecordLit [ ("mapKey", Core.recordFieldValue -> Core.TextLit (Core.Chunks [] key)), ("mapValue", value) ]) =
269+
Just (key, value)
270+
toKeyValue _ =
271+
Nothing
272+
assertRecordLit e =
273+
Left (NotARecord e)
254274

255275
toTomlTable :: Map Text (Core.RecordField Void Void) -> Either CompileError TOML
256276
toTomlTable r = foldM (toTomlRecordFold []) (mempty :: TOML) (Map.toList r)
@@ -292,24 +312,6 @@ toToml toml pieces expr = case expr of
292312
Core.App Core.None _ ->
293313
return toml
294314

295-
Core.ListLit _ a -> case toList a of
296-
-- TODO: unions need to be handled here as well, it's a bit tricky
297-
-- because they also have to be probed for being a "simple"
298-
-- array of table
299-
union@(UnionApp (Core.RecordLit _)) : unions -> do
300-
insertTables (union :| unions)
301-
302-
record@(Core.RecordLit _) : records -> do
303-
insertTables (record :| records)
304-
305-
-- inline array
306-
expressions -> do
307-
anyValues <- mapM toAnyValue expressions
308-
309-
case AnyValue.toMArray anyValues of
310-
Left _ -> Left (HeterogeneousArray expr)
311-
Right array -> insertPrim array
312-
313315
Core.RecordLit r -> do
314316
let (inline, nested) =
315317
Map.partition (isInline . Core.recordFieldValue) r
@@ -331,6 +333,28 @@ toToml toml pieces expr = case expr of
331333
else do
332334
newPairs <- foldM (toTomlRecordFold []) mempty pairs
333335
return (TOML.insertTable key newPairs toml)
336+
337+
_ | Right keyValues <- assertRecordLit expr ->
338+
toToml toml pieces (Core.RecordLit keyValues)
339+
340+
Core.ListLit _ a -> case toList a of
341+
-- TODO: unions need to be handled here as well, it's a bit tricky
342+
-- because they also have to be probed for being a "simple"
343+
-- array of table
344+
union@(UnionApp (Core.RecordLit _)) : unions -> do
345+
insertTables (union :| unions)
346+
347+
record@(Core.RecordLit _) : records -> do
348+
insertTables (record :| records)
349+
350+
-- inline array
351+
expressions -> do
352+
anyValues <- mapM toAnyValue expressions
353+
354+
case AnyValue.toMArray anyValues of
355+
Left _ -> Left (HeterogeneousArray expr)
356+
Right array -> insertPrim array
357+
334358
_ ->
335359
Left (Unsupported expr)
336360
where

dhall-toml/src/Dhall/TomlToDhall.hs

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
{-# LANGUAGE ApplicativeDo #-}
2-
{-# LANGUAGE GADTs #-}
3-
{-# LANGUAGE OverloadedLists #-}
4-
{-# LANGUAGE RecordWildCards #-}
1+
{-# LANGUAGE ApplicativeDo #-}
2+
{-# LANGUAGE BlockArguments #-}
3+
{-# LANGUAGE GADTs #-}
4+
{-# LANGUAGE OverloadedLists #-}
5+
{-# LANGUAGE OverloadedStrings #-}
6+
{-# LANGUAGE RecordWildCards #-}
7+
{-# LANGUAGE ViewPatterns #-}
58

69
{-| This module exports the `tomlToDhall` function for translating a
710
TOML syntax tree from @tomland@ to a Dhall syntax tree. For now,
@@ -250,13 +253,6 @@ objectToDhall type_ object = case (type_, object) of
250253
[] -> Left (Incompatible type_ object)
251254
x : _ -> Right x
252255

253-
(Core.App Core.List t, Array []) ->
254-
Right (Core.ListLit (Just t) [])
255-
256-
(Core.App Core.List t, Array elements) -> do
257-
expressions <- mapM (objectToDhall t) elements
258-
return (Core.ListLit Nothing (Seq.fromList expressions))
259-
260256
(Core.Record record, Table table) -> do
261257
let process key fieldType
262258
| Just nestedObject <- HashMap.lookup (Piece key) table =
@@ -272,6 +268,30 @@ objectToDhall type_ object = case (type_, object) of
272268

273269
return (Core.RecordLit (fmap Core.makeRecordField expressions))
274270

271+
(Core.App Core.List (Core.Record [("mapKey", Core.recordFieldValue -> Core.Text), ("mapValue", Core.recordFieldValue -> valueType)]), Table table) -> do
272+
hashMap <- traverse (objectToDhall valueType) table
273+
274+
let expressions = Seq.fromList do
275+
(Piece key, value) <- HashMap.toList hashMap
276+
277+
let newKey =
278+
Core.makeRecordField (Core.TextLit (Core.Chunks [] key))
279+
280+
let newValue = Core.makeRecordField value
281+
282+
pure (Core.RecordLit [("mapKey", newKey), ("mapValue", newValue)])
283+
284+
let listType = if Seq.null expressions then Just type_ else Nothing
285+
286+
return (Core.ListLit listType expressions)
287+
288+
(Core.App Core.List t, Array []) ->
289+
Right (Core.ListLit (Just t) [])
290+
291+
(Core.App Core.List t, Array elements) -> do
292+
expressions <- mapM (objectToDhall t) elements
293+
return (Core.ListLit Nothing (Seq.fromList expressions))
294+
275295
(_, Prim (AnyValue value)) ->
276296
valueToDhall type_ value
277297

dhall-toml/tasty/Main.hs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ testTree =
4646
, "./tasty/data/union-typed"
4747
, "./tasty/data/union-nested"
4848
, "./tasty/data/optional"
49+
, "./tasty/data/map-simple"
50+
, "./tasty/data/map-complex"
51+
, "./tasty/data/map-empty"
4952
]
5053
tomlToDhallTests = map testTomlToDhall
5154
[ "./tasty/data/empty"
@@ -59,6 +62,8 @@ testTree =
5962
, "./tasty/data/union-empty"
6063
, "./tasty/data/union-typed"
6164
, "./tasty/data/optional"
65+
, "./tasty/data/map-simple"
66+
, "./tasty/data/map-empty"
6267
]
6368

6469
testDhallToToml :: String -> TestTree
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{ foo : List { mapKey : Text, mapValue : { baz : Natural } } }
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{ foo = [ { mapValue = { baz = 1 }, mapKey = "bar" } ] }
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[foo.bar]
2+
baz = 1
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
List { mapKey : Text, mapValue : Natural }

dhall-toml/tasty/data/map-empty.dhall

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[] : List { mapKey : Text, mapValue : Natural }

dhall-toml/tasty/data/map-empty.toml

Whitespace-only changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
List { mapKey : Text, mapValue : Natural }

0 commit comments

Comments
 (0)