{-# LANGUAGE TemplateHaskell #-} module ADP.Fusion.TH where import Language.Haskell.TH import Language.Haskell.TH.Syntax import Data.List import qualified Data.Vector.Fusion.Stream.Monadic as SM -- | Create the algebra product function from a signature type constructor. makeAlgebraProduct :: Name -> Q [Dec] makeAlgebraProduct nm = do rnm <- reify nm case rnm of TyConI (DataD ctx tyConName args cs d) -> case cs of -- we analyze the accessor functions and look for the objective function -- accessor. It's stream parameter is the type of the non-terminal. -- Everything else in accessors are terminal parameters. [RecC dataConName fs] -> do -- find the objective function type (we crash if the user has more than -- one) let [oF] = filter (isObjectiveF . sel3) fs error $ unlines $ intersperse "\n" $ map show fs _ -> fail "more than one data ctor" _ -> fail "unsupported data type" sel3 (a,b,c) = c zzz :: VarStrictType -> String zzz (nm,s,t) = show (nm,s,t) isObjectiveF :: Type -> Bool isObjectiveF (AppT (AppT ArrowT (AppT (AppT (ConT s) _) _)) (AppT _ _)) | s == ''SM.Stream = True isObjectiveF _ = False -- AppT (AppT ArrowT -- (AppT (AppT (ConT Data.Vector.Fusion.Stream.Monadic.Stream) -- (VarT m_1627401654) -- ) -- (VarT x_1627401655) -- ) -- ) -- (AppT (VarT m_1627401654) (VarT r_1627401656))