Skip to content

Commit 779885b

Browse files
committed
Allow comments on group entries
This addresses part of #36 - comments are still not supported _everywhere_, but they are allowed on group entries, which represent the area (other than top-level rules) where comments are the most useful. The same "comment" syntax is used as with top-level rules. Note that this does not (yet) work within groups - that will be addressed as part of #32. As yet, the parser still does not deal with comments, or attribute them to any entity. The tests are likewise oblivious to comments. But this does allow Huddle to define comments and have them reflected in the generated CDDL, which was the principal outcome.
1 parent b09cd50 commit 779885b

File tree

7 files changed

+116
-86
lines changed

7 files changed

+116
-86
lines changed

example/Monad.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ spec2 =
4242
_transaction <-
4343
"transaction"
4444
=:= mp
45-
[ idx 0 ==> set txIn,
46-
idx 1 ==> set txOut,
47-
idx 2 ==> metadata
45+
[ comment "Transaction inputs" $ idx 0 ==> set txIn,
46+
comment "Transaction outputs" $ idx 1 ==> set txOut,
47+
comment "Metadata" $ idx 2 ==> metadata
4848
]
4949
metadata <- "metadata" =:= VBytes
5050
_value <- "value" =:= mp ["token" ==> VText, "quantity" ==> VUInt]

src/Codec/CBOR/Cuddle/CDDL.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ instance Hashable OccurrenceIndicator
274274
newtype Group = Group (NE.NonEmpty GrpChoice)
275275
deriving (Eq, Generic, Show, Semigroup)
276276

277-
type GrpChoice = [GroupEntry]
277+
type GrpChoice = [WithComments GroupEntry]
278278

279279
-- |
280280
-- A group entry can be given by a value type, which needs to be matched

src/Codec/CBOR/Cuddle/CDDL/Resolve.hs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,9 @@ buildRefCTree rules = CTreeRoot $ fmap toCTreeRule rules
193193
It $ CTree.Postlude PTAny
194194
toCTreeT2 T2Any = It $ CTree.Postlude PTAny
195195

196+
toCTreeGroupEntryNC :: WithComments GroupEntry -> CTree.Node OrRef
197+
toCTreeGroupEntryNC = toCTreeGroupEntry . stripComment
198+
196199
toCTreeGroupEntry :: GroupEntry -> CTree.Node OrRef
197200
toCTreeGroupEntry (GEType (Just occi) mmkey t0) =
198201
It $
@@ -223,18 +226,18 @@ buildRefCTree rules = CTreeRoot $ fmap toCTreeRule rules
223226
-- choice options
224227
toCTreeEnum :: Group -> CTree.Node OrRef
225228
toCTreeEnum (Group (a NE.:| [])) =
226-
It . CTree.Enum . It . CTree.Group $ fmap toCTreeGroupEntry a
229+
It . CTree.Enum . It . CTree.Group $ fmap toCTreeGroupEntryNC a
227230
toCTreeEnum (Group xs) =
228231
It . CTree.Choice $
229-
fmap (It . CTree.Enum . It . CTree.Group . fmap toCTreeGroupEntry) xs
232+
fmap (It . CTree.Enum . It . CTree.Group . fmap toCTreeGroupEntryNC) xs
230233

231234
-- Embed a group in another group, again floating out the choice options
232235
groupToGroup :: Group -> CTree.Node OrRef
233236
groupToGroup (Group (a NE.:| [])) =
234-
It . CTree.Group $ fmap toCTreeGroupEntry a
237+
It . CTree.Group $ fmap toCTreeGroupEntryNC a
235238
groupToGroup (Group xs) =
236239
It . CTree.Choice $
237-
fmap (It . CTree.Group . fmap toCTreeGroupEntry) xs
240+
fmap (It . CTree.Group . fmap toCTreeGroupEntryNC) xs
238241

239242
toKVPair :: Maybe MemberKey -> Type0 -> CTree.Node OrRef
240243
toKVPair Nothing t0 = toCTreeT0 t0
@@ -249,20 +252,20 @@ buildRefCTree rules = CTreeRoot $ fmap toCTreeRule rules
249252

250253
-- Interpret a group as a map. Note that we float out the choice options
251254
toCTreeMap :: Group -> CTree.Node OrRef
252-
toCTreeMap (Group (a NE.:| [])) = It . CTree.Map $ fmap toCTreeGroupEntry a
255+
toCTreeMap (Group (a NE.:| [])) = It . CTree.Map $ fmap toCTreeGroupEntryNC a
253256
toCTreeMap (Group xs) =
254257
It
255258
. CTree.Choice
256-
$ fmap (It . CTree.Map . fmap toCTreeGroupEntry) xs
259+
$ fmap (It . CTree.Map . fmap toCTreeGroupEntryNC) xs
257260

258261
-- Interpret a group as an array. Note that we float out the choice
259262
-- options
260263
toCTreeArray :: Group -> CTree.Node OrRef
261264
toCTreeArray (Group (a NE.:| [])) =
262-
It . CTree.Array $ fmap toCTreeGroupEntry a
265+
It . CTree.Array $ fmap toCTreeGroupEntryNC a
263266
toCTreeArray (Group xs) =
264267
It . CTree.Choice $
265-
fmap (It . CTree.Array . fmap toCTreeGroupEntry) xs
268+
fmap (It . CTree.Array . fmap toCTreeGroupEntryNC) xs
266269

267270
toCTreeMemberKey :: MemberKey -> CTree.Node OrRef
268271
toCTreeMemberKey (MKValue v) = It $ CTree.Literal v

src/Codec/CBOR/Cuddle/Huddle.hs

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ import Control.Monad (when)
9292
import Control.Monad.State (MonadState (get), execState, modify)
9393
import Data.ByteString (ByteString)
9494
import Data.Default.Class (Default (..))
95-
import Data.Generics.Product (field, getField)
95+
import Data.Generics.Product (HasField' (field'), field, getField)
9696
import Data.List.NonEmpty qualified as NE
9797
import Data.Map.Ordered.Strict (OMap)
9898
import Data.Map.Ordered.Strict qualified as OMap
@@ -113,9 +113,9 @@ data Named a = Named
113113
}
114114
deriving (Functor, Generic)
115115

