hslua-examples-2.0.0: low-level-factorial/low-level-factorial.hs
-- lua_setglobal is unsafe in general and causes a compiler warning.
{-# OPTIONS_GHC -Wno-warnings-deprecations #-}
{-| Expose factorial function to Lua, using the low-level API. -}
module Main where
import Prelude
import Control.Monad (void)
import Foreign.C (withCString, withCStringLen)
import Foreign.Ptr (nullPtr)
import Lua
luaScript :: String
luaScript = unlines
[ "print(' 5! =', factorial(5), type(factorial(5)))"
, "print('30! =', factorial(30), type(factorial(30)))"
]
factorial :: PreCFunction
factorial l = do
-- Get the first function argument as an integer.
n <- lua_tointegerx l (nthBottom 1) nullPtr
let result = product [1..fromIntegral n] :: Prelude.Integer
-- push as integer if the result is small enough,
-- and as string otherwise.
if result <= fromIntegral (maxBound :: Lua.Integer)
then lua_pushinteger l (fromIntegral result)
else withCString (show result) (void . lua_pushstring l)
-- Signal that one result value is on the top of the stack.
return (NumResults 1)
main :: IO ()
main = void . withNewState $ \l -> do
luaL_openlibs l
-- expose Haskell function `factorial` as a Lua function of the same name.
hslua_pushhsfunction l factorial
_ <- withCString "factorial" (lua_setglobal l)
-- Load the script.
LUA_OK <- withCStringLen luaScript $ \(sPtr, sLen) ->
withCString "script" $ luaL_loadbuffer l sPtr (fromIntegral sLen)
-- Call the loaded script.
LUA_OK <- lua_pcall l (NumArgs 0) LUA_MULTRET (StackIndex 0)
return ()