Skip to content

Commit b52fb4f

Browse files
authored
toml: fix bug converting nested union values (#2282)
Lists of records should be represented as TOML tables, the logic for this was only checking for `RecordLit`s. Howver, unions can also be translated to TOML tables. This commit adds a check for this case.
1 parent 46a8f56 commit b52fb4f

File tree

4 files changed

+34
-4
lines changed

4 files changed

+34
-4
lines changed

dhall-toml/src/Dhall/DhallToToml.hs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
{-# LANGUAGE PatternSynonyms #-}
2+
13
{-| This module exports the `dhallToToml` function for translating a
24
Dhall syntax tree to a TOML syntax tree (`TOML`) for the @tomland@
35
library.
@@ -223,8 +225,16 @@ dhallToToml e0 = do
223225
r <- assertRecordLit (Core.normalize e0)
224226
toTomlTable r
225227

228+
-- empty union alternative like < A | B >.A
229+
pattern UnionEmpty :: Text -> Expr s a
230+
pattern UnionEmpty x <- Core.Field (Core.Union _) (Core.FieldSelection _ x _)
231+
-- union alternative with type like < A : Natural | B>.A 1
232+
pattern UnionApp :: Expr s a -> Expr s a
233+
pattern UnionApp x <- Core.App (Core.Field (Core.Union _) _) x
234+
226235
assertRecordLit :: Expr Void Void -> Either CompileError (Map.Map Text (Core.RecordField Void Void))
227236
assertRecordLit (Core.RecordLit r) = Right r
237+
assertRecordLit (UnionApp x) = assertRecordLit x
228238
assertRecordLit e = Left $ NotARecord e
229239

230240
toTomlTable :: Map.Map Text (Core.RecordField Void Void) -> Either CompileError TOML
@@ -238,6 +248,8 @@ toTomlRecordFold curKey toml' (key', val) = toToml toml' newKey (Core.recordFiel
238248
append (x:xs) y = x :| xs ++ [y]
239249
newKey = Key $ append curKey $ Piece key'
240250

251+
252+
241253
toToml :: TOML -> Key -> Expr Void Void -> Either CompileError TOML
242254
toToml toml key expr = case expr of
243255
Core.BoolLit a -> return $ insertPrim (Toml.Value.Bool a)
@@ -246,16 +258,21 @@ toToml toml key expr = case expr of
246258
Core.TextLit (Core.Chunks [] a) -> return $ insertPrim (Toml.Value.Text a)
247259
Core.App Core.None _ -> return toml
248260
Core.Some a -> toToml toml key a
249-
-- empty union alternative like < A | B >.A
250-
Core.Field (Core.Union _) (Core.FieldSelection _ a _) -> return $ insertPrim (Toml.Value.Text a)
251-
-- union alternative with type like < A : Natural | B>.A 1
252-
Core.App (Core.Field (Core.Union _) _) a -> toToml toml key a
261+
UnionEmpty a -> return $ insertPrim (Toml.Value.Text a)
262+
UnionApp a -> toToml toml key a
253263
Core.ListLit _ a -> case toList a of
254264
-- empty array
255265
[] -> return $ insertPrim (Toml.Value.Array [])
256266
-- TODO: unions need to be handled here as well, it's a bit tricky
257267
-- because they also have to be probed for being a "simple"
258268
-- array of table
269+
union@(UnionApp (Core.RecordLit _)) : unions -> do
270+
tables' <- case mapM assertRecordLit (union :| unions) of
271+
Right x -> mapM toTomlTable x
272+
Left (NotARecord e) -> Left (HeterogeneousArray e)
273+
Left x -> Left x
274+
return $ Toml.TOML.insertTableArrays key tables' toml
275+
259276
record@(Core.RecordLit _) : records -> do
260277
tables' <- case mapM assertRecordLit (record :| records) of
261278
Right x -> mapM toTomlTable x
@@ -323,6 +340,8 @@ toToml toml key expr = case expr of
323340
Core.NaturalLit x -> rightAny $ Toml.Value.Integer $ toInteger x
324341
Core.DoubleLit (DhallDouble x) -> rightAny $ Toml.Value.Double x
325342
Core.TextLit (Core.Chunks [] x) -> rightAny $ Toml.Value.Text x
343+
UnionEmpty x -> rightAny $ Toml.Value.Text x
344+
UnionApp x -> toAny x
326345
Core.ListLit _ x -> do
327346
anyList <- mapM toAny $ toList x
328347
case Toml.AnyValue.toMArray anyList of
@@ -331,6 +350,7 @@ toToml toml key expr = case expr of
331350
Core.RecordLit _ -> Left $ UnsupportedArray e
332351
_ -> Left $ Unsupported e
333352

353+
334354
{-| Runs the @dhall-to-toml@ command
335355
-}
336356
dhallToTomlMain :: IO ()

dhall-toml/tasty/Main.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ testTree =
4444
, "./tasty/data/record-list"
4545
, "./tasty/data/union-empty"
4646
, "./tasty/data/union-typed"
47+
, "./tasty/data/union-nested"
4748
, "./tasty/data/optional"
4849
]
4950
tomlToDhallTests = map testTomlToDhall
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
let U = <A : {} | B : Natural >
2+
in
3+
{ recs = [ U.A {=} ]
4+
, nats = [ U.B 1 ]
5+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
nats = [ 1 ]
2+
3+
[[recs]]
4+

0 commit comments

Comments
 (0)