Skip to content

Commit dbc6a5f

Browse files
committed
Add compiler support for BiSeqDict, MultiSeqDict, and MultiBiSeqDict
This adds Wire3 codec generation support for three new container types from lamdera/containers: - BiSeqDict: Bidirectional many-to-one dictionary - MultiSeqDict: One-to-many dictionary - MultiBiSeqDict: Many-to-many bidirectional dictionary Changes: - Add DiffableType constructors for the three new types - Add Wire3 encoder/decoder patterns following SeqDict pattern - Add TypeHash support for type hashing and migrations - Add Evergreen migration helpers for all three types Related PR: lamdera/containers#1 Test repo: https://github.com/supermario/qwertytrewq All three types use the same 2-parameter (key, value) structure as SeqDict and work with opaque types that aren't comparable.
1 parent 94a4e63 commit dbc6a5f

6 files changed

Lines changed: 222 additions & 0 deletions

File tree

extra/Lamdera/Evergreen/MigrationGenerator.hs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,6 +1001,21 @@ typeToMigration oldVersion newVersion scope interfaces recursionSet_ typeNew@(Ca
10011001
(\m_p1 -> T.concat [ "SeqDict.map (\\k -> ", m_p1, ")" ])
10021002
(\m_p0 m_p1 -> T.concat [ "SeqDict.toList |> List.map (Tuple.mapBoth (", m_p0, ") (", m_p1, ")) |> SeqDict.fromList" ])
10031003

1004+
("lamdera", "containers", "BiSeqDict", "BiSeqDict") -> migrate2ParamCollection
1005+
(\m_p0 -> T.concat [ "BiSeqDict.toList |> List.map (Tuple.mapFirst ", m_p0, ") |> BiSeqDict.fromList" ])
1006+
(\m_p1 -> T.concat [ "BiSeqDict.map (\\k -> ", m_p1, ")" ])
1007+
(\m_p0 m_p1 -> T.concat [ "BiSeqDict.toList |> List.map (Tuple.mapBoth (", m_p0, ") (", m_p1, ")) |> BiSeqDict.fromList" ])
1008+
1009+
("lamdera", "containers", "MultiSeqDict", "MultiSeqDict") -> migrate2ParamCollection
1010+
(\m_p0 -> T.concat [ "MultiSeqDict.toList |> List.map (Tuple.mapFirst ", m_p0, ") |> MultiSeqDict.fromList" ])
1011+
(\m_p1 -> T.concat [ "MultiSeqDict.map (\\k -> ", m_p1, ")" ])
1012+
(\m_p0 m_p1 -> T.concat [ "MultiSeqDict.toList |> List.map (Tuple.mapBoth (", m_p0, ") (", m_p1, ")) |> MultiSeqDict.fromList" ])
1013+
1014+
("lamdera", "containers", "MultiBiSeqDict", "MultiBiSeqDict") -> migrate2ParamCollection
1015+
(\m_p0 -> T.concat [ "MultiBiSeqDict.toList |> List.map (Tuple.mapFirst ", m_p0, ") |> MultiBiSeqDict.fromList" ])
1016+
(\m_p1 -> T.concat [ "MultiBiSeqDict.map (\\k -> ", m_p1, ")" ])
1017+
(\m_p0 m_p1 -> T.concat [ "MultiBiSeqDict.toList |> List.map (Tuple.mapBoth (", m_p0, ") (", m_p1, ")) |> MultiBiSeqDict.fromList" ])
1018+
10041019
(author, pkg, module_, typeName_) ->
10051020
if (Set.member recursionIdentifier recursionSet_) then
10061021
handleSeenRecursiveType oldVersion newVersion scope identifierNew interfaces newRecursionSet typeNew typeOld tvarMapOld tvarMapNew oldValueRef

extra/Lamdera/TypeHash.hs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,27 @@ canonicalToDiffableType targetName interfaces recursionSet canonical tvarMap =
356356
_ ->
357357
DError "❗️impossible !1 param SeqSet type"
358358

359+
("lamdera", "containers", "BiSeqDict", "BiSeqDict") ->
360+
case tvarResolvedParams of
361+
key:value:_ ->
362+
DLamderaBiSeqDict (canonicalToDiffableType targetName interfaces recursionSet key tvarMap) (canonicalToDiffableType targetName interfaces recursionSet value tvarMap)
363+
_ ->
364+
DError "❗️impossible !2 param BiSeqDict type"
365+
366+
("lamdera", "containers", "MultiSeqDict", "MultiSeqDict") ->
367+
case tvarResolvedParams of
368+
key:value:_ ->
369+
DLamderaMultiSeqDict (canonicalToDiffableType targetName interfaces recursionSet key tvarMap) (canonicalToDiffableType targetName interfaces recursionSet value tvarMap)
370+
_ ->
371+
DError "❗️impossible !2 param MultiSeqDict type"
372+
373+
("lamdera", "containers", "MultiBiSeqDict", "MultiBiSeqDict") ->
374+
case tvarResolvedParams of
375+
key:value:_ ->
376+
DLamderaMultiBiSeqDict (canonicalToDiffableType targetName interfaces recursionSet key tvarMap) (canonicalToDiffableType targetName interfaces recursionSet value tvarMap)
377+
_ ->
378+
DError "❗️impossible !2 param MultiBiSeqDict type"
379+
359380

360381
-- Values backed by JS Kernel types we cannot encode/decode
361382
("elm", "virtual-dom", "VirtualDom", "Node") -> kernelError
@@ -580,6 +601,9 @@ diffableTypeToText dtype =
580601
DExternalWarning _ tipe -> diffableTypeToText tipe
581602
DLamderaSeqDict key value -> "LD["<> diffableTypeToText key <>","<> diffableTypeToText value <>"]"
582603
DLamderaSeqSet tipe -> "LS["<> diffableTypeToText tipe <>"]"
604+
DLamderaBiSeqDict key value -> "LBD["<> diffableTypeToText key <>","<> diffableTypeToText value <>"]"
605+
DLamderaMultiSeqDict key value -> "LMD["<> diffableTypeToText key <>","<> diffableTypeToText value <>"]"
606+
DLamderaMultiBiSeqDict key value -> "LMBD["<> diffableTypeToText key <>","<> diffableTypeToText value <>"]"
583607

584608

585609
diffableTypeErrors :: DiffableType -> [Text]
@@ -625,6 +649,9 @@ diffableTypeErrors dtype =
625649

626650
DLamderaSeqDict key value -> diffableTypeErrors key ++ diffableTypeErrors value
627651
DLamderaSeqSet tipe -> diffableTypeErrors tipe
652+
DLamderaBiSeqDict key value -> diffableTypeErrors key ++ diffableTypeErrors value
653+
DLamderaMultiSeqDict key value -> diffableTypeErrors key ++ diffableTypeErrors value
654+
DLamderaMultiBiSeqDict key value -> diffableTypeErrors key ++ diffableTypeErrors value
628655

629656

630657
diffableTypeExternalWarnings :: DiffableType -> [Text]
@@ -669,3 +696,6 @@ diffableTypeExternalWarnings dtype =
669696

670697
DLamderaSeqDict key value -> diffableTypeExternalWarnings key ++ diffableTypeExternalWarnings value
671698
DLamderaSeqSet tipe -> diffableTypeExternalWarnings tipe
699+
DLamderaBiSeqDict key value -> diffableTypeExternalWarnings key ++ diffableTypeExternalWarnings value
700+
DLamderaMultiSeqDict key value -> diffableTypeExternalWarnings key ++ diffableTypeExternalWarnings value
701+
DLamderaMultiBiSeqDict key value -> diffableTypeExternalWarnings key ++ diffableTypeExternalWarnings value

extra/Lamdera/Types.hs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ data DiffableType
4040
-- Lamdera lib types special cased with support for efficiency
4141
| DLamderaSeqDict DiffableType DiffableType
4242
| DLamderaSeqSet DiffableType
43+
| DLamderaBiSeqDict DiffableType DiffableType
44+
| DLamderaMultiSeqDict DiffableType DiffableType
45+
| DLamderaMultiBiSeqDict DiffableType DiffableType
4346

4447
deriving (Show)
4548

extra/Lamdera/Wire3/Decoder.hs

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,123 @@ decoderForType ifaces cname tipe =
341341
, decoderForType ifaces cname val
342342
]))
343343

