{-# OPTIONS_HADDOCK hide #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE TemplateHaskellQuotes #-}
module Clash.Sized.Vector.ToTuple.TH (vecToTupleInstance, vecToTupleInstances) where
import Clash.Sized.Vector (Vec((:>)))
import Language.Haskell.TH
appTs :: Q Type -> [Q Type] -> Q Type
appTs = foldl appT
appPsInfix :: Name -> [Q Pat] -> Q Pat
appPsInfix f = foldl1 (\l r -> uInfixP l f r)
tupT :: [Q Type] -> Q Type
tupT tyArgs = tupleT (length tyArgs) `appTs` tyArgs
vecToTupleInstances :: Integer -> Q [Dec]
vecToTupleInstances n = mapM vecToTupleInstance [3..n]
vecToTupleInstance :: Integer -> Q Dec
vecToTupleInstance n =
instanceD
(pure [])
(vecToTupleCon `appT` vecType)
[ tySynInstD
#if !MIN_VERSION_template_haskell(2,15,0)
(mkName "TupType")
#endif
( tySynEqn
#if MIN_VERSION_template_haskell(2,15,0)
Nothing aTypeLhs
#else
[vecType]
#endif
aTypeRhs )
, funD vecToTupleFunName [clause [vecToTuplePat] (normalB vecToTupleImpl) []]
]
where
vecToTupleCon = conT (mkName "VecToTuple")
vecType = conT ''Vec `appT` litT (numTyLit n) `appT` varT (mkName "a")
#if MIN_VERSION_template_haskell(2,15,0)
tupTypeCon = conT (mkName "TupType")
aTypeLhs = tupTypeCon `appT` vecType
#endif
aTypeRhs = tupT [varT (mkName "a") | _ <- [1..n]]
vecToTupleFunName = mkName "vecToTuple"
vecToTuplePat = appPsInfix '(:>) (map varP varNames ++ [wildP])
vecToTupleImpl = tupE (map varE varNames)
varNames = map (mkName . ('a':) . show) [1..n]