116-
-- | Add a description to a rule, to be included as a comment.
117-
comment :: T.Text -> Named a -> Named a
118-
comment desc n = n & field @"description" .~ Just desc
116+
-- | Add a description to a rule or group entry, to be included as a comment.
117+
comment :: (HasField' "description" a (Maybe T.Text)) => T.Text -> a -> a
118+
comment desc n = n & field' @"description" .~ Just desc
119119

120120
instance Show (Named a) where
121121
show (Named n _ _) = T.unpack n
@@ -201,7 +201,8 @@ asKey r = case toType0 r of
201201
data MapEntry = MapEntry
202202
{ key :: Key,
203203
value :: Type0,
204-
quantifier :: Occurs
204+
quantifier :: Occurs,
205+
description :: Maybe T.Text
205206
}
206207
deriving (Generic, Show)
207208

@@ -221,7 +222,8 @@ data ArrayEntry = ArrayEntry
221222
-- here because they can be illustrative in the generated CDDL.
222223
key :: Maybe Key,
223224
value :: Type0,
224-
quantifier :: Occurs
225+
quantifier :: Occurs,
226+
description :: Maybe T.Text
225227
}
226228
deriving (Generic, Show)
227229

@@ -231,6 +233,7 @@ instance Num ArrayEntry where
231233
Nothing
232234
(NoChoice . T2Literal . Unranged $ LInt (fromIntegral i))
233235
def
236+
Nothing
234237
(+) = error "Cannot treat ArrayEntry as a number"
235238
(*) = error "Cannot treat ArrayEntry as a number"
236239
abs = error "Cannot treat ArrayEntry as a number"
@@ -584,7 +587,8 @@ instance IsEntryLike ArrayEntry where
584587
{ key = Just $ getField @"key" me,
585588
value =
586589
getField @"value" me,
587-
quantifier = getField @"quantifier" me
590+
quantifier = getField @"quantifier" me,
591+
description = Nothing
588592
}
589593

590594
instance IsEntryLike Type0 where
@@ -596,7 +600,8 @@ k ==> gc =
596600
MapEntry
597601
{ key = k,
598602
value = toType0 gc,
599-
quantifier = def
603+
quantifier = def,
604+
description = Nothing
600605
}
601606

602607
infixl 8 ==>
@@ -620,7 +625,8 @@ instance IsGroupOrArrayEntry ArrayEntry where
620625
ArrayEntry
621626
{ key = Nothing,
622627
value = toType0 x,
623-
quantifier = def
628+
quantifier = def,
629+
description = Nothing
624630
}
625631

626632
instance IsGroupOrArrayEntry Type0 where
@@ -899,9 +905,9 @@ collectFrom topRs =
899905
mapM_ goT2 $ args g
900906
goT2 (T2Basic (Constrained _ _ refs)) = mapM_ goRule refs
901907
goT2 _ = pure ()
902-
goArrayEntry (ArrayEntry (Just k) t0 _) = goKey k >> goT0 t0
903-
goArrayEntry (ArrayEntry Nothing t0 _) = goT0 t0
904-
goMapEntry (MapEntry k t0 _) = goKey k >> goT0 t0
908+
goArrayEntry (ArrayEntry (Just k) t0 _ _) = goKey k >> goT0 t0
909+
goArrayEntry (ArrayEntry Nothing t0 _ _) = goT0 t0
910+
goMapEntry (MapEntry k t0 _ _) = goKey k >> goT0 t0
905911
goKey (TypeKey k) = goT2 k
906912
goKey _ = pure ()
907913
goGroup (Group g) = mapM_ goT0 g
@@ -960,12 +966,15 @@ toCDDL' mkPseudoRoot hdl =
960966
mapChoiceToCDDL :: MapChoice -> C.GrpChoice
961967
mapChoiceToCDDL (MapChoice entries) = fmap mapEntryToCDDL entries
962968

