module Hasql.TH where
import Hasql.Prelude
import Language.Haskell.TH
import qualified Data.Vector as Vector
import qualified Data.Vector.Mutable as MVector
applicativeE :: Exp -> [Exp] -> Exp
applicativeE head =
\case
[] -> error "Empty expressions list"
exps ->
reduce $
head : VarE '(<$>) : intersperse (VarE '(<*>)) exps
where
reduce =
\case
e : o : t -> UInfixE e o (reduce t)
e : [] -> e
_ -> error $ "Unexpected queue size. Exps: " <> show exps
purify :: Q a -> a
purify = unsafePerformIO . runQ
vectorLamE :: Int -> Exp
vectorLamE arity =
LamE (map VarP argNames) body
where
argNames =
map (mkName . ('_' :) . show) [1 .. arity]
body =
vectorE $ map VarE argNames
vectorE :: [Exp] -> Exp
vectorE cellExps =
if null cellExps
then
VarE 'Vector.empty
else
AppE (VarE 'runST) $ DoE $
pure vectorDeclarationStmt <> cellAssignmentStmts <> pure freezingStmt
where
vectorVarName =
mkName "v"
vectorDeclarationStmt =
(BindS
(VarP vectorVarName)
(AppE
(VarE 'MVector.unsafeNew)
(LitE (IntegerL (fromIntegral (length cellExps))))))
cellAssignmentStmts =
map (NoBindS . uncurry cellAssignmentExp) $ zip [0..] cellExps
where
cellAssignmentExp index exp =
(AppE
(AppE
(AppE
(VarE 'MVector.unsafeWrite)
(VarE vectorVarName))
(LitE (IntegerL (fromIntegral index))))
(exp))
freezingStmt =
(NoBindS
(AppE
(VarE 'Vector.unsafeFreeze)
(VarE vectorVarName)))