344+
TType (Module.Canonical (Name "lamdera" "containers") "BiSeqDict") "BiSeqDict" [key, val] ->
345+
(a (Call
346+
(a (VarForeign mLamdera_BiSeqDict "decodeBiSeqDict"
347+
(Forall
348+
(Map.fromList [("k", ()), ("value", ())])
349+
(TLambda
350+
(TAlias mLamdera_Wire "Decoder" [("a", TVar "k")]
351+
(Filled
352+
(TType
353+
(Module.Canonical (Name "elm" "bytes") "Bytes.Decode")
354+
"Decoder"
355+
[TVar "k"])))
356+
(TLambda
357+
(TAlias mLamdera_Wire "Decoder" [("a", TVar "value")]
358+
(Filled
359+
(TType
360+
(Module.Canonical (Name "elm" "bytes") "Bytes.Decode")
361+
"Decoder"
362+
[TVar "value"])))
363+
(TAlias mLamdera_Wire "Decoder"
364+
[ ( "a"
365+
, TType
366+
mLamdera_BiSeqDict
367+
"BiSeqDict"
368+
[TVar "k", TVar "value"])
369+
]
370+
(Filled
371+
(TType
372+
(Module.Canonical (Name "elm" "bytes") "Bytes.Decode")
373+
"Decoder"
374+
[ TType
375+
mLamdera_BiSeqDict
376+
"BiSeqDict"
377+
[TVar "k", TVar "value"]
378+
]))))))))
379+
[ decoderForType ifaces cname key
380+
, decoderForType ifaces cname val
381+
]))
382+
383+
TType (Module.Canonical (Name "lamdera" "containers") "MultiSeqDict") "MultiSeqDict" [key, val] ->
384+
(a (Call
385+
(a (VarForeign mLamdera_MultiSeqDict "decodeMultiSeqDict"
386+
(Forall
387+
(Map.fromList [("k", ()), ("value", ())])
388+
(TLambda
389+
(TAlias mLamdera_Wire "Decoder" [("a", TVar "k")]
390+
(Filled
391+
(TType
392+
(Module.Canonical (Name "elm" "bytes") "Bytes.Decode")
393+
"Decoder"
394+
[TVar "k"])))
395+
(TLambda
396+
(TAlias mLamdera_Wire "Decoder" [("a", TVar "value")]
397+
(Filled
398+
(TType
399+
(Module.Canonical (Name "elm" "bytes") "Bytes.Decode")
400+
"Decoder"
401+
[TVar "value"])))
402+
(TAlias mLamdera_Wire "Decoder"
403+
[ ( "a"
404+
, TType
405+
mLamdera_MultiSeqDict
406+
"MultiSeqDict"
407+
[TVar "k", TVar "value"])
408+
]
409+
(Filled
410+
(TType
411+
(Module.Canonical (Name "elm" "bytes") "Bytes.Decode")
412+
"Decoder"
413+
[ TType
414+
mLamdera_MultiSeqDict
415+
"MultiSeqDict"
416+
[TVar "k", TVar "value"]
417+
]))))))))
418+
[ decoderForType ifaces cname key
419+
, decoderForType ifaces cname val
420+
]))
421+
422+
TType (Module.Canonical (Name "lamdera" "containers") "MultiBiSeqDict") "MultiBiSeqDict" [key, val] ->
423+
(a (Call
424+
(a (VarForeign mLamdera_MultiBiSeqDict "decodeMultiBiSeqDict"
425+
(Forall
426+
(Map.fromList [("k", ()), ("value", ())])
427+
(TLambda
428+
(TAlias mLamdera_Wire "Decoder" [("a", TVar "k")]
429+
(Filled
430+
(TType
431+
(Module.Canonical (Name "elm" "bytes") "Bytes.Decode")
432+
"Decoder"
433+
[TVar "k"])))
434+
(TLambda
435+
(TAlias mLamdera_Wire "Decoder" [("a", TVar "value")]
436+
(Filled
437+
(TType
438+
(Module.Canonical (Name "elm" "bytes") "Bytes.Decode")
439+
"Decoder"
440+
[TVar "value"])))
441+
(TAlias mLamdera_Wire "Decoder"
442+
[ ( "a"
443+
, TType
444+
mLamdera_MultiBiSeqDict
445+
"MultiBiSeqDict"
446+
[TVar "k", TVar "value"])
447+
]
448+
(Filled
449+
(TType
450+
(Module.Canonical (Name "elm" "bytes") "Bytes.Decode")
451+
"Decoder"
452+
[ TType
453+
mLamdera_MultiBiSeqDict
454+
"MultiBiSeqDict"
455+
[TVar "k", TVar "value"]
456+
]))))))))
457+
[ decoderForType ifaces cname key
458+
, decoderForType ifaces cname val
459+
]))
460+
344461
TType (Module.Canonical (Name "elm" "bytes") "Bytes") "Bytes" _ ->
345462
callDecoder "decodeBytes" tipe
346463