963-
mapEntryToCDDL :: MapEntry -> C.GroupEntry
964-
mapEntryToCDDL (MapEntry k v occ) =
965-
C.GEType
966-
(toOccurrenceIndicator occ)
967-
(Just $ toMemberKey k)
968-
(toCDDLType0 v)
969+
mapEntryToCDDL :: MapEntry -> C.WithComments C.GroupEntry
970+
mapEntryToCDDL (MapEntry k v occ cmnt) =
971+
C.WithComments
972+
( C.GEType
973+
(toOccurrenceIndicator occ)
974+
(Just $ toMemberKey k)
975+
(toCDDLType0 v)
976+
)
977+
(fmap C.Comment cmnt)
969978

970979
toOccurrenceIndicator :: Occurs -> Maybe C.OccurrenceIndicator
971980
toOccurrenceIndicator (Occurs Nothing Nothing) = Nothing
@@ -1006,13 +1015,15 @@ toCDDL' mkPseudoRoot hdl =
10061015
arrayChoiceToCDDL :: ArrayChoice -> C.GrpChoice
10071016
arrayChoiceToCDDL (ArrayChoice entries) = fmap arrayEntryToCDDL entries
10081017

1009-
arrayEntryToCDDL :: ArrayEntry -> C.GroupEntry
1010-
arrayEntryToCDDL (ArrayEntry k v occ) =
1011-
C.GEType
1012-
(toOccurrenceIndicator occ)
1013-
(fmap toMemberKey k)
1014-
(toCDDLType0 v)
1015-
1018+
arrayEntryToCDDL :: ArrayEntry -> C.WithComments C.GroupEntry
1019+
arrayEntryToCDDL (ArrayEntry k v occ cmnt) =
1020+
C.WithComments
1021+
( C.GEType
1022+
(toOccurrenceIndicator occ)
1023+
(fmap toMemberKey k)
1024+
(toCDDLType0 v)
1025+
)
1026+
(fmap C.Comment cmnt)
10161027
toCDDLPostlude :: Value a -> C.Name
10171028
toCDDLPostlude VBool = C.Name "bool"
10181029
toCDDLPostlude VUInt = C.Name "uint"
@@ -1042,7 +1053,7 @@ toCDDL' mkPseudoRoot hdl =
10421053
. C.GEGroup Nothing
10431054
. C.Group
10441055
. (NE.:| [])
1045-
$ fmap (C.GEType Nothing Nothing . toCDDLType0) t0s
1056+
$ fmap (C.noComment . C.GEType Nothing Nothing . toCDDLType0) t0s
10461057
)
10471058
(fmap C.Comment c)
10481059

src/Codec/CBOR/Cuddle/Parser.hs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,11 @@ pGroup :: Parser Group
122122
pGroup = Group <$> NE.sepBy1 (space *> pGrpChoice <* space) (string "//")
123123

124124
pGrpChoice :: Parser GrpChoice
125-
pGrpChoice = many ((space *> pGrpEntry <* space) <* optional (char ','))
125+
pGrpChoice =
126+
many
127+
( (space *> (noComment <$> pGrpEntry) <* space)
128+
<* optional (char ',')
129+
)
126130

127131
pGrpEntry :: Parser GroupEntry
128132
pGrpEntry =

test/Test/Codec/CBOR/Cuddle/CDDL/Gen.hs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ instance Arbitrary Group where
167167
shrink (Group gr) = Group <$> shrinkNE gr
168168

169169
genGrpChoice :: Gen GrpChoice
170-
genGrpChoice = listOf' genGroupEntry
170+
genGrpChoice = listOf' (noComment <$> genGroupEntry)
171171

172172
genGroupEntry :: Gen GroupEntry
173173
genGroupEntry =
@@ -241,6 +241,11 @@ instance Arbitrary CtlOp where
241241
arbitrary = genCtlOp
242242
shrink = genericShrink
243243

244+
instance Arbitrary a => Arbitrary (WithComments a) where
245+
arbitrary = noComment <$> arbitrary
246+
shrink (WithComments x _) = noComment <$> shrink x
247+
248+
244249
--------------------------------------------------------------------------------
245250
-- Utility
246251
--------------------------------------------------------------------------------

