module Foreign.Lua.Module.SystemUtils
( AnyValue (..)
, Callback (..)
, addPackagePreloader
, addField
, addFunction
, invoke
, invokeWithFilePath
, ioToLua
)
where
import Control.Exception (IOException, try)
import Foreign.Lua (Lua, NumResults(..), Peekable, Pushable,
StackIndex, ToHaskellFunction)
import qualified Foreign.Lua as Lua
addPackagePreloader :: String -> Lua NumResults -> Lua ()
addPackagePreloader name modulePusher = do
Lua.getfield Lua.registryindex Lua.preloadTableRegistryField
Lua.pushHaskellFunction modulePusher
Lua.setfield (-2) name
Lua.pop 1
addField :: Pushable a => String -> a -> Lua ()
addField name value = do
Lua.push name
Lua.push value
Lua.rawset (Lua.nthFromTop 3)
addFunction :: ToHaskellFunction a => String -> a -> Lua ()
addFunction name fn = do
Lua.push name
Lua.pushHaskellFunction fn
Lua.rawset (-3)
newtype Callback = Callback StackIndex
instance Peekable Callback where
peek idx = do
isFn <- Lua.isfunction idx
if isFn
then return (Callback idx)
else Lua.throwException "Function expected"
instance Pushable Callback where
push (Callback idx) = Lua.pushvalue idx
newtype AnyValue = AnyValue { fromAnyValue :: StackIndex }
instance Peekable AnyValue where
peek = return . AnyValue
instance Pushable AnyValue where
push (AnyValue idx) = Lua.pushvalue idx
invoke :: Callback -> Lua NumResults
invoke callback = do
oldTop <- Lua.gettop
Lua.push callback
Lua.call 0 Lua.multret
newTop <- Lua.gettop
return . NumResults . fromIntegral . Lua.fromStackIndex $
newTop - oldTop
invokeWithFilePath :: Callback -> FilePath -> Lua NumResults
invokeWithFilePath callback filename = do
oldTop <- Lua.gettop
Lua.push callback
Lua.push filename
Lua.call (Lua.NumArgs 1) Lua.multret
newTop <- Lua.gettop
return . NumResults . fromIntegral . Lua.fromStackIndex $
newTop - oldTop
ioToLua :: IO a -> Lua a
ioToLua action = do
result <- Lua.liftIO (try action)
case result of
Right result' -> return result'
Left err -> Lua.throwException (show (err :: IOException))