Skip to content

Commit 65e4402

Browse files
committed
Implement optional expand functionality for Swift
1 parent fd6436e commit 65e4402

File tree

7 files changed

+150
-88
lines changed

7 files changed

+150
-88
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
data class Data(
2+
val field0: Int,
3+
val field1: Int? = null,
4+
)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
struct Data {
2+
let field0: Int
3+
let field1: Optional<Int>
4+
}

moat.cabal

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ test-suite spec
6767
BasicNewtypeWithConcreteFieldSpec
6868
BasicNewtypeWithEitherFieldSpec
6969
BasicRecordSpec
70+
BasicRecordWithExpandOptionalSpec
7071
Common
7172
SumOfProductSpec
7273
SumOfProductWithLinkEnumInterfaceSpec
@@ -79,7 +80,7 @@ test-suite spec
7980
hs-source-dirs:
8081
test
8182
src
82-
default-extensions: LambdaCase RecordWildCards AllowAmbiguousTypes DataKinds ScopedTypeVariables TemplateHaskell
83+
default-extensions: LambdaCase RecordWildCards AllowAmbiguousTypes DataKinds ScopedTypeVariables TemplateHaskell TypeApplications
8384
ghc-options: -Wall -Wno-unused-top-binds
8485
build-depends:
8586
base >=4.11 && <4.15

src/Moat.hs

Lines changed: 56 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,7 @@ consToMoatType ::
662662
consToMoatType o@Options {..} parentName instTys variant ts bs = \case
663663
[] -> do
664664
value <- lift $ newName "value"
665-
matches <- liftCons (mkVoid parentName instTys ts)
665+
matches <- liftCons (mkVoid o parentName instTys ts)
666666
lift $ lamE [varP value] (caseE (varE value) matches)
667667
cons -> do
668668
-- TODO: use '_' instead of matching
@@ -677,14 +677,14 @@ consToMoatType o@Options {..} parentName instTys variant ts bs = \case
677677
case variant of
678678
NewtypeInstance -> do
679679
if typeAlias
680-
then mkNewtypeInstanceAlias instTys con
680+
then mkNewtypeInstanceAlias o instTys con
681681
else mkNewtypeInstance o instTys con
682682
Newtype -> do
683683
if
684684
| newtypeTag -> do
685685
mkTypeTag o parentName instTys con
686686
| typeAlias -> do
687-
mkTypeAlias parentName instTys con
687+
mkTypeAlias o parentName instTys con
688688
| otherwise -> do
689689
mkNewtype o parentName instTys con
690690
_ -> do
@@ -695,7 +695,7 @@ consToMoatType o@Options {..} parentName instTys variant ts bs = \case
695695
cases <- forM cons' (liftEither . mkCase o)
696696
ourMatch <-
697697
matchProxy
698-
=<< lift (enumExp parentName instTys dataInterfaces dataProtocols dataAnnotations cases dataRawValue ts bs)
698+
=<< lift (enumExp o parentName instTys dataInterfaces dataProtocols dataAnnotations cases dataRawValue ts bs)
699699
pure [pure ourMatch]
700700

701701
liftCons :: (Functor f, Applicative g) => f a -> f [g a]
@@ -770,13 +770,14 @@ mkLabel Options {..} =
770770
. show
771771

