packages feed

clash-prelude-1.10.0: src/Clash/Sized/Vector/ToTuple/TH.hs

{-# OPTIONS_HADDOCK hide #-}

{-# 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
    -- No superclasses
    (pure [])

    -- Head
    (vecToTupleCon `appT` vecType)

    -- Implementation
    [ tySynInstD (tySynEqn Nothing aTypeLhs aTypeRhs)
    , funD vecToTupleFunName [clause [vecToTuplePat] (normalB vecToTupleImpl) []]
    ]

 where
  vecToTupleCon = conT (mkName "VecToTuple")
  vecType = conT ''Vec `appT` litT (numTyLit n) `appT` varT (mkName "a")

  -- associated type
  tupTypeCon = conT (mkName "TupType")
  aTypeLhs = tupTypeCon `appT` vecType
  aTypeRhs = tupT [varT (mkName "a") | _ <- [1..n]]

  -- vecToTuple
  vecToTupleFunName = mkName "vecToTuple"
  vecToTuplePat = appPsInfix '(:>) (map varP varNames ++ [wildP])
  vecToTupleImpl = tupE (map varE varNames)

  varNames = map (mkName . ('a':) . show) [1..n]