88{-# LANGUAGE TypeApplications #-}
99{-# LANGUAGE TypeFamilies #-}
1010{-# LANGUAGE UndecidableInstances #-}
11+ {-# LANGUAGE ViewPatterns #-}
1112{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
1213
1314-- | Module for building CDDL in Haskell
@@ -76,10 +77,14 @@ module Codec.CBOR.Cuddle.Huddle
7677 -- * Generics
7778 GRef ,
7879 GRuleDef ,
80+ GRuleDef' ,
7981 GRuleCall ,
82+ GRuleCall' ,
8083 binding ,
8184 binding2 ,
85+ binding' ,
8286 callToDef ,
87+ (<--) ,
8388
8489 -- * Conversion to CDDL
8590 collectFrom ,
9196import Codec.CBOR.Cuddle.CDDL (CDDL )
9297import Codec.CBOR.Cuddle.CDDL qualified as C
9398import Codec.CBOR.Cuddle.CDDL.CtlOp qualified as CtlOp
99+ import Codec.CBOR.Cuddle.Huddle.Generic (FnWithArg (.. ), result )
94100import Control.Monad (when )
95101import Control.Monad.State (MonadState (get ), execState , modify )
96102import Data.ByteString (ByteString )
@@ -128,6 +134,7 @@ type Rule = Named Type0
128134data HuddleItem
129135 = HIRule Rule
130136 | HIGRule GRuleDef
137+ | HIGRule' GRuleDef'
131138 | HIGroup (Named Group )
132139 deriving (Generic , Show )
133140
@@ -273,6 +280,7 @@ data Type2
273280 | T2Group (Named Group )
274281 | -- | Call to a generic rule, binding arguments
275282 T2Generic GRuleCall
283+ | T2Generic' GRuleCall'
276284 | -- | Reference to a generic parameter within the body of the definition
277285 T2GenericRef GRef
278286 deriving (Show )
@@ -433,7 +441,7 @@ class IsSize a where
433441
434442instance IsSize Word where
435443 sizeAsCDDL = C. T2Value . C. VUInt . fromIntegral
436- sizeAsString = show
444+ sizeAsString = show
437445
438446instance IsSize Word64 where
439447 sizeAsCDDL = C. T2Value . C. VUInt
@@ -474,10 +482,13 @@ sized v sz =
474482 }
475483 []
476484
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
481492
482493cbor :: (IsCborable b , IsConstrainable c b ) => c -> Rule -> Constrained
483494cbor v r@ (Named n _ _) =
@@ -492,9 +503,12 @@ cbor v r@(Named n _ _) =
492503 }
493504 [r]
494505
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+
498512instance IsComparable CGRef
499513
500514le :: (IsComparable a , IsConstrainable c a ) => c -> Word64 -> Constrained
@@ -512,16 +526,16 @@ le v bound =
512526
513527-- Ranges
514528
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 )
519533
520534class IsRangeBound a where
521- toRangeBound :: a -> RangeBound
535+ toRangeBound :: a -> RangeBound
522536
523537instance IsRangeBound Literal where
524- toRangeBound = RangeBoundLiteral
538+ toRangeBound = RangeBoundLiteral
525539
526540instance IsRangeBound Integer where
527541 toRangeBound = RangeBoundLiteral . inferInteger
@@ -605,6 +619,9 @@ instance IsType0 (Named Group) where
605619instance IsType0 GRuleCall where
606620 toType0 = NoChoice . T2Generic
607621
622+ instance IsType0 GRuleCall' where
623+ toType0 = NoChoice . T2Generic'
624+
608625instance IsType0 GRef where
609626 toType0 = NoChoice . T2GenericRef
610627
@@ -617,6 +634,9 @@ instance IsType0 HuddleItem where
617634 toType0 (HIGRule g) =
618635 error $
619636 " 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
620640
621641class CanQuantify a where
622642 -- | Apply a lower bound
@@ -933,6 +953,50 @@ binding2 fRule t0 t1 =
933953 NoChoice x -> x
934954 _ -> error " Cannot use a choice of types as a generic argument"
935955
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+
9361000--------------------------------------------------------------------------------
9371001-- Collecting all top-level rules
9381002--------------------------------------------------------------------------------
@@ -960,7 +1024,7 @@ collectFrom topRs =
9601024 goChoice f (NoChoice x) = f x
9611025 goChoice f (ChoiceOf x xs) = f x >> goChoice f xs
9621026 goT0 = goChoice goT2
963- goT2 (T2Range r) = goRanged r
1027+ goT2 (T2Range r) = goRanged r
9641028 goT2 (T2Map m) = goChoice (mapM_ goMapEntry . unMapChoice) m
9651029 goT2 (T2Array m) = goChoice (mapM_ goArrayEntry . unArrayChoice) m
9661030 goT2 (T2Tagged (Tagged _ t0)) = goT0 t0
@@ -993,10 +1057,10 @@ collectFrom topRs =
9931057 goKey _ = pure ()
9941058 goGroup (Group g) = mapM_ goArrayEntry g
9951059 goRanged (Unranged _) = pure ()
996- goRanged (Ranged lb ub _) = goRangeBound lb >> goRangeBound ub
1060+ goRanged (Ranged lb ub _) = goRangeBound lb >> goRangeBound ub
9971061 goRangeBound (RangeBoundLiteral _) = pure ()
9981062 goRangeBound (RangeBoundRef r) = goRule r
999-
1063+
10001064--------------------------------------------------------------------------------
10011065-- Conversion to CDDL
10021066--------------------------------------------------------------------------------
@@ -1022,6 +1086,7 @@ toCDDL' mkPseudoRoot hdl =
10221086 toCDDLItem (HIRule r) = toCDDLRule r
10231087 toCDDLItem (HIGroup g) = toCDDLGroup g
10241088 toCDDLItem (HIGRule g) = toGenRuleDef g
1089+ toCDDLItem (HIGRule' g) = toGenRuleDef' g
10251090 toTopLevelPseudoRoot :: [Rule ] -> C. WithComments C. Rule
10261091 toTopLevelPseudoRoot topRs =
10271092 toCDDLRule $
@@ -1084,6 +1149,7 @@ toCDDL' mkPseudoRoot hdl =
10841149 T2Ref (Named n _ _) -> C. Type1 (C. T2Name (C. Name n) Nothing ) Nothing
10851150 T2Group (Named n _ _) -> C. Type1 (C. T2Name (C. Name n) Nothing ) Nothing
10861151 T2Generic g -> C. Type1 (toGenericCall g) Nothing
1152+ T2Generic' g -> C. Type1 (toGenericCall' g) Nothing
10871153 T2GenericRef (GRef n) -> C. Type1 (C. T2Name (C. Name n) Nothing ) Nothing
10881154
10891155 toMemberKey :: Key -> C. MemberKey
@@ -1136,7 +1202,7 @@ toCDDL' mkPseudoRoot hdl =
11361202 (toCDDLRangeBound lb)
11371203 (Just (C. RangeOp rop, toCDDLRangeBound ub))
11381204
1139- toCDDLRangeBound :: RangeBound -> C. Type2
1205+ toCDDLRangeBound :: RangeBound -> C. Type2
11401206 toCDDLRangeBound (RangeBoundLiteral l) = C. T2Value $ toCDDLValue l
11411207 toCDDLRangeBound (RangeBoundRef (Named n _ _)) = C. T2Name (C. Name n) Nothing
11421208
@@ -1158,6 +1224,12 @@ toCDDL' mkPseudoRoot hdl =
11581224 (C. Name n)
11591225 (Just . C. GenericArg $ fmap toCDDLType1 (args gr))
11601226
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+
11611233 toGenRuleDef :: GRuleDef -> C. WithComments C. Rule
11621234 toGenRuleDef (Named n gr c) =
11631235 C. WithComments
@@ -1170,3 +1242,16 @@ toCDDL' mkPseudoRoot hdl =
11701242 where
11711243 gps =
11721244 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