module TH.YQL(generateYQLs, generateYQL) where
import Control.Applicative ((<$>))
import Control.Monad.Catch (MonadThrow)
import Control.Monad.IO.Class (MonadIO(liftIO))
import Data.Aeson
import Data.Char
import Data.Monoid ((<>))
import Language.Haskell.TH (Body(..), Dec(..), Pat(..),
Pred(..), Q, Type(..), TyVarBndr(..),
mkName)
import System.Log.Logger
import Control.Monad.Trans.API
import Data.JSON.Void ()
import Data.Settings.YQL
import Data.State.YQL
import Data.TH.API
import Data.TH.YQL
import Data.TH.Object
import Helper.Name
import YQL
generateYQLs :: [API] -> Q [YQL]
generateYQLs apis = do
sequence $ generateYQL <$> apis
generateYQL :: API -> Q YQL
generateYQL api = do
let cc = camelCase . apiName $ api
name = (toLower . head $ cc):(tail cc)
inType = apiInputType . apiInput $ api
outType = apiOutputType . apiOutput $ api
pipe <- generateYQLPipe name api
return $ YQL inType outType pipe
generateYQLPipe :: String -> API -> Q YQLPipe
generateYQLPipe base API {..} = do
let name = mkName base
opentable = snd $ apiInputOpenDataTable apiInput
inType = apiInputType $ apiInput
outType = apiOutputType $ apiOutput
let r = mkName "r"
s = mkName "s"
m = mkName "m"
a = mkName "a"
t = AppT (AppT ArrowT (ConT ''YQLSettings)) (AppT (AppT ArrowT inType) (AppT (AppT (AppT (ConT ''APIT) (VarT s)) (VarT m)) (AppT (ConT ''Maybe) outType)))
t' = ForallT
[ PlainTV s, PlainTV m, PlainTV a ]
[ ClassP ''MonadIO [VarT m]
, ClassP ''MonadThrow [VarT m]
, ClassP ''YQLState [VarT s] ]
t
sig = SigD name t'
body <-
[| \YQLSettings {..} input -> do
value <- liftIO $ runYQL opentable (toObject input)
case fromJSON value of
Success output -> do
return . Just $ output
Error _ -> do
liftIO $
errorM
("YQL." ++ apiName)
"Could not decode response body"
return Nothing |]
let dec = ValD (VarP name) (NormalB body) []
return $ YQLPipe name sig dec