extra/Lamdera/Wire3/Encoder.hs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,39 @@ encoderForType depth ifaces cname tipe =
178178
(TType mLamdera_SeqDict "SeqDict" [TVar "key", TVar "value"])
179179
tLamdera_Wire_Encoder))))))
180180

181+
TType (Module.Canonical (Name "lamdera" "containers") "BiSeqDict") "BiSeqDict" [key, value] ->
182+
(a (VarForeign mLamdera_BiSeqDict "encodeBiSeqDict"
183+
(Forall
184+
(Map.fromList [("key", ()), ("value", ())])
185+
(TLambda
186+
(TLambda (TVar "key") tLamdera_Wire_Encoder)
187+
(TLambda (TLambda (TVar "value") tLamdera_Wire_Encoder)
188+
(TLambda
189+
(TType mLamdera_BiSeqDict "BiSeqDict" [TVar "key", TVar "value"])
190+
tLamdera_Wire_Encoder))))))
191+
192+
TType (Module.Canonical (Name "lamdera" "containers") "MultiSeqDict") "MultiSeqDict" [key, value] ->
193+
(a (VarForeign mLamdera_MultiSeqDict "encodeMultiSeqDict"
194+
(Forall
195+
(Map.fromList [("key", ()), ("value", ())])
196+
(TLambda
197+
(TLambda (TVar "key") tLamdera_Wire_Encoder)
198+
(TLambda (TLambda (TVar "value") tLamdera_Wire_Encoder)
199+
(TLambda
200+
(TType mLamdera_MultiSeqDict "MultiSeqDict" [TVar "key", TVar "value"])
201+
tLamdera_Wire_Encoder))))))
202+
203+
TType (Module.Canonical (Name "lamdera" "containers") "MultiBiSeqDict") "MultiBiSeqDict" [key, value] ->
204+
(a (VarForeign mLamdera_MultiBiSeqDict "encodeMultiBiSeqDict"
205+
(Forall
206+
(Map.fromList [("key", ()), ("value", ())])
207+
(TLambda
208+
(TLambda (TVar "key") tLamdera_Wire_Encoder)
209+
(TLambda (TLambda (TVar "value") tLamdera_Wire_Encoder)
210+
(TLambda
211+
(TType mLamdera_MultiBiSeqDict "MultiBiSeqDict" [TVar "key", TVar "value"])
212+
tLamdera_Wire_Encoder))))))
213+
181214
TType (Module.Canonical (Name "elm" "bytes") "Bytes") "Bytes" _ ->
182215
(a (VarForeign mLamdera_Wire "encodeBytes" (Forall Map.empty (TLambda tipe tLamdera_Wire_Encoder))))
183216

