{-# LANGUAGE CPP #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RecordWildCards #-}
#if __GLASGOW_HASKELL__ >= 800
{-# LANGUAGE TemplateHaskellQuotes #-}
#else
{-# LANGUAGE TemplateHaskell #-}
#endif
#if __GLASGOW_HASKELL__ >= 702
{-# LANGUAGE Trustworthy #-}
#endif
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ViewPatterns #-}
{-# OPTIONS -Wall #-}
module Data.Vector.Unboxed.Deriving
    ( 
      derivingUnbox
    ) where
#if !MIN_VERSION_base(4,8,0)
import Control.Applicative
#endif
import Control.Arrow
import Control.Monad
import Data.Char (isAlphaNum)
import qualified Data.Vector.Generic as G
import qualified Data.Vector.Generic.Mutable as M
import Data.Vector.Unboxed.Base (MVector (..), Vector (..), Unbox)
import Language.Haskell.TH
newPatExp :: String -> Q (Pat, Exp)
newPatExp :: String -> Q (Pat, Exp)
newPatExp = (Name -> (Pat, Exp)) -> Q Name -> Q (Pat, Exp)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Name -> Pat
VarP (Name -> Pat) -> (Name -> Exp) -> Name -> (Pat, Exp)
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& Name -> Exp
VarE) (Q Name -> Q (Pat, Exp))
-> (String -> Q Name) -> String -> Q (Pat, Exp)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Q Name
newName
data Common = Common
    { Common -> Name
mvName, Common -> Name
vName :: Name
    , Common -> (Pat, Exp)
i, Common -> (Pat, Exp)
n, Common -> (Pat, Exp)
mv, Common -> (Pat, Exp)
mv', Common -> (Pat, Exp)
v :: (Pat, Exp) }
common :: String -> Q Common
common :: String -> Q Common
common String
name = do
    
    let valid :: Char -> Bool
valid Char
c = Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'_' Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'\'' Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'#' Bool -> Bool -> Bool
|| Char -> Bool
isAlphaNum Char
c
    Bool -> Q () -> Q ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ((Char -> Bool) -> String -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Char -> Bool
valid String
name) (Q () -> Q ()) -> Q () -> Q ()
forall a b. (a -> b) -> a -> b
$ do
        String -> Q ()
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> String
forall a. Show a => a -> String
show String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" is not a valid constructor suffix!")
    let mvName :: Name
mvName = String -> Name
mkName (String
"MV_" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
name)
    let vName :: Name
vName = String -> Name
mkName (String
"V_" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
name)
    (Pat, Exp)
i <- String -> Q (Pat, Exp)
newPatExp String
"idx"
    (Pat, Exp)
n <- String -> Q (Pat, Exp)
newPatExp String
"len"
    (Pat, Exp)
mv  <- (Pat -> Pat) -> (Pat, Exp) -> (Pat, Exp)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first (Name -> [Pat] -> Pat
ConP Name
mvName ([Pat] -> Pat) -> (Pat -> [Pat]) -> Pat -> Pat
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Pat -> [Pat] -> [Pat]
forall a. a -> [a] -> [a]
:[])) ((Pat, Exp) -> (Pat, Exp)) -> Q (Pat, Exp) -> Q (Pat, Exp)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Q (Pat, Exp)
newPatExp String
"mvec"
    (Pat, Exp)
mv' <- (Pat -> Pat) -> (Pat, Exp) -> (Pat, Exp)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first (Name -> [Pat] -> Pat
ConP Name
mvName ([Pat] -> Pat) -> (Pat -> [Pat]) -> Pat -> Pat
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Pat -> [Pat] -> [Pat]
forall a. a -> [a] -> [a]
:[])) ((Pat, Exp) -> (Pat, Exp)) -> Q (Pat, Exp) -> Q (Pat, Exp)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Q (Pat, Exp)
newPatExp String
"mvec'"
    (Pat, Exp)
v   <- (Pat -> Pat) -> (Pat, Exp) -> (Pat, Exp)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first (Name -> [Pat] -> Pat
ConP Name
vName  ([Pat] -> Pat) -> (Pat -> [Pat]) -> Pat -> Pat
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Pat -> [Pat] -> [Pat]
forall a. a -> [a] -> [a]
:[])) ((Pat, Exp) -> (Pat, Exp)) -> Q (Pat, Exp) -> Q (Pat, Exp)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Q (Pat, Exp)
newPatExp String
"vec"
    Common -> Q Common
