{-# LANGUAGE TemplateHaskellQuotes #-}
module Clash.XException.TH
( mkShowXTupleInstances
, mkNFDataXTupleInstances
) where
import Data.Either (isLeft)
import Data.List (intersperse)
import Language.Haskell.TH.Syntax
isXName, hasUndefinedName, deepErrorXName, rnfXName, ensureSpineName :: Name
isXName :: Name
isXName = String -> Name
mkName "isX"
hasUndefinedName :: Name
hasUndefinedName = String -> Name
mkName "hasUndefined"
deepErrorXName :: Name
deepErrorXName = String -> Name
mkName "deepErrorX"
rnfXName :: Name
rnfXName = String -> Name
mkName "rnfX"
ensureSpineName :: Name
ensureSpineName = String -> Name
mkName "ensureSpine"
showxName :: Name
showxName :: Name
showxName = String -> Name
mkName "ShowX"
showXFnName :: Name
showXFnName :: Name
showXFnName = String -> Name
mkName "showX"
showsPrecXName :: Name
showsPrecXName :: Name
showsPrecXName = String -> Name
mkName "showsPrecX"
nfdataxName :: Name
nfdataxName :: Name
nfdataxName = String -> Name
mkName "NFDataX"
mkTup :: [Type] -> Type
mkTup :: [Type] -> Type
mkTup names :: [Type]
names@([Type] -> Int
forall (t :: Type -> Type) a. Foldable t => t a -> Int
length -> Int
n) =
(Type -> Type -> Type) -> Type -> [Type] -> Type
forall (t :: Type -> Type) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl Type -> Type -> Type
AppT (Int -> Type
TupleT Int
n) [Type]
names
mkShowXTupleInstance :: Int -> Dec
mkShowXTupleInstance :: Int -> Dec
mkShowXTupleInstance n :: Int
n =
Maybe Overlap -> [Type] -> Type -> [Dec] -> Dec
InstanceD Maybe Overlap
forall a. Maybe a
Nothing [Type]
constraints Type
instanceTyp [Dec
showsPrecXDecl, Dec
showXDecl]
where
constraints :: [Type]
constraints = (Type -> Type) -> [Type] -> [Type]
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap (Type -> Type -> Type
AppT (Name -> Type
ConT Name
showxName)) [Type]
vars
instanceTyp :: Type
instanceTyp = Name -> Type
ConT Name
showxName Type -> Type -> Type
`AppT` [Type] -> Type
mkTup [Type]
vars
names :: [Name]
names = (Int -> Name) -> [Int] -> [Name]
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap (String -> Name
mkName (String -> Name) -> (Int -> String) -> Int -> Name
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ('a'Char -> String -> String
forall a. a -> [a] -> [a]
:) (String -> String) -> (Int -> String) -> Int -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> String
forall a. Show a => a -> String
show) [0..Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-1]
vars :: [Type]
vars = (Name -> Type) -> [Name] -> [Type]
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap Name -> Type
VarT [Name]
names
x :: Name
x = String -> Name
mkName "x"
s :: Name
s = String -> Name
mkName "s"
showsPrecXDecl :: Dec
showsPrecXDecl = Name -> [Clause] -> Dec
FunD Name
showsPrecXName
[ [Pat] -> Body -> [Dec] -> Clause
Clause
[Pat
WildP, Name -> Pat
VarP Name
x, Name -> Pat
VarP Name
s]
(Exp -> Body
NormalB
(Name -> Exp
VarE 'mappend Exp -> Exp -> Exp
`AppE` (Name -> Exp
VarE Name
showXFnName Exp -> Exp -> Exp
`AppE` Name -> Exp
VarE Name
x) Exp -> Exp -> Exp
`AppE` Name -> Exp
VarE Name
s))
[]
]
showXDecl :: Dec
showXDecl = Name -> [Clause] -> Dec
FunD Name
showXFnName
[ [Pat] -> Body -> [Dec] -> Clause
Clause
[[Pat] -> Pat
TupP ((Name -> Pat) -> [Name] -> [Pat]
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap Name -> Pat
VarP [Name]
names)]
(Exp -> Body
NormalB
(Name -> Exp
VarE 'mconcat Exp -> Exp -> Exp
`AppE` ([Exp] -> Exp
ListE
([Lit -> Exp
LitE (String -> Lit
StringL "(")]
[Exp] -> [Exp] -> [Exp]
forall a. Semigroup a => a -> a -> a
<> Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
intersperse (Lit -> Exp
LitE (String -> Lit
StringL ",")) ((Name -> Exp) -> [Name] -> [Exp]
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap Name -> Exp
toShowX [Name]
names)
[Exp] -> [Exp] -> [Exp]
forall a. Semigroup a => a -> a -> a
<> [Lit -> Exp
LitE (String -> Lit
StringL ")")]))))
[]
]
where
toShowX :: Name -> Exp
toShowX a :: Name
a = Name -> Exp
VarE Name
showXFnName Exp -> Exp -> Exp
`AppE` Name -> Exp
VarE Name
a
mkShowXTupleInstances :: [Int] -> Q [Dec]
mkShowXTupleInstances :: [Int] -> Q [Dec]
mkShowXTupleInstances tupSizes :: [Int]
tupSizes =
[Dec] -> Q [Dec]
forall (m :: Type -> Type) a. Monad m => a -> m a
return ((Int -> Dec) -> [Int] -> [Dec]
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap Int -> Dec
mkShowXTupleInstance [Int]
tupSizes)
mkNFDataXTupleInstance :: Int -> Dec
mkNFDataXTupleInstance :: Int -> Dec
mkNFDataXTupleInstance n :: Int
n =
Maybe Overlap -> [Type] -> Type -> [Dec] -> Dec
InstanceD
Maybe Overlap
forall a. Maybe a
Nothing
[Type]
constraints
Type
instanceTyp
[ Dec
ensureSpineDecl
, Dec
hasUndefinedDecl
, Dec
deepErrorXDecl
, Dec
rnfXDecl
]
where
constraints :: [Type]
constraints = (Type -> Type) -> [Type] -> [Type]
forall a b. (a -> b) -> [a] -> [b]
map (Type -> Type -> Type
AppT (Name -> Type
ConT Name
nfdataxName)) [Type]
vars
instanceTyp :: Type
instanceTyp = Name -> Type
ConT Name
nfdataxName Type -> Type -> Type
`AppT` [Type] -> Type
mkTup [Type]
vars
names :: [Name]
names = (Int -> Name) -> [Int] -> [Name]
forall a b. (a -> b) -> [a] -> [b]
map (String -> Name
mkName (String -> Name) -> (Int -> String) -> Int -> Name
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ('a'Char -> String -> String
forall a. a -> [a] -> [a]
:) (String -> String) -> (Int -> String) -> Int -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> String
forall a. Show a => a -> String
show) [0..Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-1]
vars :: [Type]
vars = (Name -> Type) -> [Name] -> [Type]
forall a b. (a -> b) -> [a] -> [b]
map Name -> Type
VarT [Name]
names
t :: Name
t = String -> Name
mkName "t"
s :: Name
s = String -> Name
mkName "s"
rnfXDecl :: Dec
rnfXDecl = Name -> [Clause] -> Dec
FunD Name
rnfXName [
[Pat] -> Body -> [Dec] -> Clause
Clause
[Name -> Pat -> Pat
AsP Name
t (Pat -> Pat
TildeP ([Pat] -> Pat
TupP ((Name -> Pat) -> [Name] -> [Pat]
forall a b. (a -> b) -> [a] -> [b]
map Name -> Pat
VarP [Name]
names)))]
(Exp -> Body
NormalB (
Exp -> Exp -> Exp -> Exp
CondE
(Name -> Exp
VarE 'isLeft Exp -> Exp -> Exp
`AppE` (Name -> Exp
VarE Name
isXName Exp -> Exp -> Exp
`AppE` Name -> Exp
VarE Name
t))
([Exp] -> Exp
TupE [])
((Exp -> Exp -> Exp) -> Exp -> [Exp] -> Exp
forall (t :: Type -> Type) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl
(\e1 :: Exp
e1 e2 :: Exp
e2 -> Exp -> Exp -> Exp -> Exp
UInfixE Exp
e1 (Name -> Exp
VarE 'seq) (Name -> Exp
VarE Name
rnfXName Exp -> Exp -> Exp
`AppE` Exp
e2))
(Name -> Exp
VarE Name
rnfXName Exp -> Exp -> Exp
`AppE` Name -> Exp
VarE ([Name] -> Name
forall a. [a] -> a
head [Name]
names))
((Name -> Exp) -> [Name] -> [Exp]
forall a b. (a -> b) -> [a] -> [b]
map Name -> Exp
VarE ([Name] -> [Name]
forall a. [a] -> [a]
tail [Name]
names)))
))
[]
]
hasUndefinedDecl :: Dec
hasUndefinedDecl = Name -> [Clause] -> Dec
FunD Name
hasUndefinedName [
[Pat] -> Body -> [Dec] -> Clause
Clause
[Name -> Pat -> Pat
AsP Name
t (Pat -> Pat
TildeP ([Pat] -> Pat
TupP ((Name -> Pat) -> [Name] -> [Pat]
forall a b. (a -> b) -> [a] -> [b]
map Name -> Pat
VarP [Name]
names)))]
(Exp -> Body
NormalB (
Exp -> Exp -> Exp -> Exp
CondE
(Name -> Exp
VarE 'isLeft Exp -> Exp -> Exp
`AppE` (Name -> Exp
VarE Name
isXName Exp -> Exp -> Exp
`AppE` Name -> Exp
VarE Name
t))
(Name -> Exp
ConE 'True)
(Name -> Exp
VarE 'or Exp -> Exp -> Exp
`AppE` [Exp] -> Exp
ListE
((Name -> Exp) -> [Name] -> [Exp]
forall a b. (a -> b) -> [a] -> [b]
map ((Name -> Exp
VarE Name
hasUndefinedName Exp -> Exp -> Exp
`AppE`) (Exp -> Exp) -> (Name -> Exp) -> Name -> Exp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> Exp
VarE) [Name]
names))
))
[]
]
ensureSpineDecl :: Dec
ensureSpineDecl = Name -> [Clause] -> Dec
FunD Name
ensureSpineName [
[Pat] -> Body -> [Dec] -> Clause
Clause
[Pat -> Pat
TildeP ([Pat] -> Pat
TupP ((Name -> Pat) -> [Name] -> [Pat]
forall a b. (a -> b) -> [a] -> [b]
map Name -> Pat
VarP [Name]
names))]
(Exp -> Body
NormalB ([Exp] -> Exp
TupE ((Name -> Exp) -> [Name] -> [Exp]
forall a b. (a -> b) -> [a] -> [b]
map (Exp -> Exp -> Exp
AppE (Name -> Exp
VarE Name
ensureSpineName) (Exp -> Exp) -> (Name -> Exp) -> Name -> Exp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> Exp
VarE) [Name]
names)))
[]
]
deepErrorXDecl :: Dec
deepErrorXDecl = Name -> [Clause] -> Dec
FunD Name
deepErrorXName [
[Pat] -> Body -> [Dec] -> Clause
Clause
[Name -> Pat
VarP Name
s]
(Exp -> Body
NormalB ([Exp] -> Exp
TupE (Int -> Exp -> [Exp]
forall a. Int -> a -> [a]
replicate Int
n (Name -> Exp
VarE Name
deepErrorXName Exp -> Exp -> Exp
`AppE` Name -> Exp
VarE Name
s))))
[]
]
mkNFDataXTupleInstances :: [Int] -> Q [Dec]
mkNFDataXTupleInstances :: [Int] -> Q [Dec]
mkNFDataXTupleInstances tupSizes :: [Int]
tupSizes =
[Dec] -> Q [Dec]
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure ((Int -> Dec) -> [Int] -> [Dec]
forall a b. (a -> b) -> [a] -> [b]
map Int -> Dec
mkNFDataXTupleInstance [Int]
tupSizes)