772772
mkNewtypeInstanceAlias ::
773-
() =>
773+
-- | Options
774+
Options ->
774775
-- | type variables
775776
[Type] ->
776777
-- | constructor info
777778
ConstructorInfo ->
778779
MoatM Match
779-
mkNewtypeInstanceAlias (stripConT -> instTys) = \case
780+
mkNewtypeInstanceAlias o (stripConT -> instTys) = \case
780781
ConstructorInfo
781782
{ constructorName = conName,
782783
constructorFields = [field]
@@ -785,8 +786,7 @@ mkNewtypeInstanceAlias (stripConT -> instTys) = \case
785786
match
786787
(conP 'Proxy [])
787788
( normalB
788-
( pure
789-
(aliasExp conName instTys field)
789+
( aliasExp o conName instTys field
790790
)
791791
)
792792
[]
@@ -807,7 +807,7 @@ mkNewtypeInstance o@Options {..} (stripConT -> instTys) = \case
807807
{ constructorFields = [field],
808808
..
809809
} -> do
810-
matchProxy =<< lift (newtypeExp constructorName instTys dataInterfaces dataProtocols dataAnnotations (prettyField o (mkName "value") field))
810+
matchProxy =<< lift (newtypeExp o constructorName instTys dataInterfaces dataProtocols dataAnnotations (prettyField o (mkName "value") field))
811811
_ -> throwError ExpectedNewtypeInstance
812812

813813
-- make a newtype into an empty enum
@@ -823,53 +823,55 @@ mkTypeTag ::
823823
-- | constructor info
824824
ConstructorInfo ->
825825
MoatM Match
826-
mkTypeTag Options {..} typName instTys = \case
826+
mkTypeTag o@Options {..} typName instTys = \case
827827
ConstructorInfo
828828
{ constructorFields = [field]
829829
} -> do
830830
let parentName =
831831
mkName
832832
(nameStr typName ++ "Tag")
833833
let tag = tagExp typName parentName field False
834-
matchProxy =<< lift (enumExp parentName instTys dataInterfaces dataProtocols dataAnnotations [] dataRawValue [tag] (False, Nothing, []))
834+
matchProxy =<< lift (enumExp o parentName instTys dataInterfaces dataProtocols dataAnnotations [] dataRawValue [tag] (False, Nothing, []))
835835
_ -> throwError $ NotANewtype typName
836836

837837
-- make a newtype into a type alias
838838
mkTypeAlias ::
839-
() =>
839+
-- | Options
840+
Options ->
840841
-- | type name
841842
Name ->
842843
-- | type variables
843844
[Type] ->
844845
-- | constructor info
845846
ConstructorInfo ->
846847
MoatM Match
847-
mkTypeAlias typName instTys = \case
848+
mkTypeAlias o typName instTys = \case
848849
ConstructorInfo
849850
{ constructorFields = [field]
850851
} -> do
851852
lift $
852853
match
853854
(conP 'Proxy [])
854855
( normalB
855-
(pure (aliasExp typName instTys field))
856+
(aliasExp o typName instTys field)
856857
)
857858
[]
858859
_ -> throwError $ NotANewtype typName
859860

860861
-- | Make a void type (empty enum)
861862
mkVoid ::
862-
() =>
863+
-- | Options
864+
Options ->
863865
-- | type name
864866
Name ->
865867
-- | type variables
866868
[Type] ->
867869
-- | tags
868870
[Exp] ->
869871
MoatM Match
870-
mkVoid typName instTys ts =
872+
mkVoid o typName instTys ts =
871873
matchProxy
872-
=<< lift (enumExp typName instTys [] [] [] [] Nothing ts (False, Nothing, []))
874+
=<< lift (enumExp o typName instTys [] [] [] [] Nothing ts (False, Nothing, []))
873875

874876
mkNewtype ::
875877
() =>
@@ -883,11 +885,11 @@ mkNewtype o@Options {..} typName instTys = \case
883885
{ constructorFields = [field],
884886
constructorVariant = RecordConstructor [name]
885887
} -> do
886-
matchProxy =<< lift (newtypeExp typName instTys dataInterfaces dataProtocols dataAnnotations (prettyField o name field))
888+
matchProxy =<< lift (newtypeExp o typName instTys dataInterfaces dataProtocols dataAnnotations (prettyField o name field))
887889
ConstructorInfo
888890
{ constructorFields = [field]
889891
} -> do
890-
matchProxy =<< lift (newtypeExp typName instTys dataInterfaces dataProtocols dataAnnotations (prettyField o (mkName "value") field))
892+
matchProxy =<< lift (newtypeExp o typName instTys dataInterfaces dataProtocols dataAnnotations (prettyField o (mkName "value") field))
891893
ci -> throwError $ ImproperNewtypeConstructorInfo ci
892894

893895
-- | Make a single-constructor product (struct)
@@ -910,7 +912,7 @@ mkProd o@Options {..} typName instTys ts = \case
910912
{ constructorVariant = NormalConstructor,
911913
constructorFields = []
912914
} -> do
913-
matchProxy =<< lift (structExp typName instTys dataInterfaces dataProtocols dataAnnotations [] ts makeBase)
915+
matchProxy =<< lift (structExp o typName instTys dataInterfaces dataProtocols dataAnnotations [] ts makeBase)
914916
-- single constructor, non-record (Normal)
915917
ConstructorInfo
916918
{ constructorVariant = NormalConstructor,
@@ -931,7 +933,7 @@ mkProd o@Options {..} typName instTys ts = \case
931933
..
932934
} -> do
933935
let fields = zipFields o fieldNames constructorFields
934-
matchProxy =<< lift (structExp typName instTys dataInterfaces dataProtocols dataAnnotations fields ts makeBase)
936+
matchProxy =<< lift (structExp o typName instTys dataInterfaces dataProtocols dataAnnotations fields ts makeBase)
935937

936938
zipFields :: Options -> [Name] -> [Type] -> [Exp]
937939
zipFields o = zipWithPred p (prettyField o)
@@ -1402,21 +1404,25 @@ stripConT = mapMaybe noConT
14021404

14031405
-- | Construct a Type Alias.
14041406
aliasExp ::
1405-
() =>
1407+
-- | Options
1408+
Options ->
14061409
-- | alias name
14071410
Name ->
14081411
-- | type variables
14091412
[Type] ->
14101413
-- | type (RHS)
14111414
Type ->
1412-
Exp
1413-
aliasExp name tyVars field =
1414-
RecConE
1415-
'MoatAlias
1416-
[ ('aliasName, unqualName name),
1417-
('aliasTyVars, prettyTyVars tyVars),
1418-
('aliasTyp, toMoatTypeECxt field)
1419-
]
1415+
Q Exp
1416+
aliasExp Options {..} name tyVars field = do
1417+
optionalExpand_ <- Syntax.lift optionalExpand
1418+
pure $
1419+
RecConE
1420+
'MoatAlias
1421+
[ ('aliasName, unqualName name),
1422+
('aliasTyVars, prettyTyVars tyVars),
1423+
('aliasTyp, toMoatTypeECxt field),
1424+
('aliasOptionalExpand, optionalExpand_)
1425+
]
14201426

14211427
-- | Construct a Tag.
14221428
tagExp ::
@@ -1443,7 +1449,8 @@ tagExp tyconName parentName typ dis =
14431449

14441450
-- | Construct an Enum.
14451451
enumExp ::
1446-
() =>
1452+
-- | Options
1453+
Options ->
14471454
-- | parent name
14481455
Name ->
14491456
-- | type variables
@@ -1463,11 +1470,12 @@ enumExp ::
14631470
-- | Make base?
14641471
(Bool, Maybe MoatType, [Protocol]) ->
14651472
Q Exp
1466-
enumExp parentName tyVars ifaces protos anns cases raw tags bs =
1473+
enumExp Options {..} parentName tyVars ifaces protos anns cases raw tags bs =
14671474
do
14681475
enumInterfaces_ <- Syntax.lift ifaces
14691476
enumAnnotations_ <- Syntax.lift anns
14701477
enumProtocols_ <- Syntax.lift protos
1478+
optionalExpand_ <- Syntax.lift optionalExpand
14711479
applyBase bs $
14721480
RecConE
14731481
'MoatEnum
@@ -1479,33 +1487,36 @@ enumExp parentName tyVars ifaces protos anns cases raw tags bs =
14791487
('enumCases, ListE cases),
14801488
('enumRawValue, rawValueE raw),
14811489
('enumPrivateTypes, ListE []),
1482-
('enumTags, ListE tags)
1490+
('enumTags, ListE tags),
1491+
('enumOptionalExpand, optionalExpand_)
14831492
]
14841493

14851494
newtypeExp ::
1486-
() =>
1495+
Options ->
14871496
Name ->
14881497
[Type] ->
14891498
[Interface] ->
14901499
[Protocol] ->
14911500
[Annotation] ->
14921501
Exp ->
14931502
Q Exp
1494-
newtypeExp name tyVars ifaces protos anns field =
1503+
newtypeExp Options {..} name tyVars ifaces protos anns field =
14951504
[|
14961505
MoatNewtype
14971506
{ newtypeName = $(pure $ unqualName name),
14981507
newtypeTyVars = $(pure $ prettyTyVars tyVars),
14991508
newtypeField = $(pure field),
15001509
newtypeProtocols = $(Syntax.lift protos),
15011510
newtypeAnnotations = $(Syntax.lift anns),
1502-
newtypeInterfaces = $(Syntax.lift ifaces)
1511+
newtypeInterfaces = $(Syntax.lift ifaces),
1512+
newtypeOptionalExpand = $(Syntax.lift optionalExpand)
15031513
}
15041514
|]
15051515

15061516
-- | Construct a Struct.
15071517
structExp ::
1508-
() =>
1518+
-- | Options
1519+
Options ->
15091520
-- | struct name
15101521
Name ->
15111522
-- | type variables
@@ -1523,10 +1534,11 @@ structExp ::
15231534
-- | Make base?
15241535
(Bool, Maybe MoatType, [Protocol]) ->
15251536
Q Exp
1526-
structExp name tyVars ifaces protos anns fields tags bs = do
1537+
structExp Options {..} name tyVars ifaces protos anns fields tags bs = do
15271538
structInterfaces_ <- Syntax.lift ifaces
15281539
structAnnotations_ <- Syntax.lift anns
15291540
structProtocols_ <- Syntax.lift protos
1541+
optionalExpand_ <- Syntax.lift optionalExpand
15301542
applyBase bs $
15311543
RecConE
15321544
'MoatStruct
@@ -1537,7 +1549,8 @@ structExp name tyVars ifaces protos anns fields tags bs = do
15371549
('structAnnotations, structAnnotations_),
15381550
('structFields, ListE fields),
15391551
('structPrivateTypes, ListE []),
1540-
('structTags, ListE tags)
1552+
('structTags, ListE tags),
1553+
('structOptionalExpand, optionalExpand_)
15411554
]
15421555

15431556
matchProxy :: Exp -> MoatM Match
@@ -1608,7 +1621,8 @@ aliasToNewtype MoatAlias {..} =
16081621
newtypeField = ("value", aliasTyp),
16091622
newtypeInterfaces = [],
16101623
newtypeProtocols = [],
1611-
newtypeAnnotations = []
1624+
newtypeAnnotations = [],
1625+
newtypeOptionalExpand = aliasOptionalExpand
16121626
}
16131627
aliasToNewtype m = m
16141628

@@ -1618,6 +1632,7 @@ newtypeToAlias MoatNewtype {..} =
16181632
MoatAlias
16191633
{ aliasName = newtypeName,
16201634
aliasTyVars = newtypeTyVars,
1621-
aliasTyp = snd newtypeField
1635+
aliasTyp = snd newtypeField,
1636+
aliasOptionalExpand = newtypeOptionalExpand
16221637
}
16231638
newtypeToAlias m = m

0 commit comments

Comments
 (0)