@@ -306,6 +339,12 @@ deepEncoderForType depth ifaces cname tipe =
306339
call (encoderForType depth ifaces cname tipe) [ deepEncoderForType depth ifaces cname key, deepEncoderForType depth ifaces cname val ]
307340
TType (Module.Canonical (Name "lamdera" "containers") "SeqDict") "SeqDict" [key, val] ->
308341
call (encoderForType depth ifaces cname tipe) [ deepEncoderForType depth ifaces cname key, deepEncoderForType depth ifaces cname val ]
342+
TType (Module.Canonical (Name "lamdera" "containers") "BiSeqDict") "BiSeqDict" [key, val] ->
343+
call (encoderForType depth ifaces cname tipe) [ deepEncoderForType depth ifaces cname key, deepEncoderForType depth ifaces cname val ]
344+
TType (Module.Canonical (Name "lamdera" "containers") "MultiSeqDict") "MultiSeqDict" [key, val] ->
345+
call (encoderForType depth ifaces cname tipe) [ deepEncoderForType depth ifaces cname key, deepEncoderForType depth ifaces cname val ]
346+
TType (Module.Canonical (Name "lamdera" "containers") "MultiBiSeqDict") "MultiBiSeqDict" [key, val] ->
347+
call (encoderForType depth ifaces cname tipe) [ deepEncoderForType depth ifaces cname key, deepEncoderForType depth ifaces cname val ]
309348
TType (Module.Canonical (Name "elm" "bytes") "Bytes") "Bytes" _ -> encoderForType depth ifaces cname tipe
310349
TType (Module.Canonical (Name "elm" "time") "Time") "Posix" _ -> encoderForType depth ifaces cname tipe
311350

