{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE LambdaCase #-}
module Generics.Linear.TH.Internal where
import Control.Monad (unless)
import Data.Foldable (foldr')
import qualified Data.List as List
import qualified Data.Set as Set
import Data.Set (Set)
import Language.Haskell.TH.Datatype
import Language.Haskell.TH.Datatype.TyVarBndr
import Language.Haskell.TH.Lib
import Language.Haskell.TH.Ppr (pprint)
import Language.Haskell.TH.Syntax hiding (Extension (..))
typeKind :: Type -> Kind
typeKind :: Type -> Type
typeKind (SigT Type
_ Type
k) = Type
k
typeKind Type
_ = Type
starK
makeFunType :: [Type] -> Type -> Type
makeFunType :: [Type] -> Type -> Type
makeFunType [Type]
argTys Type
resTy = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr' (Type -> Type -> Type
AppT forall b c a. (b -> c) -> (a -> b) -> a -> c
. Type -> Type -> Type
AppT Type
ArrowT) Type
resTy [Type]
argTys
makeFunKind :: [Kind] -> Kind -> Kind
makeFunKind :: [Type] -> Type -> Type
makeFunKind = [Type] -> Type -> Type
makeFunType
dustOff :: Type -> Type
dustOff :: Type -> Type
dustOff (SigT Type
ty Type
_) = Type -> Type
dustOff Type
ty
dustOff (ParensT Type
ty) = Type -> Type
dustOff Type
ty
dustOff (InfixT Type
ty1 Name
n Type
ty2) = Name -> Type
ConT Name
n Type -> Type -> Type
`AppT` Type
ty1 Type -> Type -> Type
`AppT` Type
ty2
dustOff Type
ty = Type
ty
isUnsaturatedType :: Type -> Q Bool
isUnsaturatedType :: Type -> Q Bool
isUnsaturatedType = Int -> Type -> Q Bool
go Int
0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Type -> Type
dustOff
where
go :: Int -> Type -> Q Bool
go :: Int -> Type -> Q Bool
go Int
d Type
t = case Type
t of
ConT Name
tcName -> Int -> Name -> Q Bool
check Int
d Name
tcName
AppT Type
f Type
_ -> Int -> Type -> Q Bool
go (Int
d forall a. Num a => a -> a -> a
+ Int
1) (Type -> Type
dustOff Type
f)
Type
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
check :: Int -> Name -> Q Bool
check :: Int -> Name -> Q Bool
check Int
d Name
tcName = do
Maybe [TyVarBndr_ ()]
mbinders <- Name -> Q (Maybe [TyVarBndr_ ()])
getTypeFamilyBinders Name
tcName
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ case Maybe [TyVarBndr_ ()]
mbinders of
Just [TyVarBndr_ ()]
bndrs -> forall (t :: * -> *) a. Foldable t => t a -> Int
length [TyVarBndr_ ()]
bndrs forall a. Ord a => a -> a -> Bool
> Int
d
Maybe [TyVarBndr_ ()]
Nothing -> Bool
False
getTypeFamilyBinders :: Name -> Q (Maybe [TyVarBndr_ ()])
getTypeFamilyBinders :: Name -> Q (Maybe [TyVarBndr_ ()])
getTypeFamilyBinders Name
tcName = do
Info
info <- Name -> Q Info
reify Name
tcName
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ case Info
info of
FamilyI (OpenTypeFamilyD (TypeFamilyHead Name
_ [TyVarBndr_ ()]
bndrs FamilyResultSig
_ Maybe InjectivityAnn
_)) [Dec]
_
-> forall a. a -> Maybe a
Just [TyVarBndr_ ()]
bndrs
FamilyI (ClosedTypeFamilyD (TypeFamilyHead Name
_ [TyVarBndr_ ()]
bndrs FamilyResultSig
_ Maybe InjectivityAnn
_) [TySynEqn]
_) [Dec]
_
-> forall a. a -> Maybe a
Just [TyVarBndr_ ()]
bndrs
Info
_ -> forall a. Maybe a
Nothing
ground :: Type -> Name -> Bool
ground :: Type -> Name -> Bool
ground Type
ty Name
name = Name
name forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` forall a. TypeSubstitution a => a -> [Name]
freeVariables Type
ty
applyTyToTys :: Type -> [Type] -> Type
applyTyToTys :: Type -> [Type] -> Type
applyTyToTys = forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
List.foldl' Type -> Type -> Type
AppT
newNameList :: String -> Int -> Q [Name]
newNameList :: String -> Int -> Q [Name]
newNameList String
prefix Int
n = forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (forall (m :: * -> *). Quote m => String -> m Name
newName forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
prefix forall a. [a] -> [a] -> [a]
++) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> String
show) [Int
1..Int
n]
canEtaReduce :: [Type] -> [Type] -> Bool
canEtaReduce :: [Type] -> [Type] -> Bool
canEtaReduce [Type]
remaining [Type]
dropped =
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Type -> Bool
isTyVar [Type]
dropped
Bool -> Bool -> Bool
&& forall a. Ord a => [a] -> Bool
allDistinct [Name]
droppedNames
Bool -> Bool -> Bool
&& Bool -> Bool
not (forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Type -> [Name] -> Bool
`mentionsName` [Name]
droppedNames) [Type]
remaining)
where
droppedNames :: [Name]
droppedNames :: [Name]
droppedNames = forall a b. (a -> b) -> [a] -> [b]
map Type -> Name
varTToName [Type]
dropped
varTToName :: Type -> Name
varTToName :: Type -> Name
varTToName (VarT Name
n) = Name
n
varTToName (SigT Type
t Type
_) = Type -> Name
varTToName Type
t
varTToName Type
_ = forall a. HasCallStack => String -> a
error String
"Not a type variable!"
isTyVar :: Type -> Bool
isTyVar :: Type -> Bool
isTyVar VarT{} = Bool
True
isTyVar (SigT Type
t Type
_) = Type -> Bool
isTyVar Type
t
isTyVar Type
_ = Bool
False
isKindVar :: Kind -> Bool
isKindVar :: Type -> Bool
isKindVar = Type -> Bool
isTyVar
mentionsName :: Type -> [Name] -> Bool
mentionsName :: Type -> [Name] -> Bool
mentionsName = Type -> [Name] -> Bool
go
where
go :: Type -> [Name] -> Bool
go :: Type -> [Name] -> Bool
go (AppT Type
t1 Type
t2) [Name]
names = Type -> [Name] -> Bool
go Type
t1 [Name]
names Bool -> Bool -> Bool
|| Type -> [Name] -> Bool
go Type
t2 [Name]
names
go (SigT Type
t Type
k) [Name]
names = Type -> [Name] -> Bool
go Type
t [Name]
names Bool -> Bool -> Bool
|| Type -> [Name] -> Bool
go Type
k [Name]
names
go (VarT Name
n) [Name]
names = Name
n forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Name]
names
go Type
_ [Name]
_ = Bool
False
allDistinct :: Ord a => [a] -> Bool
allDistinct :: forall a. Ord a => [a] -> Bool
allDistinct = forall a. Ord a => Set a -> [a] -> Bool
allDistinct' forall a. Set a
Set.empty
where
allDistinct' :: Ord a => Set a -> [a] -> Bool
allDistinct' :: forall a. Ord a => Set a -> [a] -> Bool
allDistinct' Set a
uniqs (a
x:[a]
xs)
| a
x forall a. Ord a => a -> Set a -> Bool
`Set.member` Set a
uniqs = Bool
False
| Bool
otherwise = forall a. Ord a => Set a -> [a] -> Bool
allDistinct' (forall a. Ord a => a -> Set a -> Set a
Set.insert a
x Set a
uniqs) [a]
xs
allDistinct' Set a
_ [a]
_ = Bool
True
fst3 :: (a, b, c) -> a
fst3 :: forall a b c. (a, b, c) -> a
fst3 (a
a, b
_, c
_) = a
a
snd3 :: (a, b, c) -> b
snd3 :: forall a b c. (a, b, c) -> b
snd3 (a
_, b
b, c
_) = b
b
trd3 :: (a, b, c) -> c
trd3 :: forall a b c. (a, b, c) -> c
trd3 (a
_, b
_, c
c) = c
c
foldBal :: (a -> a -> a) -> a -> [a] -> a
{-# INLINE foldBal #-}
foldBal :: forall a. (a -> a -> a) -> a -> [a] -> a
foldBal a -> a -> a
op0 a
x0 [a]
xs0 = forall {t}. (t -> t -> t) -> t -> Int -> [t] -> t
fold_bal a -> a -> a
op0 a
x0 (forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
xs0) [a]
xs0
where
fold_bal :: (t -> t -> t) -> t -> Int -> [t] -> t
fold_bal t -> t -> t
op t
x !Int
n [t]
xs = case [t]
xs of
[] -> t
x
[t
a] -> t
a
[t]
_ -> let !nl :: Int
nl = Int
n forall a. Integral a => a -> a -> a
`div` Int
2
!nr :: Int
nr = Int
n forall a. Num a => a -> a -> a
- Int
nl
([t]
l,[t]
r) = forall a. Int -> [a] -> ([a], [a])
splitAt Int
nl [t]
xs
in (t -> t -> t) -> t -> Int -> [t] -> t
fold_bal t -> t -> t
op t
x Int
nl [t]
l
t -> t -> t
`op` (t -> t -> t) -> t -> Int -> [t] -> t
fold_bal t -> t -> t
op t
x Int
nr [t]
r
isNewtypeVariant :: DatatypeVariant_ -> Bool
isNewtypeVariant :: DatatypeVariant_ -> Bool
isNewtypeVariant DatatypeVariant_
Datatype_ = Bool
False
isNewtypeVariant DatatypeVariant_
Newtype_ = Bool
True
isNewtypeVariant (DataInstance_ {}) = Bool
False
isNewtypeVariant (NewtypeInstance_ {}) = Bool
True
data GenericClass = Generic | Generic1 deriving Int -> GenericClass
GenericClass -> Int
GenericClass -> [GenericClass]
GenericClass -> GenericClass
GenericClass -> GenericClass -> [GenericClass]
GenericClass -> GenericClass -> GenericClass -> [GenericClass]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: GenericClass -> GenericClass -> GenericClass -> [GenericClass]
$cenumFromThenTo :: GenericClass -> GenericClass -> GenericClass -> [GenericClass]
enumFromTo :: GenericClass -> GenericClass -> [GenericClass]
$cenumFromTo :: GenericClass -> GenericClass -> [GenericClass]
enumFromThen :: GenericClass -> GenericClass -> [GenericClass]
$cenumFromThen :: GenericClass -> GenericClass -> [GenericClass]
enumFrom :: GenericClass -> [GenericClass]
$cenumFrom :: GenericClass -> [GenericClass]
fromEnum :: GenericClass -> Int
$cfromEnum :: GenericClass -> Int
toEnum :: Int -> GenericClass
$ctoEnum :: Int -> GenericClass
pred :: GenericClass -> GenericClass
$cpred :: GenericClass -> GenericClass
succ :: GenericClass -> GenericClass
$csucc :: GenericClass -> GenericClass
Enum
data GenericTvbs
= Gen0
{ GenericTvbs -> [TyVarBndr_ ()]
gen0Tvbs :: [TyVarBndrUnit]
}
| Gen1
{ GenericTvbs -> [TyVarBndr_ ()]
gen1InitTvbs :: [TyVarBndrUnit]
, GenericTvbs -> Name
gen1LastTvbName :: Name
}
mkGenericTvbs :: GenericClass -> [Type] -> GenericTvbs
mkGenericTvbs :: GenericClass -> [Type] -> GenericTvbs
mkGenericTvbs GenericClass
gClass [Type]
tySynVars =
case GenericClass
gClass of
GenericClass
Generic -> Gen0{gen0Tvbs :: [TyVarBndr_ ()]
gen0Tvbs = [Type] -> [TyVarBndr_ ()]
freeVariablesWellScoped [Type]
tySynVars}
GenericClass
Generic1 -> Gen1{ gen1InitTvbs :: [TyVarBndr_ ()]
gen1InitTvbs = [Type] -> [TyVarBndr_ ()]
freeVariablesWellScoped [Type]
initArgs
, gen1LastTvbName :: Name
gen1LastTvbName = Type -> Name
varTToName Type
lastArg
}
where
initArgs :: [Type]
initArgs :: [Type]
initArgs = forall a. [a] -> [a]
init [Type]
tySynVars
lastArg :: Type
lastArg :: Type
lastArg = forall a. [a] -> a
last [Type]
tySynVars
genericInitTvbs :: GenericTvbs -> [TyVarBndrUnit]
genericInitTvbs :: GenericTvbs -> [TyVarBndr_ ()]
genericInitTvbs (Gen0{gen0Tvbs :: GenericTvbs -> [TyVarBndr_ ()]
gen0Tvbs = [TyVarBndr_ ()]
tvbs}) = [TyVarBndr_ ()]
tvbs
genericInitTvbs (Gen1{gen1InitTvbs :: GenericTvbs -> [TyVarBndr_ ()]
gen1InitTvbs = [TyVarBndr_ ()]
tvbs}) = [TyVarBndr_ ()]
tvbs
data DatatypeVariant_
= Datatype_
| Newtype_
| DataInstance_ ConstructorInfo
| NewtypeInstance_ ConstructorInfo
etaReductionError :: Type -> Q a
etaReductionError :: forall a. Type -> Q a
etaReductionError Type
instanceType = forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall a b. (a -> b) -> a -> b
$
String
"Cannot eta-reduce to an instance of form \n\tinstance (...) => "
forall a. [a] -> [a] -> [a]
++ forall a. Ppr a => a -> String
pprint Type
instanceType
derivingKindError :: Name -> Q a
derivingKindError :: forall a. Name -> Q a
derivingKindError Name
tyConName = forall (m :: * -> *) a. MonadFail m => String -> m a
fail
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> String
showString String
"Cannot derive well-kinded instance of form ‘Generic1 "
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> (String -> String) -> String -> String
showParen Bool
True
( String -> String -> String
showString (Name -> String
nameBase Name
tyConName)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> String
showString String
" ..."
)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> String
showString String
"‘\n\tClass Generic1 expects an argument of kind k -> Type"
forall a b. (a -> b) -> a -> b
$ String
""
outOfPlaceTyVarError :: Q a
outOfPlaceTyVarError :: forall a. Q a
outOfPlaceTyVarError = forall (m :: * -> *) a. MonadFail m => String -> m a
fail
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> String
showString String
"Constructor must only use its last type variable as"
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> String
showString String
" the last argument of a data type"
forall a b. (a -> b) -> a -> b
$ String
""
typeFamilyApplicationError :: Q a
typeFamilyApplicationError :: forall a. Q a
typeFamilyApplicationError = forall (m :: * -> *) a. MonadFail m => String -> m a
fail
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> String
showString String
"Constructor must not apply its last type variable"
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> String
showString String
" to an unsaturated type family"
forall a b. (a -> b) -> a -> b
$ String
""
rankNError :: Q a
rankNError :: forall a. Q a
rankNError = forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Cannot have polymorphic arguments"
reifyDataInfo :: Name
-> Q (Name, [Type], [ConstructorInfo], DatatypeVariant_)
reifyDataInfo :: Name -> Q (Name, [Type], [ConstructorInfo], DatatypeVariant_)
reifyDataInfo Name
name = do
do
DatatypeInfo { datatypeContext :: DatatypeInfo -> [Type]
datatypeContext = [Type]
ctxt
, datatypeName :: DatatypeInfo -> Name
datatypeName = Name
parentName
, datatypeInstTypes :: DatatypeInfo -> [Type]
datatypeInstTypes = [Type]
tys
, datatypeVariant :: DatatypeInfo -> DatatypeVariant
datatypeVariant = DatatypeVariant
variant
, datatypeCons :: DatatypeInfo -> [ConstructorInfo]
datatypeCons = [ConstructorInfo]
cons
} <-
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String
ns forall a. [a] -> [a] -> [a]
++ String
" Could not reify " forall a. [a] -> [a] -> [a]
++ Name -> String
nameBase Name
name)
forall a. Q a -> Q a -> Q a
`recover`
Name -> Q DatatypeInfo
reifyDatatype Name
name
DatatypeVariant_
variant_ <- case DatatypeVariant
variant of
DatatypeVariant
Datatype -> forall (f :: * -> *) a. Applicative f => a -> f a
pure DatatypeVariant_
Datatype_
DatatypeVariant
Newtype -> forall (f :: * -> *) a. Applicative f => a -> f a
pure DatatypeVariant_
Newtype_
DatatypeVariant
DataInstance -> forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ ConstructorInfo -> DatatypeVariant_
DataInstance_ (forall a. [a] -> a
head [ConstructorInfo]
cons)
DatatypeVariant
NewtypeInstance -> forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ ConstructorInfo -> DatatypeVariant_
NewtypeInstance_ (forall a. [a] -> a
head [ConstructorInfo]
cons)
DatatypeVariant
TypeData -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall a b. (a -> b) -> a -> b
$ String
"Cannot derive Generic instances for TypeData " forall a. [a] -> [a] -> [a]
++ Name -> String
nameBase Name
name
Name -> [Type] -> Q ()
checkDataContext Name
parentName [Type]
ctxt
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Name
parentName, [Type]
tys, [ConstructorInfo]
cons, DatatypeVariant_
variant_)
where
ns :: String
ns :: String
ns = String
"Generics.Linear.TH.reifyDataInfo: "
checkDataContext :: Name -> Cxt -> Q ()
checkDataContext :: Name -> [Type] -> Q ()
checkDataContext Name
_ [] = forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
checkDataContext Name
dataName [Type]
_ = forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall a b. (a -> b) -> a -> b
$
Name -> String
nameBase Name
dataName forall a. [a] -> [a] -> [a]
++ String
" must not have a datatype context"
checkExistentialContext :: Name -> [TyVarBndrUnit] -> Cxt -> Q ()
checkExistentialContext :: Name -> [TyVarBndr_ ()] -> [Type] -> Q ()
checkExistentialContext Name
conName [TyVarBndr_ ()]
vars [Type]
ctxt =
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (forall (t :: * -> *) a. Foldable t => t a -> Bool
null [TyVarBndr_ ()]
vars Bool -> Bool -> Bool
&& forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Type]
ctxt) forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall a b. (a -> b) -> a -> b
$
Name -> String
nameBase Name
conName forall a. [a] -> [a] -> [a]
++ String
" must be a vanilla data constructor"