forall (m :: * -> *) a. Monad m => a -> m a
return Common :: Name
-> Name
-> (Pat, Exp)
-> (Pat, Exp)
-> (Pat, Exp)
-> (Pat, Exp)
-> (Pat, Exp)
-> Common
Common {Name
(Pat, Exp)
v :: (Pat, Exp)
mv' :: (Pat, Exp)
mv :: (Pat, Exp)
n :: (Pat, Exp)
i :: (Pat, Exp)
vName :: Name
mvName :: Name
v :: (Pat, Exp)
mv' :: (Pat, Exp)
mv :: (Pat, Exp)
n :: (Pat, Exp)
i :: (Pat, Exp)
vName :: Name
mvName :: Name
..}
capture :: Name -> Name
#if __GLASGOW_HASKELL__ == 704
capture = mkName . nameBase
#else
capture :: Name -> Name
capture = Name -> Name
forall a. a -> a
id
#endif
liftE :: Exp -> Exp -> Exp
liftE :: Exp -> Exp -> Exp
liftE Exp
e = Maybe Exp -> Exp -> Maybe Exp -> Exp
InfixE (Exp -> Maybe Exp
forall a. a -> Maybe a
Just Exp
e) (Name -> Exp
VarE 'liftM) (Maybe Exp -> Exp) -> (Exp -> Maybe Exp) -> Exp -> Exp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Exp -> Maybe Exp
forall a. a -> Maybe a
Just
wrap :: Name -> [(Pat, Exp)] -> (Exp -> Exp) -> [Dec]
wrap :: Name -> [(Pat, Exp)] -> (Exp -> Exp) -> [Dec]
wrap Name
fun ([(Pat, Exp)] -> ([Pat], [Exp])
forall a b. [(a, b)] -> ([a], [b])
unzip -> ([Pat]
pats, [Exp]
exps)) Exp -> Exp
coerce = [Dec
inline, Dec
method] where
    name :: Name
name = Name -> Name
capture Name
fun
#if MIN_VERSION_template_haskell(2,8,0)
    inline :: Dec
inline = Pragma -> Dec
PragmaD (Name -> Inline -> RuleMatch -> Phases -> Pragma
InlineP Name
name Inline
Inline RuleMatch
FunLike Phases
AllPhases)
#else
    inline = PragmaD ( InlineP name (InlineSpec True False Nothing) )
#endif
    body :: Exp
body = Exp -> Exp
coerce (Exp -> Exp) -> Exp -> Exp
forall a b. (a -> b) -> a -> b
$ (Exp -> Exp -> Exp) -> Exp -> [Exp] -> Exp
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl Exp -> Exp -> Exp
AppE (Name -> Exp
VarE Name
fun) [Exp]
exps
    method :: Dec
method = Name -> [Clause] -> Dec
FunD Name
name [[Pat] -> Body -> [Dec] -> Clause
Clause [Pat]
pats (Exp -> Body
NormalB Exp
body) []]
derivingUnbox
    :: String   
    -> TypeQ    
    -> ExpQ     
    -> ExpQ     
    -> DecsQ    
derivingUnbox :: String -> TypeQ -> ExpQ -> ExpQ -> DecsQ
derivingUnbox String
name TypeQ
argsQ ExpQ
toRepQ ExpQ
fromRepQ = do
    Common {Name
(Pat, Exp)
v :: (Pat, Exp)
mv' :: (Pat, Exp)
mv :: (Pat, Exp)
n :: (Pat, Exp)
i :: (Pat, Exp)
vName :: Name
mvName :: Name
v :: Common -> (Pat, Exp)
mv' :: Common -> (Pat, Exp)
mv :: Common -> (Pat, Exp)
n :: Common -> (Pat, Exp)
i :: Common -> (Pat, Exp)
vName :: Common -> Name
mvName :: Common -> Name
..} <- String -> Q Common
common String
name
    Exp
toRep <- ExpQ
toRepQ
    Exp
fromRep <- ExpQ
fromRepQ
    (Pat, Exp)
a <- (Exp -> Exp) -> (Pat, Exp) -> (Pat, Exp)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (d, b) (d, c)
second (Exp -> Exp -> Exp
AppE Exp
toRep) ((Pat, Exp) -> (Pat, Exp)) -> Q (Pat, Exp) -> Q (Pat, Exp)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Q (Pat, Exp)
newPatExp String
"val"
    Type
args <- TypeQ
argsQ
    (Cxt
cxts, Type
typ, Type
rep) <- case Type
args of
        ForallT [TyVarBndr]
_ Cxt
cxts (Type
ArrowT `AppT` Type
typ `AppT` Type
rep) -> (Cxt, Type, Type) -> Q (Cxt, Type, Type)
forall (m :: * -> *) a. Monad m => a -> m a
return (Cxt
cxts, Type
typ, Type
rep)
        Type
ArrowT `AppT` Type
typ `AppT` Type
rep -> (Cxt, Type, Type) -> Q (Cxt, Type, Type)
forall (m :: * -> *) a. Monad m => a -> m a
return ([], Type
typ, Type
rep)
        Type
_ -> String -> Q (Cxt, Type, Type)
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Expecting a type of the form: cxts => typ -> rep"
    let s :: Type
s = Name -> Type
VarT (String -> Name
mkName String
"s")
#if MIN_VERSION_template_haskell(2,11,0)
    let lazy :: Bang
lazy = SourceUnpackedness -> SourceStrictness -> Bang
Bang SourceUnpackedness
NoSourceUnpackedness SourceStrictness
NoSourceStrictness
# define MAYBE_OVERLAP Nothing
#else
    let lazy = NotStrict
# define MAYBE_OVERLAP
#endif
    let newtypeMVector :: Dec
newtypeMVector = Name -> Cxt -> Con -> Dec
newtypeInstD' ''MVector [Type
s, Type
typ]
            (Name -> [BangType] -> Con
NormalC Name
mvName [(Bang
lazy, Name -> Type
ConT ''MVector Type -> Type -> Type
`AppT` Type
s Type -> Type -> Type
`AppT` Type
rep)])
    let mvCon :: Exp
