Skip to content

Commit

Permalink
Generate Protocol instances via template-haskell (#71)
Browse files Browse the repository at this point in the history
This ensures that instances are available up to `maxTupleSize`.
  • Loading branch information
bgamari authored Apr 3, 2024
1 parent 84b5f78 commit 48b4b55
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 7 deletions.
1 change: 1 addition & 0 deletions clash-protocols.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ library
Protocols.Internal
Protocols.Internal.TaggedBundle
Protocols.Internal.TaggedBundle.TH
Protocols.Internal.TH
Protocols.Internal.Units
Protocols.Internal.Units.TH

Expand Down
15 changes: 9 additions & 6 deletions src/Protocols/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ import Clash.Prelude (Signal, type (+), type (*))
import qualified Clash.Prelude as C
import qualified Clash.Explicit.Prelude as CE

import Protocols.Internal.TH (protocolTupleInstances)
import Protocols.Cpp (maxTupleSize)

import Control.Arrow ((***))
import Data.Coerce (coerce)
import Data.Default (Default(def))
Expand Down Expand Up @@ -185,17 +188,17 @@ instance Protocol () where
type Fwd () = ()
type Bwd () = ()

-- | __NB__: The documentation only shows instances up to /3/-tuples. By
-- default, instances up to and including /12/-tuples will exist. If the flag
-- @large-tuples@ is set instances up to the GHC imposed limit will exist. The
-- GHC imposed limit is either 62 or 64 depending on the GHC version.
instance Protocol (a, b) where
type Fwd (a, b) = (Fwd a, Fwd b)
type Bwd (a, b) = (Bwd a, Bwd b)

instance Protocol (a, b, c) where
type Fwd (a, b, c) = (Fwd a, Fwd b, Fwd c)
type Bwd (a, b, c) = (Bwd a, Bwd b, Bwd c)

instance Protocol (a, b, c, d) where
type Fwd (a, b, c, d) = (Fwd a, Fwd b, Fwd c, Fwd d)
type Bwd (a, b, c, d) = (Bwd a, Bwd b, Bwd c, Bwd d)
-- Generate n-tuple instances, where n > 2
protocolTupleInstances maxTupleSize

instance C.KnownNat n => Protocol (C.Vec n a) where
type Fwd (C.Vec n a) = C.Vec n (Fwd a)
Expand Down
37 changes: 37 additions & 0 deletions src/Protocols/Internal/TH.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{-# OPTIONS_HADDOCK hide #-}

module Protocols.Internal.TH (protocolTupleInstances) where

import Language.Haskell.TH

appTs :: Q Type -> [Q Type] -> Q Type
appTs = foldl appT

protocolTupleInstances :: Int -> Q [Dec]
protocolTupleInstances n = mapM protocolTupleInstance [3..n]

protocolTupleInstance :: Int -> Q Dec
protocolTupleInstance n =
instanceD
(pure []) -- context
(protocolConT `appT` tup) -- head
[mkTyInst fwdConName, mkTyInst bwdConName] -- body

where
fwdConName = mkName "Fwd"
bwdConName = mkName "Bwd"
protocolConT = conT (mkName "Protocol")

tyVars :: [TypeQ]
tyVars = map (varT . mkName . ('a':) . show) [1..n]

tup = tupleT n `appTs` tyVars

mkTyInst :: Name -> DecQ
mkTyInst con =
tySynInstD $ tySynEqn Nothing lhs rhs
where
lhs, rhs :: TypeQ
lhs = conT con `appT` tup
rhs = tupleT n `appTs` map (conT con `appT`) tyVars

2 changes: 1 addition & 1 deletion src/Protocols/Internal/Units/TH.hs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{-# OPTIONS_HADDOCK hide #-}

module Protocols.Internal.Units.TH where
module Protocols.Internal.Units.TH (unitsTupleInstances) where

import Language.Haskell.TH

Expand Down

0 comments on commit 48b4b55

Please sign in to comment.