neovimhaskell / nvim-hs

Neovim API for Haskell plugins as well as the plugin provider
Other
267 stars 18 forks source link

fix message type written to message queue #9

Closed osa1 closed 9 years ago

osa1 commented 9 years ago

This was incredibly hard to track down, and it finally fixes the example plugin:

{-# LANGUAGE MultiWayIf, OverloadedStrings, RankNTypes #-}

import           Neovim
import           Neovim.API.IPC
import           Neovim.API.Plugin

import           System.Log.Logger
import           System.Random

main :: IO ()
main = neovim def
    { logOptions = Just ("nvim-log.txt", DEBUG)
    , plugins    = [ randPlugin ]
    }

randPlugin :: IO SomePlugin
randPlugin = do
    logM "Random" INFO "Starting Rand plugin"
    q <- newTQueueIO
    g <- newStdGen
    return $ SomePlugin $ Plugin
      { name = "Random number generator"
      , functions = []
      , statefulFunctions = [("Random", q)]
      , services = [ ( (), g, nextRand q ) ]
      }

nextRand :: RandomGen s => TQueue SomeMessage -> Neovim cfg s ()
nextRand q = do
    liftIO $ debugM "Random" "nextRand is running"
    req <- awaitRequest q
    liftIO $ debugM "Random" "nextRand got a request"
    if | reqMethod req == "Random" -> do
         (r,g) <- random <$> get
         put g
         respond (reqId req) (Right (r :: Int64))
       | True      -> error "damn!"
       | otherwise -> error "what what what"
    nextRand q

neovim doesn't hang anymore, because we're immediately sending a response. However, I think we're still doing something wrong, because neovim is now giving this error message: Error converting the call result: Integer value outside the range. this is probably something related with the protocol implementation. @saep any ideas?

osa1 commented 9 years ago

This version works fine:

{-# LANGUAGE MultiWayIf, OverloadedStrings, RankNTypes, ScopedTypeVariables #-}

import           Neovim
import           Neovim.API.IPC
import           Neovim.API.Plugin

import           Data.Int
import           System.Log.Logger
import           System.Random

main :: IO ()
main = neovim def
    { logOptions = Just ("nvim-log.txt", DEBUG)
    , plugins    = [ randPlugin ]
    }

randPlugin :: IO SomePlugin
randPlugin = do
    logM "Random" INFO "Starting Rand plugin"
    q <- newTQueueIO
    g <- newStdGen
    return $ SomePlugin $ Plugin
      { name = "Random number generator"
      , functions = []
      , statefulFunctions = [("Random", q)]
      , services = [ ( (), g, nextRand q ) ]
      }

nextRand :: RandomGen s => TQueue SomeMessage -> Neovim cfg s ()
nextRand q = do
    liftIO $ debugM "Random" "nextRand is running"
    req <- awaitRequest q
    liftIO $ debugM "Random" "nextRand got a request"
    if | reqMethod req == "Random" -> do
         (r :: Int32, g) <- random <$> get
         put g
         respond (reqId req) (Right (fromIntegral r :: Int64))
       | True      -> error "damn!"
       | otherwise -> error "what what what"
    nextRand q

It seems like neovim has an upper limit smaller than 64bit.

osa1 commented 9 years ago

Let's note what's going on here: (thanks to @saep for the investigation)

Apparently Neovim is using INT_MAX and INT_MIN internally for bounds check. msgpack allows 64bit integers which are bigger than INT_MAX even on 64bit systems. So we should be careful about that while using the API.