mvCon = Name -> Exp
ConE Name
mvName
    let instanceMVector :: Dec
instanceMVector = Maybe Overlap -> Cxt -> Type -> [Dec] -> Dec
InstanceD MAYBE_OVERLAP cxts
            (Name -> Type
ConT ''M.MVector Type -> Type -> Type
`AppT` Name -> Type
ConT ''MVector Type -> Type -> Type
`AppT` Type
typ) ([Dec] -> Dec) -> [Dec] -> Dec
forall a b. (a -> b) -> a -> b
$ [[Dec]] -> [Dec]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
            [ Name -> [(Pat, Exp)] -> (Exp -> Exp) -> [Dec]
wrap 'M.basicLength           [(Pat, Exp)
mv]        Exp -> Exp
forall a. a -> a
id
            , Name -> [(Pat, Exp)] -> (Exp -> Exp) -> [Dec]
wrap 'M.basicUnsafeSlice      [(Pat, Exp)
i, (Pat, Exp)
n, (Pat, Exp)
mv]  (Exp -> Exp -> Exp
AppE Exp
mvCon)
            , Name -> [(Pat, Exp)] -> (Exp -> Exp) -> [Dec]
wrap 'M.basicOverlaps         [(Pat, Exp)
mv, (Pat, Exp)
mv']   Exp -> Exp
forall a. a -> a
id
            , Name -> [(Pat, Exp)] -> (Exp -> Exp) -> [Dec]
wrap 'M.basicUnsafeNew        [(Pat, Exp)
n]         (Exp -> Exp -> Exp
liftE Exp
mvCon)
#if MIN_VERSION_vector(0,11,0)
            , Name -> [(Pat, Exp)] -> (Exp -> Exp) -> [Dec]
wrap 'M.basicInitialize       [(Pat, Exp)
mv]        Exp -> Exp
forall a. a -> a
id
#endif
            , Name -> [(Pat, Exp)] -> (Exp -> Exp) -> [Dec]
wrap 'M.basicUnsafeReplicate  [(Pat, Exp)
n, (Pat, Exp)
a]      (Exp -> Exp -> Exp
liftE Exp
mvCon)
            , Name -> [(Pat, Exp)] -> (Exp -> Exp) -> [Dec]
wrap 'M.basicUnsafeRead       [(Pat, Exp)
mv, (Pat, Exp)
i]     (Exp -> Exp -> Exp
liftE Exp
fromRep)
            , Name -> [(Pat, Exp)] -> (Exp -> Exp) -> [Dec]
wrap 'M.basicUnsafeWrite      [(Pat, Exp)
mv, (Pat, Exp)
i, (Pat, Exp)
a]  Exp -> Exp
forall a. a -> a
id
            , Name -> [(Pat, Exp)] -> (Exp -> Exp) -> [Dec]
wrap 'M.basicClear            [(Pat, Exp)
mv]        Exp -> Exp
forall a. a -> a
id
            , Name -> [(Pat, Exp)] -> (Exp -> Exp) -> [Dec]
wrap 'M.basicSet              [(Pat, Exp)
mv, (Pat, Exp)
a]     Exp -> Exp
forall a. a -> a
id
            , Name -> [(Pat, Exp)] -> (Exp -> Exp) -> [Dec]
wrap 'M.basicUnsafeCopy       [(Pat, Exp)
mv, (Pat, Exp)
mv']   Exp -> Exp
forall a. a -> a
id
            , Name -> [(Pat, Exp)] -> (Exp -> Exp) -> [Dec]