test/Test/Codec/CBOR/Cuddle/CDDL/Parser.hs

Lines changed: 53 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,11 @@ type2Spec = describe "type2" $ do
161161
`shouldParse` T2Map
162162
( Group
163163
( (NE.:| [])
164-
[ GEType
165-
Nothing
166-
(Just (MKType (Type1 (T2Name (Name "int") Nothing) Nothing)))
167-
(Type0 ((NE.:| []) (Type1 (T2Name (Name "string") Nothing) Nothing)))
164+
[ noComment $
165+
GEType
166+
Nothing
167+
(Just (MKType (Type1 (T2Name (Name "int") Nothing) Nothing)))
168+
(Type0 ((NE.:| []) (Type1 (T2Name (Name "string") Nothing) Nothing)))
168169
]
169170
)
170171
)
@@ -173,10 +174,11 @@ type2Spec = describe "type2" $ do
173174
`shouldParse` T2Map
174175
( Group
175176
( (NE.:| [])
176-
[ GEType
177-
(Just OIZeroOrMore)
178-
(Just (MKType (Type1 (T2Name (Name "int") Nothing) Nothing)))
179-
(Type0 ((NE.:| []) (Type1 (T2Name (Name "string") Nothing) Nothing)))
177+
[ noComment $
178+
GEType
179+
(Just OIZeroOrMore)
180+
(Just (MKType (Type1 (T2Name (Name "int") Nothing) Nothing)))
181+
(Type0 ((NE.:| []) (Type1 (T2Name (Name "string") Nothing) Nothing)))
180182
]
181183
)
182184
)
@@ -185,27 +187,29 @@ type2Spec = describe "type2" $ do
185187
parse pType2 "" "[int // string]"
186188
`shouldParse` T2Array
187189
( Group
188-
( [ GEType
189-
Nothing
190-
Nothing
191-
( Type0
192-
( Type1
193-
(T2Name (Name "int") Nothing)
194-
Nothing
195-
NE.:| []
196-
)
197-
)
198-
]
199-
NE.:| [ [ GEType
200-
Nothing
190+
( [ noComment $
191+
GEType
192+
Nothing
193+
Nothing
194+
( Type0
195+
( Type1
196+
(T2Name (Name "int") Nothing)
201197
Nothing
202-
( Type0
203-
( Type1
204-
(T2Name (Name "string") Nothing)
205-
Nothing
206-
NE.:| []
207-
)
208-
)
198+
NE.:| []
199+
)
200+
)
201+
]
202+
NE.:| [ [ noComment $
203+
GEType
204+
Nothing
205+
Nothing
206+
( Type0
207+
( Type1
208+
(T2Name (Name "string") Nothing)
209+
Nothing
210+
NE.:| []
211+
)
212+
)
209213
]
210214
]
211215
)
@@ -215,15 +219,17 @@ type2Spec = describe "type2" $ do
215219
parse pType2 "" "[0 // 1]"
216220
`shouldParse` T2Array
217221
( Group
218-
( [ GEType
219-
Nothing
220-
Nothing
221-
(Type0 ((NE.:| []) (Type1 (T2Value (VUInt 0)) Nothing)))
222+
( [ noComment $
223+
GEType
224+
Nothing
225+
Nothing
226+
(Type0 ((NE.:| []) (Type1 (T2Value (VUInt 0)) Nothing)))
222227
]
223-
NE.:| [ [ GEType
224-
Nothing
225-
Nothing
226-
(Type0 ((NE.:| []) (Type1 (T2Value (VUInt 1)) Nothing)))
228+
NE.:| [ [ noComment $
229+
GEType
230+
Nothing
231+
Nothing
232+
(Type0 ((NE.:| []) (Type1 (T2Value (VUInt 1)) Nothing)))
227233
]
228234
]
229235
)
@@ -293,16 +299,17 @@ grpChoiceSpec :: SpecWith ()
293299
grpChoiceSpec = describe "GroupChoice" $ do
294300
it "Should parse part of a group alternative" $
295301
parse pGrpChoice "" "int // string"
296-
`shouldParse` [ GEType
297-
Nothing
298-
Nothing
299-
( Type0
300-
( Type1
301-
(T2Name (Name "int") Nothing)
302-
Nothing
303-
NE.:| []
304-
)
305-
)
302+
`shouldParse` [ noComment $
303+
GEType
304+
Nothing
305+
Nothing
306+
( Type0
307+
( Type1
308+
(T2Name (Name "int") Nothing)
309+
Nothing
310+
NE.:| []
311+
)
312+
)
306313
]
307314

308315
type1Spec :: Spec

0 commit comments

Comments
 (0)