ribosome-0.4.0.0: lib/Ribosome/Nvim/Api/GenerateIO.hs
module Ribosome.Nvim.Api.GenerateIO where
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
import Neovim.API.Parser (NeovimType(SimpleType))
import Ribosome.Control.Monad.Ribo (Nvim(call))
import Ribosome.Msgpack.Decode (MsgpackDecode)
import Ribosome.Nvim.Api.Generate (FunctionData(FunctionData), generateFromApi, haskellType)
import Ribosome.Nvim.Api.RpcCall (RpcError)
rpcModule :: Module
rpcModule =
Module (mkPkgName "Ribosome.Nvim.Api") (mkModName "Data")
msgpackDecodeConstraint :: NeovimType -> Q (Maybe Type)
msgpackDecodeConstraint (SimpleType "Object") =
Just <$> [t|MsgpackDecode $(varT $ mkName "a")|]
msgpackDecodeConstraint _ =
return Nothing
newT :: String -> TypeQ
newT =
varT <=< newName
ioReturnType :: NeovimType -> Q Type
ioReturnType (SimpleType "Object") =
return (VarT $ mkName "a")
ioReturnType a =
haskellType a
analyzeReturnType :: NeovimType -> Q (Type, Maybe Type)
analyzeReturnType tpe = do
rt <- ioReturnType tpe
constraint <- msgpackDecodeConstraint tpe
return (rt, constraint)
ioSig :: Name -> [Type] -> NeovimType -> DecQ
ioSig name types returnType = do
mType <- newT "m"
nvimConstraint <- [t|Nvim $(pure mType)|]
(retType, decodeConstraint) <- analyzeReturnType returnType
monadErrorConstraint <- [t|MonadDeepError $(newT "e") RpcError $(pure mType)|]
let
params = foldr (AppT . AppT ArrowT) (AppT mType retType) types
constraints = [nvimConstraint, monadErrorConstraint] <> maybeToList decodeConstraint
sigD name $ return (ForallT [] constraints params)
ioBody :: Name -> Bool -> [Name] -> DecQ
ioBody name _ names =
funD name [clause (varP <$> names) (normalB body) []]
where
responseName = mkName "response"
callPat = varP responseName
callExp = appE [|call|] args
checkExp = appE [|hoistEither|] (varE responseName)
args = foldl appE (varE $ mkName $ "RpcData." <> show name) (varE <$> names)
body = doE [bindS callPat callExp, noBindS checkExp]
genIO :: FunctionData -> Q [Dec]
genIO (FunctionData _ name async names types returnType) = do
sig <- ioSig name types returnType
body <- ioBody name async names
return [sig, body]
generateIO :: Q [Dec]
generateIO =
generateFromApi genIO (const . const . return $ [])