wrap 'M.basicUnsafeMove       [(Pat, Exp)
mv, (Pat, Exp)
mv']   Exp -> Exp
forall a. a -> a
id
            , Name -> [(Pat, Exp)] -> (Exp -> Exp) -> [Dec]
wrap 'M.basicUnsafeGrow       [(Pat, Exp)
mv, (Pat, Exp)
n]     (Exp -> Exp -> Exp
liftE Exp
mvCon) ]
    let newtypeVector :: Dec
newtypeVector = Name -> Cxt -> Con -> Dec
newtypeInstD' ''Vector [Type
typ]
            (Name -> [BangType] -> Con
NormalC Name
vName [(Bang
lazy, Name -> Type
ConT ''Vector Type -> Type -> Type
`AppT` Type
rep)])
    let vCon :: Exp
vCon  = Name -> Exp
ConE Name
vName
    let instanceVector :: Dec
instanceVector = Maybe Overlap -> Cxt -> Type -> [Dec] -> Dec
InstanceD MAYBE_OVERLAP cxts
            (Name -> Type
ConT ''G.Vector Type -> Type -> Type
`AppT` Name -> Type
ConT ''Vector Type -> Type -> Type
`AppT` Type
typ) ([Dec] -> Dec) -> [Dec] -> Dec
forall a b. (a -> b) -> a -> b
$ [[Dec]] -> [Dec]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
            [ Name -> [(Pat, Exp)] -> (Exp -> Exp) -> [Dec]
wrap 'G.basicUnsafeFreeze     [(Pat, Exp)
mv]        (Exp -> Exp -> Exp
liftE Exp
vCon)
            , Name -> [(Pat, Exp)] -> (Exp -> Exp) -> [Dec]
wrap 'G.basicUnsafeThaw       [(Pat, Exp)
v]         (Exp -> Exp -> Exp
liftE Exp
mvCon)
            , Name -> [(Pat, Exp)] -> (Exp -> Exp) -> [Dec]
wrap 'G.basicLength           [(Pat, Exp)
v]         Exp -> Exp
forall a. a -> a
id
            , Name -> [(Pat, Exp)] -> (Exp -> Exp) -> [Dec]
wrap 'G.basicUnsafeSlice      [(Pat, Exp)
i, (Pat, Exp)
n, (Pat, Exp)
v]   (Exp -> Exp -> Exp
AppE Exp
vCon)
            , Name -> [(Pat, Exp)] -> (Exp -> Exp) -> [Dec]
wrap 'G.basicUnsafeIndexM     [(Pat, Exp)
v, (Pat, Exp)
i]      (Exp -> Exp -> Exp
liftE Exp
fromRep)
            , Name -> [(Pat, Exp)] -> (Exp -> Exp) -> [Dec]
wrap 'G.basicUnsafeCopy       [(Pat, Exp)
mv, (Pat, Exp)
v]     Exp -> Exp
forall a. a -> a
id
            , Name -> [(Pat, Exp)] -> (Exp -> Exp) -> [Dec]
wrap 'G.elemseq               [(Pat, Exp)
v, (Pat, Exp)
a]      Exp -> Exp
forall a. a -> a
id ]
    [Dec] -> DecsQ
forall (m :: * -> *) a. Monad m => a -> m a
return [ Maybe Overlap -> Cxt -> Type -> [Dec] -> Dec
InstanceD MAYBE_OVERLAP Name -> Type
cxts (ConT ''Unbox `AppT` typ) []
        , Dec
newtypeMVector, Dec
instanceMVector
        , Dec
newtypeVector, Dec
instanceVector ]
newtypeInstD' :: Name -> [Type] -> Con -> Dec
newtypeInstD' :: Name -> Cxt -> Con -> Dec
newtypeInstD' Name
name Cxt
args Con
con = 
#if MIN_VERSION_template_haskell(2,15,0)
    Cxt
-> Maybe [TyVarBndr]
-> Type
-> Maybe Type
-> Con
-> [DerivClause]
-> Dec
NewtypeInstD [] Maybe [TyVarBndr]
forall a. Maybe a
Nothing ((Type -> Type -> Type) -> Type -> Cxt -> Type
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl Type -> Type -> Type
AppT (Name -> Type
ConT Name
name) Cxt
args) Maybe Type
forall a. Maybe a
Nothing Con
con []
#elif MIN_VERSION_template_haskell(2,11,0)
    NewtypeInstD [] name args Nothing con []
#else
    NewtypeInstD [] name args con []
#endif
#undef __GLASGOW_HASKELL__