8
8
{-# LANGUAGE TypeApplications #-}
9
9
{-# LANGUAGE TypeFamilies #-}
10
10
{-# LANGUAGE UndecidableInstances #-}
11
+ {-# LANGUAGE ViewPatterns #-}
11
12
{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
12
13
13
14
-- | Module for building CDDL in Haskell
@@ -76,10 +77,14 @@ module Codec.CBOR.Cuddle.Huddle
76
77
-- * Generics
77
78
GRef ,
78
79
GRuleDef ,
80
+ GRuleDef' ,
79
81
GRuleCall ,
82
+ GRuleCall' ,
80
83
binding ,
81
84
binding2 ,
85
+ binding' ,
82
86
callToDef ,
87
+ (<--) ,
83
88
84
89
-- * Conversion to CDDL
85
90
collectFrom ,
91
96
import Codec.CBOR.Cuddle.CDDL (CDDL )
92
97
import Codec.CBOR.Cuddle.CDDL qualified as C
93
98
import Codec.CBOR.Cuddle.CDDL.CtlOp qualified as CtlOp
99
+ import Codec.CBOR.Cuddle.Huddle.Generic (FnWithArg (.. ), result )
94
100
import Control.Monad (when )
95
101
import Control.Monad.State (MonadState (get ), execState , modify )
96
102
import Data.ByteString (ByteString )
@@ -128,6 +134,7 @@ type Rule = Named Type0
128
134
data HuddleItem
129
135
= HIRule Rule
130
136
| HIGRule GRuleDef
137
+ | HIGRule' GRuleDef'
131
138
| HIGroup (Named Group )
132
139
deriving (Generic , Show )
133
140
@@ -273,6 +280,7 @@ data Type2
273
280
| T2Group (Named Group )
274
281
| -- | Call to a generic rule, binding arguments
275
282
T2Generic GRuleCall
283
+ | T2Generic' GRuleCall'
276
284
| -- | Reference to a generic parameter within the body of the definition
277
285
T2GenericRef GRef
278
286
deriving (Show )
@@ -433,7 +441,7 @@ class IsSize a where
433
441
434
442
instance IsSize Word where
435
443
sizeAsCDDL = C. T2Value . C. VUInt . fromIntegral
436
- sizeAsString = show
444
+ sizeAsString = show
437
445
438
446
instance IsSize Word64 where
439
447
sizeAsCDDL = C. T2Value . C. VUInt
@@ -474,10 +482,13 @@ sized v sz =
474
482
}
475
483
[]
476
484
477
- class IsCborable a
478
- instance IsCborable ByteString
479
- instance IsCborable CRef
480
- instance IsCborable CGRef
485
+ class IsCborable a
486
+
487
+ instance IsCborable ByteString
488
+
489
+ instance IsCborable CRef
490
+
491
+ instance IsCborable CGRef
481
492
482
493
cbor :: (IsCborable b , IsConstrainable c b ) => c -> Rule -> Constrained
483
494
cbor v r@ (Named n _ _) =
@@ -492,9 +503,12 @@ cbor v r@(Named n _ _) =
492
503
}
493
504
[r]
494
505
495
- class IsComparable a
496
- instance IsComparable Int
497
- instance IsComparable CRef
506
+ class IsComparable a
507
+
508
+ instance IsComparable Int
509
+
510
+ instance IsComparable CRef
511
+
498
512
instance IsComparable CGRef
499
513
500
514
le :: (IsComparable a , IsConstrainable c a ) => c -> Word64 -> Constrained
@@ -512,16 +526,16 @@ le v bound =
512
526
513
527
-- Ranges
514
528
515
- data RangeBound =
516
- RangeBoundLiteral Literal
517
- | RangeBoundRef (Named Type0 )
518
- deriving Show
529
+ data RangeBound
530
+ = RangeBoundLiteral Literal
531
+ | RangeBoundRef (Named Type0 )
532
+ deriving ( Show )
519
533
520
534
class IsRangeBound a where
521
- toRangeBound :: a -> RangeBound
535
+ toRangeBound :: a -> RangeBound
522
536
523
537
instance IsRangeBound Literal where
524
- toRangeBound = RangeBoundLiteral
538
+ toRangeBound = RangeBoundLiteral
525
539
526
540
instance IsRangeBound Integer where
527
541
toRangeBound = RangeBoundLiteral . inferInteger
@@ -605,6 +619,9 @@ instance IsType0 (Named Group) where
605
619
instance IsType0 GRuleCall where
606
620
toType0 = NoChoice . T2Generic
607
621
622
+ instance IsType0 GRuleCall' where
623
+ toType0 = NoChoice . T2Generic'
624
+
608
625
instance IsType0 GRef where
609
626
toType0 = NoChoice . T2GenericRef
610
627
@@ -617,6 +634,9 @@ instance IsType0 HuddleItem where
617
634
toType0 (HIGRule g) =
618
635
error $
619
636
" Attempt to reference generic rule from HuddleItem not supported: " <> show g
637
+ toType0 (HIGRule' g) =
638
+ error $
639
+ " Attempt to reference generic rule from HuddleItem not supported: " <> show g
620
640
621
641
class CanQuantify a where
622
642
-- | Apply a lower bound
@@ -933,6 +953,50 @@ binding2 fRule t0 t1 =
933
953
NoChoice x -> x
934
954
_ -> error " Cannot use a choice of types as a generic argument"
935
955
956
+ --------------------------------------------------------------------------------
957
+ -- Generics (Take 2)
958
+ --------------------------------------------------------------------------------
959
+
960
+ type GRuleDef' = Named (FnWithArg GRef Type0 )
961
+
962
+ data GRuleCallAux = GRuleCallAux
963
+ { defFn :: FnWithArg GRef Type0 ,
964
+ callArg :: Type2
965
+ }
966
+
967
+ type GRuleCall' = Named GRuleCallAux
968
+
969
+ binding' :: (GRef -> Rule ) -> GRuleDef'
970
+ binding' fRule =
971
+ Named
972
+ (getField @ " name" $ result defFn)
973
+ (getField @ " value" <$> defFn)
974
+ Nothing
975
+ where
976
+ defFn = FnWithArg fRule (freshName 0 )
977
+
978
+ class IsGRuleDef f where
979
+ toGRuleDef :: f -> GRuleDef'
980
+
981
+ instance IsGRuleDef GRuleDef' where
982
+ toGRuleDef = id
983
+
984
+ instance IsGRuleDef HuddleItem where
985
+ toGRuleDef (HIGRule' gd) = gd
986
+ toGRuleDef _ = error " Attempt to use a non-generic rule as a GRuleDef"
987
+
988
+ (<--) :: (IsType0 t0 , IsGRuleDef gd ) => gd -> t0 -> GRuleCall'
989
+ (toGRuleDef -> f) <-- t0 = fmap toCall f
990
+ where
991
+ toCall rd =
992
+ GRuleCallAux
993
+ { defFn = rd,
994
+ callArg = t2
995
+ }
996
+ t2 = case toType0 t0 of
997
+ NoChoice x -> x
998
+ _ -> error " Cannot use a choice of types as a generic argument"
999
+
936
1000
--------------------------------------------------------------------------------
937
1001
-- Collecting all top-level rules
938
1002
--------------------------------------------------------------------------------
@@ -960,7 +1024,7 @@ collectFrom topRs =
960
1024
goChoice f (NoChoice x) = f x
961
1025
goChoice f (ChoiceOf x xs) = f x >> goChoice f xs
962
1026
goT0 = goChoice goT2
963
- goT2 (T2Range r) = goRanged r
1027
+ goT2 (T2Range r) = goRanged r
964
1028
goT2 (T2Map m) = goChoice (mapM_ goMapEntry . unMapChoice) m
965
1029
goT2 (T2Array m) = goChoice (mapM_ goArrayEntry . unArrayChoice) m
966
1030
goT2 (T2Tagged (Tagged _ t0)) = goT0 t0
@@ -993,10 +1057,10 @@ collectFrom topRs =
993
1057
goKey _ = pure ()
994
1058
goGroup (Group g) = mapM_ goArrayEntry g
995
1059
goRanged (Unranged _) = pure ()
996
- goRanged (Ranged lb ub _) = goRangeBound lb >> goRangeBound ub
1060
+ goRanged (Ranged lb ub _) = goRangeBound lb >> goRangeBound ub
997
1061
goRangeBound (RangeBoundLiteral _) = pure ()
998
1062
goRangeBound (RangeBoundRef r) = goRule r
999
-
1063
+
1000
1064
--------------------------------------------------------------------------------
1001
1065
-- Conversion to CDDL
1002
1066
--------------------------------------------------------------------------------
@@ -1022,6 +1086,7 @@ toCDDL' mkPseudoRoot hdl =
1022
1086
toCDDLItem (HIRule r) = toCDDLRule r
1023
1087
toCDDLItem (HIGroup g) = toCDDLGroup g
1024
1088
toCDDLItem (HIGRule g) = toGenRuleDef g
1089
+ toCDDLItem (HIGRule' g) = toGenRuleDef' g
1025
1090
toTopLevelPseudoRoot :: [Rule ] -> C. WithComments C. Rule
1026
1091
toTopLevelPseudoRoot topRs =
1027
1092
toCDDLRule $
@@ -1084,6 +1149,7 @@ toCDDL' mkPseudoRoot hdl =
1084
1149
T2Ref (Named n _ _) -> C. Type1 (C. T2Name (C. Name n) Nothing ) Nothing
1085
1150
T2Group (Named n _ _) -> C. Type1 (C. T2Name (C. Name n) Nothing ) Nothing
1086
1151
T2Generic g -> C. Type1 (toGenericCall g) Nothing
1152
+ T2Generic' g -> C. Type1 (toGenericCall' g) Nothing
1087
1153
T2GenericRef (GRef n) -> C. Type1 (C. T2Name (C. Name n) Nothing ) Nothing
1088
1154
1089
1155
toMemberKey :: Key -> C. MemberKey
@@ -1136,7 +1202,7 @@ toCDDL' mkPseudoRoot hdl =
1136
1202
(toCDDLRangeBound lb)
1137
1203
(Just (C. RangeOp rop, toCDDLRangeBound ub))
1138
1204
1139
- toCDDLRangeBound :: RangeBound -> C. Type2
1205
+ toCDDLRangeBound :: RangeBound -> C. Type2
1140
1206
toCDDLRangeBound (RangeBoundLiteral l) = C. T2Value $ toCDDLValue l
1141
1207
toCDDLRangeBound (RangeBoundRef (Named n _ _)) = C. T2Name (C. Name n) Nothing
1142
1208
@@ -1158,6 +1224,12 @@ toCDDL' mkPseudoRoot hdl =
1158
1224
(C. Name n)
1159
1225
(Just . C. GenericArg $ fmap toCDDLType1 (args gr))
1160
1226
1227
+ toGenericCall' :: GRuleCall' -> C. Type2
1228
+ toGenericCall' (Named n gr _) =
1229
+ C. T2Name
1230
+ (C. Name n)
1231
+ (Just . C. GenericArg $ NE. singleton (toCDDLType1 (callArg gr)))
1232
+
1161
1233
toGenRuleDef :: GRuleDef -> C. WithComments C. Rule
1162
1234
toGenRuleDef (Named n gr c) =
1163
1235
C. WithComments
@@ -1170,3 +1242,16 @@ toCDDL' mkPseudoRoot hdl =
1170
1242
where
1171
1243
gps =
1172
1244
C. GenericParam $ fmap (\ (GRef t) -> C. Name t) (args gr)
1245
+
1246
+ toGenRuleDef' :: GRuleDef' -> C. WithComments C. Rule
1247
+ toGenRuleDef' (Named n g c) =
1248
+ C. WithComments
1249
+ ( C. Rule (C. Name n) (Just gps) C. AssignEq
1250
+ . C. TOGType
1251
+ $ C. Type0
1252
+ $ toCDDLType1 <$> choiceToNE (fn g (arg g))
1253
+ )
1254
+ (fmap C. Comment c)
1255
+ where
1256
+ gps =
1257
+ C. GenericParam $ fmap (\ (GRef t) -> C. Name t) (NE. singleton $ arg g)
0 commit comments