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 , TopLevel (.. ), WithComments (.. ))
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 )
@@ -475,9 +483,12 @@ sized v sz =
475
483
[]
476
484
477
485
class IsCborable a
486
+
478
487
instance IsCborable ByteString
479
- instance IsCborable (AnyRef a )
480
- instance IsCborable GRef
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 _ _) =
@@ -493,9 +504,12 @@ cbor v r@(Named n _ _) =
493
504
[r]
494
505
495
506
class IsComparable a
507
+
496
508
instance IsComparable Int
497
- instance IsComparable (AnyRef a )
498
- instance IsComparable GRef
509
+
510
+ instance IsComparable CRef
511
+
512
+ instance IsComparable CGRef
499
513
500
514
le :: (IsComparable a , IsConstrainable c a ) => c -> Word64 -> Constrained
501
515
le v bound =
@@ -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
--------------------------------------------------------------------------------
@@ -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
@@ -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
+ (C. comment <$> c)
1255
+ where
1256
+ gps =
1257
+ C. GenericParam $ fmap (\ (GRef t) -> C. Name t) (NE. singleton $ arg g)
0 commit comments