packages feed

hslua 1.1.2 → 1.2.0

raw patch · 39 files changed

+2731/−1669 lines, 39 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Foreign.Lua.Core.Error: Failable :: CInt -> Failable a
- Foreign.Lua.Core.Error: boolFromFailable :: Failable LuaBool -> Lua Bool
- Foreign.Lua.Core.Error: fromFailable :: (CInt -> a) -> Failable a -> Lua a
- Foreign.Lua.Core.Error: hsluaErrorRegistryField :: String
- Foreign.Lua.Core.Error: newtype Failable a
- Foreign.Lua.Core.Error: throwOnError :: Failable () -> Lua ()
- Foreign.Lua.Core.RawBindings: hslua_compare :: State -> StackIndex -> StackIndex -> CInt -> IO (Failable LuaBool)
- Foreign.Lua.Core.RawBindings: hslua_concat :: State -> NumArgs -> IO (Failable ())
- Foreign.Lua.Core.RawBindings: hslua_error :: State -> IO NumResults
- Foreign.Lua.Core.RawBindings: hslua_getglobal :: State -> CString -> CSize -> IO (Failable ())
- Foreign.Lua.Core.RawBindings: hslua_gettable :: State -> StackIndex -> IO (Failable ())
- Foreign.Lua.Core.RawBindings: hslua_next :: State -> StackIndex -> IO (Failable LuaBool)
- Foreign.Lua.Core.RawBindings: hslua_setglobal :: State -> CString -> CSize -> IO (Failable ())
- Foreign.Lua.Core.RawBindings: hslua_settable :: State -> StackIndex -> IO (Failable ())
- Foreign.Lua.Core.RawBindings: luaL_openlibs :: State -> IO ()
- Foreign.Lua.Core.RawBindings: lua_absindex :: State -> StackIndex -> IO StackIndex
- Foreign.Lua.Core.RawBindings: lua_checkstack :: State -> CInt -> IO LuaBool
- Foreign.Lua.Core.RawBindings: lua_close :: State -> IO ()
- Foreign.Lua.Core.RawBindings: lua_copy :: State -> StackIndex -> StackIndex -> IO ()
- Foreign.Lua.Core.RawBindings: lua_createtable :: State -> CInt -> CInt -> IO ()
- Foreign.Lua.Core.RawBindings: lua_gc :: State -> CInt -> CInt -> IO CInt
- Foreign.Lua.Core.RawBindings: lua_getmetatable :: State -> StackIndex -> IO LuaBool
- Foreign.Lua.Core.RawBindings: lua_gettop :: State -> IO StackIndex
- Foreign.Lua.Core.RawBindings: lua_insert :: State -> StackIndex -> IO ()
- Foreign.Lua.Core.RawBindings: lua_iscfunction :: State -> StackIndex -> IO LuaBool
- Foreign.Lua.Core.RawBindings: lua_isinteger :: State -> StackIndex -> IO LuaBool
- Foreign.Lua.Core.RawBindings: lua_isnumber :: State -> StackIndex -> IO LuaBool
- Foreign.Lua.Core.RawBindings: lua_isstring :: State -> StackIndex -> IO LuaBool
- Foreign.Lua.Core.RawBindings: lua_isuserdata :: State -> StackIndex -> IO LuaBool
- Foreign.Lua.Core.RawBindings: lua_load :: State -> Reader -> Ptr () -> CString -> CString -> IO StatusCode
- Foreign.Lua.Core.RawBindings: lua_newuserdata :: State -> CSize -> IO (Ptr ())
- Foreign.Lua.Core.RawBindings: lua_open_base_ptr :: CFunction
- Foreign.Lua.Core.RawBindings: lua_open_debug_ptr :: CFunction
- Foreign.Lua.Core.RawBindings: lua_open_io_ptr :: CFunction
- Foreign.Lua.Core.RawBindings: lua_open_math_ptr :: CFunction
- Foreign.Lua.Core.RawBindings: lua_open_os_ptr :: CFunction
- Foreign.Lua.Core.RawBindings: lua_open_package_ptr :: CFunction
- Foreign.Lua.Core.RawBindings: lua_open_string_ptr :: CFunction
- Foreign.Lua.Core.RawBindings: lua_open_table_ptr :: CFunction
- Foreign.Lua.Core.RawBindings: lua_pcall :: State -> NumArgs -> NumResults -> StackIndex -> IO StatusCode
- Foreign.Lua.Core.RawBindings: lua_pushboolean :: State -> LuaBool -> IO ()
- Foreign.Lua.Core.RawBindings: lua_pushcclosure :: State -> CFunction -> NumArgs -> IO ()
- Foreign.Lua.Core.RawBindings: lua_pushglobaltable :: State -> IO ()
- Foreign.Lua.Core.RawBindings: lua_pushinteger :: State -> Integer -> IO ()
- Foreign.Lua.Core.RawBindings: lua_pushlightuserdata :: State -> Ptr a -> IO ()
- Foreign.Lua.Core.RawBindings: lua_pushlstring :: State -> Ptr CChar -> CSize -> IO ()
- Foreign.Lua.Core.RawBindings: lua_pushnil :: State -> IO ()
- Foreign.Lua.Core.RawBindings: lua_pushnumber :: State -> Number -> IO ()
- Foreign.Lua.Core.RawBindings: lua_pushthread :: State -> IO CInt
- Foreign.Lua.Core.RawBindings: lua_pushvalue :: State -> StackIndex -> IO ()
- Foreign.Lua.Core.RawBindings: lua_rawequal :: State -> StackIndex -> StackIndex -> IO LuaBool
- Foreign.Lua.Core.RawBindings: lua_rawget :: State -> StackIndex -> IO ()
- Foreign.Lua.Core.RawBindings: lua_rawgeti :: State -> StackIndex -> Integer -> IO ()
- Foreign.Lua.Core.RawBindings: lua_rawlen :: State -> StackIndex -> IO CSize
- Foreign.Lua.Core.RawBindings: lua_rawset :: State -> StackIndex -> IO ()
- Foreign.Lua.Core.RawBindings: lua_rawseti :: State -> StackIndex -> Integer -> IO ()
- Foreign.Lua.Core.RawBindings: lua_remove :: State -> StackIndex -> IO ()
- Foreign.Lua.Core.RawBindings: lua_replace :: State -> StackIndex -> IO ()
- Foreign.Lua.Core.RawBindings: lua_setmetatable :: State -> StackIndex -> IO ()
- Foreign.Lua.Core.RawBindings: lua_settop :: State -> StackIndex -> IO ()
- Foreign.Lua.Core.RawBindings: lua_status :: State -> IO StatusCode
- Foreign.Lua.Core.RawBindings: lua_toboolean :: State -> StackIndex -> IO LuaBool
- Foreign.Lua.Core.RawBindings: lua_tocfunction :: State -> StackIndex -> IO CFunction
- Foreign.Lua.Core.RawBindings: lua_tointegerx :: State -> StackIndex -> Ptr LuaBool -> IO Integer
- Foreign.Lua.Core.RawBindings: lua_tolstring :: State -> StackIndex -> Ptr CSize -> IO (Ptr CChar)
- Foreign.Lua.Core.RawBindings: lua_tonumberx :: State -> StackIndex -> Ptr LuaBool -> IO Number
- Foreign.Lua.Core.RawBindings: lua_topointer :: State -> StackIndex -> IO (Ptr ())
- Foreign.Lua.Core.RawBindings: lua_tothread :: State -> StackIndex -> IO State
- Foreign.Lua.Core.RawBindings: lua_touserdata :: State -> StackIndex -> IO (Ptr a)
- Foreign.Lua.Core.RawBindings: lua_type :: State -> StackIndex -> IO TypeCode
- Foreign.Lua.Core.RawBindings: lua_typename :: State -> TypeCode -> IO CString
- Foreign.Lua.Core.Types: instance Foreign.Storable.Storable Foreign.Lua.Core.Types.LuaBool
- Foreign.Lua.Core.Types: instance GHC.Classes.Eq Foreign.Lua.Core.Types.GCCONTROL
- Foreign.Lua.Core.Types: instance GHC.Classes.Eq Foreign.Lua.Core.Types.Integer
- Foreign.Lua.Core.Types: instance GHC.Classes.Eq Foreign.Lua.Core.Types.LuaBool
- Foreign.Lua.Core.Types: instance GHC.Classes.Eq Foreign.Lua.Core.Types.NumArgs
- Foreign.Lua.Core.Types: instance GHC.Classes.Eq Foreign.Lua.Core.Types.NumResults
- Foreign.Lua.Core.Types: instance GHC.Classes.Eq Foreign.Lua.Core.Types.Number
- Foreign.Lua.Core.Types: instance GHC.Classes.Eq Foreign.Lua.Core.Types.Reference
- Foreign.Lua.Core.Types: instance GHC.Classes.Eq Foreign.Lua.Core.Types.RelationalOperator
- Foreign.Lua.Core.Types: instance GHC.Classes.Eq Foreign.Lua.Core.Types.StackIndex
- Foreign.Lua.Core.Types: instance GHC.Classes.Eq Foreign.Lua.Core.Types.State
- Foreign.Lua.Core.Types: instance GHC.Classes.Eq Foreign.Lua.Core.Types.Status
- Foreign.Lua.Core.Types: instance GHC.Classes.Eq Foreign.Lua.Core.Types.StatusCode
- Foreign.Lua.Core.Types: instance GHC.Classes.Eq Foreign.Lua.Core.Types.Type
- Foreign.Lua.Core.Types: instance GHC.Classes.Eq Foreign.Lua.Core.Types.TypeCode
- Foreign.Lua.Core.Types: instance GHC.Classes.Ord Foreign.Lua.Core.Types.GCCONTROL
- Foreign.Lua.Core.Types: instance GHC.Classes.Ord Foreign.Lua.Core.Types.Integer
- Foreign.Lua.Core.Types: instance GHC.Classes.Ord Foreign.Lua.Core.Types.NumArgs
- Foreign.Lua.Core.Types: instance GHC.Classes.Ord Foreign.Lua.Core.Types.NumResults
- Foreign.Lua.Core.Types: instance GHC.Classes.Ord Foreign.Lua.Core.Types.Number
- Foreign.Lua.Core.Types: instance GHC.Classes.Ord Foreign.Lua.Core.Types.RelationalOperator
- Foreign.Lua.Core.Types: instance GHC.Classes.Ord Foreign.Lua.Core.Types.StackIndex
- Foreign.Lua.Core.Types: instance GHC.Classes.Ord Foreign.Lua.Core.Types.Type
- Foreign.Lua.Core.Types: instance GHC.Classes.Ord Foreign.Lua.Core.Types.TypeCode
- Foreign.Lua.Core.Types: instance GHC.Enum.Bounded Foreign.Lua.Core.Types.Integer
- Foreign.Lua.Core.Types: instance GHC.Enum.Bounded Foreign.Lua.Core.Types.Type
- Foreign.Lua.Core.Types: instance GHC.Enum.Enum Foreign.Lua.Core.Types.GCCONTROL
- Foreign.Lua.Core.Types: instance GHC.Enum.Enum Foreign.Lua.Core.Types.Integer
- Foreign.Lua.Core.Types: instance GHC.Enum.Enum Foreign.Lua.Core.Types.StackIndex
- Foreign.Lua.Core.Types: instance GHC.Enum.Enum Foreign.Lua.Core.Types.Type
- Foreign.Lua.Core.Types: instance GHC.Float.Floating Foreign.Lua.Core.Types.Number
- Foreign.Lua.Core.Types: instance GHC.Float.RealFloat Foreign.Lua.Core.Types.Number
- Foreign.Lua.Core.Types: instance GHC.Generics.Generic Foreign.Lua.Core.Types.State
- Foreign.Lua.Core.Types: instance GHC.Num.Num Foreign.Lua.Core.Types.Integer
- Foreign.Lua.Core.Types: instance GHC.Num.Num Foreign.Lua.Core.Types.NumArgs
- Foreign.Lua.Core.Types: instance GHC.Num.Num Foreign.Lua.Core.Types.NumResults
- Foreign.Lua.Core.Types: instance GHC.Num.Num Foreign.Lua.Core.Types.Number
- Foreign.Lua.Core.Types: instance GHC.Num.Num Foreign.Lua.Core.Types.StackIndex
- Foreign.Lua.Core.Types: instance GHC.Real.Fractional Foreign.Lua.Core.Types.Number
- Foreign.Lua.Core.Types: instance GHC.Real.Integral Foreign.Lua.Core.Types.Integer
- Foreign.Lua.Core.Types: instance GHC.Real.Real Foreign.Lua.Core.Types.Integer
- Foreign.Lua.Core.Types: instance GHC.Real.Real Foreign.Lua.Core.Types.Number
- Foreign.Lua.Core.Types: instance GHC.Real.RealFrac Foreign.Lua.Core.Types.Number
- Foreign.Lua.Core.Types: instance GHC.Show.Show Foreign.Lua.Core.Types.GCCONTROL
- Foreign.Lua.Core.Types: instance GHC.Show.Show Foreign.Lua.Core.Types.Integer
- Foreign.Lua.Core.Types: instance GHC.Show.Show Foreign.Lua.Core.Types.LuaBool
- Foreign.Lua.Core.Types: instance GHC.Show.Show Foreign.Lua.Core.Types.NumArgs
- Foreign.Lua.Core.Types: instance GHC.Show.Show Foreign.Lua.Core.Types.NumResults
- Foreign.Lua.Core.Types: instance GHC.Show.Show Foreign.Lua.Core.Types.Number
- Foreign.Lua.Core.Types: instance GHC.Show.Show Foreign.Lua.Core.Types.Reference
- Foreign.Lua.Core.Types: instance GHC.Show.Show Foreign.Lua.Core.Types.RelationalOperator
- Foreign.Lua.Core.Types: instance GHC.Show.Show Foreign.Lua.Core.Types.StackIndex
- Foreign.Lua.Core.Types: instance GHC.Show.Show Foreign.Lua.Core.Types.Status
- Foreign.Lua.Core.Types: instance GHC.Show.Show Foreign.Lua.Core.Types.Type
- Foreign.Lua.Core.Types: instance GHC.Show.Show Foreign.Lua.Core.Types.TypeCode
- Foreign.Lua.Types.Peekable: instance Foreign.Lua.Types.Peekable.Peekable Foreign.Lua.Core.Types.CFunction
- Foreign.Lua.Types.Peekable: instance Foreign.Lua.Types.Peekable.Peekable Foreign.Lua.Core.Types.Integer
- Foreign.Lua.Types.Peekable: instance Foreign.Lua.Types.Peekable.Peekable Foreign.Lua.Core.Types.Number
- Foreign.Lua.Types.Peekable: instance Foreign.Lua.Types.Peekable.Peekable Foreign.Lua.Core.Types.State
- Foreign.Lua.Types.Pushable: instance Foreign.Lua.Types.Pushable.Pushable Foreign.Lua.Core.Types.CFunction
- Foreign.Lua.Types.Pushable: instance Foreign.Lua.Types.Pushable.Pushable Foreign.Lua.Core.Types.Integer
- Foreign.Lua.Types.Pushable: instance Foreign.Lua.Types.Pushable.Pushable Foreign.Lua.Core.Types.Number
+ Foreign.Lua.Call: (#?) :: HaskellFunction -> Text -> HaskellFunction
+ Foreign.Lua.Call: (<#>) :: HsFnPrecursor (a -> b) -> Parameter a -> HsFnPrecursor b
+ Foreign.Lua.Call: (=#>) :: HsFnPrecursor a -> FunctionResults a -> HaskellFunction
+ Foreign.Lua.Call: FunctionDoc :: Text -> [ParameterDoc] -> [FunctionResultDoc] -> FunctionDoc
+ Foreign.Lua.Call: FunctionResult :: Pusher a -> FunctionResultDoc -> FunctionResult a
+ Foreign.Lua.Call: FunctionResultDoc :: Text -> Text -> FunctionResultDoc
+ Foreign.Lua.Call: HaskellFunction :: Lua NumResults -> Maybe FunctionDoc -> HaskellFunction
+ Foreign.Lua.Call: Parameter :: Peeker a -> ParameterDoc -> Parameter a
+ Foreign.Lua.Call: ParameterDoc :: Text -> Text -> Text -> Bool -> ParameterDoc
+ Foreign.Lua.Call: [callFunction] :: HaskellFunction -> Lua NumResults
+ Foreign.Lua.Call: [fnResultDoc] :: FunctionResult a -> FunctionResultDoc
+ Foreign.Lua.Call: [fnResultPusher] :: FunctionResult a -> Pusher a
+ Foreign.Lua.Call: [functionDescription] :: FunctionDoc -> Text
+ Foreign.Lua.Call: [functionDoc] :: HaskellFunction -> Maybe FunctionDoc
+ Foreign.Lua.Call: [functionResultDescription] :: FunctionResultDoc -> Text
+ Foreign.Lua.Call: [functionResultDocs] :: FunctionDoc -> [FunctionResultDoc]
+ Foreign.Lua.Call: [functionResultType] :: FunctionResultDoc -> Text
+ Foreign.Lua.Call: [parameterDescription] :: ParameterDoc -> Text
+ Foreign.Lua.Call: [parameterDoc] :: Parameter a -> ParameterDoc
+ Foreign.Lua.Call: [parameterDocs] :: FunctionDoc -> [ParameterDoc]
+ Foreign.Lua.Call: [parameterIsOptional] :: ParameterDoc -> Bool
+ Foreign.Lua.Call: [parameterName] :: ParameterDoc -> Text
+ Foreign.Lua.Call: [parameterPeeker] :: Parameter a -> Peeker a
+ Foreign.Lua.Call: [parameterType] :: ParameterDoc -> Text
+ Foreign.Lua.Call: applyParameter :: HsFnPrecursor (a -> b) -> Parameter a -> HsFnPrecursor b
+ Foreign.Lua.Call: data FunctionDoc
+ Foreign.Lua.Call: data FunctionResult a
+ Foreign.Lua.Call: data FunctionResultDoc
+ Foreign.Lua.Call: data HaskellFunction
+ Foreign.Lua.Call: data Parameter a
+ Foreign.Lua.Call: data ParameterDoc
+ Foreign.Lua.Call: functionResult :: Pusher a -> Text -> Text -> FunctionResults a
+ Foreign.Lua.Call: infixl 8 #?
+ Foreign.Lua.Call: instance GHC.Base.Functor Foreign.Lua.Call.HsFnPrecursor
+ Foreign.Lua.Call: instance GHC.Classes.Eq Foreign.Lua.Call.FunctionDoc
+ Foreign.Lua.Call: instance GHC.Classes.Eq Foreign.Lua.Call.FunctionResultDoc
+ Foreign.Lua.Call: instance GHC.Classes.Eq Foreign.Lua.Call.ParameterDoc
+ Foreign.Lua.Call: instance GHC.Classes.Ord Foreign.Lua.Call.FunctionDoc
+ Foreign.Lua.Call: instance GHC.Classes.Ord Foreign.Lua.Call.FunctionResultDoc
+ Foreign.Lua.Call: instance GHC.Classes.Ord Foreign.Lua.Call.ParameterDoc
+ Foreign.Lua.Call: instance GHC.Show.Show Foreign.Lua.Call.FunctionDoc
+ Foreign.Lua.Call: instance GHC.Show.Show Foreign.Lua.Call.FunctionResultDoc
+ Foreign.Lua.Call: instance GHC.Show.Show Foreign.Lua.Call.ParameterDoc
+ Foreign.Lua.Call: optionalParameter :: Peeker a -> Text -> Text -> Text -> Parameter (Maybe a)
+ Foreign.Lua.Call: parameter :: Peeker a -> Text -> Text -> Text -> Parameter a
+ Foreign.Lua.Call: pushHaskellFunction :: HaskellFunction -> Lua ()
+ Foreign.Lua.Call: render :: FunctionDoc -> Text
+ Foreign.Lua.Call: returnResult :: HsFnPrecursor a -> FunctionResult a -> HaskellFunction
+ Foreign.Lua.Call: toHsFnPrecursor :: a -> HsFnPrecursor a
+ Foreign.Lua.Call: toHsFnPrecursorWithStartIndex :: StackIndex -> a -> HsFnPrecursor a
+ Foreign.Lua.Call: type FunctionResults a = [FunctionResult a]
+ Foreign.Lua.Core: nth :: CInt -> StackIndex
+ Foreign.Lua.Core: top :: StackIndex
+ Foreign.Lua.Core.Error: liftLuaThrow :: (State -> Ptr StatusCode -> IO a) -> Lua a
+ Foreign.Lua.Core.Types: nth :: CInt -> StackIndex
+ Foreign.Lua.Core.Types: top :: StackIndex
+ Foreign.Lua.Module: Field :: Text -> Text -> Lua () -> Field
+ Foreign.Lua.Module: Module :: Text -> Text -> [Field] -> [(Text, HaskellFunction)] -> Module
+ Foreign.Lua.Module: [fieldDescription] :: Field -> Text
+ Foreign.Lua.Module: [fieldName] :: Field -> Text
+ Foreign.Lua.Module: [fieldPushValue] :: Field -> Lua ()
+ Foreign.Lua.Module: [moduleDescription] :: Module -> Text
+ Foreign.Lua.Module: [moduleFields] :: Module -> [Field]
+ Foreign.Lua.Module: [moduleFunctions] :: Module -> [(Text, HaskellFunction)]
+ Foreign.Lua.Module: [moduleName] :: Module -> Text
+ Foreign.Lua.Module: data Field
+ Foreign.Lua.Module: data Module
+ Foreign.Lua.Module: preloadModule :: Module -> Lua ()
+ Foreign.Lua.Module: pushModule :: Module -> Lua ()
+ Foreign.Lua.Module: registerModule :: Module -> Lua ()
+ Foreign.Lua.Module: render :: Module -> Text
+ Foreign.Lua.Peek: formatPeekError :: PeekError -> String
+ Foreign.Lua.Peek: optional :: Peeker a -> Peeker (Maybe a)
+ Foreign.Lua.Peek: pushMsg :: Text -> PeekError -> PeekError
+ Foreign.Lua.Raw.Auxiliary: RefNil :: Reference
+ Foreign.Lua.Raw.Auxiliary: Reference :: CInt -> Reference
+ Foreign.Lua.Raw.Auxiliary: c_loaded_table :: CString
+ Foreign.Lua.Raw.Auxiliary: c_preload_table :: CString
+ Foreign.Lua.Raw.Auxiliary: data Reference
+ Foreign.Lua.Raw.Auxiliary: fromReference :: Reference -> CInt
+ Foreign.Lua.Raw.Auxiliary: hsluaL_newstate :: IO State
+ Foreign.Lua.Raw.Auxiliary: hsluaL_tolstring :: State -> StackIndex -> Ptr CSize -> IO (Ptr CChar)
+ Foreign.Lua.Raw.Auxiliary: instance GHC.Classes.Eq Foreign.Lua.Raw.Auxiliary.Reference
+ Foreign.Lua.Raw.Auxiliary: instance GHC.Show.Show Foreign.Lua.Raw.Auxiliary.Reference
+ Foreign.Lua.Raw.Auxiliary: loadedTableRegistryField :: String
+ Foreign.Lua.Raw.Auxiliary: luaL_getmetafield :: State -> StackIndex -> CString -> IO TypeCode
+ Foreign.Lua.Raw.Auxiliary: luaL_getmetatable :: State -> CString -> IO TypeCode
+ Foreign.Lua.Raw.Auxiliary: luaL_loadbuffer :: State -> Ptr CChar -> CSize -> CString -> IO StatusCode
+ Foreign.Lua.Raw.Auxiliary: luaL_newmetatable :: State -> CString -> IO LuaBool
+ Foreign.Lua.Raw.Auxiliary: luaL_ref :: State -> StackIndex -> IO CInt
+ Foreign.Lua.Raw.Auxiliary: luaL_testudata :: State -> StackIndex -> CString -> IO (Ptr ())
+ Foreign.Lua.Raw.Auxiliary: luaL_traceback :: State -> State -> CString -> CInt -> IO ()
+ Foreign.Lua.Raw.Auxiliary: luaL_unref :: State -> StackIndex -> CInt -> IO ()
+ Foreign.Lua.Raw.Auxiliary: preloadTableRegistryField :: String
+ Foreign.Lua.Raw.Auxiliary: toReference :: CInt -> Reference
+ Foreign.Lua.Raw.Call: hslua_newhsfunction :: State -> StablePtr a -> IO ()
+ Foreign.Lua.Raw.Call: hslua_pushhsfunction :: State -> HsFunction -> IO ()
+ Foreign.Lua.Raw.Call: type HsFunction = State -> IO NumResults
+ Foreign.Lua.Raw.Constants: multret :: NumResults
+ Foreign.Lua.Raw.Constants: noref :: Int
+ Foreign.Lua.Raw.Constants: refnil :: Int
+ Foreign.Lua.Raw.Constants: registryindex :: StackIndex
+ Foreign.Lua.Raw.Error: errorMessage :: State -> IO ByteString
+ Foreign.Lua.Raw.Functions: hslua_compare :: State -> StackIndex -> StackIndex -> CInt -> Ptr StatusCode -> IO LuaBool
+ Foreign.Lua.Raw.Functions: hslua_concat :: State -> NumArgs -> Ptr StatusCode -> IO ()
+ Foreign.Lua.Raw.Functions: hslua_error :: State -> IO NumResults
+ Foreign.Lua.Raw.Functions: hslua_getglobal :: State -> CString -> CSize -> Ptr StatusCode -> IO ()
+ Foreign.Lua.Raw.Functions: hslua_gettable :: State -> StackIndex -> Ptr StatusCode -> IO ()
+ Foreign.Lua.Raw.Functions: hslua_next :: State -> StackIndex -> Ptr StatusCode -> IO LuaBool
+ Foreign.Lua.Raw.Functions: hslua_setglobal :: State -> CString -> CSize -> Ptr StatusCode -> IO ()
+ Foreign.Lua.Raw.Functions: hslua_settable :: State -> StackIndex -> Ptr StatusCode -> IO ()
+ Foreign.Lua.Raw.Functions: luaL_openlibs :: State -> IO ()
+ Foreign.Lua.Raw.Functions: lua_absindex :: State -> StackIndex -> IO StackIndex
+ Foreign.Lua.Raw.Functions: lua_checkstack :: State -> CInt -> IO LuaBool
+ Foreign.Lua.Raw.Functions: lua_close :: State -> IO ()
+ Foreign.Lua.Raw.Functions: lua_copy :: State -> StackIndex -> StackIndex -> IO ()
+ Foreign.Lua.Raw.Functions: lua_createtable :: State -> CInt -> CInt -> IO ()
+ Foreign.Lua.Raw.Functions: lua_gc :: State -> CInt -> CInt -> IO CInt
+ Foreign.Lua.Raw.Functions: lua_getmetatable :: State -> StackIndex -> IO LuaBool
+ Foreign.Lua.Raw.Functions: lua_gettop :: State -> IO StackIndex
+ Foreign.Lua.Raw.Functions: lua_insert :: State -> StackIndex -> IO ()
+ Foreign.Lua.Raw.Functions: lua_iscfunction :: State -> StackIndex -> IO LuaBool
+ Foreign.Lua.Raw.Functions: lua_isinteger :: State -> StackIndex -> IO LuaBool
+ Foreign.Lua.Raw.Functions: lua_isnumber :: State -> StackIndex -> IO LuaBool
+ Foreign.Lua.Raw.Functions: lua_isstring :: State -> StackIndex -> IO LuaBool
+ Foreign.Lua.Raw.Functions: lua_isuserdata :: State -> StackIndex -> IO LuaBool
+ Foreign.Lua.Raw.Functions: lua_load :: State -> Reader -> Ptr () -> CString -> CString -> IO StatusCode
+ Foreign.Lua.Raw.Functions: lua_newuserdata :: State -> CSize -> IO (Ptr ())
+ Foreign.Lua.Raw.Functions: lua_open_base_ptr :: CFunction
+ Foreign.Lua.Raw.Functions: lua_open_debug_ptr :: CFunction
+ Foreign.Lua.Raw.Functions: lua_open_io_ptr :: CFunction
+ Foreign.Lua.Raw.Functions: lua_open_math_ptr :: CFunction
+ Foreign.Lua.Raw.Functions: lua_open_os_ptr :: CFunction
+ Foreign.Lua.Raw.Functions: lua_open_package_ptr :: CFunction
+ Foreign.Lua.Raw.Functions: lua_open_string_ptr :: CFunction
+ Foreign.Lua.Raw.Functions: lua_open_table_ptr :: CFunction
+ Foreign.Lua.Raw.Functions: lua_pcall :: State -> NumArgs -> NumResults -> StackIndex -> IO StatusCode
+ Foreign.Lua.Raw.Functions: lua_pop :: State -> StackIndex -> IO ()
+ Foreign.Lua.Raw.Functions: lua_pushboolean :: State -> LuaBool -> IO ()
+ Foreign.Lua.Raw.Functions: lua_pushcclosure :: State -> CFunction -> NumArgs -> IO ()
+ Foreign.Lua.Raw.Functions: lua_pushglobaltable :: State -> IO ()
+ Foreign.Lua.Raw.Functions: lua_pushinteger :: State -> Integer -> IO ()
+ Foreign.Lua.Raw.Functions: lua_pushlightuserdata :: State -> Ptr a -> IO ()
+ Foreign.Lua.Raw.Functions: lua_pushlstring :: State -> Ptr CChar -> CSize -> IO ()
+ Foreign.Lua.Raw.Functions: lua_pushnil :: State -> IO ()
+ Foreign.Lua.Raw.Functions: lua_pushnumber :: State -> Number -> IO ()
+ Foreign.Lua.Raw.Functions: lua_pushthread :: State -> IO CInt
+ Foreign.Lua.Raw.Functions: lua_pushvalue :: State -> StackIndex -> IO ()
+ Foreign.Lua.Raw.Functions: lua_rawequal :: State -> StackIndex -> StackIndex -> IO LuaBool
+ Foreign.Lua.Raw.Functions: lua_rawget :: State -> StackIndex -> IO ()
+ Foreign.Lua.Raw.Functions: lua_rawgeti :: State -> StackIndex -> Integer -> IO ()
+ Foreign.Lua.Raw.Functions: lua_rawlen :: State -> StackIndex -> IO CSize
+ Foreign.Lua.Raw.Functions: lua_rawset :: State -> StackIndex -> IO ()
+ Foreign.Lua.Raw.Functions: lua_rawseti :: State -> StackIndex -> Integer -> IO ()
+ Foreign.Lua.Raw.Functions: lua_remove :: State -> StackIndex -> IO ()
+ Foreign.Lua.Raw.Functions: lua_replace :: State -> StackIndex -> IO ()
+ Foreign.Lua.Raw.Functions: lua_setmetatable :: State -> StackIndex -> IO ()
+ Foreign.Lua.Raw.Functions: lua_settop :: State -> StackIndex -> IO ()
+ Foreign.Lua.Raw.Functions: lua_status :: State -> IO StatusCode
+ Foreign.Lua.Raw.Functions: lua_toboolean :: State -> StackIndex -> IO LuaBool
+ Foreign.Lua.Raw.Functions: lua_tocfunction :: State -> StackIndex -> IO CFunction
+ Foreign.Lua.Raw.Functions: lua_tointegerx :: State -> StackIndex -> Ptr LuaBool -> IO Integer
+ Foreign.Lua.Raw.Functions: lua_tolstring :: State -> StackIndex -> Ptr CSize -> IO (Ptr CChar)
+ Foreign.Lua.Raw.Functions: lua_tonumberx :: State -> StackIndex -> Ptr LuaBool -> IO Number
+ Foreign.Lua.Raw.Functions: lua_topointer :: State -> StackIndex -> IO (Ptr ())
+ Foreign.Lua.Raw.Functions: lua_tothread :: State -> StackIndex -> IO State
+ Foreign.Lua.Raw.Functions: lua_touserdata :: State -> StackIndex -> IO (Ptr a)
+ Foreign.Lua.Raw.Functions: lua_type :: State -> StackIndex -> IO TypeCode
+ Foreign.Lua.Raw.Functions: lua_typename :: State -> TypeCode -> IO CString
+ Foreign.Lua.Raw.Types: EQ :: RelationalOperator
+ Foreign.Lua.Raw.Types: ErrErr :: Status
+ Foreign.Lua.Raw.Types: ErrFile :: Status
+ Foreign.Lua.Raw.Types: ErrGcmm :: Status
+ Foreign.Lua.Raw.Types: ErrMem :: Status
+ Foreign.Lua.Raw.Types: ErrRun :: Status
+ Foreign.Lua.Raw.Types: ErrSyntax :: Status
+ Foreign.Lua.Raw.Types: GCCOLLECT :: GCCONTROL
+ Foreign.Lua.Raw.Types: GCCOUNT :: GCCONTROL
+ Foreign.Lua.Raw.Types: GCCOUNTB :: GCCONTROL
+ Foreign.Lua.Raw.Types: GCRESTART :: GCCONTROL
+ Foreign.Lua.Raw.Types: GCSETPAUSE :: GCCONTROL
+ Foreign.Lua.Raw.Types: GCSETSTEPMUL :: GCCONTROL
+ Foreign.Lua.Raw.Types: GCSTEP :: GCCONTROL
+ Foreign.Lua.Raw.Types: GCSTOP :: GCCONTROL
+ Foreign.Lua.Raw.Types: Integer :: Int64 -> Integer
+ Foreign.Lua.Raw.Types: LE :: RelationalOperator
+ Foreign.Lua.Raw.Types: LT :: RelationalOperator
+ Foreign.Lua.Raw.Types: LuaBool :: CInt -> LuaBool
+ Foreign.Lua.Raw.Types: NumArgs :: CInt -> NumArgs
+ Foreign.Lua.Raw.Types: NumResults :: CInt -> NumResults
+ Foreign.Lua.Raw.Types: Number :: Double -> Number
+ Foreign.Lua.Raw.Types: OK :: Status
+ Foreign.Lua.Raw.Types: StackIndex :: CInt -> StackIndex
+ Foreign.Lua.Raw.Types: State :: Ptr () -> State
+ Foreign.Lua.Raw.Types: StatusCode :: CInt -> StatusCode
+ Foreign.Lua.Raw.Types: TypeBoolean :: Type
+ Foreign.Lua.Raw.Types: TypeCode :: CInt -> TypeCode
+ Foreign.Lua.Raw.Types: TypeFunction :: Type
+ Foreign.Lua.Raw.Types: TypeLightUserdata :: Type
+ Foreign.Lua.Raw.Types: TypeNil :: Type
+ Foreign.Lua.Raw.Types: TypeNone :: Type
+ Foreign.Lua.Raw.Types: TypeNumber :: Type
+ Foreign.Lua.Raw.Types: TypeString :: Type
+ Foreign.Lua.Raw.Types: TypeTable :: Type
+ Foreign.Lua.Raw.Types: TypeThread :: Type
+ Foreign.Lua.Raw.Types: TypeUserdata :: Type
+ Foreign.Lua.Raw.Types: Yield :: Status
+ Foreign.Lua.Raw.Types: [fromNumArgs] :: NumArgs -> CInt
+ Foreign.Lua.Raw.Types: [fromNumResults] :: NumResults -> CInt
+ Foreign.Lua.Raw.Types: [fromStackIndex] :: StackIndex -> CInt
+ Foreign.Lua.Raw.Types: [fromTypeCode] :: TypeCode -> CInt
+ Foreign.Lua.Raw.Types: data GCCONTROL
+ Foreign.Lua.Raw.Types: data RelationalOperator
+ Foreign.Lua.Raw.Types: data Status
+ Foreign.Lua.Raw.Types: data Type
+ Foreign.Lua.Raw.Types: false :: LuaBool
+ Foreign.Lua.Raw.Types: fromLuaBool :: LuaBool -> Bool
+ Foreign.Lua.Raw.Types: fromRelationalOperator :: RelationalOperator -> CInt
+ Foreign.Lua.Raw.Types: fromType :: Type -> TypeCode
+ Foreign.Lua.Raw.Types: instance Foreign.Storable.Storable Foreign.Lua.Raw.Types.LuaBool
+ Foreign.Lua.Raw.Types: instance Foreign.Storable.Storable Foreign.Lua.Raw.Types.StatusCode
+ Foreign.Lua.Raw.Types: instance GHC.Classes.Eq Foreign.Lua.Raw.Types.GCCONTROL
+ Foreign.Lua.Raw.Types: instance GHC.Classes.Eq Foreign.Lua.Raw.Types.Integer
+ Foreign.Lua.Raw.Types: instance GHC.Classes.Eq Foreign.Lua.Raw.Types.LuaBool
+ Foreign.Lua.Raw.Types: instance GHC.Classes.Eq Foreign.Lua.Raw.Types.NumArgs
+ Foreign.Lua.Raw.Types: instance GHC.Classes.Eq Foreign.Lua.Raw.Types.NumResults
+ Foreign.Lua.Raw.Types: instance GHC.Classes.Eq Foreign.Lua.Raw.Types.Number
+ Foreign.Lua.Raw.Types: instance GHC.Classes.Eq Foreign.Lua.Raw.Types.RelationalOperator
+ Foreign.Lua.Raw.Types: instance GHC.Classes.Eq Foreign.Lua.Raw.Types.StackIndex
+ Foreign.Lua.Raw.Types: instance GHC.Classes.Eq Foreign.Lua.Raw.Types.State
+ Foreign.Lua.Raw.Types: instance GHC.Classes.Eq Foreign.Lua.Raw.Types.Status
+ Foreign.Lua.Raw.Types: instance GHC.Classes.Eq Foreign.Lua.Raw.Types.StatusCode
+ Foreign.Lua.Raw.Types: instance GHC.Classes.Eq Foreign.Lua.Raw.Types.Type
+ Foreign.Lua.Raw.Types: instance GHC.Classes.Eq Foreign.Lua.Raw.Types.TypeCode
+ Foreign.Lua.Raw.Types: instance GHC.Classes.Ord Foreign.Lua.Raw.Types.GCCONTROL
+ Foreign.Lua.Raw.Types: instance GHC.Classes.Ord Foreign.Lua.Raw.Types.Integer
+ Foreign.Lua.Raw.Types: instance GHC.Classes.Ord Foreign.Lua.Raw.Types.NumArgs
+ Foreign.Lua.Raw.Types: instance GHC.Classes.Ord Foreign.Lua.Raw.Types.NumResults
+ Foreign.Lua.Raw.Types: instance GHC.Classes.Ord Foreign.Lua.Raw.Types.Number
+ Foreign.Lua.Raw.Types: instance GHC.Classes.Ord Foreign.Lua.Raw.Types.RelationalOperator
+ Foreign.Lua.Raw.Types: instance GHC.Classes.Ord Foreign.Lua.Raw.Types.StackIndex
+ Foreign.Lua.Raw.Types: instance GHC.Classes.Ord Foreign.Lua.Raw.Types.Type
+ Foreign.Lua.Raw.Types: instance GHC.Classes.Ord Foreign.Lua.Raw.Types.TypeCode
+ Foreign.Lua.Raw.Types: instance GHC.Enum.Bounded Foreign.Lua.Raw.Types.Integer
+ Foreign.Lua.Raw.Types: instance GHC.Enum.Bounded Foreign.Lua.Raw.Types.Type
+ Foreign.Lua.Raw.Types: instance GHC.Enum.Enum Foreign.Lua.Raw.Types.GCCONTROL
+ Foreign.Lua.Raw.Types: instance GHC.Enum.Enum Foreign.Lua.Raw.Types.Integer
+ Foreign.Lua.Raw.Types: instance GHC.Enum.Enum Foreign.Lua.Raw.Types.StackIndex
+ Foreign.Lua.Raw.Types: instance GHC.Enum.Enum Foreign.Lua.Raw.Types.Type
+ Foreign.Lua.Raw.Types: instance GHC.Float.Floating Foreign.Lua.Raw.Types.Number
+ Foreign.Lua.Raw.Types: instance GHC.Float.RealFloat Foreign.Lua.Raw.Types.Number
+ Foreign.Lua.Raw.Types: instance GHC.Generics.Generic Foreign.Lua.Raw.Types.State
+ Foreign.Lua.Raw.Types: instance GHC.Num.Num Foreign.Lua.Raw.Types.Integer
+ Foreign.Lua.Raw.Types: instance GHC.Num.Num Foreign.Lua.Raw.Types.NumArgs
+ Foreign.Lua.Raw.Types: instance GHC.Num.Num Foreign.Lua.Raw.Types.NumResults
+ Foreign.Lua.Raw.Types: instance GHC.Num.Num Foreign.Lua.Raw.Types.Number
+ Foreign.Lua.Raw.Types: instance GHC.Num.Num Foreign.Lua.Raw.Types.StackIndex
+ Foreign.Lua.Raw.Types: instance GHC.Real.Fractional Foreign.Lua.Raw.Types.Number
+ Foreign.Lua.Raw.Types: instance GHC.Real.Integral Foreign.Lua.Raw.Types.Integer
+ Foreign.Lua.Raw.Types: instance GHC.Real.Real Foreign.Lua.Raw.Types.Integer
+ Foreign.Lua.Raw.Types: instance GHC.Real.Real Foreign.Lua.Raw.Types.Number
+ Foreign.Lua.Raw.Types: instance GHC.Real.RealFrac Foreign.Lua.Raw.Types.Number
+ Foreign.Lua.Raw.Types: instance GHC.Show.Show Foreign.Lua.Raw.Types.GCCONTROL
+ Foreign.Lua.Raw.Types: instance GHC.Show.Show Foreign.Lua.Raw.Types.Integer
+ Foreign.Lua.Raw.Types: instance GHC.Show.Show Foreign.Lua.Raw.Types.LuaBool
+ Foreign.Lua.Raw.Types: instance GHC.Show.Show Foreign.Lua.Raw.Types.NumArgs
+ Foreign.Lua.Raw.Types: instance GHC.Show.Show Foreign.Lua.Raw.Types.NumResults
+ Foreign.Lua.Raw.Types: instance GHC.Show.Show Foreign.Lua.Raw.Types.Number
+ Foreign.Lua.Raw.Types: instance GHC.Show.Show Foreign.Lua.Raw.Types.RelationalOperator
+ Foreign.Lua.Raw.Types: instance GHC.Show.Show Foreign.Lua.Raw.Types.StackIndex
+ Foreign.Lua.Raw.Types: instance GHC.Show.Show Foreign.Lua.Raw.Types.Status
+ Foreign.Lua.Raw.Types: instance GHC.Show.Show Foreign.Lua.Raw.Types.Type
+ Foreign.Lua.Raw.Types: instance GHC.Show.Show Foreign.Lua.Raw.Types.TypeCode
+ Foreign.Lua.Raw.Types: newtype Integer
+ Foreign.Lua.Raw.Types: newtype LuaBool
+ Foreign.Lua.Raw.Types: newtype NumArgs
+ Foreign.Lua.Raw.Types: newtype NumResults
+ Foreign.Lua.Raw.Types: newtype Number
+ Foreign.Lua.Raw.Types: newtype StackIndex
+ Foreign.Lua.Raw.Types: newtype State
+ Foreign.Lua.Raw.Types: newtype StatusCode
+ Foreign.Lua.Raw.Types: newtype TypeCode
+ Foreign.Lua.Raw.Types: toLuaBool :: Bool -> LuaBool
+ Foreign.Lua.Raw.Types: toStatus :: StatusCode -> Status
+ Foreign.Lua.Raw.Types: toType :: TypeCode -> Type
+ Foreign.Lua.Raw.Types: true :: LuaBool
+ Foreign.Lua.Raw.Types: type CFunction = FunPtr (State -> IO NumResults)
+ Foreign.Lua.Raw.Types: type Reader = FunPtr (State -> Ptr () -> Ptr CSize -> IO (Ptr CChar))
+ Foreign.Lua.Raw.Userdata: hslua_fromuserdata :: State -> StackIndex -> CString -> IO (Maybe a)
+ Foreign.Lua.Raw.Userdata: hslua_newhsuserdata :: State -> a -> IO ()
+ Foreign.Lua.Raw.Userdata: hslua_newudmetatable :: State -> CString -> IO LuaBool
+ Foreign.Lua.Types.Peekable: instance Foreign.Lua.Types.Peekable.Peekable Foreign.Lua.Raw.Types.CFunction
+ Foreign.Lua.Types.Peekable: instance Foreign.Lua.Types.Peekable.Peekable Foreign.Lua.Raw.Types.Integer
+ Foreign.Lua.Types.Peekable: instance Foreign.Lua.Types.Peekable.Peekable Foreign.Lua.Raw.Types.Number
+ Foreign.Lua.Types.Peekable: instance Foreign.Lua.Types.Peekable.Peekable Foreign.Lua.Raw.Types.State
+ Foreign.Lua.Types.Pushable: instance Foreign.Lua.Types.Pushable.Pushable Foreign.Lua.Raw.Types.CFunction
+ Foreign.Lua.Types.Pushable: instance Foreign.Lua.Types.Pushable.Pushable Foreign.Lua.Raw.Types.Integer
+ Foreign.Lua.Types.Pushable: instance Foreign.Lua.Types.Pushable.Pushable Foreign.Lua.Raw.Types.Number

Files

CHANGELOG.md view
@@ -1,11 +1,61 @@ ## Changelog +### 1.2.0++Released 2020-08-15++- New module `Foreign.Lua.Call`: the module offers an alternative+  method of exposing Haskell functions to Lua. The focus is on+  maintainability: types and marshaling methods are made explicit;+  the possibility of adding documentation and parameter names+  improves error messages and allows for automatic documentation+  extraction.++  Work on this module is ongoing; the interface is likely to+  change. Suggestions and feedback are welcome.++- New types `Module`, `Field`, and new functions `registerModule`,+  `preloadModule`, `pushModule`, and `render` exported from+  `Foreign.Lua.Module`: this builds on the new `Call` module and+  allows the creation of documented modules as well as automatic+  generation of Markdown-formatted module documentation.++- Export new items `nth` and `top` from Foreign.Lua.Core and+  Foreign.Lua. They are short-hands for `nthFromTop` and+  `stackTop`.++- Performance improvements: Calling of Lua functions and creation+  of Haskell data wrapping userdata has been sped up by about 10%.+  This is mostly due to using of previously missed optimization+  opportunities.++- All foreign imports have been moved to into the new+  `Foreign.Lua.Raw` module. This module will replace the current+  `Foreign.Lua.Core` module in the future and will be distributed+  as a separate package (likely starting with the 2.0 release);+  the remaining parts of the current `Core` module will be+  promoted one level in the module hierarchy.++  The `Raw` module can be used whenever the full power of HsLua is+  not needed.++- Error-signaling of API wrapper functions has been changed:+  instead of returning special integer values, functions now take+  an additional pointer argument, which is set to the status+  result of the computation.++  The `Failable` type in Core.Error is no longer needed and has+  been removed.++- CI builds now include GHC 8.8 and GHC 8.10, ensuring that all+  GHC 8.* versions are supported.+ ### 1.1.2 -Released 2020-06-02+Released 2020-06-27  - Revert signature of function `pushList` to it's proper 1.1-  value. This fixes a mistake which made caused the 1.1.1 release+  value. This fixes a mistake which caused the 1.1.1 release   to be in violation of the PVP versioning policy.  - Module Foreign.Lua.Peek: add function `pushKeyValuePairs` (Alex
− cbits/error-conversion/error-conversion.c
@@ -1,261 +0,0 @@-#include <stdio.h>-#include <string.h>-#include <HsFFI.h>-#include "error-conversion.h"--/* *********************************************************************- * Transforming Haskell errors to Lua errors- * *********************************************************************/-void hslua_pushhaskellerr(lua_State *L)-{-  lua_getfield(L, LUA_REGISTRYINDEX, "HSLUA_ERR");-}--/*-** Marks the occurence of an error; the returned value should be used as-** the error message.-*/-int hslua_error(lua_State *L)-{-  hslua_pushhaskellerr(L);-  lua_insert(L, -2);-  return 2;-}--/*-** Checks whether the object at the given index is a Haskell error.-*/-int hslua_is_haskell_error(lua_State *L, int idx) {-  hslua_pushhaskellerr(L);-  int is_err = lua_rawequal(L, idx, -1);-  lua_pop(L, 1);                /* pop haskellerr used for equality test */-  return is_err;-}--/*-** Converts a Haskell function into a CFunction.-**-** We signal an error on the haskell side by passing two values: the-** special haskellerr object and the error message. The function-** returned an error iff there are exactly two results objects where the-** first object is the special HSLUA_ERR registry entry.-*/-int hslua_call_hs(lua_State *L)-{-  int nargs = lua_gettop(L);-  /* Push HaskellImportFunction and call the underlying function */-  lua_pushvalue(L, lua_upvalueindex(1));-  lua_insert(L, 1);-  lua_call(L, nargs, LUA_MULTRET);--  /* Check whether an error value was returned */-  int nres = lua_gettop(L);--  /* If there are two results, the first of which is the special error-   * object, then the other object is thrown as an error.-   */-  if (nres == 2 && hslua_is_haskell_error(L, 1)) {-    return lua_error(L);        /* throw 2nd return value as error */-  }--  return nres;-}--/* *********************************************************************- * Garbage Collection- * *********************************************************************/--/*-** Free stable Haskell pointer in userdata.-*/-int hslua_userdata_gc(lua_State *L)-{-  HsStablePtr *userdata = lua_touserdata(L, 1);-  if (userdata) {-    hs_free_stable_ptr(*userdata);-  }-  return 0;-}---/* *********************************************************************- * Transforming Lua errors to Haskell errors- * *********************************************************************/--/*-** compare-*/-int hslua__compare(lua_State *L)-{-  int op = lua_tointeger(L, 3);-  int res = lua_compare(L, 1, 2, op);-  lua_pushinteger(L, res);-  return 1;-}--int hslua_compare(lua_State *L, int index1, int index2, int op)-{-  index1 = lua_absindex(L, index1);-  index2 = lua_absindex(L, index2);-  lua_pushcfunction(L, hslua__compare);-  lua_pushvalue(L, index1);-  lua_pushvalue(L, index2);-  lua_pushinteger(L, op);-  int callres = lua_pcall(L, 3, 1, 0);-  if (callres != 0) {-    return -callres;-  }-  int res = lua_tointeger(L, -1);-  lua_pop(L, 1);-  return res;-}---/*-** concat-*/-int hslua__concat(lua_State *L)-{-  lua_concat(L, lua_gettop(L));-  return 1;-}--int hslua_concat(lua_State *L, int n)-{-  lua_pushcfunction(L, hslua__concat);-  lua_insert(L, -n - 1);-  return -lua_pcall(L, n, 1, 0);-}---/*-** getglobal-*/-int hslua__getglobal(lua_State *L)-{-  lua_gettable(L, 1);-  return 1;-}--int hslua_getglobal(lua_State *L, const char *name, size_t len)-{-  lua_pushcfunction(L, hslua__getglobal);-  lua_pushglobaltable(L);-  lua_pushlstring(L, name, len);-  return -lua_pcall(L, 2, 1, 0);-}---/*-** gettable-*/-int hslua__gettable(lua_State *L)-{-  lua_pushvalue(L, 1);-  lua_gettable(L, 2);-  return 1;-}--int hslua_gettable(lua_State *L, int index)-{-  lua_pushvalue(L, index);-  lua_pushcfunction(L, hslua__gettable);-  lua_insert(L, -3);-  return -lua_pcall(L, 2, 1, 0);-}---/*-** setglobal-*/-int hslua__setglobal(lua_State *L)-{-  /* index 1: value */-  /* index 2: the global table */-  /* index 3: key */-  lua_pushvalue(L, 1);-  lua_settable(L, 2);-  return 0;-}--int hslua_setglobal(lua_State *L, const char *name, size_t len)-{-  /* we expect the new value to be at the top of the stack */-  lua_pushglobaltable(L);-  lua_pushlstring(L, name, len);-  lua_pushcfunction(L, hslua__setglobal);-  lua_insert(L, -4);-  return -lua_pcall(L, 3, 0, 0);-}---/*-** settable-*/-int hslua__settable(lua_State *L)-{-  lua_pushvalue(L, 1); /* key */-  lua_pushvalue(L, 2); /* value */-  lua_settable(L, 3);  /* table is the third argument */-  return 0;-}--int hslua_settable(lua_State *L, int index)-{-  lua_pushvalue(L, index);-  lua_pushcfunction(L, hslua__settable);-  lua_insert(L, -4);-  return -lua_pcall(L, 3, 0, 0);-}---/*-** next-*/-int hslua__next(lua_State *L)-{-  lua_pushvalue(L, 1);-  return lua_next(L, 2) ? 2 : 0;-}--int hslua_next(lua_State *L, int index)-{-  int oldsize = lua_gettop(L);-  lua_pushvalue(L, index);-  lua_pushcfunction(L, hslua__next);-  lua_insert(L, -3);-  int res = lua_pcall(L, 2, LUA_MULTRET, 0);-  if (res != 0) {-    /* error */-    return (- res);-  }-  /* success */-  return (lua_gettop(L) - oldsize + 1); /* correct for popped value */-}---/*-** Auxiliary Library-*/--/*-** tolstring'-*/-int hsluaL__tolstring(lua_State *L)-{-  luaL_tolstring(L, 1, NULL);-  return 1;-}--const char *hsluaL_tolstring(lua_State *L, int index, size_t *len)-{-  lua_pushvalue(L, index);-  lua_pushcfunction(L, hsluaL__tolstring);-  lua_insert(L, -2);-  int res = lua_pcall(L, 1, 1, 0);-  if (res != 0) {-    /* error */-    return NULL;-  }-  return lua_tolstring(L, -1, len);-}
− cbits/error-conversion/error-conversion.h
@@ -1,26 +0,0 @@-#include "lua.h"-#include "lauxlib.h"--int hslua_error(lua_State *L);--int hslua_call_hs(lua_State *L);--int hslua_userdata_gc(lua_State *L);--int hslua_compare(lua_State *L, int index1, int index2, int op);--int hslua_concat(lua_State *L, int n);--int hslua_getglobal(lua_State *L, const char *name, size_t len);--int hslua_gettable(lua_State *L, int index);--int hslua_setglobal(lua_State *L, const char *k, size_t len);--int hslua_settable(lua_State *L, int index);--int hslua_next(lua_State *L, int index);---/* auxiliary library */-const char *hsluaL_tolstring(lua_State *L, int index, size_t *len);
+ cbits/hslua/hslcall.c view
@@ -0,0 +1,102 @@+#include <HsFFI.h>+#include <lua.h>+#include <lauxlib.h>+#include "hslua-export.h"+#include "hslcall.h"+#include "hsludata.h"++/* ***************************************************************+ * Transforming Haskell errors to Lua errors+ * ***************************************************************/+void hslua_pushhaskellerr(lua_State *L)+{+  lua_getfield(L, LUA_REGISTRYINDEX, HSLUA_ERR);+}++/*+** Marks the occurence of an error; the returned value should be+** used as the error message.+*/+int hslua_error(lua_State *L)+{+  hslua_pushhaskellerr(L);+  lua_insert(L, -2);+  return 2;+}++/*+** Checks whether the object at the given index is a Haskell error.+*/+int hslua_is_haskell_error(lua_State *L, int idx)+{+  int erridx = lua_absindex(L, idx);+  hslua_pushhaskellerr(L);+  int is_err = lua_rawequal(L, erridx, -1);+  lua_pop(L, 1);        /* pop haskellerr used for equality test */+  return is_err;+}++/*+** Converts a Haskell function into a CFunction.+**+** We signal an error on the haskell side by passing two values:+** the special HSLUA_ERR object and the error message. The+** function returned an error iff there are exactly two results+** objects where the first object is the special HSLUA_ERR+** registry entry.+*/+int hslua_call_hs(lua_State *L)+{+  int nargs = lua_gettop(L);+  /* Push HaskellFunction and call the underlying function */+  lua_pushvalue(L, lua_upvalueindex(1));+  lua_insert(L, 1);+  lua_call(L, nargs, LUA_MULTRET);++  /* Check whether an error value was returned */+  int nres = lua_gettop(L);++  /* If there are two results, the first of which is the special+   * error object, then the other object is thrown as an error.+   */+  if (nres == 2 && hslua_is_haskell_error(L, 1)) {+    return lua_error(L);      /* throw 2nd return value as error */+  }++  return nres;+}++/*+** Retrieves a HsStablePtr to a Haskell function from a+** function-wrapping userdata when it's been called and removes+** the userdata from the stack.+*/+void *hslua_hs_fun_ptr(lua_State *L)+{+  void *fn = luaL_testudata(L, 1, HSLUA_HSFUN_NAME);+  lua_remove(L, 1);+  return fn;+}++/*+** Pushes a metatable for Haskell function wrapping userdata to+** the stack.+*/+void hslua_registerhsfunmetatable(lua_State *L)+{+  hslua_newudmetatable(L, HSLUA_HSFUN_NAME);+  lua_pushcfunction(L, &hslua_call_wrapped_hs_fun);+  lua_setfield(L, -2, "__call");+  lua_pop(L, 1);+}++/*+** Creates a new C function from a Haskell function.+*/+void hslua_newhsfunction(lua_State *L, HsStablePtr fn)+{+  HsStablePtr *ud = lua_newuserdata(L, sizeof fn);+  *ud = fn;+  luaL_setmetatable(L, HSLUA_HSFUN_NAME);+  lua_pushcclosure(L, &hslua_call_hs, 1);+}
+ cbits/hslua/hslcall.h view
@@ -0,0 +1,12 @@+#ifndef hslcall_h+#define hslcall_h++#define HSLUA_ERR "HSLUA_ERR"+#define HSLUA_HSFUN_NAME "HsLuaFunction"+#include <lua.h>+#include <HsFFI.h>++/*  register metatable for HaskellFunction userdata wrappers */+void hslua_registerhsfunmetatable(lua_State *L);++#endif
+ cbits/hslua/hslua-export.h view
@@ -0,0 +1,8 @@+/* ***************************************************************+ * Functions exported from Haskell+ * ***************************************************************/++#include <lua.h>++/*  exported from Foreign.Lua.Raw.Call */+int hslua_call_wrapped_hs_fun(lua_State *L);
+ cbits/hslua/hslua.c view
@@ -0,0 +1,205 @@+#include <stdio.h>+#include <string.h>+#include <HsFFI.h>+#include "hslua.h"+#include "hslcall.h"++/* ***************************************************************+ * Transforming Lua errors to Haskell errors+ * ***************************************************************/++/*+** compare+*/+int hslua__compare(lua_State *L)+{+  int op = lua_tointeger(L, 3);+  int res = lua_compare(L, 1, 2, op);+  lua_pushinteger(L, res);+  return 1;+}++int hslua_compare(lua_State *L, int index1, int index2, int op, int *status)+{+  index1 = lua_absindex(L, index1);+  index2 = lua_absindex(L, index2);+  lua_pushcfunction(L, hslua__compare);+  lua_pushvalue(L, index1);+  lua_pushvalue(L, index2);+  lua_pushinteger(L, op);+  *status = lua_pcall(L, 3, 1, 0);+  if (*status != LUA_OK) {+    return 0;+  }+  int result = lua_tointeger(L, -1);+  lua_pop(L, 1);+  return result;+}+++/*+** concat+*/+int hslua__concat(lua_State *L)+{+  lua_concat(L, lua_gettop(L));+  return 1;+}++void hslua_concat(lua_State *L, int n, int *status)+{+  lua_pushcfunction(L, hslua__concat);+  lua_insert(L, -n - 1);+  *status = lua_pcall(L, n, 1, 0);+}+++/*+** getglobal+*/+int hslua__getglobal(lua_State *L)+{+  lua_gettable(L, 1);+  return 1;+}++void hslua_getglobal(lua_State *L, const char *name, size_t len, int *status)+{+  lua_pushcfunction(L, hslua__getglobal);+  lua_pushglobaltable(L);+  lua_pushlstring(L, name, len);+  *status = lua_pcall(L, 2, 1, 0);+}+++/*+** gettable+*/+int hslua__gettable(lua_State *L)+{+  lua_pushvalue(L, 1);+  lua_gettable(L, 2);+  return 1;+}++void hslua_gettable(lua_State *L, int index, int *status)+{+  lua_pushvalue(L, index);+  lua_pushcfunction(L, hslua__gettable);+  lua_insert(L, -3);+  *status = lua_pcall(L, 2, 1, 0);+}+++/*+** setglobal+*/+int hslua__setglobal(lua_State *L)+{+  /* index 1: value */+  /* index 2: the global table */+  /* index 3: key */+  lua_pushvalue(L, 1);+  lua_settable(L, 2);+  return 0;+}++void hslua_setglobal(lua_State *L, const char *name, size_t len, int *status)+{+  /* we expect the new value to be at the top of the stack */+  lua_pushglobaltable(L);+  lua_pushlstring(L, name, len);+  lua_pushcfunction(L, hslua__setglobal);+  lua_insert(L, -4);+  *status = lua_pcall(L, 3, 0, 0);+}+++/*+** settable+*/+int hslua__settable(lua_State *L)+{+  lua_pushvalue(L, 1); /* key */+  lua_pushvalue(L, 2); /* value */+  lua_settable(L, 3);  /* table is the third argument */+  return 0;+}++void hslua_settable(lua_State *L, int index, int *status)+{+  lua_pushvalue(L, index);+  lua_pushcfunction(L, hslua__settable);+  lua_insert(L, -4);+  *status = lua_pcall(L, 3, 0, 0);+}+++/*+** next+*/+int hslua__next(lua_State *L)+{+  lua_pushvalue(L, 1);+  return lua_next(L, 2) ? 2 : 0;+}++int hslua_next(lua_State *L, int index, int *status)+{+  int oldsize = lua_gettop(L);+  lua_pushvalue(L, index);+  lua_pushcfunction(L, hslua__next);+  lua_insert(L, -3);+  *status = lua_pcall(L, 2, LUA_MULTRET, 0);+  if (*status != 0) {+    /* error */+    return 0;+  }+  /* success */+  return (lua_gettop(L) - oldsize + 1); /* correct for popped value */+}+++/*+** Auxiliary Library+*/++/*+** newstate+*/+lua_State *hsluaL_newstate()+{+  lua_State *L = luaL_newstate();++  /* add error value */+  lua_createtable(L, 0, 0);+  lua_setfield(L, LUA_REGISTRYINDEX, HSLUA_ERR);++  /* register HaskellFunction userdata metatable */+  hslua_registerhsfunmetatable(L);++  return L;+}+++/*+** tolstring'+*/+int hsluaL__tolstring(lua_State *L)+{+  luaL_tolstring(L, 1, NULL);+  return 1;+}++const char *hsluaL_tolstring(lua_State *L, int index, size_t *len)+{+  lua_pushvalue(L, index);+  lua_pushcfunction(L, hsluaL__tolstring);+  lua_insert(L, -2);+  int res = lua_pcall(L, 1, 1, 0);+  if (res != 0) {+    /* error */+    return NULL;+  }+  return lua_tolstring(L, -1, len);+}
+ cbits/hslua/hslua.h view
@@ -0,0 +1,33 @@+#include "lua.h"+#include "lauxlib.h"++int hslua_error(lua_State *L);++int hslua_call_hs(lua_State *L);++int hslua_userdata_gc(lua_State *L);++int hslua_compare(lua_State *L, int index1, int index2, int op, int *status);++void hslua_concat(lua_State *L, int n, int *status);++void hslua_getglobal(lua_State *L, const char *name, size_t len, int *status);++void hslua_gettable(lua_State *L, int index, int *status);++void hslua_setglobal(lua_State *L, const char *k, size_t len, int *status);++void hslua_settable(lua_State *L, int index, int *status);++int hslua_next(lua_State *L, int index, int *status);+++/* auxiliary library */+const char *hsluaL_tolstring(lua_State *L, int index, size_t *len);++/*+** function calling+*/++/* Wraps a Haskell function with an userdata object.  */+void hslua_newhsfunwrapper(lua_State *L, HsStablePtr fn);
+ cbits/hslua/hsludata.c view
@@ -0,0 +1,41 @@+#include <HsFFI.h>+#include "hslua.h"+#include "hsludata.h"++/* ***************************************************************+ * Userdata Creation and Garbage Collection+ * ***************************************************************/++/*+** Free stable Haskell pointer in userdata.+**+** The userdata whose contents is garbage collected must be on+** stack index 1 (i.e., the first argument).+*/+int hslua_userdata_gc(lua_State *L)+{+  HsStablePtr *userdata = lua_touserdata(L, 1);+  if (userdata) {+    hs_free_stable_ptr(*userdata);+  }+  return 0;+}++/*+** Creates a new userdata metatable for Haskell objects, or gets+** is from the registry if possible.+*/+int hslua_newudmetatable(lua_State *L, const char *tname)+{+  int created = luaL_newmetatable(L, tname);+  if (created) {+    /* Prevent accessing or changing the metatable with+     * getmetatable/setmetatable. */+    lua_pushboolean(L, 1);+    lua_setfield(L, -2, "__metatable");+    /* Mark objects for finalization when collecting garbage. */+    lua_pushcfunction(L, &hslua_userdata_gc);+    lua_setfield(L, -2, "__gc");+  }+  return created;+}
+ cbits/hslua/hsludata.h view
@@ -0,0 +1,11 @@+#include <HsFFI.h>+#include <lua.h>++/* ***************************************************************+ * Userdata for Haskell values+ * ***************************************************************/++/*+** Creates a new userdata metatable for Haskell objects.+*/+int hslua_newudmetatable(lua_State *L, const char *tname);
hslua.cabal view
@@ -1,5 +1,6 @@+cabal-version:       2.2 name:                hslua-version:             1.1.2+version:             1.2.0 synopsis:            Bindings to Lua, an embeddable scripting language description:         HsLua provides bindings, wrappers, types, and helper                      functions to bridge Haskell and <https://www.lua.org/ Lua>.@@ -22,16 +23,16 @@ category:            Foreign build-type:          Simple extra-source-files:  cbits/lua-5.3.5/*.h-                     cbits/error-conversion/*.h-                     README.md-                     CHANGELOG.md-                     test/lua/*.lua-cabal-version:       >=1.10+                   , cbits/hslua/*.h+                   , README.md+                   , CHANGELOG.md+                   , test/lua/*.lua tested-with:         GHC == 8.0.2                    , GHC == 8.2.2                    , GHC == 8.4.3                    , GHC == 8.6.5                    , GHC == 8.8.3+                   , GHC == 8.10.1  source-repository head   type:                git@@ -85,6 +86,7 @@  library   exposed-modules:     Foreign.Lua+                     , Foreign.Lua.Call                      , Foreign.Lua.Core                      , Foreign.Lua.Core.Constants                      , Foreign.Lua.Core.Error@@ -94,6 +96,13 @@                      , Foreign.Lua.Module                      , Foreign.Lua.Peek                      , Foreign.Lua.Push+                     , Foreign.Lua.Raw.Auxiliary+                     , Foreign.Lua.Raw.Call+                     , Foreign.Lua.Raw.Constants+                     , Foreign.Lua.Raw.Error+                     , Foreign.Lua.Raw.Functions+                     , Foreign.Lua.Raw.Types+                     , Foreign.Lua.Raw.Userdata                      , Foreign.Lua.Types                      , Foreign.Lua.Types.Peekable                      , Foreign.Lua.Types.Pushable@@ -111,6 +120,17 @@   hs-source-dirs:      src   default-language:    Haskell2010   ghc-options:         -Wall+                       -Wincomplete-record-updates+                       -Wnoncanonical-monad-instances+                       -Wredundant-constraints+  if impl(ghc >= 8.2)+    ghc-options:         -Wcpp-undef+                         -Werror=missing-home-modules+  if impl(ghc >= 8.4)+    ghc-options:         -Widentities+                         -Wincomplete-uni-patterns+                         -Wpartial-fields+                         -fhide-source-paths   default-extensions:  CApiFFI                      , ForeignFunctionInterface                      , LambdaCase@@ -120,9 +140,10 @@                      , FlexibleContexts                      , FlexibleInstances                      , ScopedTypeVariables-  c-sources:           cbits/error-conversion/error-conversion.c-  include-dirs:        cbits/error-conversion-+  c-sources:           cbits/hslua/hsludata.c+                     , cbits/hslua/hslcall.c+                     , cbits/hslua/hslua.c+  include-dirs:        cbits/hslua   if flag(system-lua) || flag(pkg-config)     if flag(pkg-config)       pkgconfig-depends: lua5.3@@ -205,8 +226,18 @@   main-is:             test-hslua.hs   hs-source-dirs:      test   ghc-options:         -Wall -threaded+                       -Wincomplete-record-updates+                       -Wnoncanonical-monad-instances+  if impl(ghc >= 8.2)+    ghc-options:         -Wcpp-undef+  if impl(ghc >= 8.4)+    ghc-options:         -Wincomplete-uni-patterns+                         -Widentities+                         -Werror=missing-home-modules+                         -fhide-source-paths   default-language:    Haskell2010   other-modules:       Foreign.LuaTests+                     , Foreign.Lua.CallTests                      , Foreign.Lua.CoreTests                      , Foreign.Lua.Core.AuxiliaryTests                      , Foreign.Lua.Core.ErrorTests
+ src/Foreign/Lua/Call.hs view
@@ -0,0 +1,301 @@+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+{-|+Module      : Foreign.Lua.Call+Copyright   : © 2020 Albert Krewinkel+License     : MIT+Maintainer  : Albert Krewinkel <tarleb+hslua@zeitkraut.de>+Stability   : alpha+Portability : Portable++Marshaling and documenting Haskell functions.+-}+module Foreign.Lua.Call+  ( HaskellFunction (..)+  , toHsFnPrecursor+  , toHsFnPrecursorWithStartIndex+  , applyParameter+  , returnResult+  , Parameter (..)+  , FunctionResult (..)+  , FunctionResults+    -- * Operators+  , (<#>)+  , (=#>)+  , (#?)+    -- * Documentation+  , FunctionDoc (..)+  , ParameterDoc (..)+  , FunctionResultDoc (..)+  , render+    -- * Pushing to Lua+  , pushHaskellFunction+    -- * Convenience functions+  , parameter+  , optionalParameter+  , functionResult+  ) where++import Control.Monad.Except+import Data.Text (Text)+import Foreign.Lua.Core as Lua+import Foreign.Lua.Core.Types (liftLua)+import Foreign.Lua.Peek+import Foreign.Lua.Push+import Foreign.Lua.Raw.Call (hslua_pushhsfunction)+import qualified Data.Text as T++-- | Lua operation with an explicit error type and state (i.e.,+-- without exceptions).+type LuaExcept a = ExceptT PeekError Lua a+++--+-- Function components+--++-- | Result of a call to a Haskell function.+data FunctionResult a+  = FunctionResult+  { fnResultPusher :: Pusher a+  , fnResultDoc :: FunctionResultDoc+  }++-- | List of function results in the order in which they are+-- returned in Lua.+type FunctionResults a = [FunctionResult a]++-- | Function parameter.+data Parameter a = Parameter+  { parameterPeeker :: Peeker a+  , parameterDoc    :: ParameterDoc+  }++-- | Haskell equivallent to CFunction, i.e., function callable+-- from Lua.+data HaskellFunction = HaskellFunction+  { callFunction :: Lua NumResults+  , functionDoc :: Maybe FunctionDoc+  }++--+-- Documentation+--++-- | Documentation for a Haskell function+data FunctionDoc = FunctionDoc+  { functionDescription :: Text+  , parameterDocs       :: [ParameterDoc]+  , functionResultDocs  :: [FunctionResultDoc]+  }+  deriving (Eq, Ord, Show)++-- | Documentation for function parameters.+data ParameterDoc = ParameterDoc+  { parameterName :: Text+  , parameterType :: Text+  , parameterDescription :: Text+  , parameterIsOptional :: Bool+  }+  deriving (Eq, Ord, Show)++-- | Documentation for the result of a function.+data FunctionResultDoc = FunctionResultDoc+  { functionResultType :: Text+  , functionResultDescription :: Text+  }+  deriving (Eq, Ord, Show)+++--+-- Haskell function building+--++-- | Helper type used to create 'HaskellFunction's.+data HsFnPrecursor a = HsFnPrecursor+  { hsFnPrecursorAction :: LuaExcept a+  , hsFnMaxParameterIdx :: StackIndex+  , hsFnParameterDocs :: [ParameterDoc]+  }+  deriving (Functor)++-- | Create a HaskellFunction precursor from a pure function.+toHsFnPrecursor :: a -> HsFnPrecursor a+toHsFnPrecursor = toHsFnPrecursorWithStartIndex (StackIndex 0)++toHsFnPrecursorWithStartIndex :: StackIndex -> a -> HsFnPrecursor a+toHsFnPrecursorWithStartIndex idx f = HsFnPrecursor+  { hsFnPrecursorAction = return f+  , hsFnMaxParameterIdx = idx+  , hsFnParameterDocs = mempty+  }++-- | Partially apply a parameter.+applyParameter :: HsFnPrecursor (a -> b)+               -> Parameter a+               -> HsFnPrecursor b+applyParameter bldr param = do+  let action = hsFnPrecursorAction bldr+  let i = hsFnMaxParameterIdx bldr + 1+  let context = "retrieving function argument " <>+        (parameterName . parameterDoc) param+  let nextAction f = withExceptT (pushMsg context) $ do+        x <- ExceptT $ parameterPeeker param i+        return $ f x+  HsFnPrecursor+    { hsFnPrecursorAction = action >>= nextAction+    , hsFnMaxParameterIdx = i+    , hsFnParameterDocs = parameterDoc param : hsFnParameterDocs bldr+    }++-- | Take a 'HaskellFunction' precursor and convert it into a full+-- 'HaskellFunction', using the given 'FunctionResult's to return+-- the result to Lua.+returnResults :: HsFnPrecursor a+              -> FunctionResults a+              -> HaskellFunction+returnResults bldr fnResults = HaskellFunction+  { callFunction = do+      hsResult <- runExceptT $ hsFnPrecursorAction bldr+      case hsResult of+        Left err -> do+          pushString $ formatPeekError err+          Lua.error+        Right x -> do+          forM_ fnResults $ \(FunctionResult push _) -> push x+          return $ NumResults (fromIntegral $ length fnResults)++  , functionDoc = Just $ FunctionDoc+    { functionDescription = ""+    , parameterDocs = reverse $ hsFnParameterDocs bldr+    , functionResultDocs = map fnResultDoc fnResults+    }+  }++-- | Like @'returnResult'@, but returns only a single result.+returnResult :: HsFnPrecursor a+             -> FunctionResult a+             -> HaskellFunction+returnResult bldr = returnResults bldr . (:[])++-- | Updates the description of a Haskell function. Leaves the function+-- unchanged if it has no documentation.+updateFunctionDescription :: HaskellFunction -> Text -> HaskellFunction+updateFunctionDescription fn desc =+  case functionDoc fn of+    Nothing -> fn+    Just fnDoc ->+      fn { functionDoc = Just $ fnDoc { functionDescription = desc} }++--+-- Operators+--++infixl 8 <#>, =#>, #?++-- | Inline version of @'applyParameter'@.+(<#>) :: HsFnPrecursor (a -> b)+      -> Parameter a+      -> HsFnPrecursor b+(<#>) = applyParameter++-- | Inline version of @'returnResult'@.+(=#>) :: HsFnPrecursor a+      -> FunctionResults a+      -> HaskellFunction+(=#>) = returnResults++-- | Inline version of @'updateFunctionDescription'@.+(#?) :: HaskellFunction -> Text -> HaskellFunction+(#?) = updateFunctionDescription++--+-- Render documentation+--++render :: FunctionDoc -> Text+render (FunctionDoc desc paramDocs resultDoc) =+  (if T.null desc then "" else desc <> "\n\n") <>+  renderParamDocs paramDocs <>+  case resultDoc of+    [] -> ""+    rd -> "\nReturns:\n\n" <> T.intercalate "\n" (map renderResultDoc rd)++renderParamDocs :: [ParameterDoc] -> Text+renderParamDocs pds = "Parameters:\n\n" <>+  T.intercalate "\n" (map renderParamDoc pds)++renderParamDoc :: ParameterDoc -> Text+renderParamDoc pd = mconcat+  [ parameterName pd+  ,  "\n:   "+  , parameterDescription pd+  , " (", parameterType pd, ")\n"+  ]++renderResultDoc :: FunctionResultDoc -> Text+renderResultDoc rd = mconcat+  [ " - "+  , functionResultDescription rd+  , " (", functionResultType rd, ")\n"+  ]++--+-- Push to Lua+--++pushHaskellFunction :: HaskellFunction -> Lua ()+pushHaskellFunction fn = do+  errConv <- Lua.errorConversion+  let hsFn = flip (runWithConverter errConv) $ callFunction fn+  liftLua $ \l -> hslua_pushhsfunction l hsFn++--+-- Convenience functions+--++-- | Creates a parameter.+parameter :: Peeker a     -- ^ method to retrieve value from Lua+          -> Text         -- ^ expected Lua type+          -> Text         -- ^ parameter name+          -> Text         -- ^ parameter description+          -> Parameter a+parameter peeker type_ name desc = Parameter+  { parameterPeeker = peeker+  , parameterDoc = ParameterDoc+    { parameterName = name+    , parameterDescription = desc+    , parameterType = type_+    , parameterIsOptional = False+    }+  }++-- | Creates an optional parameter.+optionalParameter :: Peeker a     -- ^ method to retrieve the value from Lua+                  -> Text         -- ^ expected Lua type+                  -> Text         -- ^ parameter name+                  -> Text         -- ^ parameter description+                  -> Parameter (Maybe a)+optionalParameter peeker type_ name desc = Parameter+  { parameterPeeker = optional peeker+  , parameterDoc = ParameterDoc+    { parameterName = name+    , parameterDescription = desc+    , parameterType = type_+    , parameterIsOptional = True+    }+  }++-- | Creates a function result.+functionResult :: Pusher a        -- ^ method to push the Haskell result to Lua+               -> Text            -- ^ Lua type of result+               -> Text            -- ^ result description+               -> FunctionResults a+functionResult pusher type_ desc = (:[]) $ FunctionResult+  { fnResultPusher = pusher+  , fnResultDoc = FunctionResultDoc+    { functionResultType = type_+    , functionResultDescription = desc+    }+  }
src/Foreign/Lua/Core.hs view
@@ -30,10 +30,12 @@   , Lua.Number (..)   -- ** Stack index   , StackIndex (..)+  , nth   , nthFromBottom   , nthFromTop   , stackTop   , stackBottom+  , top   -- ** Number of arguments and return values   , NumArgs (..)   , NumResults (..)
+ src/Foreign/Lua/Core/Auxiliary.hs view
@@ -0,0 +1,259 @@+{-# LANGUAGE OverloadedStrings #-}+{-|+Module      : Foreign.Lua.Core.Auxiliary+Copyright   : © 2007–2012 Gracjan Polak,+                2012–2016 Ömer Sinan Ağacan,+                2017-2020 Albert Krewinkel+License     : MIT+Maintainer  : Albert Krewinkel <tarleb+hslua@zeitkraut.de>+Stability   : beta+Portability : non-portable (depends on GHC)++Wrappers for the auxiliary library.+-}+module Foreign.Lua.Core.Auxiliary+  ( dostring+  , dofile+  , getmetafield+  , getmetatable'+  , getsubtable+  , loadbuffer+  , loadfile+  , loadstring+  , newmetatable+  , newstate+  , tostring'+  , traceback+  -- * References+  , getref+  , ref+  , unref+  -- * Registry fields+  , loadedTableRegistryField+  , preloadTableRegistryField+  ) where++import Control.Exception (IOException, try)+import Data.ByteString (ByteString)+import Foreign.C (withCString)+import Foreign.Lua.Core.Types (Lua, liftLua)+import Foreign.Lua.Raw.Auxiliary+import Foreign.Lua.Raw.Constants (multret)+import Foreign.Lua.Raw.Types (StackIndex, Status)+import Foreign.Marshal.Alloc (alloca)+import Foreign.Ptr++import qualified Data.ByteString as B+import qualified Foreign.Lua.Core.Functions as Lua+import qualified Foreign.Lua.Core.Types as Lua+import qualified Foreign.Lua.Utf8 as Utf8+import qualified Foreign.Storable as Storable++-- * The Auxiliary Library++-- | Loads and runs the given string.+--+-- Returns 'Lua.OK' on success, or an error if either loading of the+-- string or calling of the thunk failed.+dostring :: ByteString -> Lua Status+dostring s = do+  loadRes <- loadstring s+  if loadRes == Lua.OK+    then Lua.pcall 0 multret Nothing+    else return loadRes++-- | Loads and runs the given file. Note that the filepath is interpreted by+-- Haskell, not Lua. The resulting chunk is named using the UTF8 encoded+-- filepath.+dofile :: FilePath -> Lua Status+dofile fp = do+  loadRes <- loadfile fp+  if loadRes == Lua.OK+    then Lua.pcall 0 multret Nothing+    else return loadRes++-- | Pushes onto the stack the field @e@ from the metatable of the object at+-- index @obj@ and returns the type of the pushed value. If the object does not+-- have a metatable, or if the metatable does not have this field, pushes+-- nothing and returns TypeNil.+getmetafield :: StackIndex -- ^ obj+             -> String     -- ^ e+             -> Lua Lua.Type+getmetafield obj e = liftLua $ \l ->+  withCString e $ fmap Lua.toType . luaL_getmetafield l obj++-- | Pushes onto the stack the metatable associated with name @tname@ in the+-- registry (see @newmetatable@) (@nil@ if there is no metatable associated+-- with that name). Returns the type of the pushed value.+getmetatable' :: String -- ^ tname+              -> Lua Lua.Type+getmetatable' tname = liftLua $ \l ->+  withCString tname $ fmap Lua.toType . luaL_getmetatable l++-- | Push referenced value from the table at the given index.+getref :: StackIndex -> Reference -> Lua ()+getref idx ref' = Lua.rawgeti idx (fromIntegral (Lua.fromReference ref'))++-- | Ensures that the value @t[fname]@, where @t@ is the value at index @idx@,+-- is a table, and pushes that table onto the stack. Returns True if it finds a+-- previous table there and False if it creates a new table.+getsubtable :: StackIndex -> String -> Lua Bool+getsubtable idx fname = do+  -- This is a reimplementation of luaL_getsubtable from lauxlib.c.+  idx' <- Lua.absindex idx+  Lua.pushstring (Utf8.fromString fname)+  Lua.gettable idx'+  isTbl <- Lua.istable Lua.stackTop+  if isTbl+    then return True+    else do+      Lua.pop 1+      Lua.newtable+      Lua.pushvalue Lua.stackTop -- copy to be left at top+      Lua.setfield idx' fname+      return False++-- | Loads a ByteString as a Lua chunk.+--+-- This function returns the same results as @'Lua.load'@. @name@ is the+-- chunk name, used for debug information and error messages. Note that+-- @name@ is used as a C string, so it may not contain null-bytes.+--+-- See <https://www.lua.org/manual/5.3/manual.html#luaL_loadbuffer luaL_loadbuffer>.+loadbuffer :: ByteString -- ^ Program to load+           -> String     -- ^ chunk name+           -> Lua Status+loadbuffer bs name = liftLua $ \l ->+  B.useAsCStringLen bs $ \(str, len) ->+  withCString name+    (fmap Lua.toStatus . luaL_loadbuffer l str (fromIntegral len))++-- | Loads a file as a Lua chunk. This function uses @lua_load@ (see+-- @'Lua.load'@) to load the chunk in the file named filename. The first+-- line in the file is ignored if it starts with a @#@.+--+-- The string mode works as in function @'Lua.load'@.+--+-- This function returns the same results as @'Lua.load'@, but it has an+-- extra error code @'Lua.ErrFile'@ for file-related errors (e.g., it+-- cannot open or read the file).+--+-- As @'Lua.load'@, this function only loads the chunk; it does not run+-- it.+--+-- Note that the file is opened by Haskell, not Lua.+--+-- See <https://www.lua.org/manual/5.3/manual.html#luaL_loadfile luaL_loadfile>.+loadfile :: FilePath -- ^ filename+         -> Lua Status+loadfile fp = Lua.liftIO contentOrError >>= \case+  Right script -> loadbuffer script ("@" <> fp)+  Left e -> do+    Lua.pushstring (Utf8.fromString (show e))+    return Lua.ErrFile+ where+  contentOrError :: IO (Either IOException ByteString)+  contentOrError = try (B.readFile fp)+++-- | Loads a string as a Lua chunk. This function uses @lua_load@ to+-- load the chunk in the given ByteString. The given string may not+-- contain any NUL characters.+--+-- This function returns the same results as @lua_load@ (see+-- @'Lua.load'@).+--+-- Also as @'Lua.load'@, this function only loads the chunk; it does not+-- run it.+--+-- See <https://www.lua.org/manual/5.3/manual.html#luaL_loadstring luaL_loadstring>.+loadstring :: ByteString -> Lua Status+loadstring s = loadbuffer s (Utf8.toString s)+++-- | If the registry already has the key tname, returns @False@. Otherwise,+-- creates a new table to be used as a metatable for userdata, adds to this new+-- table the pair @__name = tname@, adds to the registry the pair @[tname] = new+-- table@, and returns @True@. (The entry @__name@ is used by some+-- error-reporting functions.)+--+-- In both cases pushes onto the stack the final value associated with @tname@ in+-- the registry.+--+-- The value of @tname@ is used as a C string and hence must not contain null+-- bytes.+--+-- See also:+-- <https://www.lua.org/manual/5.3/manual.html#luaL_newmetatable luaL_newmetatable>.+newmetatable :: String -> Lua Bool+newmetatable tname = liftLua $ \l ->+  Lua.fromLuaBool <$> withCString tname (luaL_newmetatable l)++-- | Creates a new Lua state. It calls @lua_newstate@ with an allocator+-- based on the standard C @realloc@ function and then sets a panic+-- function (see <https://www.lua.org/manual/5.3/manual.html#4.6 §4.6>+-- of the Lua 5.3 Reference Manual) that prints an error message to the+-- standard error output in case of fatal errors.+--+-- See also:+-- <https://www.lua.org/manual/5.3/manual.html#luaL_newstate luaL_newstate>.+newstate :: IO Lua.State+newstate = hsluaL_newstate++-- | Creates and returns a reference, in the table at index @t@, for the object+-- at the top of the stack (and pops the object).+--+-- A reference is a unique integer key. As long as you do not manually add+-- integer keys into table @t@, @ref@ ensures the uniqueness of the key it+-- returns. You can retrieve an object referred by reference @r@ by calling+-- @rawgeti t r@. Function @'unref'@ frees a reference and its associated+-- object.+--+-- If the object at the top of the stack is nil, @'ref'@ returns the+-- constant @'Lua.refnil'@. The constant @'Lua.noref'@ is guaranteed to+-- be different from any reference returned by @'ref'@.+--+-- See also: <https://www.lua.org/manual/5.3/manual.html#luaL_ref luaL_ref>.+ref :: StackIndex -> Lua Reference+ref t = liftLua $ \l -> Lua.toReference <$> luaL_ref l t++-- | Converts any Lua value at the given index to a @'ByteString'@ in a+-- reasonable format. The resulting string is pushed onto the stack and also+-- returned by the function.+--+-- If the value has a metatable with a @__tostring@ field, then @tolstring'@+-- calls the corresponding metamethod with the value as argument, and uses the+-- result of the call as its result.+tostring' :: StackIndex -> Lua B.ByteString+tostring' n = do+  l <- Lua.state+  e2e <- Lua.errorToException <$> Lua.errorConversion+  Lua.liftIO $ alloca $ \lenPtr -> do+    cstr <- hsluaL_tolstring l n lenPtr+    if cstr == nullPtr+      then e2e l+      else do+        cstrLen <- Storable.peek lenPtr+        B.packCStringLen (cstr, fromIntegral cstrLen)++-- | Creates and pushes a traceback of the stack L1. If a message is given it+-- appended at the beginning of the traceback. The level parameter tells at+-- which level to start the traceback.+traceback :: Lua.State -> Maybe String -> Int -> Lua ()+traceback l1 msg level = liftLua $ \l ->+  case msg of+    Nothing -> luaL_traceback l l1 nullPtr (fromIntegral level)+    Just msg' -> withCString msg' $ \cstr ->+      luaL_traceback l l1 cstr (fromIntegral level)++-- | Releases reference @'ref'@ from the table at index @idx@ (see @'ref'@). The+-- entry is removed from the table, so that the referred object can be+-- collected. The reference @'ref'@ is also freed to be used again.+--+-- See also:+-- <https://www.lua.org/manual/5.3/manual.html#luaL_unref luaL_unref>.+unref :: StackIndex -- ^ idx+      -> Reference  -- ^ ref+      -> Lua ()+unref idx r = liftLua $ \l ->+  luaL_unref l idx (Lua.fromReference r)
− src/Foreign/Lua/Core/Auxiliary.hsc
@@ -1,335 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE OverloadedStrings #-}-{-|-Module      : Foreign.Lua.Core.Auxiliary-Copyright   : © 2007–2012 Gracjan Polak,-                2012–2016 Ömer Sinan Ağacan,-                2017-2020 Albert Krewinkel-License     : MIT-Maintainer  : Albert Krewinkel <tarleb+hslua@zeitkraut.de>-Stability   : beta-Portability : non-portable (depends on GHC)--Wrappers for the auxiliary library.--}-module Foreign.Lua.Core.Auxiliary-  ( dostring-  , dofile-  , getmetafield-  , getmetatable'-  , getsubtable-  , loadbuffer-  , loadfile-  , loadstring-  , newmetatable-  , newstate-  , tostring'-  , traceback-  -- * References-  , getref-  , ref-  , unref-  -- * Registry fields-  , loadedTableRegistryField-  , preloadTableRegistryField-  ) where--import Control.Exception (IOException, try)-import Data.ByteString (ByteString)-import Foreign.C ( CChar, CInt (CInt), CSize (CSize), CString, withCString )-import Foreign.Lua.Core.Constants (multret, registryindex)-import Foreign.Lua.Core.Error (hsluaErrorRegistryField)-import Foreign.Lua.Core.Types (Lua, Reference, StackIndex, Status, liftLua)-import Foreign.Marshal.Alloc (alloca)-import Foreign.Ptr--import qualified Data.ByteString as B-import qualified Foreign.Lua.Core.Functions as Lua-import qualified Foreign.Lua.Core.Types as Lua-import qualified Foreign.Lua.Utf8 as Utf8-import qualified Foreign.Storable as Storable--#ifndef HARDCODE_REG_KEYS-import System.IO.Unsafe (unsafePerformIO)-import qualified Foreign.C as C-#endif--##ifdef ALLOW_UNSAFE_GC-##define SAFTY unsafe-##else-##define SAFTY safe-##endif-------------------------------------------------------------------------------------- * The Auxiliary Library---- | Key, in the registry, for table of loaded modules.-loadedTableRegistryField :: String-#ifdef HARDCODE_REG_KEYS-loadedTableRegistryField = "_LOADED"-#else-loadedTableRegistryField = unsafePerformIO (C.peekCString c_loaded_table)-{-# NOINLINE loadedTableRegistryField #-}--foreign import capi "lauxlib.h value LUA_LOADED_TABLE"-  c_loaded_table :: CString-#endif---- | Key, in the registry, for table of preloaded loaders.-preloadTableRegistryField :: String-#ifdef HARDCODE_REG_KEYS-preloadTableRegistryField = "_PRELOAD"-#else-preloadTableRegistryField = unsafePerformIO (C.peekCString c_preload_table)-{-# NOINLINE preloadTableRegistryField #-}--foreign import capi "lauxlib.h value LUA_PRELOAD_TABLE"-  c_preload_table :: CString-#endif---- | Loads and runs the given string.------ Returns 'Lua.OK' on success, or an error if either loading of the--- string or calling of the thunk failed.-dostring :: ByteString -> Lua Status-dostring s = do-  loadRes <- loadstring s-  if loadRes == Lua.OK-    then Lua.pcall 0 multret Nothing-    else return loadRes---- | Loads and runs the given file. Note that the filepath is interpreted by--- Haskell, not Lua. The resulting chunk is named using the UTF8 encoded--- filepath.-dofile :: FilePath -> Lua Status-dofile fp = do-  loadRes <- loadfile fp-  if loadRes == Lua.OK-    then Lua.pcall 0 multret Nothing-    else return loadRes---- | Pushes onto the stack the field @e@ from the metatable of the object at--- index @obj@ and returns the type of the pushed value. If the object does not--- have a metatable, or if the metatable does not have this field, pushes--- nothing and returns TypeNil.-getmetafield :: StackIndex -- ^ obj-             -> String     -- ^ e-             -> Lua Lua.Type-getmetafield obj e = liftLua $ \l ->-  withCString e $ fmap Lua.toType . luaL_getmetafield l obj--foreign import capi SAFTY "lauxlib.h luaL_getmetafield"-  luaL_getmetafield :: Lua.State -> StackIndex -> CString -> IO Lua.TypeCode---- | Pushes onto the stack the metatable associated with name @tname@ in the--- registry (see @newmetatable@) (@nil@ if there is no metatable associated--- with that name). Returns the type of the pushed value.-getmetatable' :: String -- ^ tname-              -> Lua Lua.Type-getmetatable' tname = liftLua $ \l ->-  withCString tname $ fmap Lua.toType . luaL_getmetatable l--foreign import capi SAFTY "lauxlib.h luaL_getmetatable"-  luaL_getmetatable :: Lua.State -> CString -> IO Lua.TypeCode---- | Push referenced value from the table at the given index.-getref :: StackIndex -> Reference -> Lua ()-getref idx ref' = Lua.rawgeti idx (fromIntegral (Lua.fromReference ref'))---- | Ensures that the value @t[fname]@, where @t@ is the value at index @idx@,--- is a table, and pushes that table onto the stack. Returns True if it finds a--- previous table there and False if it creates a new table.-getsubtable :: StackIndex -> String -> Lua Bool-getsubtable idx fname = do-  -- This is a reimplementation of luaL_getsubtable from lauxlib.c.-  idx' <- Lua.absindex idx-  Lua.pushstring (Utf8.fromString fname)-  Lua.gettable idx'-  isTbl <- Lua.istable Lua.stackTop-  if isTbl-    then return True-    else do-      Lua.pop 1-      Lua.newtable-      Lua.pushvalue Lua.stackTop -- copy to be left at top-      Lua.setfield idx' fname-      return False---- | Loads a ByteString as a Lua chunk.------ This function returns the same results as @'Lua.load'@. @name@ is the--- chunk name, used for debug information and error messages. Note that--- @name@ is used as a C string, so it may not contain null-bytes.------ See <https://www.lua.org/manual/5.3/manual.html#luaL_loadbuffer luaL_loadbuffer>.-loadbuffer :: ByteString -- ^ Program to load-           -> String     -- ^ chunk name-           -> Lua Status-loadbuffer bs name = liftLua $ \l ->-  B.useAsCStringLen bs $ \(str, len) ->-  withCString name-    (fmap Lua.toStatus . luaL_loadbuffer l str (fromIntegral len))--foreign import capi SAFTY "lauxlib.h luaL_loadbuffer"-  luaL_loadbuffer :: Lua.State -> Ptr CChar -> CSize -> CString-                  -> IO Lua.StatusCode----- | Loads a file as a Lua chunk. This function uses @lua_load@ (see--- @'Lua.load'@) to load the chunk in the file named filename. The first--- line in the file is ignored if it starts with a @#@.------ The string mode works as in function @'Lua.load'@.------ This function returns the same results as @'Lua.load'@, but it has an--- extra error code @'Lua.ErrFile'@ for file-related errors (e.g., it--- cannot open or read the file).------ As @'Lua.load'@, this function only loads the chunk; it does not run--- it.------ Note that the file is opened by Haskell, not Lua.------ See <https://www.lua.org/manual/5.3/manual.html#luaL_loadfile luaL_loadfile>.-loadfile :: FilePath -- ^ filename-         -> Lua Status-loadfile fp = Lua.liftIO contentOrError >>= \case-  Right script -> loadbuffer script ("@" <> fp)-  Left e -> do-    Lua.pushstring (Utf8.fromString (show e))-    return Lua.ErrFile- where-  contentOrError :: IO (Either IOException ByteString)-  contentOrError = try (B.readFile fp)----- | Loads a string as a Lua chunk. This function uses @lua_load@ to--- load the chunk in the given ByteString. The given string may not--- contain any NUL characters.------ This function returns the same results as @lua_load@ (see--- @'Lua.load'@).------ Also as @'Lua.load'@, this function only loads the chunk; it does not--- run it.------ See <https://www.lua.org/manual/5.3/manual.html#luaL_loadstring luaL_loadstring>.-loadstring :: ByteString -> Lua Status-loadstring s = loadbuffer s (Utf8.toString s)----- | If the registry already has the key tname, returns @False@. Otherwise,--- creates a new table to be used as a metatable for userdata, adds to this new--- table the pair @__name = tname@, adds to the registry the pair @[tname] = new--- table@, and returns @True@. (The entry @__name@ is used by some--- error-reporting functions.)------ In both cases pushes onto the stack the final value associated with @tname@ in--- the registry.------ The value of @tname@ is used as a C string and hence must not contain null--- bytes.------ See also:--- <https://www.lua.org/manual/5.3/manual.html#luaL_newmetatable luaL_newmetatable>.-newmetatable :: String -> Lua Bool-newmetatable tname = liftLua $ \l ->-  Lua.fromLuaBool <$> withCString tname (luaL_newmetatable l)--foreign import ccall SAFTY "lauxlib.h luaL_newmetatable"-  luaL_newmetatable :: Lua.State -> CString -> IO Lua.LuaBool----- | Creates a new Lua state. It calls @lua_newstate@ with an allocator--- based on the standard C @realloc@ function and then sets a panic--- function (see <https://www.lua.org/manual/5.3/manual.html#4.6 §4.6>--- of the Lua 5.3 Reference Manual) that prints an error message to the--- standard error output in case of fatal errors.------ See also:--- <https://www.lua.org/manual/5.3/manual.html#luaL_newstate luaL_newstate>.-newstate :: IO Lua.State-newstate = do-  l <- luaL_newstate-  Lua.unsafeRunWith l $ do-    Lua.createtable 0 0-    Lua.setfield registryindex hsluaErrorRegistryField-    return l--foreign import ccall unsafe "lauxlib.h luaL_newstate"-  luaL_newstate :: IO Lua.State----- | Creates and returns a reference, in the table at index @t@, for the object--- at the top of the stack (and pops the object).------ A reference is a unique integer key. As long as you do not manually add--- integer keys into table @t@, @ref@ ensures the uniqueness of the key it--- returns. You can retrieve an object referred by reference @r@ by calling--- @rawgeti t r@. Function @'unref'@ frees a reference and its associated--- object.------ If the object at the top of the stack is nil, @'ref'@ returns the--- constant @'Lua.refnil'@. The constant @'Lua.noref'@ is guaranteed to--- be different from any reference returned by @'ref'@.------ See also: <https://www.lua.org/manual/5.3/manual.html#luaL_ref luaL_ref>.-ref :: StackIndex -> Lua Reference-ref t = liftLua $ \l -> Lua.toReference <$> luaL_ref l t--foreign import ccall SAFTY "lauxlib.h luaL_ref"-  luaL_ref :: Lua.State -> StackIndex -> IO CInt----- | Converts any Lua value at the given index to a @'ByteString'@ in a--- reasonable format. The resulting string is pushed onto the stack and also--- returned by the function.------ If the value has a metatable with a @__tostring@ field, then @tolstring'@--- calls the corresponding metamethod with the value as argument, and uses the--- result of the call as its result.-tostring' :: StackIndex -> Lua B.ByteString-tostring' n = do-  l <- Lua.state-  e2e <- Lua.errorToException <$> Lua.errorConversion-  Lua.liftIO $ alloca $ \lenPtr -> do-    cstr <- hsluaL_tolstring l n lenPtr-    if cstr == nullPtr-      then e2e l-      else do-        cstrLen <- Storable.peek lenPtr-        B.packCStringLen (cstr, fromIntegral cstrLen)--foreign import ccall safe "error-conversion.h hsluaL_tolstring"-  hsluaL_tolstring :: Lua.State -> StackIndex -> Ptr CSize -> IO (Ptr CChar)----- | Creates and pushes a traceback of the stack L1. If a message is given it--- appended at the beginning of the traceback. The level parameter tells at--- which level to start the traceback.-traceback :: Lua.State -> Maybe String -> Int -> Lua ()-traceback l1 msg level = liftLua $ \l ->-  case msg of-    Nothing -> luaL_traceback l l1 nullPtr (fromIntegral level)-    Just msg' -> withCString msg' $ \cstr ->-      luaL_traceback l l1 cstr (fromIntegral level)--foreign import capi unsafe "lauxlib.h luaL_traceback"-  luaL_traceback :: Lua.State -> Lua.State -> CString -> CInt -> IO ()----- | Releases reference @'ref'@ from the table at index @idx@ (see @'ref'@). The--- entry is removed from the table, so that the referred object can be--- collected. The reference @'ref'@ is also freed to be used again.------ See also:--- <https://www.lua.org/manual/5.3/manual.html#luaL_unref luaL_unref>.-unref :: StackIndex -- ^ idx-      -> Reference  -- ^ ref-      -> Lua ()-unref idx r = liftLua $ \l ->-  luaL_unref l idx (Lua.fromReference r)--foreign import ccall SAFTY "lauxlib.h luaL_unref"-  luaL_unref :: Lua.State -> StackIndex -> CInt -> IO ()
+ src/Foreign/Lua/Core/Constants.hs view
@@ -0,0 +1,22 @@+{-|+Module      : Foreign.Lua.Core.Constants+Copyright   : © 2007–2012 Gracjan Polak,+                2012–2016 Ömer Sinan Ağacan,+                2017-2020 Albert Krewinkel+License     : MIT+Maintainer  : Albert Krewinkel <tarleb+hslua@zeitkraut.de>+Stability   : beta+Portability : ForeignFunctionInterface++Lua constants. This module was moved to+@'Foreign.Lua.Raw.Constants'@. It now merely exists for backwards+compatibility and will be removed in the future.+-}+module Foreign.Lua.Core.Constants+  ( multret+  , registryindex+  , refnil+  , noref+  ) where++import Foreign.Lua.Raw.Constants
− src/Foreign/Lua/Core/Constants.hsc
@@ -1,41 +0,0 @@-{-|-Module      : Foreign.Lua.Core.Constants-Copyright   : © 2007–2012 Gracjan Polak,-                2012–2016 Ömer Sinan Ağacan,-                2017-2020 Albert Krewinkel-License     : MIT-Maintainer  : Albert Krewinkel <tarleb+hslua@zeitkraut.de>-Stability   : beta-Portability : ForeignFunctionInterface--Lua constants--}-module Foreign.Lua.Core.Constants-  ( multret-  , registryindex-  , refnil-  , noref-  ) where--import Foreign.Lua.Core.Types--#include "lua.h"-#include "lauxlib.h"---- | Alias for C constant @LUA_MULTRET@. See--- <https://www.lua.org/manual/5.3/#lua_call lua_call>.-multret :: NumResults-multret = NumResults $ #{const LUA_MULTRET}---- | Alias for C constant @LUA_REGISTRYINDEX@. See--- <https://www.lua.org/manual/5.3/#3.5 Lua registry>.-registryindex :: StackIndex-registryindex = StackIndex $ #{const LUA_REGISTRYINDEX}---- | Value signaling that no reference was created.-refnil :: Int-refnil = #{const LUA_REFNIL}---- | Value signaling that no reference was found.-noref :: Int-noref = #{const LUA_NOREF}
src/Foreign/Lua/Core/Error.hs view
@@ -23,30 +23,24 @@   , errorMessage   , try     -- * Helpers for hslua C wrapper functions.-  , Failable (..)-  , fromFailable-  , throwOnError   , throwMessage-  , boolFromFailable-    -- * Signaling errors to Lua-  , hsluaErrorRegistryField+  , liftLuaThrow   ) where  import Control.Applicative (Alternative (..)) import Data.Typeable (Typeable)-import Foreign.C (CChar, CInt (CInt), CSize (CSize))+import Foreign.Lua.Core.Types (Lua)+import Foreign.Lua.Raw.Error (errorMessage)+import Foreign.Lua.Raw.Functions (lua_pushlstring) import Foreign.Marshal.Alloc (alloca)-import Foreign.Ptr (Ptr, nullPtr)-import Foreign.Lua.Core.Types (Lua, StackIndex, fromLuaBool)+import Foreign.Ptr +import qualified Data.ByteString.Unsafe as B import qualified Control.Exception as E import qualified Control.Monad.Catch as Catch-import qualified Data.ByteString as B-import qualified Data.ByteString.Char8 as Char8-import qualified Data.ByteString.Unsafe as B-import qualified Foreign.Storable as Storable import qualified Foreign.Lua.Core.Types as Lua import qualified Foreign.Lua.Utf8 as Utf8+import qualified Foreign.Storable as F  -- | Exceptions raised by Lua-related operations. newtype Exception = Exception { exceptionMessage :: String}@@ -92,6 +86,15 @@ throwTopMessage :: Lua a throwTopMessage = throwErrorAsException +-- | Helper function which uses proper error-handling to throw an+-- exception with the given message.+throwMessage :: String -> Lua a+throwMessage msg = do+  Lua.liftLua $ \l ->+    B.unsafeUseAsCStringLen (Utf8.fromString msg) $ \(msgPtr, z) ->+      lua_pushlstring l msgPtr (fromIntegral z)+  Lua.errorConversion >>= Lua.liftLua . Lua.errorToException+ instance Alternative Lua where   empty = throwMessage "empty"   x <|> y = do@@ -108,66 +111,15 @@   msg <- Lua.liftIO (errorMessage l)   Catch.throwM $ Exception (Utf8.toString msg) --- | Helper function which uses proper error-handling to throw an--- exception with the given message.-throwMessage :: String -> Lua a-throwMessage msg = do-  Lua.liftLua $ \l ->-    B.unsafeUseAsCStringLen (Utf8.fromString msg) $ \(msgPtr, z) ->-      lua_pushlstring l msgPtr (fromIntegral z)-  Lua.errorConversion >>= Lua.liftLua . Lua.errorToException---- | Retrieve and pop the top object as an error message. This is very similar--- to tostring', but ensures that we don't recurse if getting the message--- failed.-errorMessage :: Lua.State -> IO B.ByteString-errorMessage l = alloca $ \lenPtr -> do-  cstr <- hsluaL_tolstring l Lua.stackTop lenPtr-  if cstr == nullPtr-    then return $ Char8.pack ("An error occurred, but the error object " ++-                              "cannot be converted into a string.")-    else do-      cstrLen <- Storable.peek lenPtr-      msg <- B.packCStringLen (cstr, fromIntegral cstrLen)-      lua_pop l 2-      return msg--foreign import ccall safe "error-conversion.h hsluaL_tolstring"-  hsluaL_tolstring :: Lua.State -> StackIndex -> Ptr CSize -> IO (Ptr CChar)--foreign import capi unsafe "lua.h lua_pop"-  lua_pop :: Lua.State -> CInt -> IO ()--foreign import capi unsafe "lua.h lua_pushlstring"-  lua_pushlstring :: Lua.State -> Ptr CChar -> CSize -> IO ()---- | Registry field under which the special HsLua error indicator is stored.-hsluaErrorRegistryField :: String-hsluaErrorRegistryField = "HSLUA_ERR"------- * Custom protocol to communicate with hslua C wrapper functions.------- | CInt value or an error, using the convention that value below zero indicate--- an error. Values greater than zero are used verbatim. The phantom type is--- used for additional type safety and gives the type into which the wrapped--- CInt should be converted.-newtype Failable a = Failable CInt---- | Convert from Failable to target type, throwing an error if the value--- indicates a failure.-fromFailable :: (CInt -> a) -> Failable a -> Lua a-fromFailable fromCInt (Failable x) =-  if x < 0-  then throwTopMessage-  else return (fromCInt x)---- | Throw a Haskell exception if the computation signaled a failure.-throwOnError :: Failable () -> Lua ()-throwOnError = fromFailable (const ())---- | Convert lua boolean to Haskell Bool, throwing an exception if the return--- value indicates that an error had happened.-boolFromFailable :: Failable Lua.LuaBool -> Lua Bool-boolFromFailable = fmap fromLuaBool . fromFailable Lua.LuaBool+-- | Takes a failable HsLua function and transforms it into a+-- monadic 'Lua' operation. Throws an exception if an error+-- occured.+liftLuaThrow :: (Lua.State -> Ptr Lua.StatusCode -> IO a) -> Lua a+liftLuaThrow f = do+  (result, status) <- Lua.liftLua $ \l -> alloca $ \statusPtr -> do+    result <- f l statusPtr+    status <- Lua.toStatus <$> F.peek statusPtr+    return (result, status)+  if status == Lua.OK+    then return result+    else throwTopMessage
src/Foreign/Lua/Core/Functions.hs view
@@ -142,8 +142,8 @@ -- This is a wrapper function of -- <https://www.lua.org/manual/5.3/manual.html#lua_compare lua_compare>. compare :: StackIndex -> StackIndex -> RelationalOperator -> Lua Bool-compare idx1 idx2 relOp = boolFromFailable =<< do-  liftLua $ \l -> hslua_compare l idx1 idx2 (fromRelationalOperator relOp)+compare idx1 idx2 relOp = fromLuaBool <$> do+  liftLuaThrow $ \l -> hslua_compare l idx1 idx2 (fromRelationalOperator relOp)  -- | Concatenates the @n@ values at the top of the stack, pops them, and leaves -- the result at the top. If @n@ is 1, the result is the single value on the@@ -155,7 +155,7 @@ -- This is a wrapper function of -- <https://www.lua.org/manual/5.3/manual.html#lua_concat lua_concat>. concat :: NumArgs -> Lua ()-concat n = throwOnError =<< liftLua (`hslua_concat` n)+concat n = liftLuaThrow (`hslua_concat` n)  -- | Copies the element at index @fromidx@ into the valid index @toidx@, -- replacing the value at that position. Values at other positions are not@@ -256,9 +256,9 @@ -- Wrapper of -- <https://www.lua.org/manual/5.3/manual.html#lua_getglobal lua_getglobal>. getglobal :: String -> Lua ()-getglobal name = throwOnError <=< liftLua $ \l ->+getglobal name = liftLuaThrow $ \l status' ->   C.withCStringLen name $ \(namePtr, len) ->-  hslua_getglobal l namePtr (fromIntegral len)+  hslua_getglobal l namePtr (fromIntegral len) status'  -- | If the value at the given index has a metatable, the function pushes that -- metatable onto the stack and returns @True@. Otherwise, the function returns@@ -283,8 +283,7 @@ -- See also: -- <https://www.lua.org/manual/5.3/manual.html#lua_gettable lua_gettable>. gettable :: StackIndex -> Lua ()-gettable n = throwOnError =<<-  liftLua (\l -> hslua_gettable l n)+gettable n = liftLuaThrow (\l -> hslua_gettable l n)  -- | Returns the index of the top element in the stack. Because indices start at -- 1, this result is equal to the number of elements in the stack (and so 0@@ -473,7 +472,7 @@ -- See also: -- <https://www.lua.org/manual/5.3/manual.html#lua_next lua_next>. next :: StackIndex -> Lua Bool-next idx = boolFromFailable =<< liftLua (\l -> hslua_next l idx)+next idx = fromLuaBool <$> liftLuaThrow (\l -> hslua_next l idx)  -- | Opens all standard Lua libraries into the current state and sets each -- library name as a global value.@@ -566,7 +565,7 @@ -- -- See also: <https://www.lua.org/manual/5.3/manual.html#lua_pop lua_pop>. pop :: StackIndex -> Lua ()-pop n = settop (-n - 1)+pop n = liftLua $ \l -> lua_pop l n  -- | Pushes a boolean value with the given value onto the stack. --@@ -774,9 +773,9 @@ -- See also: -- <https://www.lua.org/manual/5.3/manual.html#lua_setglobal lua_setglobal>. setglobal :: String -> Lua ()-setglobal name = throwOnError <=< liftLua $ \l ->+setglobal name = liftLuaThrow $ \l status' ->   C.withCStringLen name $ \(namePtr, nameLen) ->-  hslua_setglobal l namePtr (fromIntegral nameLen)+  hslua_setglobal l namePtr (fromIntegral nameLen) status'  -- | Pops a table from the stack and sets it as the new metatable for the value -- at the given index.@@ -801,8 +800,7 @@ -- See also: -- <https://www.lua.org/manual/5.3/manual.html#lua_settable lua_settable>. settable :: StackIndex -> Lua ()-settable index = throwOnError =<<-  liftLua (\l -> hslua_settable l index)+settable index = liftLuaThrow $ \l -> hslua_settable l index  -- | Accepts any index, or 0, and sets the stack top to this index. If the new -- top is larger than the old one, then the new elements are filled with nil. If
+ src/Foreign/Lua/Core/RawBindings.hs view
@@ -0,0 +1,21 @@+{-|+Module      : Foreign.Lua.Core.RawBindings+Copyright   : © 2007–2012 Gracjan Polak,+                2012–2016 Ömer Sinan Ağacan,+                2017-2020 Albert Krewinkel+License     : MIT+Maintainer  : Albert Krewinkel <tarleb+hslua@zeitkraut.de>+Stability   : beta+Portability : ForeignFunctionInterface++Haskell bindings to Lua C API functions.++This module was moved to @'Foreign.Lua.Raw.Functions'@. It now+merely exists for backwards compatibility and will be removed in+the future.+-}+module Foreign.Lua.Core.RawBindings+  ( module Foreign.Lua.Raw.Functions+  ) where++import Foreign.Lua.Raw.Functions
− src/Foreign/Lua/Core/RawBindings.hsc
@@ -1,389 +0,0 @@-{-# LANGUAGE CPP #-}-{-|-Module      : Foreign.Lua.Core.RawBindings-Copyright   : © 2007–2012 Gracjan Polak,-                2012–2016 Ömer Sinan Ağacan,-                2017-2020 Albert Krewinkel-License     : MIT-Maintainer  : Albert Krewinkel <tarleb+hslua@zeitkraut.de>-Stability   : beta-Portability : ForeignFunctionInterface--Haskell bindings to lua C API functions.--}-module Foreign.Lua.Core.RawBindings where--import Foreign.C-import Foreign.Lua.Core.Error (Failable (Failable))-import Foreign.Lua.Core.Types as Lua-import Foreign.Ptr--##ifdef ALLOW_UNSAFE_GC-##define SAFTY unsafe-##else-##define SAFTY safe-##endif---- TODO: lua_getallocf, lua_setallocf--- TODO: Debugger functions---- Some of the Lua functions may call a Haskell function, and trigger--- garbage collection, rescheduling etc. This means we must declare these--- functions as 'safe'.-------------------------------------------------------------------------------------- * State manipulation---- lua_newstate is currently not supported.---- | See <https://www.lua.org/manual/5.3/manual.html#lua_close lua_close>-foreign import ccall "lua.h lua_close"-  lua_close :: Lua.State -> IO ()---- lua_newthread is currently not supported.-------------------------------------------------------------------------------------- * Basic stack manipulation---- | See <https://www.lua.org/manual/5.3/manual.html#lua_absindex lua_absindex>-foreign import ccall unsafe "lua.h lua_absindex"-  lua_absindex :: Lua.State -> StackIndex -> IO StackIndex---- | See <https://www.lua.org/manual/5.3/manual.html#lua_gettop lua_gettop>-foreign import ccall unsafe "lua.h lua_gettop"-  lua_gettop :: Lua.State -> IO StackIndex---- | See <https://www.lua.org/manual/5.3/manual.html#lua_settop lua_settop>-foreign import ccall SAFTY "lua.h lua_settop"-  lua_settop :: Lua.State -> StackIndex -> IO ()---- | See <https://www.lua.org/manual/5.3/manual.html#lua_pushvalue lua_pushvalue>-foreign import ccall SAFTY "lua.h lua_pushvalue"-  lua_pushvalue :: Lua.State -> StackIndex -> IO ()---- | See <https://www.lua.org/manual/5.3/manual.html#lua_copy lua_copy>-foreign import ccall SAFTY "lua.h lua_copy"-  lua_copy :: Lua.State -> StackIndex -> StackIndex -> IO ()---- | See <https://www.lua.org/manual/5.2/manual.html#lua_remove lua_remove>-foreign import capi SAFTY "lua.h lua_remove"-  lua_remove :: Lua.State -> StackIndex -> IO ()---- | See <https://www.lua.org/manual/5.2/manual.html#lua_insert lua_insert>-foreign import capi SAFTY "lua.h lua_insert"-  lua_insert :: Lua.State -> StackIndex -> IO ()---- | See <https://www.lua.org/manual/5.2/manual.html#lua_replace lua_replace>-foreign import capi SAFTY "lua.h lua_replace"-  lua_replace :: Lua.State -> StackIndex -> IO ()---- | See <https://www.lua.org/manual/5.3/manual.html#lua_checkstack lua_checkstack>-foreign import capi SAFTY "lua.h lua_checkstack"-  lua_checkstack :: Lua.State -> CInt -> IO LuaBool---- lua_xmove is currently not supported.-------------------------------------------------------------------------------------- * Stack access functions---- | See <https://www.lua.org/manual/5.3/manual.html#lua_isnumber lua_isnumber>-foreign import ccall SAFTY "lua.h lua_isnumber"-  lua_isnumber :: Lua.State -> StackIndex -> IO LuaBool---- | See <https://www.lua.org/manual/5.3/manual.html#lua_isinteger lua_isinteger>-foreign import ccall SAFTY "lua.h lua_isinteger"-  lua_isinteger :: Lua.State -> StackIndex -> IO LuaBool---- | See <https://www.lua.org/manual/5.3/manual.html#lua_isstring lua_isstring>-foreign import ccall SAFTY "lua.h lua_isstring"-  lua_isstring :: Lua.State -> StackIndex -> IO LuaBool---- | See <https://www.lua.org/manual/5.3/manual.html#lua_iscfunction lua_iscfunction>-foreign import ccall SAFTY "lua.h lua_iscfunction"-  lua_iscfunction :: Lua.State -> StackIndex -> IO LuaBool---- | See <https://www.lua.org/manual/5.3/manual.html#lua_isuserdata lua_isuserdata>-foreign import ccall SAFTY "lua.h lua_isuserdata"-  lua_isuserdata :: Lua.State -> StackIndex -> IO LuaBool---- | See <https://www.lua.org/manual/5.3/manual.html#lua_type lua_type>-foreign import ccall SAFTY "lua.h lua_type"-  lua_type :: Lua.State -> StackIndex -> IO TypeCode---- | See <https://www.lua.org/manual/5.3/manual.html#lua_typename lua_typename>-foreign import ccall SAFTY "lua.h lua_typename"-  lua_typename :: Lua.State -> TypeCode -> IO CString---- lua_compare is unsafe (might cause a longjmp), use hslua_compare instead.---- | Wrapper around <https://lua.org/manual/5.3/manual.html#lua_compare \--- @lua_compare@> which catches any @longjmp@s.-foreign import ccall "error-conversion.h hslua_compare"-  hslua_compare :: Lua.State -> StackIndex -> StackIndex -> CInt-                -> IO (Failable LuaBool)---- | See <https://www.lua.org/manual/5.3/manual.html#lua_rawequal lua_rawequal>-foreign import ccall SAFTY "lua.h lua_rawequal"-  lua_rawequal :: Lua.State -> StackIndex -> StackIndex -> IO LuaBool------- Type coercion------ | See <https://www.lua.org/manual/5.3/manual.html#lua_toboolean lua_toboolean>-foreign import capi SAFTY "lua.h lua_toboolean"-  lua_toboolean :: Lua.State -> StackIndex -> IO LuaBool---- | See <https://www.lua.org/manual/5.3/manual.html#lua_tocfunction lua_tocfunction>-foreign import ccall SAFTY "lua.h lua_tocfunction"-  lua_tocfunction :: Lua.State -> StackIndex -> IO CFunction---- | See <https://www.lua.org/manual/5.3/manual.html#lua_tointegerx lua_tointegerx>-foreign import ccall SAFTY "lua.h lua_tointegerx"-  lua_tointegerx :: Lua.State -> StackIndex -> Ptr LuaBool -> IO Lua.Integer---- | See <https://www.lua.org/manual/5.3/manual.html#lua_tonumberx lua_tonumberx>-foreign import ccall SAFTY "lua.h lua_tonumberx"-  lua_tonumberx :: Lua.State -> StackIndex -> Ptr LuaBool -> IO Lua.Number---- | See <https://www.lua.org/manual/5.3/manual.html#lua_tolstring lua_tolstring>-foreign import ccall SAFTY "lua.h lua_tolstring"-  lua_tolstring :: Lua.State -> StackIndex -> Ptr CSize -> IO (Ptr CChar)---- | See <https://www.lua.org/manual/5.3/manual.html#lua_topointer lua_topointer>-foreign import ccall SAFTY "lua.h lua_topointer"-  lua_topointer :: Lua.State -> StackIndex -> IO (Ptr ())---- | See <https://www.lua.org/manual/5.3/manual.html#lua_tothread lua_tothread>-foreign import ccall SAFTY "lua.h lua_tothread"-  lua_tothread :: Lua.State -> StackIndex -> IO Lua.State---- | See <https://www.lua.org/manual/5.3/manual.html#lua_touserdata lua_touserdata>-foreign import ccall SAFTY "lua.h lua_touserdata"-  lua_touserdata :: Lua.State -> StackIndex -> IO (Ptr a)-------- Object size------- | See <https://www.lua.org/manual/5.3/manual.html#lua_rawlen lua_rawlen>-foreign import ccall SAFTY "lua.h lua_rawlen"-  lua_rawlen :: Lua.State -> StackIndex -> IO CSize-------------------------------------------------------------------------------------- * Push functions---- | See <https://www.lua.org/manual/5.3/manual.html#lua_pushnil lua_pushnil>-foreign import ccall SAFTY "lua.h lua_pushnil"-  lua_pushnil :: Lua.State -> IO ()---- | See <https://www.lua.org/manual/5.3/manual.html#lua_pushnumber lua_pushnumber>-foreign import ccall SAFTY "lua.h lua_pushnumber"-  lua_pushnumber :: Lua.State -> Lua.Number -> IO ()---- | See <https://www.lua.org/manual/5.3/manual.html#lua_pushinteger lua_pushinteger>-foreign import ccall SAFTY "lua.h lua_pushinteger"-  lua_pushinteger :: Lua.State -> Lua.Integer -> IO ()---- | See <https://www.lua.org/manual/5.3/manual.html#lua_pushlstring lua_pushlstring>-foreign import ccall SAFTY "lua.h lua_pushlstring"-  lua_pushlstring :: Lua.State -> Ptr CChar -> CSize -> IO ()---- lua_pushstring is currently not supported. It's difficult to use in a haskell--- context.---- | See <https://www.lua.org/manual/5.3/manual.html#lua_pushcclosure lua_pushcclosure>-foreign import ccall SAFTY "lua.h lua_pushcclosure"-  lua_pushcclosure :: Lua.State -> CFunction -> NumArgs -> IO ()---- | See <https://www.lua.org/manual/5.3/manual.html#lua_pushboolean lua_pushboolean>-foreign import ccall SAFTY "lua.h lua_pushboolean"-  lua_pushboolean :: Lua.State -> LuaBool -> IO ()---- | See <https://www.lua.org/manual/5.3/manual.html#lua_pushlightuserdata lua_pushlightuserdata>-foreign import ccall SAFTY "lua.h lua_pushlightuserdata"-  lua_pushlightuserdata :: Lua.State -> Ptr a -> IO ()---- | See <https://www.lua.org/manual/5.3/manual.html#lua_pushthread lua_pushthread>-foreign import ccall SAFTY "lua.h lua_pushthread"-  lua_pushthread :: Lua.State -> IO CInt-------------------------------------------------------------------------------------- * Get functions---- + lua_gettable is unsafe, use hslua_gettable instead.--- + lua_getglobal is unsafe, use hslua_getglobal instead.--- + lua_getfield is unsafe, we build something equivallent using pushlstring and---   gettable.---- | Wrapper around <https://lua.org/manual/5.3/manual.html#lua_gettable \--- @lua_gettable@> which catches any @longjmp@s.-foreign import ccall "error-conversion.h hslua_gettable"-  hslua_gettable :: Lua.State -> StackIndex -> IO (Failable ())---- | See <https://www.lua.org/manual/5.3/manual.html#lua_rawget lua_rawget>-foreign import ccall SAFTY "lua.h lua_rawget"-  lua_rawget :: Lua.State -> StackIndex -> IO ()---- | See <https://www.lua.org/manual/5.3/manual.html#lua_rawgeti lua_rawgeti>-foreign import ccall SAFTY "lua.h lua_rawgeti"-  lua_rawgeti :: Lua.State -> StackIndex -> Lua.Integer -> IO ()---- | See <https://www.lua.org/manual/5.3/manual.html#lua_createtable lua_createtable>-foreign import ccall SAFTY "lua.h lua_createtable"-  lua_createtable :: Lua.State -> CInt -> CInt -> IO ()---- | See <https://www.lua.org/manual/5.3/manual.html#lua_newuserdata lua_newuserdata>-foreign import ccall SAFTY "lua.h lua_newuserdata"-  lua_newuserdata :: Lua.State -> CSize -> IO (Ptr ())---- | See <https://www.lua.org/manual/5.3/manual.html#lua_getmetatable lua_getmetatable>-foreign import ccall SAFTY "lua.h lua_getmetatable"-  lua_getmetatable :: Lua.State -> StackIndex -> IO LuaBool---- | Wrapper around <https://lua.org/manual/5.3/manual.html#lua_getglobal \--- @lua_getglobal@> which catches any @longjmp@s.-foreign import ccall "error-conversion.h hslua_getglobal"-  hslua_getglobal :: Lua.State -> CString -> CSize -> IO (Failable ())-------------------------------------------------------------------------------------- * Set functions---- lua_settable is unsafe, use hslua_settable instead.--- lua_setfield is unsafe, use hslua_setfield instead.--- lua_setglobal is unsafe, use hslua_setglobal instead.--- lua_setfenv (5.1 only) is not supported.---- | Wrapper around <https://lua.org/manual/5.3/manual.html#lua_settable \--- @lua_settable@> which catches any @longjmp@s.-foreign import ccall "error-conversion.h hslua_settable"-  hslua_settable :: Lua.State -> StackIndex -> IO (Failable ())---- | See <https://www.lua.org/manual/5.3/manual.html#lua_rawset lua_rawset>-foreign import ccall SAFTY "lua.h lua_rawset"-  lua_rawset :: Lua.State -> StackIndex -> IO ()---- | See <https://www.lua.org/manual/5.3/manual.html#lua_rawseti lua_rawseti>-foreign import ccall SAFTY "lua.h lua_rawseti"-  lua_rawseti :: Lua.State -> StackIndex -> Lua.Integer -> IO ()---- | See <https://www.lua.org/manual/5.3/manual.html#lua_setmetatable lua_setmetatable>-foreign import ccall SAFTY "lua.h lua_setmetatable"-  lua_setmetatable :: Lua.State -> StackIndex -> IO ()---- | Wrapper around <https://lua.org/manual/5.3/manual.html#lua_setglobal \--- @lua_setglobal@> which catches any @longjmp@s.-foreign import ccall "error-conversion.h hslua_setglobal"-  hslua_setglobal :: Lua.State -> CString -> CSize -> IO (Failable ())-------------------------------------------------------------------------------------- * \'load\' and \'call\' functions (load and run Lua code)---- lua_call is inherently unsafe, we do not support it.---- | See <https://www.lua.org/manual/5.1/manual.html#lua_pcall lua_pcall>-foreign import capi "lua.h lua_pcall"-  lua_pcall :: Lua.State -> NumArgs -> NumResults -> StackIndex-            -> IO StatusCode---- | See <https://www.lua.org/manual/5.3/manual.html#lua_load lua_load>-foreign import ccall safe "lua.h lua_load"-  lua_load :: Lua.State -> Lua.Reader -> Ptr () -> CString -> CString-           -> IO StatusCode---- currently unsupported:--- lua_dump------------------------------------------------------------------------------------ * Coroutine functions---- lua_yield / lua_yieldk and lua_resume are currently not supported.---- | See <https://www.lua.org/manual/5.3/manual.html#lua_status lua_status>-foreign import ccall unsafe "lua.h lua_status"-  lua_status :: Lua.State -> IO StatusCode------------------------------------------------------------------------------------ * Garbage-collection functions and options---- | See <https://www.lua.org/manual/5.3/manual.html#lua_gc lua_gc>-foreign import ccall "lua.h lua_gc"-  lua_gc :: Lua.State -> CInt -> CInt -> IO CInt------------------------------------------------------------------------------------ * Miscellaneous functions---- lua_error is unsafe, use hslua_error instead.--- lua_next is unsafe, use hslua_next instead.--- lua_concat is unsafe (may trigger a longjmp), use hslua_concat instead.---- | Replacement for <https://lua.org/manual/5.3/manual.html#lua_error \--- @lua_error@>; it uses the HsLua error signaling convention instead of raw--- @longjmp@.-foreign import ccall "error-conversion.h hslua_error"-  hslua_error :: Lua.State -> IO NumResults---- | Wrapper around <https://lua.org/manual/5.3/manual.html#lua_next \--- @lua_next@> which catches any @longjmp@s.-foreign import ccall "error-conversion.h hslua_next"-  hslua_next :: Lua.State -> StackIndex -> IO (Failable LuaBool)---- | Wrapper around <https://lua.org/manual/5.3/manual.html#lua_concat \--- @lua_concat@> which catches any @longjmp@s.-foreign import ccall "error-conversion.h hslua_concat"-  hslua_concat :: Lua.State -> NumArgs -> IO (Failable ())---- | See <https://www.lua.org/manual/5.3/manual.html#lua_pushglobaltable \--- lua_pushglobaltable>-foreign import capi unsafe "lua.h lua_pushglobaltable"-  lua_pushglobaltable :: Lua.State -> IO ()------------------------------------------------------------------------------------ * Lua Libraries---- | See <https://www.lua.org/manual/5.3/manual.html#luaL_openlibs luaL_openlibs>-foreign import ccall unsafe "lualib.h luaL_openlibs"-  luaL_openlibs :: Lua.State -> IO ()---- | Point to function opening the base library.-foreign import ccall unsafe "lualib.h &luaopen_base"-  lua_open_base_ptr :: CFunction---- | Point to function opening the table library.-foreign import ccall unsafe "lualib.h &luaopen_table"-  lua_open_table_ptr :: CFunction---- | Point to function opening the io library.-foreign import ccall unsafe "lualib.h &luaopen_io"-  lua_open_io_ptr :: CFunction---- | Point to function opening the os library.-foreign import ccall unsafe "lualib.h &luaopen_os"-  lua_open_os_ptr :: CFunction---- | Point to function opening the string library.-foreign import ccall unsafe "lualib.h &luaopen_string"-  lua_open_string_ptr :: CFunction---- | Point to function opening the math library.-foreign import ccall unsafe "lualib.h &luaopen_math"-  lua_open_math_ptr :: CFunction---- | Point to function opening the debug library.-foreign import ccall unsafe "lualib.h &luaopen_debug"-  lua_open_debug_ptr :: CFunction---- | Point to function opening the package library.-foreign import ccall unsafe "lualib.h &luaopen_package"-  lua_open_package_ptr :: CFunction
+ src/Foreign/Lua/Core/Types.hs view
@@ -0,0 +1,178 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE RankNTypes                 #-}+{-|+Module      : Foreign.Lua.Core.Types+Copyright   : © 2007–2012 Gracjan Polak,+                2012–2016 Ömer Sinan Ağacan,+                2017-2020 Albert Krewinkel+License     : MIT+Maintainer  : Albert Krewinkel <tarleb+hslua@zeitkraut.de>+Stability   : beta+Portability : non-portable (depends on GHC)++The core Lua types, including mappings of Lua types to Haskell.++This module has mostly been moved to @'Foreign.Lua.Raw.Types'@ and+currently re-exports that module. This module might be removed in+the future.+-}+module Foreign.Lua.Core.Types+  ( Lua (..)+  , LuaEnvironment (..)+  , ErrorConversion (..)+  , errorConversion+  , State (..)+  , Reader+  , liftLua+  , liftLua1+  , state+  , runWithConverter+  , unsafeRunWith+  , unsafeErrorConversion+  , GCCONTROL (..)+  , Type (..)+  , TypeCode (..)+  , fromType+  , toType+  , liftIO+  , CFunction+  , LuaBool (..)+  , false+  , true+  , fromLuaBool+  , toLuaBool+  , Integer (..)+  , Number (..)+  , StackIndex (..)+  , nth+  , nthFromBottom+  , nthFromTop+  , stackTop+  , stackBottom+  , top+  , NumArgs (..)+  , NumResults (..)+  , RelationalOperator (..)+  , fromRelationalOperator+  , Status (..)+  , StatusCode (..)+  , toStatus+    -- * References+  , Reference (..)+  , fromReference+  , toReference+  ) where++import Prelude hiding (Integer)++import Control.Monad.Catch (MonadCatch, MonadMask, MonadThrow)+import Control.Monad.Reader (ReaderT (..), MonadReader, MonadIO, asks, liftIO)+import Foreign.C (CInt)+import Foreign.Lua.Raw.Types+import Foreign.Lua.Raw.Auxiliary+  ( Reference (..)+  , fromReference+  , toReference+  )++-- | Define the ways in which exceptions and errors are handled.+data ErrorConversion = ErrorConversion+  { errorToException :: forall a . State -> IO a+    -- ^ Translate Lua errors to Haskell exceptions+  , addContextToException :: forall a . String -> Lua a -> Lua a+    -- ^ Add information on the current context to an exception.+  , alternative :: forall a . Lua a -> Lua a -> Lua a+    -- ^ Runs the second computation only if the first fails; returns+    -- the result of the first successful computation, if any.+  , exceptionToError :: Lua NumResults -> Lua NumResults+    -- ^ Translate Haskell exceptions to Lua errors+  }++-- | Environment in which Lua computations are evaluated.+data LuaEnvironment = LuaEnvironment+  { luaEnvErrorConversion :: ErrorConversion+    -- ^ Functions for error and exception handling and conversion+  , luaEnvState :: State+    -- ^ Lua interpreter state+  }++-- | A Lua computation. This is the base type used to run Lua programs of any+-- kind. The Lua state is handled automatically, but can be retrieved via+-- @'state'@.+newtype Lua a = Lua { unLua :: ReaderT LuaEnvironment IO a }+  deriving+    ( Applicative+    , Functor+    , Monad+    , MonadCatch+    , MonadIO+    , MonadMask+    , MonadReader LuaEnvironment+    , MonadThrow+    )++-- | Turn a function of typ @Lua.State -> IO a@ into a monadic Lua operation.+liftLua :: (State -> IO a) -> Lua a+liftLua f = state >>= liftIO . f++-- | Turn a function of typ @Lua.State -> a -> IO b@ into a monadic Lua operation.+liftLua1 :: (State -> a -> IO b) -> a -> Lua b+liftLua1 f x = liftLua $ \l -> f l x++-- | Get the Lua state of this Lua computation.+state :: Lua State+state = asks luaEnvState++-- | Get the error-to-exception function.+errorConversion :: Lua ErrorConversion+errorConversion = asks luaEnvErrorConversion++-- | Run Lua computation with the given Lua state and error-to-exception+-- converter. Any resulting exceptions are left unhandled.+runWithConverter :: ErrorConversion -> State -> Lua a -> IO a+runWithConverter e2e l s =+  runReaderT (unLua s) (LuaEnvironment e2e l)++-- | Run the given operation, but crash if any Haskell exceptions occur.+unsafeRunWith :: State -> Lua a -> IO a+unsafeRunWith = runWithConverter unsafeErrorConversion++-- | Unsafe @'ErrorConversion'@; no proper error handling is attempted,+-- any error leads to a crash.+unsafeErrorConversion :: ErrorConversion+unsafeErrorConversion = ErrorConversion+  { errorToException = const (error "An unrecoverable Lua error occured.")+  , addContextToException = const id+  , alternative = const+  , exceptionToError = id+  }++-- | Stack index of the nth element from the top of the stack.+nthFromTop :: CInt -> StackIndex+nthFromTop n = StackIndex (-n)+{-# INLINABLE nthFromTop #-}++-- | Stack index of the nth element from the top of the stack.+nth :: CInt -> StackIndex+nth = nthFromTop+{-# INLINABLE nth #-}++-- | Stack index of the nth element from the bottom of the stack.+nthFromBottom :: CInt -> StackIndex+nthFromBottom = StackIndex+{-# INLINABLE nthFromBottom #-}++-- | Top of the stack+top :: StackIndex+top = -1+{-# INLINABLE top #-}++-- | Top of the stack+stackTop :: StackIndex+stackTop = top+{-# INLINABLE stackTop #-}++-- | Bottom of the stack+stackBottom :: StackIndex+stackBottom = 1+{-# INLINABLE stackBottom #-}
− src/Foreign/Lua/Core/Types.hsc
@@ -1,422 +0,0 @@-{-# LANGUAGE DeriveGeneric              #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE RankNTypes                 #-}-{-|-Module      : Foreign.Lua.Core.Types-Copyright   : © 2007–2012 Gracjan Polak,-                2012–2016 Ömer Sinan Ağacan,-                2017-2020 Albert Krewinkel-License     : MIT-Maintainer  : Albert Krewinkel <tarleb+hslua@zeitkraut.de>-Stability   : beta-Portability : non-portable (depends on GHC)--The core Lua types, including mappings of Lua types to Haskell.--}-module Foreign.Lua.Core.Types-  ( Lua (..)-  , LuaEnvironment (..)-  , ErrorConversion (..)-  , errorConversion-  , State (..)-  , Reader-  , liftLua-  , liftLua1-  , state-  , runWithConverter-  , unsafeRunWith-  , unsafeErrorConversion-  , GCCONTROL (..)-  , Type (..)-  , TypeCode (..)-  , fromType-  , toType-  , liftIO-  , CFunction-  , LuaBool (..)-  , false-  , true-  , fromLuaBool-  , toLuaBool-  , Integer (..)-  , Number (..)-  , StackIndex (..)-  , nthFromBottom-  , nthFromTop-  , stackTop-  , stackBottom-  , NumArgs (..)-  , NumResults (..)-  , RelationalOperator (..)-  , fromRelationalOperator-  , Status (..)-  , StatusCode (..)-  , toStatus-    -- * References-  , Reference (..)-  , fromReference-  , toReference-  ) where--#include "lua.h"--- required only for LUA_ERRFILE-#include "lauxlib.h"--import Prelude hiding (Integer, EQ, LT)--import Control.Monad.Catch (MonadCatch, MonadMask, MonadThrow)-import Control.Monad.Reader (ReaderT (..), MonadReader, MonadIO, asks, liftIO)-import Data.Int (#{type LUA_INTEGER})-import Foreign.C (CChar, CInt, CSize)-import Foreign.Ptr (FunPtr, Ptr)-import Foreign.Storable (Storable)-import GHC.Generics (Generic)---- | Define the ways in which exceptions and errors are handled.-data ErrorConversion = ErrorConversion-  { errorToException :: forall a . State -> IO a-    -- ^ Translate Lua errors to Haskell exceptions-  , addContextToException :: forall a . String -> Lua a -> Lua a-    -- ^ Add information on the current context to an exception.-  , alternative :: forall a . Lua a -> Lua a -> Lua a-    -- ^ Runs the second computation only if the first fails; returns-    -- the result of the first successful computation, if any.-  , exceptionToError :: Lua NumResults -> Lua NumResults-    -- ^ Translate Haskell exceptions to Lua errors-  }---- | Environment in which Lua computations are evaluated.-data LuaEnvironment = LuaEnvironment-  { luaEnvErrorConversion :: ErrorConversion-    -- ^ Functions for error and exception handling and conversion-  , luaEnvState :: State-    -- ^ Lua interpreter state-  }---- | A Lua computation. This is the base type used to run Lua programs of any--- kind. The Lua state is handled automatically, but can be retrieved via--- @'state'@.-newtype Lua a = Lua { unLua :: ReaderT LuaEnvironment IO a }-  deriving-    ( Applicative-    , Functor-    , Monad-    , MonadCatch-    , MonadIO-    , MonadMask-    , MonadReader LuaEnvironment-    , MonadThrow-    )---- | Turn a function of typ @Lua.State -> IO a@ into a monadic Lua operation.-liftLua :: (State -> IO a) -> Lua a-liftLua f = state >>= liftIO . f---- | Turn a function of typ @Lua.State -> a -> IO b@ into a monadic Lua operation.-liftLua1 :: (State -> a -> IO b) -> a -> Lua b-liftLua1 f x = liftLua $ \l -> f l x---- | Get the Lua state of this Lua computation.-state :: Lua State-state = asks luaEnvState---- | Get the error-to-exception function.-errorConversion :: Lua ErrorConversion-errorConversion = asks luaEnvErrorConversion---- | Run Lua computation with the given Lua state and error-to-exception--- converter. Any resulting exceptions are left unhandled.-runWithConverter :: ErrorConversion -> State -> Lua a -> IO a-runWithConverter e2e l s =-  runReaderT (unLua s) (LuaEnvironment e2e l)---- | Run the given operation, but crash if any Haskell exceptions occur.-unsafeRunWith :: State -> Lua a -> IO a-unsafeRunWith = runWithConverter unsafeErrorConversion---- | Unsafe @'ErrorConversion'@; no proper error handling is attempted,--- any error leads to a crash.-unsafeErrorConversion :: ErrorConversion-unsafeErrorConversion = ErrorConversion-  { errorToException = const (error "An unrecoverable Lua error occured.")-  , addContextToException = const id-  , alternative = const-  , exceptionToError = id-  }---- | An opaque structure that points to a thread and indirectly (through the--- thread) to the whole state of a Lua interpreter. The Lua library is fully--- reentrant: it has no global variables. All information about a state is--- accessible through this structure.------ Synonym for @lua_State *@. See <https://www.lua.org/manual/5.3/#lua_State lua_State>.-newtype State = State (Ptr ()) deriving (Eq, Generic)---- |  Type for C functions.------ In order to communicate properly with Lua, a C function must use the--- following protocol, which defines the way parameters and results are--- passed: a C function receives its arguments from Lua in its stack in--- direct order (the first argument is pushed first). So, when the--- function starts, @'Foreign.Lua.Core.Functions.gettop'@ returns the--- number of arguments received by the function. The first argument (if--- any) is at index 1 and its last argument is at index--- @'Foreign.Lua.Core.Functions.gettop'@. To return values to Lua, a C--- function just pushes them onto the stack, in direct order (the first--- result is pushed first), and returns the number of results. Any other--- value in the stack below the results will be properly discarded by--- Lua. Like a Lua function, a C function called by Lua can also return--- many results.------ See <https://www.lua.org/manual/5.3/manual.html#lua_CFunction lua_CFunction>.-type CFunction = FunPtr (State -> IO NumResults)---- | The reader function used by @'Foreign.Lua.Core.Functions.load'@.--- Every time it needs another piece of the chunk, lua_load calls the--- reader, passing along its data parameter. The reader must return a--- pointer to a block of memory with a new piece of the chunk and set--- size to the block size. The block must exist until the reader--- function is called again. To signal the end of the chunk, the reader--- must return @NULL@ or set size to zero. The reader function may--- return pieces of any size greater than zero.------ See <https://www.lua.org/manual/5.3/manual.html#lua_Reader lua_Reader>.-type Reader = FunPtr (State -> Ptr () -> Ptr CSize -> IO (Ptr CChar))---- |  The type of integers in Lua.------ By default this type is @'Int64'@, but that can be changed to different--- values in lua. (See @LUA_INT_TYPE@ in @luaconf.h@.)------ See <https://www.lua.org/manual/5.3/manual.html#lua_Integer lua_Integer>.-newtype Integer = Integer #{type LUA_INTEGER}-  deriving (Bounded, Enum, Eq, Integral, Num, Ord, Real, Show)---- |  The type of floats in Lua.------ By default this type is @'Double'@, but that can be changed in Lua to a--- single float or a long double. (See @LUA_FLOAT_TYPE@ in @luaconf.h@.)------ See <https://www.lua.org/manual/5.3/manual.html#lua_Number lua_Number>.-newtype Number = Number #{type LUA_NUMBER}-  deriving (Eq, Floating, Fractional, Num, Ord, Real, RealFloat, RealFrac, Show)-------- LuaBool------- | Boolean value returned by a Lua C API function. This is a @'CInt'@ and--- interpreted as @'False'@ iff the value is @0@, @'True'@ otherwise.-newtype LuaBool = LuaBool CInt-  deriving (Eq, Storable, Show)---- | Generic Lua representation of a value interpreted as being true.-true :: LuaBool-true = LuaBool 1---- | Lua representation of the value interpreted as false.-false :: LuaBool-false = LuaBool 0---- | Convert a @'LuaBool'@ to a Haskell @'Bool'@.-fromLuaBool :: LuaBool -> Bool-fromLuaBool (LuaBool 0) = False-fromLuaBool _           = True-{-# INLINABLE fromLuaBool #-}---- | Convert a Haskell @'Bool'@ to a @'LuaBool'@.-toLuaBool :: Bool -> LuaBool-toLuaBool True  = true-toLuaBool False = false-{-# INLINABLE toLuaBool #-}-------- * Type of Lua values------- | Enumeration used as type tag.--- See <https://www.lua.org/manual/5.3/manual.html#lua_type lua_type>.-data Type-  = TypeNone           -- ^ non-valid stack index-  | TypeNil            -- ^ type of lua's @nil@ value-  | TypeBoolean        -- ^ type of lua booleans-  | TypeLightUserdata  -- ^ type of light userdata-  | TypeNumber         -- ^ type of lua numbers. See @'Lua.Number'@-  | TypeString         -- ^ type of lua string values-  | TypeTable          -- ^ type of lua tables-  | TypeFunction       -- ^ type of functions, either normal or @'CFunction'@-  | TypeUserdata       -- ^ type of full user data-  | TypeThread         -- ^ type of lua threads-  deriving (Bounded, Eq, Ord, Show)---- | Integer code used to encode the type of a lua value.-newtype TypeCode = TypeCode { fromTypeCode :: CInt }-  deriving (Eq, Ord, Show)--instance Enum Type where-  fromEnum = fromIntegral . fromTypeCode . fromType-  toEnum = toType . TypeCode . fromIntegral---- | Convert a lua Type to a type code which can be passed to the C API.-fromType :: Type -> TypeCode-fromType tp = TypeCode $ case tp of-  TypeNone          -> #{const LUA_TNONE}-  TypeNil           -> #{const LUA_TNIL}-  TypeBoolean       -> #{const LUA_TBOOLEAN}-  TypeLightUserdata -> #{const LUA_TLIGHTUSERDATA}-  TypeNumber        -> #{const LUA_TNUMBER}-  TypeString        -> #{const LUA_TSTRING}-  TypeTable         -> #{const LUA_TTABLE}-  TypeFunction      -> #{const LUA_TFUNCTION}-  TypeUserdata      -> #{const LUA_TUSERDATA}-  TypeThread        -> #{const LUA_TTHREAD}---- | Convert numerical code to lua type.-toType :: TypeCode -> Type-toType (TypeCode c) = case c of-  #{const LUA_TNONE}          -> TypeNone-  #{const LUA_TNIL}           -> TypeNil-  #{const LUA_TBOOLEAN}       -> TypeBoolean-  #{const LUA_TLIGHTUSERDATA} -> TypeLightUserdata-  #{const LUA_TNUMBER}        -> TypeNumber-  #{const LUA_TSTRING}        -> TypeString-  #{const LUA_TTABLE}         -> TypeTable-  #{const LUA_TFUNCTION}      -> TypeFunction-  #{const LUA_TUSERDATA}      -> TypeUserdata-  #{const LUA_TTHREAD}        -> TypeThread-  _ -> error ("No Type corresponding to " ++ show c)------- * Relational Operator------- | Lua comparison operations.-data RelationalOperator-  = EQ -- ^ Correponds to lua's equality (==) operator.-  | LT -- ^ Correponds to lua's strictly-lesser-than (<) operator-  | LE -- ^ Correponds to lua's lesser-or-equal (<=) operator-  deriving (Eq, Ord, Show)---- | Convert relation operator to its C representation.-fromRelationalOperator :: RelationalOperator -> CInt-fromRelationalOperator EQ = #{const LUA_OPEQ}-fromRelationalOperator LT = #{const LUA_OPLT}-fromRelationalOperator LE = #{const LUA_OPLE}-{-# INLINABLE fromRelationalOperator #-}-------- * Status------- | Lua status values.-data Status-  = OK        -- ^ success-  | Yield     -- ^ yielding / suspended coroutine-  | ErrRun    -- ^ a runtime rror-  | ErrSyntax -- ^ syntax error during precompilation-  | ErrMem    -- ^ memory allocation (out-of-memory) error.-  | ErrErr    -- ^ error while running the message handler.-  | ErrGcmm   -- ^ error while running a @__gc@ metamethod.-  | ErrFile   -- ^ opening or reading a file failed.-  deriving (Eq, Show)---- | Convert C integer constant to @'Status'@.-toStatus :: StatusCode -> Status-toStatus (StatusCode c) = case c of-  #{const LUA_OK}        -> OK-  #{const LUA_YIELD}     -> Yield-  #{const LUA_ERRRUN}    -> ErrRun-  #{const LUA_ERRSYNTAX} -> ErrSyntax-  #{const LUA_ERRMEM}    -> ErrMem-  #{const LUA_ERRGCMM}   -> ErrGcmm-  #{const LUA_ERRERR}    -> ErrErr-  #{const LUA_ERRFILE}   -> ErrFile-  n -> error $ "Cannot convert (" ++ show n ++ ") to Status"-{-# INLINABLE toStatus #-}---- | Integer code used to signal the status of a thread or computation.--- See @'Status'@.-newtype StatusCode = StatusCode CInt deriving Eq-------- * Gargabe Collection Control------- | Enumeration used by @gc@ function.-data GCCONTROL-  = GCSTOP-  | GCRESTART-  | GCCOLLECT-  | GCCOUNT-  | GCCOUNTB-  | GCSTEP-  | GCSETPAUSE-  | GCSETSTEPMUL-  deriving (Enum, Eq, Ord, Show)---- | A stack index-newtype StackIndex = StackIndex { fromStackIndex :: CInt }-  deriving (Enum, Eq, Num, Ord, Show)---- | Stack index of the nth element from the top of the stack.-nthFromTop :: CInt -> StackIndex-nthFromTop n = StackIndex (-n)-{-# INLINABLE nthFromTop #-}---- | Stack index of the nth element from the bottom of the stack.-nthFromBottom :: CInt -> StackIndex-nthFromBottom = StackIndex-{-# INLINABLE nthFromBottom #-}---- | Top of the stack-stackTop :: StackIndex-stackTop = -1-{-# INLINABLE stackTop #-}---- | Bottom of the stack-stackBottom :: StackIndex-stackBottom = 1-{-# INLINABLE stackBottom #-}------- Number of arguments and return values------- | The number of arguments expected a function.-newtype NumArgs = NumArgs { fromNumArgs :: CInt }-  deriving (Eq, Num, Ord, Show)---- | The number of results returned by a function call.-newtype NumResults = NumResults { fromNumResults :: CInt }-  deriving (Eq, Num, Ord, Show)------- References------- | Value signaling that no reference was created.-refnil :: CInt-refnil = #{const LUA_REFNIL}---- | Reference to a stored value.-data Reference =-    Reference CInt -- ^ Reference to a stored value-  | RefNil         -- ^ Reference to a nil value-  deriving (Eq, Show)---- | Convert a reference to its C representation.-fromReference :: Reference -> CInt-fromReference = \case-  Reference x -> x-  RefNil      -> refnil---- | Create a reference from its C representation.-toReference :: CInt -> Reference-toReference x =-  if x == refnil-  then RefNil-  else Reference x
src/Foreign/Lua/FunctionCalling.hsc view
@@ -30,17 +30,17 @@   , registerHaskellFunction   ) where -import Data.ByteString (ByteString) import Foreign.C (CInt (..)) import Foreign.Lua.Core as Lua+import Foreign.Lua.Core.Types (liftLua)+import Foreign.Lua.Raw.Call (hslua_pushhsfunction) import Foreign.Lua.Types-import Foreign.Lua.Userdata ( ensureUserdataMetatable, pushAnyWithMetatable-                            , toAnyWithName )-import Foreign.Lua.Util (getglobal', popValue, raiseError)+import Foreign.Lua.Util (getglobal', popValue) import Foreign.Ptr (freeHaskellFunPtr) --- | Type of raw Haskell functions that can be made into 'CFunction's.-type PreCFunction = Lua.State -> IO NumResults+-- | Type of raw Haskell functions that can be made into+-- 'CFunction's.+type PreCFunction = State -> IO NumResults  -- | Haskell function that can be called from Lua. type HaskellFunction = Lua NumResults@@ -101,7 +101,7 @@   liftIO . mkWrapper . flip (Lua.runWithConverter e2e) . toHaskellFunction $ f  -- | Turn a @'PreCFunction'@ into an actual @'CFunction'@.-foreign import ccall "wrapper"+foreign import ccall unsafe "wrapper"   mkWrapper :: PreCFunction -> IO CFunction  -- | Free function pointer created with @newcfunction@.@@ -146,41 +146,13 @@ pushHaskellFunction :: ToHaskellFunction a => a -> Lua () pushHaskellFunction hsFn = do   errConv <- Lua.errorConversion-  pushPreCFunction . flip (runWithConverter errConv) $ toHaskellFunction hsFn-  -- Convert userdata object into a CFuntion.-  pushcclosure hslua_call_hs_ptr 1---- | Convert callable userdata at top of stack into a CFunction, translating--- errors to Lua errors.  Use with @'pushcclosure'@.-foreign import ccall "error-conversion.h &hslua_call_hs"-  hslua_call_hs_ptr :: CFunction--hsLuaFunctionName :: String-hsLuaFunctionName = "HsLuaFunction"+  preCFn <- return . flip (runWithConverter errConv) $ toHaskellFunction hsFn+  pushPreCFunction preCFn  -- | Converts a pre C function to a Lua function and pushes it to the stack. -- -- Pre C functions collect parameters from the stack and return -- a `CInt` that represents number of return values left on the stack. pushPreCFunction :: PreCFunction -> Lua ()-pushPreCFunction f =-  let pushMetatable = ensureUserdataMetatable hsLuaFunctionName $ do-        -- ensure the userdata will be callable-        pushcfunction hslua_call_wrapped_hs_fun_ptr-        setfield (-2) "__call"-  in pushAnyWithMetatable pushMetatable f---- | Call the Haskell function stored in the userdata. This function is exported--- as a C function and then re-imported in order to get a C function pointer.-hslua_call_wrapped_hs_fun :: Lua.State -> IO NumResults-hslua_call_wrapped_hs_fun l = do-  mbFn <- unsafeRunWith l (toAnyWithName stackBottom hsLuaFunctionName-                           <* remove stackBottom)-  case mbFn of-    Just fn -> fn l-    Nothing -> unsafeRunWith l-               (raiseError ("Could not call function" :: ByteString))--foreign export ccall hslua_call_wrapped_hs_fun :: PreCFunction-foreign import ccall "&hslua_call_wrapped_hs_fun"-  hslua_call_wrapped_hs_fun_ptr :: CFunction+pushPreCFunction preCFn = liftLua $ \l ->+  hslua_pushhsfunction l preCFn
src/Foreign/Lua/Module.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE OverloadedStrings #-} {-| Module      : Foreign.Lua.Module Copyright   : © 2019-2020 Albert Krewinkel@@ -14,24 +15,41 @@   , addfield   , addfunction   , create+    -- * Module+  , Module (..)+  , Field (..)+  , registerModule+  , preloadModule+  , pushModule+    -- * Documentation+  , render   ) where -import Control.Monad (unless)+import Control.Monad (unless, forM_)+import Data.Text (Text)+import Foreign.Lua.Call (HaskellFunction) import Foreign.Lua.Core+import Foreign.Lua.Push (pushText) import Foreign.Lua.Types (Pushable, push)-import Foreign.Lua.FunctionCalling (ToHaskellFunction, pushHaskellFunction)+import Foreign.Lua.FunctionCalling+  ( ToHaskellFunction+  , pushHaskellFunction+  )+import qualified Data.Text as T+import qualified Foreign.Lua.Call as Call --- | Load a module, defined by a Haskell action, under the given name.+-- | Load a module, defined by a Haskell action, under the given+-- name. ----- Similar to @luaL_required@: After checking "loaded" table, calls--- @pushMod@ to push a module to the stack, and registers the result in--- @package.loaded@ table.+-- Similar to @luaL_required@: After checking "loaded" table,+-- calls @pushMod@ to push a module to the stack, and registers+-- the result in @package.loaded@ table. ----- The @pushMod@ function must push exactly one element to the top of--- the stack. This is not checked, but failure to do so will lead to--- problems. Lua's @package@ module must have been loaded by the time--- this function is invoked.+-- The @pushMod@ function must push exactly one element to the top+-- of the stack. This is not checked, but failure to do so will+-- lead to problems. Lua's @package@ module must have been loaded+-- by the time this function is invoked. -- -- Leaves a copy of the module on the stack. requirehs :: String -> Lua () -> Lua ()@@ -52,8 +70,8 @@    remove (nthFromTop 2)  -- remove table of loaded modules --- | Registers a preloading function. Takes an module name and the Lua--- operation which produces the package.+-- | Registers a preloading function. Takes an module name and the+-- Lua operation which produces the package. preloadhs :: String -> Lua NumResults -> Lua () preloadhs name pushMod = do   getfield registryindex preloadTableRegistryField@@ -61,15 +79,16 @@   setfield (nthFromTop 2) name   pop 1 --- | Add a string-indexed field to the table at the top of the stack.+-- | Add a string-indexed field to the table at the top of the+-- stack. addfield :: Pushable a => String -> a -> Lua () addfield name value = do   push name   push value   rawset (nthFromTop 3) --- | Attach a function to the table at the top of the stack, using the--- given name.+-- | Attach a function to the table at the top of the stack, using+-- the given name. addfunction :: ToHaskellFunction a => String -> a -> Lua () addfunction name fn = do   push name@@ -79,3 +98,86 @@ -- | Create a new module (i.e., a Lua table). create :: Lua () create = newtable++-- | Named and documented Lua module.+data Module = Module+  { moduleName :: Text+  , moduleDescription :: Text+  , moduleFields :: [Field]+  , moduleFunctions :: [(Text, HaskellFunction)]+  }++-- | Self-documenting module field+data Field = Field+  { fieldName :: Text+  , fieldDescription :: Text+  , fieldPushValue :: Lua ()+  }+++-- | Registers a 'Module'; leaves a copy of the module table on+-- the stack.+registerModule :: Module -> Lua ()+registerModule mdl =+  requirehs (T.unpack $ moduleName mdl) (pushModule mdl)++-- | Preload self-documenting module.+preloadModule :: Module -> Lua ()+preloadModule mdl =+  preloadhs (T.unpack $ moduleName mdl) $ do+    pushModule mdl+    return (NumResults 1)++pushModule :: Module -> Lua ()+pushModule mdl = do+  create+  forM_ (moduleFunctions mdl) $ \(name, fn) -> do+    pushText name+    Call.pushHaskellFunction fn+    rawset (nthFromTop 3)++-- | Renders module documentation as Markdown.+render :: Module -> Text+render mdl =+  let fields = moduleFields mdl+  in T.unlines+     [ "# " <> moduleName mdl+     , ""+     , moduleDescription mdl+     , if null (moduleFields mdl) then "" else renderFields fields+     , "## Functions"+     , ""+     ]+     <> T.intercalate "\n"+        (map (uncurry renderFunctionDoc) (moduleFunctions mdl))++-- | Renders documentation of a function.+renderFunctionDoc :: Text             -- ^ name+                  -> HaskellFunction  -- ^ function+                  -> Text             -- ^ function docs+renderFunctionDoc name fn =+  case Call.functionDoc fn of+    Nothing -> ""+    Just fnDoc -> T.intercalate "\n"+      [ "### " <> name <> " (" <> renderFunctionParams fnDoc <> ")"+      , ""+      , Call.render fnDoc+      ]++renderFunctionParams :: Call.FunctionDoc -> Text+renderFunctionParams fd =+    T.intercalate ", "+  . map Call.parameterName+  $ Call.parameterDocs fd++-- | Render documentation for fields as Markdown.+renderFields :: [Field] -> Text+renderFields fs =+  if null fs+  then mempty+  else T.unlines $ map renderField fs++-- | Renders documentation for a single field.+renderField :: Field -> Text+renderField f =+  "### " <> fieldName f <> "\n\n" <> fieldDescription f <> "\n"
src/Foreign/Lua/Peek.hs view
@@ -14,6 +14,8 @@   , PeekError (..)   , errorMsg   , force+  , formatPeekError+  , pushMsg   , toPeeker   -- * Primitives   , peekBool@@ -29,6 +31,8 @@   , peekList   , peekMap   , peekSet+  -- * Combinators+  , optional   ) where  import Control.Applicative ((<|>))@@ -240,3 +244,17 @@     fmap (retrieving "Set" .           second (Set.fromList . map fst . filter snd))   . peekKeyValuePairs elementPeeker peekBool++--+-- Combinators+--++-- | Makes a result optional. Returns 'Nothing' if the Lua value+-- is @nil@; otherwise applies the peeker and returns its result.+optional :: Peeker a -- ^ peeker+         -> Peeker (Maybe a)+optional peeker idx = do+  noValue <- Lua.isnoneornil idx+  if noValue+    then return $ Right Nothing+    else fmap Just <$> peeker idx
+ src/Foreign/Lua/Raw/Auxiliary.hs view
@@ -0,0 +1,135 @@+{-# LANGUAGE CPP #-}+{-|+Module      : Foreign.Lua.Raw.Auxiliary+Copyright   : © 2007–2012 Gracjan Polak,+                2012–2016 Ömer Sinan Ağacan,+                2017-2020 Albert Krewinkel+License     : MIT+Maintainer  : Albert Krewinkel <tarleb+hslua@zeitkraut.de>+Stability   : beta+Portability : non-portable (depends on GHC)++Raw bindings to functions and constants of the auxiliary library.+-}+module Foreign.Lua.Raw.Auxiliary+  ( c_loaded_table+  , c_preload_table+  , hsluaL_newstate+  , hsluaL_tolstring+  , luaL_getmetafield+  , luaL_getmetatable+  , luaL_loadbuffer+  , luaL_newmetatable+  , luaL_ref+  , luaL_testudata+  , luaL_traceback+  , luaL_unref+    -- * Registry fields+  , loadedTableRegistryField+  , preloadTableRegistryField+    -- * References+  , Reference (..)+  , fromReference+  , toReference+  ) where++import Foreign.C (CChar, CInt (CInt), CSize (CSize), CString)+import Foreign.Lua.Raw.Types (StackIndex)+import Foreign.Ptr+import qualified Foreign.Lua.Raw.Types as Lua++#ifndef HARDCODE_REG_KEYS+import System.IO.Unsafe (unsafePerformIO)+import qualified Foreign.C as C+#endif++#ifdef ALLOW_UNSAFE_GC+#define SAFTY unsafe+#else+#define SAFTY safe+#endif++-- * The Auxiliary Library++-- | Key, in the registry, for table of loaded modules.+loadedTableRegistryField :: String+#ifdef HARDCODE_REG_KEYS+loadedTableRegistryField = "_LOADED"+#else+loadedTableRegistryField = unsafePerformIO (C.peekCString c_loaded_table)+{-# NOINLINE loadedTableRegistryField #-}++foreign import capi unsafe "lauxlib.h value LUA_LOADED_TABLE"+  c_loaded_table :: CString+#endif++-- | Key, in the registry, for table of preloaded loaders.+preloadTableRegistryField :: String+#ifdef HARDCODE_REG_KEYS+preloadTableRegistryField = "_PRELOAD"+#else+preloadTableRegistryField = unsafePerformIO (C.peekCString c_preload_table)+{-# NOINLINE preloadTableRegistryField #-}++foreign import capi unsafe "lauxlib.h value LUA_PRELOAD_TABLE"+  c_preload_table :: CString+#endif++foreign import capi SAFTY "lauxlib.h luaL_getmetafield"+  luaL_getmetafield :: Lua.State -> StackIndex -> CString -> IO Lua.TypeCode++foreign import capi SAFTY "lauxlib.h luaL_getmetatable"+  luaL_getmetatable :: Lua.State -> CString -> IO Lua.TypeCode++foreign import capi SAFTY "lauxlib.h luaL_loadbuffer"+  luaL_loadbuffer :: Lua.State -> Ptr CChar -> CSize -> CString+                  -> IO Lua.StatusCode++foreign import ccall SAFTY "lauxlib.h luaL_newmetatable"+  luaL_newmetatable :: Lua.State -> CString -> IO Lua.LuaBool++foreign import ccall unsafe "lauxlib.h hsluaL_newstate"+  hsluaL_newstate :: IO Lua.State++foreign import ccall SAFTY "lauxlib.h luaL_ref"+  luaL_ref :: Lua.State -> StackIndex -> IO CInt++foreign import ccall safe "hslua.h hsluaL_tolstring"+  hsluaL_tolstring :: Lua.State -> StackIndex -> Ptr CSize -> IO (Ptr CChar)++foreign import capi SAFTY "lauxlib.h luaL_traceback"+  luaL_traceback :: Lua.State -> Lua.State -> CString -> CInt -> IO ()++foreign import ccall SAFTY "lauxlib.h luaL_unref"+  luaL_unref :: Lua.State -> StackIndex -> CInt -> IO ()++-- | See+-- <https://www.lua.org/manual/5.3/manual.html#luaL_testudata luaL_testudata>+foreign import capi SAFTY "lauxlib.h luaL_testudata"+  luaL_testudata :: Lua.State -> StackIndex -> CString -> IO (Ptr ())++--+-- References+--++-- | Reference to a stored value.+data Reference =+    Reference CInt -- ^ Reference to a stored value+  | RefNil         -- ^ Reference to a nil value+  deriving (Eq, Show)++foreign import capi SAFTY "lauxlib.h value LUA_REFNIL"+  refnil :: CInt++-- | Convert a reference to its C representation.+fromReference :: Reference -> CInt+fromReference = \case+  Reference x -> x+  RefNil      -> refnil++-- | Create a reference from its C representation.+toReference :: CInt -> Reference+toReference x =+  if x == refnil+  then RefNil+  else Reference x
+ src/Foreign/Lua/Raw/Call.hs view
@@ -0,0 +1,65 @@+{-# LANGUAGE CPP #-}+{-|+Module      : Foreign.Lua.Raw.Call+Copyright   : © 2007–2012 Gracjan Polak,+                2012–2016 Ömer Sinan Ağacan,+                2017-2020 Albert Krewinkel+License     : MIT+Maintainer  : Albert Krewinkel <tarleb+hslua@zeitkraut.de>+Stability   : beta+Portability : non-portable (depends on GHC)++Raw bindings to function call helpers.+-}+module Foreign.Lua.Raw.Call+  ( HsFunction+  , hslua_newhsfunction+  , hslua_pushhsfunction+  ) where++import Foreign.C (CInt (CInt))+import Foreign.Ptr (Ptr, castPtr, nullPtr)+import Foreign.StablePtr (StablePtr, deRefStablePtr, newStablePtr)+import Foreign.Storable (peek)+import Foreign.Lua.Raw.Types+  ( NumResults (NumResults)+  , State (State)+  )++#ifdef ALLOW_UNSAFE_GC+#define SAFTY unsafe+#else+#define SAFTY safe+#endif++-- | Type of raw Haskell functions that can be made into+-- 'CFunction's.+type HsFunction = State -> IO NumResults++-- | Retrieve the pointer to a Haskell function from the wrapping+-- userdata object.+foreign import ccall SAFTY "hslua.h hslua_hs_fun_ptr"+  hslua_hs_fun_ptr :: State -> IO (Ptr ())++-- | Pushes a new C function created from an 'HsFunction'.+foreign import ccall SAFTY "hslua.h hslua_newhsfunction"+  hslua_newhsfunction :: State -> StablePtr a -> IO ()++hslua_pushhsfunction :: State -> HsFunction -> IO ()+hslua_pushhsfunction l preCFn =+  newStablePtr preCFn >>= hslua_newhsfunction l+{-# INLINABLE hslua_pushhsfunction #-}++-- | Call the Haskell function stored in the userdata. This+-- function is exported as a C function, as the C code uses it as+-- the @__call@ value of the wrapping userdata metatable.+hslua_call_wrapped_hs_fun :: HsFunction+hslua_call_wrapped_hs_fun l = do+  udPtr <- hslua_hs_fun_ptr l+  if udPtr == nullPtr+    then error "Cannot call function; corrupted Lua object!"+    else do+      fn <- peek (castPtr udPtr) >>= deRefStablePtr+      fn l++foreign export ccall hslua_call_wrapped_hs_fun :: HsFunction
+ src/Foreign/Lua/Raw/Constants.hs view
@@ -0,0 +1,39 @@+{-|+Module      : Foreign.Lua.Raw.Constants+Copyright   : © 2007–2012 Gracjan Polak,+                2012–2016 Ömer Sinan Ağacan,+                2017-2020 Albert Krewinkel+License     : MIT+Maintainer  : Albert Krewinkel <tarleb+hslua@zeitkraut.de>+Stability   : beta+Portability : ForeignFunctionInterface++Lua constants+-}+module Foreign.Lua.Raw.Constants+  ( multret+  , registryindex+  , refnil+  , noref+  ) where++import Foreign.C (CInt (..))+import Foreign.Lua.Raw.Types++-- | Alias for C constant @LUA_MULTRET@. See+-- <https://www.lua.org/manual/5.3/#lua_call lua_call>.+foreign import capi unsafe "lua.h value LUA_MULTRET"+  multret :: NumResults++-- | Alias for C constant @LUA_REGISTRYINDEX@. See+-- <https://www.lua.org/manual/5.3/#3.5 Lua registry>.+foreign import capi unsafe "lua.h value LUA_REGISTRYINDEX"+  registryindex :: StackIndex++-- | Value signaling that no reference was created.+foreign import capi unsafe "lauxlib.h value LUA_REFNIL"+  refnil :: Int++-- | Value signaling that no reference was found.+foreign import capi unsafe "lauxlib.h value LUA_NOREF"+  noref :: Int
+ src/Foreign/Lua/Raw/Error.hs view
@@ -0,0 +1,40 @@+{-|+Module      : Foreign.Lua.Raw.Error+Copyright   : © 2017-2020 Albert Krewinkel+License     : MIT+Maintainer  : Albert Krewinkel <tarleb+hslua@zeitkraut.de>+Stability   : beta+Portability : portable++Lua exceptions and exception handling.+-}+module Foreign.Lua.Raw.Error+  ( -- * Passing Lua errors to Haskell+    errorMessage+  ) where++import Data.ByteString (ByteString)+import Foreign.Lua.Raw.Auxiliary (hsluaL_tolstring)+import Foreign.Lua.Raw.Functions (lua_pop)+import Foreign.Marshal.Alloc (alloca)+import Foreign.Ptr (nullPtr)++import qualified Data.ByteString as B+import qualified Data.ByteString.Char8 as Char8+import qualified Foreign.Storable as Storable+import qualified Foreign.Lua.Raw.Types as Lua++-- | Retrieve and pop the top object as an error message. This is very similar+-- to tostring', but ensures that we don't recurse if getting the message+-- failed.+errorMessage :: Lua.State -> IO ByteString+errorMessage l = alloca $ \lenPtr -> do+  cstr <- hsluaL_tolstring l (-1) lenPtr+  if cstr == nullPtr+    then return $ Char8.pack ("An error occurred, but the error object " +++                              "cannot be converted into a string.")+    else do+      cstrLen <- Storable.peek lenPtr+      msg <- B.packCStringLen (cstr, fromIntegral cstrLen)+      lua_pop l 2+      return msg
+ src/Foreign/Lua/Raw/Functions.hs view
@@ -0,0 +1,393 @@+{-# LANGUAGE CPP #-}+{-|+Module      : Foreign.Lua.Raw.Functions+Copyright   : © 2007–2012 Gracjan Polak,+                2012–2016 Ömer Sinan Ağacan,+                2017-2020 Albert Krewinkel+License     : MIT+Maintainer  : Albert Krewinkel <tarleb+hslua@zeitkraut.de>+Stability   : beta+Portability : ForeignFunctionInterface, CPP++Haskell bindings to Lua C API functions.+-}+module Foreign.Lua.Raw.Functions where++import Foreign.C+import Foreign.Lua.Raw.Types as Lua+import Foreign.Ptr++#ifdef ALLOW_UNSAFE_GC+#define SAFTY unsafe+#else+#define SAFTY safe+#endif++-- TODO: lua_getallocf, lua_setallocf+-- TODO: Debugger functions++-- Some of the Lua functions may call a Haskell function, and trigger+-- garbage collection, rescheduling etc. This means we must declare these+-- functions as 'safe'.+++--------------------------------------------------------------------------------+-- * State manipulation++-- lua_newstate is currently not supported.++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_close lua_close>+foreign import ccall safe "lua.h lua_close"+  lua_close :: Lua.State -> IO ()++-- lua_newthread is currently not supported.+++--------------------------------------------------------------------------------+-- * Basic stack manipulation++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_absindex lua_absindex>+foreign import ccall SAFTY "lua.h lua_absindex"+  lua_absindex :: Lua.State -> StackIndex -> IO StackIndex++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_gettop lua_gettop>+foreign import ccall SAFTY "lua.h lua_gettop"+  lua_gettop :: Lua.State -> IO StackIndex++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_settop lua_settop>+foreign import ccall SAFTY "lua.h lua_settop"+  lua_settop :: Lua.State -> StackIndex -> IO ()++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_pushvalue lua_pushvalue>+foreign import ccall SAFTY "lua.h lua_pushvalue"+  lua_pushvalue :: Lua.State -> StackIndex -> IO ()++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_pop lua_pop>+foreign import capi SAFTY "lua.h lua_pop"+  lua_pop :: Lua.State -> StackIndex -> IO ()++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_copy lua_copy>+foreign import ccall SAFTY "lua.h lua_copy"+  lua_copy :: Lua.State -> StackIndex -> StackIndex -> IO ()++-- | See <https://www.lua.org/manual/5.2/manual.html#lua_remove lua_remove>+foreign import capi SAFTY "lua.h lua_remove"+  lua_remove :: Lua.State -> StackIndex -> IO ()++-- | See <https://www.lua.org/manual/5.2/manual.html#lua_insert lua_insert>+foreign import capi SAFTY "lua.h lua_insert"+  lua_insert :: Lua.State -> StackIndex -> IO ()++-- | See <https://www.lua.org/manual/5.2/manual.html#lua_replace lua_replace>+foreign import capi SAFTY "lua.h lua_replace"+  lua_replace :: Lua.State -> StackIndex -> IO ()++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_checkstack lua_checkstack>+foreign import capi SAFTY "lua.h lua_checkstack"+  lua_checkstack :: Lua.State -> CInt -> IO LuaBool++-- lua_xmove is currently not supported.+++--------------------------------------------------------------------------------+-- * Stack access functions++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_isnumber lua_isnumber>+foreign import ccall SAFTY "lua.h lua_isnumber"+  lua_isnumber :: Lua.State -> StackIndex -> IO LuaBool++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_isinteger lua_isinteger>+foreign import ccall SAFTY "lua.h lua_isinteger"+  lua_isinteger :: Lua.State -> StackIndex -> IO LuaBool++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_isstring lua_isstring>+foreign import ccall SAFTY "lua.h lua_isstring"+  lua_isstring :: Lua.State -> StackIndex -> IO LuaBool++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_iscfunction lua_iscfunction>+foreign import ccall SAFTY "lua.h lua_iscfunction"+  lua_iscfunction :: Lua.State -> StackIndex -> IO LuaBool++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_isuserdata lua_isuserdata>+foreign import ccall SAFTY "lua.h lua_isuserdata"+  lua_isuserdata :: Lua.State -> StackIndex -> IO LuaBool++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_type lua_type>+foreign import ccall SAFTY "lua.h lua_type"+  lua_type :: Lua.State -> StackIndex -> IO TypeCode++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_typename lua_typename>+foreign import ccall SAFTY "lua.h lua_typename"+  lua_typename :: Lua.State -> TypeCode -> IO CString++-- lua_compare is unsafe (might cause a longjmp), use hslua_compare instead.++-- | Wrapper around <https://lua.org/manual/5.3/manual.html#lua_compare \+-- @lua_compare@> which catches any @longjmp@s.+foreign import capi safe "hslua.h hslua_compare"+  hslua_compare :: Lua.State+                -> StackIndex -> StackIndex -> CInt+                -> Ptr StatusCode -> IO LuaBool++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_rawequal lua_rawequal>+foreign import ccall SAFTY "lua.h lua_rawequal"+  lua_rawequal :: Lua.State -> StackIndex -> StackIndex -> IO LuaBool++--+-- Type coercion+--+-- | See <https://www.lua.org/manual/5.3/manual.html#lua_toboolean lua_toboolean>+foreign import capi SAFTY "lua.h lua_toboolean"+  lua_toboolean :: Lua.State -> StackIndex -> IO LuaBool++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_tocfunction lua_tocfunction>+foreign import ccall SAFTY "lua.h lua_tocfunction"+  lua_tocfunction :: Lua.State -> StackIndex -> IO CFunction++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_tointegerx lua_tointegerx>+foreign import ccall SAFTY "lua.h lua_tointegerx"+  lua_tointegerx :: Lua.State -> StackIndex -> Ptr LuaBool -> IO Lua.Integer++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_tonumberx lua_tonumberx>+foreign import ccall SAFTY "lua.h lua_tonumberx"+  lua_tonumberx :: Lua.State -> StackIndex -> Ptr LuaBool -> IO Lua.Number++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_tolstring lua_tolstring>+foreign import ccall SAFTY "lua.h lua_tolstring"+  lua_tolstring :: Lua.State -> StackIndex -> Ptr CSize -> IO (Ptr CChar)++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_topointer lua_topointer>+foreign import ccall SAFTY "lua.h lua_topointer"+  lua_topointer :: Lua.State -> StackIndex -> IO (Ptr ())++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_tothread lua_tothread>+foreign import ccall SAFTY "lua.h lua_tothread"+  lua_tothread :: Lua.State -> StackIndex -> IO Lua.State++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_touserdata lua_touserdata>+foreign import ccall SAFTY "lua.h lua_touserdata"+  lua_touserdata :: Lua.State -> StackIndex -> IO (Ptr a)+++--+-- Object size+--++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_rawlen lua_rawlen>+foreign import ccall SAFTY "lua.h lua_rawlen"+  lua_rawlen :: Lua.State -> StackIndex -> IO CSize+++--------------------------------------------------------------------------------+-- * Push functions++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_pushnil lua_pushnil>+foreign import ccall SAFTY "lua.h lua_pushnil"+  lua_pushnil :: Lua.State -> IO ()++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_pushnumber lua_pushnumber>+foreign import ccall SAFTY "lua.h lua_pushnumber"+  lua_pushnumber :: Lua.State -> Lua.Number -> IO ()++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_pushinteger lua_pushinteger>+foreign import ccall SAFTY "lua.h lua_pushinteger"+  lua_pushinteger :: Lua.State -> Lua.Integer -> IO ()++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_pushlstring lua_pushlstring>+foreign import ccall SAFTY "lua.h lua_pushlstring"+  lua_pushlstring :: Lua.State -> Ptr CChar -> CSize -> IO ()++-- lua_pushstring is currently not supported. It's difficult to use in a haskell+-- context.++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_pushcclosure lua_pushcclosure>+foreign import ccall SAFTY "lua.h lua_pushcclosure"+  lua_pushcclosure :: Lua.State -> CFunction -> NumArgs -> IO ()++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_pushboolean lua_pushboolean>+foreign import ccall SAFTY "lua.h lua_pushboolean"+  lua_pushboolean :: Lua.State -> LuaBool -> IO ()++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_pushlightuserdata lua_pushlightuserdata>+foreign import ccall SAFTY "lua.h lua_pushlightuserdata"+  lua_pushlightuserdata :: Lua.State -> Ptr a -> IO ()++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_pushthread lua_pushthread>+foreign import ccall SAFTY "lua.h lua_pushthread"+  lua_pushthread :: Lua.State -> IO CInt+++--------------------------------------------------------------------------------+-- * Get functions++-- + lua_gettable is unsafe, use hslua_gettable instead.+-- + lua_getglobal is unsafe, use hslua_getglobal instead.+-- + lua_getfield is unsafe, we build something equivallent using pushlstring and+--   gettable.++-- | Wrapper around <https://lua.org/manual/5.3/manual.html#lua_gettable \+-- @lua_gettable@> which catches any @longjmp@s.+foreign import ccall safe "hslua.h hslua_gettable"+  hslua_gettable :: Lua.State -> StackIndex -> Ptr StatusCode -> IO ()++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_rawget lua_rawget>+foreign import ccall SAFTY "lua.h lua_rawget"+  lua_rawget :: Lua.State -> StackIndex -> IO ()++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_rawgeti lua_rawgeti>+foreign import ccall SAFTY "lua.h lua_rawgeti"+  lua_rawgeti :: Lua.State -> StackIndex -> Lua.Integer -> IO ()++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_createtable lua_createtable>+foreign import ccall SAFTY "lua.h lua_createtable"+  lua_createtable :: Lua.State -> CInt -> CInt -> IO ()++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_newuserdata lua_newuserdata>+foreign import ccall SAFTY "lua.h lua_newuserdata"+  lua_newuserdata :: Lua.State -> CSize -> IO (Ptr ())++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_getmetatable lua_getmetatable>+foreign import ccall SAFTY "lua.h lua_getmetatable"+  lua_getmetatable :: Lua.State -> StackIndex -> IO LuaBool++-- | Wrapper around <https://lua.org/manual/5.3/manual.html#lua_getglobal \+-- @lua_getglobal@> which catches any @longjmp@s.+foreign import ccall safe "hslua.h hslua_getglobal"+  hslua_getglobal :: Lua.State -> CString -> CSize -> Ptr StatusCode -> IO ()+++--------------------------------------------------------------------------------+-- * Set functions++-- lua_settable is unsafe, use hslua_settable instead.+-- lua_setfield is unsafe, use hslua_setfield instead.+-- lua_setglobal is unsafe, use hslua_setglobal instead.+-- lua_setfenv (5.1 only) is not supported.++-- | Wrapper around <https://lua.org/manual/5.3/manual.html#lua_settable \+-- @lua_settable@> which catches any @longjmp@s.+foreign import ccall safe "hslua.h hslua_settable"+  hslua_settable :: Lua.State -> StackIndex -> Ptr StatusCode -> IO ()++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_rawset lua_rawset>+foreign import ccall SAFTY "lua.h lua_rawset"+  lua_rawset :: Lua.State -> StackIndex -> IO ()++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_rawseti lua_rawseti>+foreign import ccall SAFTY "lua.h lua_rawseti"+  lua_rawseti :: Lua.State -> StackIndex -> Lua.Integer -> IO ()++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_setmetatable lua_setmetatable>+foreign import ccall SAFTY "lua.h lua_setmetatable"+  lua_setmetatable :: Lua.State -> StackIndex -> IO ()++-- | Wrapper around <https://lua.org/manual/5.3/manual.html#lua_setglobal \+-- @lua_setglobal@> which catches any @longjmp@s.+foreign import ccall safe "hslua.h hslua_setglobal"+  hslua_setglobal :: Lua.State -> CString -> CSize -> Ptr StatusCode -> IO ()+++--------------------------------------------------------------------------------+-- * \'load\' and \'call\' functions (load and run Lua code)++-- lua_call is inherently unsafe, we do not support it.++-- | See <https://www.lua.org/manual/5.1/manual.html#lua_pcall lua_pcall>+foreign import capi safe "lua.h lua_pcall"+  lua_pcall :: Lua.State -> NumArgs -> NumResults -> StackIndex+            -> IO StatusCode++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_load lua_load>+foreign import ccall safe "lua.h lua_load"+  lua_load :: Lua.State -> Lua.Reader -> Ptr () -> CString -> CString+           -> IO StatusCode++-- currently unsupported:+-- lua_dump+++------------------------------------------------------------------------------+-- * Coroutine functions++-- lua_yield / lua_yieldk and lua_resume are currently not supported.++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_status lua_status>+foreign import ccall SAFTY "lua.h lua_status"+  lua_status :: Lua.State -> IO StatusCode+++------------------------------------------------------------------------------+-- * Garbage-collection functions and options++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_gc lua_gc>+foreign import ccall safe "lua.h lua_gc"+  lua_gc :: Lua.State -> CInt -> CInt -> IO CInt+++------------------------------------------------------------------------------+-- * Miscellaneous functions++-- lua_error is unsafe, use hslua_error instead.+-- lua_next is unsafe, use hslua_next instead.+-- lua_concat is unsafe (may trigger a longjmp), use hslua_concat instead.++-- | Replacement for <https://lua.org/manual/5.3/manual.html#lua_error \+-- @lua_error@>; it uses the HsLua error signaling convention instead of raw+-- @longjmp@.+foreign import ccall SAFTY "hslua.h hslua_error"+  hslua_error :: Lua.State -> IO NumResults++-- | Wrapper around <https://lua.org/manual/5.3/manual.html#lua_next \+-- @lua_next@> which catches any @longjmp@s.+foreign import ccall safe "hslua.h hslua_next"+  hslua_next :: Lua.State -> StackIndex -> Ptr StatusCode -> IO LuaBool++-- | Wrapper around <https://lua.org/manual/5.3/manual.html#lua_concat \+-- @lua_concat@> which catches any @longjmp@s.+foreign import ccall safe "hslua.h hslua_concat"+  hslua_concat :: Lua.State -> NumArgs -> Ptr StatusCode -> IO ()++-- | See <https://www.lua.org/manual/5.3/manual.html#lua_pushglobaltable \+-- lua_pushglobaltable>+foreign import capi SAFTY "lua.h lua_pushglobaltable"+  lua_pushglobaltable :: Lua.State -> IO ()+++------------------------------------------------------------------------------+-- * Lua Libraries++-- | See <https://www.lua.org/manual/5.3/manual.html#luaL_openlibs luaL_openlibs>+foreign import ccall unsafe "lualib.h luaL_openlibs"+  luaL_openlibs :: Lua.State -> IO ()++-- | Point to function opening the base library.+foreign import ccall unsafe "lualib.h &luaopen_base"+  lua_open_base_ptr :: CFunction++-- | Point to function opening the table library.+foreign import ccall unsafe "lualib.h &luaopen_table"+  lua_open_table_ptr :: CFunction++-- | Point to function opening the io library.+foreign import ccall unsafe "lualib.h &luaopen_io"+  lua_open_io_ptr :: CFunction++-- | Point to function opening the os library.+foreign import ccall unsafe "lualib.h &luaopen_os"+  lua_open_os_ptr :: CFunction++-- | Point to function opening the string library.+foreign import ccall unsafe "lualib.h &luaopen_string"+  lua_open_string_ptr :: CFunction++-- | Point to function opening the math library.+foreign import ccall unsafe "lualib.h &luaopen_math"+  lua_open_math_ptr :: CFunction++-- | Point to function opening the debug library.+foreign import ccall unsafe "lualib.h &luaopen_debug"+  lua_open_debug_ptr :: CFunction++-- | Point to function opening the package library.+foreign import ccall unsafe "lualib.h &luaopen_package"+  lua_open_package_ptr :: CFunction
+ src/Foreign/Lua/Raw/Types.hsc view
@@ -0,0 +1,281 @@+{-# LANGUAGE DeriveGeneric              #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-|+Module      : Foreign.Lua.Raw.Types+Copyright   : © 2007–2012 Gracjan Polak,+                2012–2016 Ömer Sinan Ağacan,+                2017-2020 Albert Krewinkel+License     : MIT+Maintainer  : Albert Krewinkel <tarleb+hslua@zeitkraut.de>+Stability   : beta+Portability : non-portable (depends on GHC)++The core Lua types, including mappings of Lua types to Haskell.+-}+module Foreign.Lua.Raw.Types+  ( State (..)+  , Reader+  , GCCONTROL (..)+  , Type (..)+  , TypeCode (..)+  , fromType+  , toType+  , CFunction+  , LuaBool (..)+  , false+  , true+  , fromLuaBool+  , toLuaBool+  , Integer (..)+  , Number (..)+  , StackIndex (..)+  , NumArgs (..)+  , NumResults (..)+  , RelationalOperator (..)+  , fromRelationalOperator+  , Status (..)+  , StatusCode (..)+  , toStatus+  ) where++#include "lua.h"+-- required only for LUA_ERRFILE+#include "lauxlib.h"++import Prelude hiding (Integer, EQ, LT)++import Data.Int (#{type LUA_INTEGER})+import Foreign.C (CChar, CInt, CSize)+import Foreign.Ptr (FunPtr, Ptr)+import Foreign.Storable (Storable)+import GHC.Generics (Generic)++-- | An opaque structure that points to a thread and indirectly (through the+-- thread) to the whole state of a Lua interpreter. The Lua library is fully+-- reentrant: it has no global variables. All information about a state is+-- accessible through this structure.+--+-- Synonym for @lua_State *@. See <https://www.lua.org/manual/5.3/#lua_State lua_State>.+newtype State = State (Ptr ()) deriving (Eq, Generic)++-- |  Type for C functions.+--+-- In order to communicate properly with Lua, a C function must use the+-- following protocol, which defines the way parameters and results are+-- passed: a C function receives its arguments from Lua in its stack in+-- direct order (the first argument is pushed first). So, when the+-- function starts, @'Foreign.Lua.Core.Functions.gettop'@ returns the+-- number of arguments received by the function. The first argument (if+-- any) is at index 1 and its last argument is at index+-- @'Foreign.Lua.Core.Functions.gettop'@. To return values to Lua, a C+-- function just pushes them onto the stack, in direct order (the first+-- result is pushed first), and returns the number of results. Any other+-- value in the stack below the results will be properly discarded by+-- Lua. Like a Lua function, a C function called by Lua can also return+-- many results.+--+-- See <https://www.lua.org/manual/5.3/manual.html#lua_CFunction lua_CFunction>.+type CFunction = FunPtr (State -> IO NumResults)++-- | The reader function used by @'Foreign.Lua.Core.Functions.load'@.+-- Every time it needs another piece of the chunk, lua_load calls the+-- reader, passing along its data parameter. The reader must return a+-- pointer to a block of memory with a new piece of the chunk and set+-- size to the block size. The block must exist until the reader+-- function is called again. To signal the end of the chunk, the reader+-- must return @NULL@ or set size to zero. The reader function may+-- return pieces of any size greater than zero.+--+-- See <https://www.lua.org/manual/5.3/manual.html#lua_Reader lua_Reader>.+type Reader = FunPtr (State -> Ptr () -> Ptr CSize -> IO (Ptr CChar))++-- |  The type of integers in Lua.+--+-- By default this type is @'Int64'@, but that can be changed to different+-- values in lua. (See @LUA_INT_TYPE@ in @luaconf.h@.)+--+-- See <https://www.lua.org/manual/5.3/manual.html#lua_Integer lua_Integer>.+newtype Integer = Integer #{type LUA_INTEGER}+  deriving (Bounded, Enum, Eq, Integral, Num, Ord, Real, Show)++-- |  The type of floats in Lua.+--+-- By default this type is @'Double'@, but that can be changed in Lua to a+-- single float or a long double. (See @LUA_FLOAT_TYPE@ in @luaconf.h@.)+--+-- See <https://www.lua.org/manual/5.3/manual.html#lua_Number lua_Number>.+newtype Number = Number #{type LUA_NUMBER}+  deriving (Eq, Floating, Fractional, Num, Ord, Real, RealFloat, RealFrac, Show)+++--+-- LuaBool+--++-- | Boolean value returned by a Lua C API function. This is a @'CInt'@ and+-- interpreted as @'False'@ iff the value is @0@, @'True'@ otherwise.+newtype LuaBool = LuaBool CInt+  deriving (Eq, Storable, Show)++-- | Generic Lua representation of a value interpreted as being true.+true :: LuaBool+true = LuaBool 1++-- | Lua representation of the value interpreted as false.+false :: LuaBool+false = LuaBool 0++-- | Convert a @'LuaBool'@ to a Haskell @'Bool'@.+fromLuaBool :: LuaBool -> Bool+fromLuaBool (LuaBool 0) = False+fromLuaBool _           = True+{-# INLINABLE fromLuaBool #-}++-- | Convert a Haskell @'Bool'@ to a @'LuaBool'@.+toLuaBool :: Bool -> LuaBool+toLuaBool True  = true+toLuaBool False = false+{-# INLINABLE toLuaBool #-}+++--+-- * Type of Lua values+--++-- | Enumeration used as type tag.+-- See <https://www.lua.org/manual/5.3/manual.html#lua_type lua_type>.+data Type+  = TypeNone           -- ^ non-valid stack index+  | TypeNil            -- ^ type of lua's @nil@ value+  | TypeBoolean        -- ^ type of lua booleans+  | TypeLightUserdata  -- ^ type of light userdata+  | TypeNumber         -- ^ type of lua numbers. See @'Lua.Number'@+  | TypeString         -- ^ type of lua string values+  | TypeTable          -- ^ type of lua tables+  | TypeFunction       -- ^ type of functions, either normal or @'CFunction'@+  | TypeUserdata       -- ^ type of full user data+  | TypeThread         -- ^ type of lua threads+  deriving (Bounded, Eq, Ord, Show)++-- | Integer code used to encode the type of a lua value.+newtype TypeCode = TypeCode { fromTypeCode :: CInt }+  deriving (Eq, Ord, Show)++instance Enum Type where+  fromEnum = fromIntegral . fromTypeCode . fromType+  toEnum = toType . TypeCode . fromIntegral++-- | Convert a lua Type to a type code which can be passed to the C API.+fromType :: Type -> TypeCode+fromType tp = TypeCode $ case tp of+  TypeNone          -> #{const LUA_TNONE}+  TypeNil           -> #{const LUA_TNIL}+  TypeBoolean       -> #{const LUA_TBOOLEAN}+  TypeLightUserdata -> #{const LUA_TLIGHTUSERDATA}+  TypeNumber        -> #{const LUA_TNUMBER}+  TypeString        -> #{const LUA_TSTRING}+  TypeTable         -> #{const LUA_TTABLE}+  TypeFunction      -> #{const LUA_TFUNCTION}+  TypeUserdata      -> #{const LUA_TUSERDATA}+  TypeThread        -> #{const LUA_TTHREAD}++-- | Convert numerical code to lua type.+toType :: TypeCode -> Type+toType (TypeCode c) = case c of+  #{const LUA_TNONE}          -> TypeNone+  #{const LUA_TNIL}           -> TypeNil+  #{const LUA_TBOOLEAN}       -> TypeBoolean+  #{const LUA_TLIGHTUSERDATA} -> TypeLightUserdata+  #{const LUA_TNUMBER}        -> TypeNumber+  #{const LUA_TSTRING}        -> TypeString+  #{const LUA_TTABLE}         -> TypeTable+  #{const LUA_TFUNCTION}      -> TypeFunction+  #{const LUA_TUSERDATA}      -> TypeUserdata+  #{const LUA_TTHREAD}        -> TypeThread+  _ -> error ("No Type corresponding to " ++ show c)++--+-- * Relational Operator+--++-- | Lua comparison operations.+data RelationalOperator+  = EQ -- ^ Correponds to lua's equality (==) operator.+  | LT -- ^ Correponds to lua's strictly-lesser-than (<) operator+  | LE -- ^ Correponds to lua's lesser-or-equal (<=) operator+  deriving (Eq, Ord, Show)++-- | Convert relation operator to its C representation.+fromRelationalOperator :: RelationalOperator -> CInt+fromRelationalOperator EQ = #{const LUA_OPEQ}+fromRelationalOperator LT = #{const LUA_OPLT}+fromRelationalOperator LE = #{const LUA_OPLE}+{-# INLINABLE fromRelationalOperator #-}+++--+-- * Status+--++-- | Lua status values.+data Status+  = OK        -- ^ success+  | Yield     -- ^ yielding / suspended coroutine+  | ErrRun    -- ^ a runtime rror+  | ErrSyntax -- ^ syntax error during precompilation+  | ErrMem    -- ^ memory allocation (out-of-memory) error.+  | ErrErr    -- ^ error while running the message handler.+  | ErrGcmm   -- ^ error while running a @__gc@ metamethod.+  | ErrFile   -- ^ opening or reading a file failed.+  deriving (Eq, Show)++-- | Convert C integer constant to @'Status'@.+toStatus :: StatusCode -> Status+toStatus (StatusCode c) = case c of+  #{const LUA_OK}        -> OK+  #{const LUA_YIELD}     -> Yield+  #{const LUA_ERRRUN}    -> ErrRun+  #{const LUA_ERRSYNTAX} -> ErrSyntax+  #{const LUA_ERRMEM}    -> ErrMem+  #{const LUA_ERRGCMM}   -> ErrGcmm+  #{const LUA_ERRERR}    -> ErrErr+  #{const LUA_ERRFILE}   -> ErrFile+  n -> error $ "Cannot convert (" ++ show n ++ ") to Status"+{-# INLINABLE toStatus #-}++-- | Integer code used to signal the status of a thread or computation.+-- See @'Status'@.+newtype StatusCode = StatusCode CInt deriving (Eq, Storable)+++--+-- * Gargabe Collection Control+--++-- | Enumeration used by @gc@ function.+data GCCONTROL+  = GCSTOP+  | GCRESTART+  | GCCOLLECT+  | GCCOUNT+  | GCCOUNTB+  | GCSTEP+  | GCSETPAUSE+  | GCSETSTEPMUL+  deriving (Enum, Eq, Ord, Show)++-- | A stack index+newtype StackIndex = StackIndex { fromStackIndex :: CInt }+  deriving (Enum, Eq, Num, Ord, Show)++--+-- Number of arguments and return values+--++-- | The number of arguments consumed curing a function call.+newtype NumArgs = NumArgs { fromNumArgs :: CInt }+  deriving (Eq, Num, Ord, Show)++-- | The number of results returned by a function call.+newtype NumResults = NumResults { fromNumResults :: CInt }+  deriving (Eq, Num, Ord, Show)
+ src/Foreign/Lua/Raw/Userdata.hs view
@@ -0,0 +1,65 @@+{-# LANGUAGE CPP #-}+{-|+Module      : Foreign.Lua.Raw.Userdata+Copyright   : © 2017-2020 Albert Krewinkel+License     : MIT+Maintainer  : Albert Krewinkel <tarleb+hslua@zeitkraut.de>+Stability   : beta+Portability : ForeignFunctionInterface++Bindings to HsLua-specific functions used to push Haskell values+as userdata.+-}+module Foreign.Lua.Raw.Userdata+  ( hslua_fromuserdata+  , hslua_newhsuserdata+  , hslua_newudmetatable+  ) where++import Foreign.C (CInt (CInt), CString)+import Foreign.Lua.Raw.Auxiliary (luaL_testudata)+import Foreign.Lua.Raw.Functions (lua_newuserdata)+import Foreign.Lua.Raw.Types+  ( LuaBool (..)+  , StackIndex (..)+  , State (..)+  )+import Foreign.Ptr (castPtr, nullPtr)+import Foreign.StablePtr (newStablePtr, deRefStablePtr)+import Foreign.Storable (peek, poke, sizeOf)++#ifdef ALLOW_UNSAFE_GC+#define SAFTY unsafe+#else+#define SAFTY safe+#endif++-- | Creates and registers a new metatable for a userdata-wrapped+-- Haskell value; checks whether a metatable of that name has been+-- registered yet and uses the registered table if possible.+foreign import ccall SAFTY "hsludata.h hslua_newudmetatable"+  hslua_newudmetatable :: State       -- ^ Lua state+                       -> CString     -- ^ Userdata name (__name)+                       -> IO LuaBool  -- ^ True iff new metatable+                                      --   was created.++-- | Creates a new userdata wrapping the given Haskell object.+hslua_newhsuserdata :: State -> a -> IO ()+hslua_newhsuserdata l x = do+  xPtr <- newStablePtr x+  udPtr <- lua_newuserdata l (fromIntegral $ sizeOf xPtr)+  poke (castPtr udPtr) xPtr+{-# INLINABLE hslua_newhsuserdata #-}++-- | Retrieves a Haskell object from userdata at the given index.+-- The userdata /must/ have the given name.+hslua_fromuserdata :: State+                   -> StackIndex  -- ^ userdata index+                   -> CString     -- ^ name+                   -> IO (Maybe a)+hslua_fromuserdata l idx name = do+  udPtr <- luaL_testudata l idx name+  if udPtr == nullPtr+    then return Nothing+    else Just <$> (peek (castPtr udPtr) >>= deRefStablePtr)+{-# INLINABLE hslua_fromuserdata #-}
src/Foreign/Lua/Userdata.hs view
@@ -39,19 +39,20 @@   , metatableName   ) where --- import Control.Applicative (empty) import Control.Monad (when) import Data.Data (Data, dataTypeName, dataTypeOf)+import Foreign.C (withCString) import Foreign.Lua.Core (Lua)+import Foreign.Lua.Core.Types (liftLua, fromLuaBool)+import Foreign.Lua.Raw.Userdata+  ( hslua_fromuserdata+  , hslua_newhsuserdata+  , hslua_newudmetatable+  ) import Foreign.Lua.Types.Peekable (reportValueOnFailure)  import qualified Foreign.Lua.Core as Lua-import qualified Foreign.C as C-import qualified Foreign.Ptr as Ptr-import qualified Foreign.StablePtr as StablePtr-import qualified Foreign.Storable as Storable - -- | Push data by wrapping it into a userdata object. pushAny :: Data a         => a@@ -67,9 +68,7 @@                      -> a            -- ^ object to push to Lua.                      -> Lua () pushAnyWithMetatable mtOp x = do-  xPtr <- Lua.liftIO (StablePtr.newStablePtr x)-  udPtr <- Lua.newuserdata (Storable.sizeOf xPtr)-  Lua.liftIO $ Storable.poke (Ptr.castPtr udPtr) xPtr+  liftLua $ \l -> hslua_newhsuserdata l x   mtOp   Lua.setmetatable (Lua.nthFromTop 2)   return ()@@ -84,17 +83,10 @@                                       -- the stack.                         -> Lua () ensureUserdataMetatable name modMt = do-  mtCreated <- Lua.newmetatable name-  when mtCreated $ do-    -- Prevent accessing or changing the metatable with-    -- getmetatable/setmetatable.-    Lua.pushboolean True-    Lua.setfield (Lua.nthFromTop 2) "__metatable"-    -- Mark objects for finalization when collecting garbage.-    Lua.pushcfunction hslua_userdata_gc_ptr-    Lua.setfield (Lua.nthFromTop 2) "__gc"-    -- Execute additional modifications on metatable-    modMt+  mtCreated <- liftLua $ \l ->+    fromLuaBool <$> withCString name (hslua_newudmetatable l)+  -- Execute additional modifications on metatable+  when mtCreated modMt  -- | Retrieve data which has been pushed with @'pushAny'@. toAny :: Data a => Lua.StackIndex -> Lua (Maybe a)@@ -108,14 +100,8 @@ toAnyWithName :: Lua.StackIndex               -> String         -- ^ expected metatable name               -> Lua (Maybe a)-toAnyWithName idx name = do-  l <- Lua.state-  udPtr <- Lua.liftIO (C.withCString name (luaL_testudata l idx))-  if udPtr == Ptr.nullPtr-    then return Nothing-    else-      fmap Just . Lua.liftIO $-      Storable.peek (Ptr.castPtr udPtr) >>= StablePtr.deRefStablePtr+toAnyWithName idx name = liftLua $ \l ->+  withCString name (hslua_fromuserdata l idx)  -- | Retrieve Haskell data which was pushed to Lua as userdata. peekAny :: Data a => Lua.StackIndex -> Lua a@@ -128,14 +114,3 @@ -- the given type as userdata.  The argument is never evaluated. metatableName :: Data a => a -> String metatableName x = "HSLUA_" ++ dataTypeName (dataTypeOf x)---- | Function to free the stable pointer in a userdata, ensuring the Haskell--- value can be garbage collected. This function does not call back into--- Haskell, making is safe to call even from functions imported as unsafe.-foreign import ccall "&hslua_userdata_gc"-  hslua_userdata_gc_ptr :: Lua.CFunction---- | See--- <https://www.lua.org/manual/5.3/manual.html#luaL_testudata luaL_testudata>-foreign import ccall "luaL_testudata"-  luaL_testudata :: Lua.State -> Lua.StackIndex -> C.CString -> IO (Ptr.Ptr ())
+ test/Foreign/Lua/CallTests.hs view
@@ -0,0 +1,142 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-|+Module      : Foreign.Lua.CallTests+Copyright   : © 2020 Albert Krewinkel+License     : MIT+Maintainer  : Albert Krewinkel <tarleb+hslua@zeitkraut.de>+Stability   : alpha+Portability : OverloadedStrings, TypeApplications++Tests for calling exposed Haskell functions.+-}+module Foreign.Lua.CallTests (tests) where++import Foreign.Lua.Core (StackIndex)+import Foreign.Lua.Call+import Foreign.Lua.Peek (peekIntegral, peekText, force)+import Foreign.Lua.Push (pushIntegral)+import Test.HsLua.Util ((=:), shouldBeResultOf)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit ((@=?))++import qualified Data.Text as T+import qualified Foreign.Lua as Lua++-- | Calling Haskell functions from Lua.+tests :: TestTree+tests = testGroup "Call"+  [ testGroup "push Haskell function"+    [ "HaskellFunction building" =:+      720+      `shouldBeResultOf` do+        factLua <- factLuaAtIndex <$> Lua.gettop+        Lua.pushinteger 6+        _ <- callFunction factLua+        peekIntegral @Integer Lua.stackTop >>= force++    , "error message" =:+      mconcat [ "retrieving function argument n"+              , "\n\texpected Integral, got 'true' (boolean)"]+      `shouldBeResultOf` do+        factLua <- factLuaAtIndex <$> Lua.gettop+        Lua.pushboolean True+        _ <- callFunction factLua+        peekText Lua.stackTop >>= force+    ]+  , testGroup "use as C function"+    [ "push factorial" =:+      Lua.TypeFunction+      `shouldBeResultOf` do+        pushHaskellFunction $ factLuaAtIndex 0+        Lua.ltype Lua.stackTop+    , "call factorial" =:+      120+      `shouldBeResultOf` do+        pushHaskellFunction $ factLuaAtIndex 0+        Lua.pushinteger 5+        Lua.call 1 1+        peekIntegral @Integer Lua.stackTop >>= force+    , "use from Lua" =:+      24+      `shouldBeResultOf` do+        pushHaskellFunction $ factLuaAtIndex 0+        Lua.setglobal "factorial"+        Lua.loadstring "return factorial(4)" *> Lua.call 0 1+        peekIntegral @Integer Lua.stackTop >>= force+    ]+  , testGroup "documentation"+    [ "rendered docs" =:+      (T.unlines+       [ "Parameters:"+       , ""+       , "n"+       , ":   number for which the factorial is computed (integer)"+       , ""+       , "Returns:"+       , ""+       , " - factorial (integer)"+       ]+       @=?+       maybe "" render (functionDoc (factLuaAtIndex 0)))+    ]++  , testGroup "helpers"+    [ "parameter doc" =:+      ( ParameterDoc+        { parameterName = "test"+        , parameterDescription = "test param"+        , parameterType = "string"+        , parameterIsOptional = False+        }+        @=?+        parameterDoc (parameter peekText "string" "test" "test param")+      )+    , "optionalParameter doc" =:+      ( ParameterDoc+        { parameterName = "test"+        , parameterDescription = "test param"+        , parameterType = "string"+        , parameterIsOptional = True+        }+        @=?+        parameterDoc (optionalParameter peekText "string" "test" "test param")+      )+    , "functionResult doc" =:+      ( FunctionResultDoc+        { functionResultDescription = "int result"+        , functionResultType = "integer"+        }+        @=?+        (fnResultDoc . head $+         functionResult (pushIntegral @Int) "integer" "int result")+      )+    ]+  ]++factLuaAtIndex :: StackIndex -> HaskellFunction+factLuaAtIndex idx =+  toHsFnPrecursorWithStartIndex idx factorial+  <#> factorialParam+  =#> factorialResult++-- | Calculate the factorial of a number.+factorial :: Integer -> Integer+factorial n = product [1..n]++factorialParam :: Parameter Integer+factorialParam = Parameter+  { parameterDoc = ParameterDoc+    { parameterName = "n"+    , parameterType = "integer"+    , parameterDescription = "number for which the factorial is computed"+    , parameterIsOptional = False+    }+  , parameterPeeker = peekIntegral @Integer+  }++factorialResult :: FunctionResults Integer+factorialResult = (:[]) $ FunctionResult+  (pushIntegral @Integer)+  (FunctionResultDoc "integer" "factorial")
test/Foreign/Lua/ModuleTests.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeApplications #-} {-| Module      : Foreign.Lua.ModuleTests Copyright   : © 2019-2020 Albert Krewinkel@@ -12,10 +13,15 @@ module Foreign.Lua.ModuleTests (tests) where  import Foreign.Lua (Lua)-import Foreign.Lua.Module (addfield, addfunction, create, preloadhs, requirehs)+import Foreign.Lua.Call hiding (render)+import Foreign.Lua.Module+import Foreign.Lua.Peek (peekIntegral)+import Foreign.Lua.Push (pushIntegral) import Test.HsLua.Util ((=:), pushLuaExpr, shouldBeResultOf) import Test.Tasty (TestTree, testGroup)+import Test.Tasty.HUnit ((@=?)) +import qualified Data.Text as T import qualified Foreign.Lua as Lua  -- | Specifications for Attributes parsing functions.@@ -79,4 +85,68 @@         Lua.call 1 1         Lua.peek Lua.stackTop     ]+  , testGroup "module type"+    [ "register module" =:+      1 `shouldBeResultOf` do+        Lua.openlibs+        old <- Lua.gettop+        registerModule mymath+        new <- Lua.gettop+        return (new - old)++    , "call module function" =:+      Right 24 `shouldBeResultOf` do+        Lua.openlibs+        registerModule mymath+        _ <- Lua.dostring $ mconcat+             [ "local mymath = require 'mymath'\n"+             , "return mymath.factorial(4)"+             ]+        peekIntegral @Integer Lua.stackTop+    ]+  , testGroup "documentation"+    [ "module docs" =:+      (T.intercalate "\n"+        [ "# mymath"+        , ""+        , "A math module."+        , ""+        , "## Functions"+        , ""+        , "### factorial (n)"+        , ""+        , "Parameters:"+        , ""+        , "n"+        , ":   number for which the factorial is computed (integer)"+        , ""+        , "Returns:"+        , ""+        , " - factorial (integer)\n"+        ] @=?+        render mymath)+    ]   ]++mymath :: Module+mymath = Module+  { moduleName = "mymath"+  , moduleDescription = "A math module."+  , moduleFields = []+  , moduleFunctions = [ ("factorial", factorial)]+  }++factorial :: HaskellFunction+factorial = toHsFnPrecursor (\n -> product [1..n])+  <#> factorialParam+  =#> factorialResult++factorialParam :: Parameter Integer+factorialParam =+  parameter (peekIntegral @Integer) "integer"+    "n"+    "number for which the factorial is computed"++factorialResult :: FunctionResults Integer+factorialResult =+  functionResult (pushIntegral @Integer) "integer" "factorial"
test/Foreign/Lua/PeekTests.hs view
@@ -270,4 +270,15 @@           peekMap (peekIntegral @Int) peekText Lua.stackTop       ]     ]++  , testGroup "combinators"+    [ "optional with nil" =:+      Right Nothing `shouldBeResultOf` do+        Lua.pushnil+        optional peekString Lua.top+    , "optional with number" =:+      Right (Just 23) `shouldBeResultOf` do+        Lua.pushinteger 23+        optional (peekIntegral @Int) Lua.top+    ]   ]
test/Foreign/Lua/PushTests.hs view
@@ -142,7 +142,7 @@           tableSize <- run $ Lua.run $ do             pushList pushString list             Lua.rawlen Lua.stackTop-          assert $ fromIntegral tableSize == length list+          assert $ tableSize == length list        , testSingleElementProperty (pushList pushText)       ]
test/test-hslua.hs view
@@ -22,6 +22,7 @@ import Test.Tasty (TestTree, defaultMain, testGroup)  import qualified Foreign.LuaTests+import qualified Foreign.Lua.CallTests import qualified Foreign.Lua.CoreTests import qualified Foreign.Lua.FunctionCallingTests import qualified Foreign.Lua.ModuleTests@@ -50,6 +51,7 @@     ]   , Foreign.Lua.UserdataTests.tests   , Foreign.Lua.ModuleTests.tests+  , Foreign.Lua.CallTests.tests   , Foreign.LuaTests.tests   , Foreign.Lua.PeekTests.tests   ]