@@ -401,6 +440,12 @@ encodeTypeValue depth ifaces cname tipe value =
401440
call (encoderForType depth ifaces cname tipe) [ deepEncoderForType depth ifaces cname key, deepEncoderForType depth ifaces cname val, value ]
402441
TType (Module.Canonical (Name "lamdera" "containers") "SeqDict") "SeqDict" [key, val] ->
403442
call (encoderForType depth ifaces cname tipe) [ deepEncoderForType depth ifaces cname key, deepEncoderForType depth ifaces cname val, value ]
443+
TType (Module.Canonical (Name "lamdera" "containers") "BiSeqDict") "BiSeqDict" [key, val] ->
444+
call (encoderForType depth ifaces cname tipe) [ deepEncoderForType depth ifaces cname key, deepEncoderForType depth ifaces cname val, value ]
445+
TType (Module.Canonical (Name "lamdera" "containers") "MultiSeqDict") "MultiSeqDict" [key, val] ->
446+
call (encoderForType depth ifaces cname tipe) [ deepEncoderForType depth ifaces cname key, deepEncoderForType depth ifaces cname val, value ]
447+
TType (Module.Canonical (Name "lamdera" "containers") "MultiBiSeqDict") "MultiBiSeqDict" [key, val] ->
448+
call (encoderForType depth ifaces cname tipe) [ deepEncoderForType depth ifaces cname key, deepEncoderForType depth ifaces cname val, value ]
404449
TType (Module.Canonical (Name "elm" "bytes") "Bytes") "Bytes" _ -> call (encoderForType depth ifaces cname tipe) [ value ]
405450
TType (Module.Canonical (Name "elm" "time") "Time") "Posix" _ -> call (encoderForType depth ifaces cname tipe) [ value ]
406451

extra/Lamdera/Wire3/Helpers.hs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,9 @@ tLamdera_Wire_Encoder_Holey =
758758
mLamdera_Wire = (Module.Canonical (Name "lamdera" "codecs") "Lamdera.Wire3")
759759
mLamdera_SeqDict = (Module.Canonical (Name "lamdera" "containers") "SeqDict")
760760
mLamdera_SeqSet = (Module.Canonical (Name "lamdera" "containers") "SeqSet")
761+
mLamdera_BiSeqDict = (Module.Canonical (Name "lamdera" "containers") "BiSeqDict")
762+
mLamdera_MultiSeqDict = (Module.Canonical (Name "lamdera" "containers") "MultiSeqDict")
763+
mLamdera_MultiBiSeqDict = (Module.Canonical (Name "lamdera" "containers") "MultiBiSeqDict")
761764
mBytes_Encode = (Module.Canonical (Name "elm" "bytes") "Bytes.Encode")
762765
mBytes_Decode = (Module.Canonical (Name "elm" "bytes") "Bytes.Decode")
763766

@@ -798,6 +801,15 @@ unwrapAliasesDeep t =
798801
TType (Module.Canonical (Name "lamdera" "containers") "SeqDict") "SeqDict" [key, val] ->
799802
TType (Module.Canonical (Name "lamdera" "containers") "SeqDict") "SeqDict" [unwrapAliasesDeep key, unwrapAliasesDeep val]
800803

804+
TType (Module.Canonical (Name "lamdera" "containers") "BiSeqDict") "BiSeqDict" [key, val] ->
805+
TType (Module.Canonical (Name "lamdera" "containers") "BiSeqDict") "BiSeqDict" [unwrapAliasesDeep key, unwrapAliasesDeep val]
806+
807+
TType (Module.Canonical (Name "lamdera" "containers") "MultiSeqDict") "MultiSeqDict" [key, val] ->
808+
TType (Module.Canonical (Name "lamdera" "containers") "MultiSeqDict") "MultiSeqDict" [unwrapAliasesDeep key, unwrapAliasesDeep val]
809+
810+
TType (Module.Canonical (Name "lamdera" "containers") "MultiBiSeqDict") "MultiBiSeqDict" [key, val] ->
811+
TType (Module.Canonical (Name "lamdera" "containers") "MultiBiSeqDict") "MultiBiSeqDict" [unwrapAliasesDeep key, unwrapAliasesDeep val]
812+
801813
TType moduleName typeName params ->
802814
-- t -- @TODO wrong to not de-alias params?
803815
TType moduleName typeName (fmap unwrapAliasesDeep params)

0 commit comments

Comments
 (0)