module Text.RowRecord.TH
( rowRecords
) where
import Text.RowRecord
import Control.Applicative
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
getColumn :: Name -> Column
getColumn = f . nameBase where
f (break (=='_') -> (_, ('_':xs))) = xs
f n = error ("RowRecord: bad label: " ++ n)
rowRecords :: [Name] -> Q [Dec]
rowRecords ns = concat <$> mapM rowRecord ns
rowRecord :: Name -> Q [Dec]
rowRecord n = do
i <- reify n
case i of
TyConI (DataD _ _ _ [c] _) -> fromCon n c
TyConI (NewtypeD _ _ _ c _) -> fromCon n c
_ -> error ("RowRecord: not a data type: " ++ show n)
fromCon :: Name -> Con -> Q [Dec]
fromCon ty (RecC ctor fields) =
let gets m = [ [| getField $(lift $ getColumn n) $(varE m) |]
| (n,_,_) <- fields ]
splat a b = [| $a <*> $b |]
bdy = [| \m -> $(foldl1 splat ([| pure $(conE ctor) |] : gets 'm)) |]
in [d| instance ParseRow $(conT ty) where { parseRow = $bdy } |]
fromCon _ c = error ("RowRecord: not a record: " ++ show c)