content: {-# LANGUAGE CPP #-}
  {-|
  Module      : Lua.Primary
  Copyright   : © 2007–2012 Gracjan Polak;
                © 2012–2016 Ömer Sinan Ağacan;
                © 2017-2024 Albert Krewinkel
  License     : MIT
  Maintainer  : Albert Krewinkel <tarleb@hslua.org>
  Stability   : beta
  Portability : ForeignFunctionInterface, CPP
  
  Haskell bindings to Lua C API functions.
  
  The exposed functions correspond closely to the respective C Lua API
  functions. However, C API functions which can throw Lua errors are not
  exported directly, as any errors would crash the program. Non-error
  throwing @hslua_@ versions are provided instead. The @hslua@ ersatz
  functions have worse performance than the original.
  
  Some of the Lua functions may, directly or indirectly, call a Haskell
  function, and trigger garbage collection, rescheduling etc. These
  functions are always imported safely (i.e., with the @safe@ keyword).
  
  However, all function can trigger garbage collection. If that can lead
  to problems, then the package should be configured without flag
  @allow-unsafe-gc@.
  -}
  module Lua.Primary
    ( lua_absindex
    , lua_arith
    , lua_checkstack
    , lua_close
    , lua_close_ptr
    , lua_concat
    , lua_copy
    , lua_createtable
    , lua_gc
    , lua_getglobal
    , lua_getmetatable
    , lua_gettable
    , lua_gettop
    , lua_getiuservalue
    , lua_insert
    , lua_isboolean
    , lua_iscfunction
    , lua_isfunction
    , lua_isinteger
    , lua_islightuserdata
    , lua_isnil
    , lua_isnone
    , lua_isnoneornil
    , lua_isnumber
    , lua_isstring
    , lua_istable
    , lua_isthread
    , lua_isuserdata
    , lua_load
    , lua_newthread
    , lua_newuserdatauv
    , lua_next
    , lua_pcall
    , lua_pop
    , lua_pushboolean
    , lua_pushcclosure
    , lua_pushcfunction
    , lua_pushglobaltable
    , lua_pushinteger
    , lua_pushlightuserdata
    , lua_pushlstring
    , lua_pushnil
    , lua_pushnumber
    , lua_pushstring
    , lua_pushthread
    , lua_pushvalue
    , lua_rawequal
    , lua_rawget
    , lua_rawgeti
    , lua_rawlen
    , lua_rawset
    , lua_rawseti
    , lua_remove
    , lua_replace
    , lua_rotate
    , lua_setglobal
    , lua_setmetatable
    , lua_settable
    , lua_settop
    , lua_setiuservalue
    , lua_setwarnf
    , lua_status
    , lua_stringtonumber
    , lua_toboolean
    , lua_tocfunction
    , lua_tointegerx
    , lua_tolstring
    , lua_tonumberx
    , lua_topointer
    , lua_tothread
    , lua_touserdata
    , lua_type
    , lua_typename
    , lua_version
    , lua_warning
    , module Lua.Ersatz.Functions
    , module Lua.Ersatz.Auxiliary
    )
  where
  
  import Foreign.C
  import Lua.Ersatz.Auxiliary
  import Lua.Ersatz.Functions
  import Lua.Types as Lua
  import Foreign.Ptr
  
  #ifdef ALLOW_UNSAFE_GC
  #define SAFTY unsafe
  #else
  #define SAFTY safe
  #endif
  
  -- | Converts the acceptable index @idx@ into an equivalent absolute
  -- index (that is, one that does not depend on the stack top).
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_absindex>
  foreign import capi unsafe "lua.h lua_absindex"
    lua_absindex :: Lua.State
                 -> StackIndex     -- ^ idx
                 -> IO StackIndex
  
  -- | Performs an arithmetic or bitwise operation over the two values (or
  -- one, in the case of negations) at the top of the stack, with the
  -- value at the top being the second operand, pops these values, and
  -- pushes the result of the operation. The function follows the
  -- semantics of the corresponding Lua operator (that is, it may call
  -- metamethods).
  --
  -- The value of @op@ must be one of the following constants:
  --
  -- -   __@LUA_OPADD@:__ performs addition (@+@)
  -- -   __@LUA_OPSUB@:__ performs subtraction (@-@)
  -- -   __@LUA_OPMUL@:__ performs multiplication (@*@)
  -- -   __@LUA_OPDIV@:__ performs float division (@\/@)
  -- -   __@LUA_OPIDIV@:__ performs floor division (@\/\/@)
  -- -   __@LUA_OPMOD@:__ performs modulo (@%@)
  -- -   __@LUA_OPPOW@:__ performs exponentiation (@^@)
  -- -   __@LUA_OPUNM@:__ performs mathematical negation (unary @-@)
  -- -   __@LUA_OPBNOT@:__ performs bitwise NOT (@~@)
  -- -   __@LUA_OPBAND@:__ performs bitwise AND (@&@)
  -- -   __@LUA_OPBOR@:__ performs bitwise OR (@|@)
  -- -   __@LUA_OPBXOR@:__ performs bitwise exclusive OR (@~@)
  -- -   __@LUA_OPSHL@:__ performs left shift (@\<\<@)
  -- -   __@LUA_OPSHR@:__ performs right shift (@>>@)
  --
  -- __WARNING__: @lua_arith@ is unsafe in Haskell: if the call to a
  -- metamethod triggers an error, then that error cannot be handled and
  -- will lead to an unrecoverable program crash. Consider using the
  -- @'Lua.hslua_arith'@ ersatz function instead. Likewise, the metamethod
  -- may not call a Haskell function unless the library was compiled
  -- without @allow-unsafe-gc@.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_arith>.
  foreign import capi SAFTY "lua.h lua_arith"
    lua_arith :: State -> ArithOPCode {- ^ op -} -> IO ()
  {-# WARNING lua_arith
        [ "This is an unsafe function, errors will lead to a program crash;"
        , "consider using hslua_arith instead."
        ] #-}
  
  -- | Ensures that the stack has space for at least @n@ extra slots (that
  -- is, that you can safely push up to @n@ values into it). It returns
  -- false if it cannot fulfill the request, either because it would cause
  -- the stack to be larger than a fixed maximum size (typically at least
  -- several thousand elements) or because it cannot allocate memory for
  -- the extra space. This function never shrinks the stack; if the stack
  -- already has space for the extra slots, it is left unchanged.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_checkstack>
  foreign import capi unsafe "lua.h lua_checkstack"
    lua_checkstack :: Lua.State -> CInt {- ^ n -} -> IO LuaBool
  
  -- | Destroys all objects in the given Lua state (calling the
  -- corresponding garbage-collection metamethods, if any) and frees all
  -- dynamic memory used by this state. In several platforms, you may not
  -- need to call this function, because all resources are naturally
  -- released when the host program ends. On the other hand, long-running
  -- programs that create multiple states, such as daemons or web servers,
  -- will probably need to close states as soon as they are not needed.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_close>
  foreign import capi safe "lua.h lua_close"
    lua_close :: Lua.State -> IO ()
  
  -- | Function pointer to function 'lua_close'; intended to be used with
  -- 'Foreign.ForeignPtr.newForeignPtr'.
  foreign import ccall safe "lua.h &lua_close"
    lua_close_ptr :: FunPtr (Ptr () -> IO ())
  
  -- | 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 stack (that is, the function does nothing); if @n@ is 0,
  -- the result is the empty string. Concatenation is performed following
  -- the usual semantics of Lua (see
  -- <https://www.lua.org/manual/5.4/manual.html#3.4.6 §3.4.6> of the Lua
  -- manual).
  --
  -- __WARNING__: @lua_concat@ is unsafe in Haskell: This function will
  -- cause an unrecoverable crash an error if any of the concatenated
  -- values causes an error when executing a metamethod. Consider using
  -- the @'Lua.hslua_concat'@ ersatz function instead.
  foreign import capi SAFTY "lua.h lua_concat"
    lua_concat :: State -> CInt {- ^ n -} -> IO ()
  {-# WARNING lua_concat
        [ "This is an unsafe function, it will cause a program crash if"
        , "a metamethod throws an error."
        , "Consider using hslua_concat instead."
        ] #-}
  
  -- | Copies the element at index @fromidx@ into the valid index @toidx@,
  -- replacing the value at that position. Values at other positions are
  -- not affected.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_copy>
  foreign import capi unsafe "lua.h lua_copy"
    lua_copy :: Lua.State
             -> StackIndex  -- ^ fromidx
             -> StackIndex  -- ^ toidx
             -> IO ()
  
  -- | Creates a new empty table and pushes it onto the stack. Parameter
  -- @narr@ is a hint for how many elements the table will have as a
  -- sequence; parameter @nrec@ is a hint for how many other elements the
  -- table will have. Lua may use these hints to preallocate memory for
  -- the new table. This preallocation is useful for performance when you
  -- know in advance how many elements the table will have. Otherwise you
  -- can use the function @lua_newtable@.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_createtable>.
  foreign import capi SAFTY "lua.h lua_createtable"
    lua_createtable :: Lua.State
                    -> CInt -- ^ narr
                    -> CInt -- ^ nrec
                    -> IO ()
  
  -- | Controls the garbage collector.
  --
  -- See the Lua docs at
  -- <https://www.lua.org/manual/5.4/manual.html#lua_gc>.
  -- Unused dataN values should be set to 0, but can be anything.
  foreign import capi safe "lua.h lua_gc"
    lua_gc :: Lua.State
           -> GCCode    -- ^ what
           -> CInt      -- ^ data1
           -> CInt      -- ^ data2
           -> CInt      -- ^ data3
           -> IO CInt
  
  -- | Pushes onto the stack the value of the global name. Returns the
  -- type of that value.
  --
  -- __WARNING__: @lua_getglobal@ is unsafe in Haskell: if the call to a
  -- metamethod triggers an error, then that error cannot be handled and
  -- will lead to an unrecoverable program crash. Consider using the
  -- @'Lua.hslua_getglobal'@ ersatz function instead. Likewise, the
  -- metamethod may not call a Haskell function unless the library was
  -- compiled without @allow-unsafe-gc@.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_getglobal>.
  foreign import capi SAFTY "lua.h lua_getglobal"
    lua_getglobal :: State -> CString {- ^ name -} -> IO TypeCode
  {-# WARNING lua_getglobal
        [ "This is an unsafe function, errors will lead to a program crash;"
        , "consider using hslua_getglobal instead."
        ] #-}
  
  -- | If the value at the given index has a metatable, the function
  -- pushes that metatable onto the stack and returns @1@. Otherwise, the
  -- function returns @0@ and pushes nothing on the stack.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_getmetatable>.
  foreign import capi unsafe "lua.h lua_getmetatable"
    lua_getmetatable :: Lua.State -> StackIndex -> IO LuaBool
  
  -- | Pushes onto the stack the value @t[k]@, where @t@ is the value at
  -- the given index and @k@ is the value at the top of the stack.
  --
  -- This function pops the key from the stack, pushing the resulting
  -- value in its place. As in Lua, this function may trigger a metamethod
  -- for the \"index\" event (see
  -- <https://www.lua.org/manual/5.4/manual.html#2.4 §2.4>).
  --
  -- Returns the type of the pushed value.
  --
  -- __WARNING__: @lua_gettable@ is unsafe in Haskell: if the call to a
  -- metamethod triggers an error, then that error cannot be handled and
  -- will lead to an unrecoverable program crash. Consider using the
  -- @'Lua.hslua_gettable'@ ersatz function instead. Likewise, the
  -- metamethod may not call a Haskell function unless the library was
  -- compiled without @allow-unsafe-gc@.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_gettable>.
  foreign import capi SAFTY "lua.h lua_gettable"
    lua_gettable :: Lua.State -> StackIndex {- ^ index -} -> IO TypeCode
  {-# WARNING lua_gettable
        [ "This is an unsafe function, errors will lead to a program crash;"
        , "consider using hslua_gettable instead."
        ] #-}
  
  -- | 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 means an empty stack).
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_gettop>
  foreign import capi unsafe "lua.h lua_gettop"
    lua_gettop :: Lua.State -> IO StackIndex
  
  -- | Pushes onto the stack the @n@-th user value associated with the
  -- full userdata at the given index and returns the type of the pushed
  -- value.
  --
  -- If the userdata does not have that value, pushes __nil__ and returns
  -- 'LUA_TNONE'.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_getiuservalue>
  foreign import capi unsafe "lua.h lua_getiuservalue"
    lua_getiuservalue :: Lua.State
                      -> StackIndex   -- ^ index
                      -> CInt         -- ^ n
                      -> IO TypeCode
  
  -- | Moves the top element into the given valid index, shifting up the
  -- elements above this index to open space. This function cannot be
  -- called with a pseudo-index, because a pseudo-index is not an actual
  -- stack position.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_insert>
  foreign import capi unsafe "lua.h lua_insert"
    lua_insert :: Lua.State -> StackIndex -> IO ()
  
  -- | Returns @'Lua.TRUE'@ if the value at the given index is a
  -- boolean, and @'Lua.FALSE'@ otherwise.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_isboolean>
  foreign import capi unsafe "lua.h lua_isboolean"
    lua_isboolean :: Lua.State -> StackIndex -> IO LuaBool
  
  -- | Returns @'Lua.TRUE'@ if the value at the given index is a C
  -- function, and @'Lua.FALSE'@ otherwise.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_iscfunction>
  foreign import capi unsafe "lua.h lua_iscfunction"
    lua_iscfunction :: Lua.State -> StackIndex -> IO LuaBool
  
  -- | Returns @'Lua.TRUE'@ if the value at the given index is a
  -- function (either C or Lua), and @'Lua.FALSE'@ otherwise.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_isfunction>
  foreign import capi unsafe "lua.h lua_isfunction"
    lua_isfunction :: Lua.State -> StackIndex -> IO LuaBool
  
  -- | Returns @'Lua.TRUE'@ if the value at the given index is an
  -- integer (that is, the value is a number and is represented as an
  -- integer), and @'Lua.FALSE'@ otherwise.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_isinteger>
  foreign import capi unsafe "lua.h lua_isinteger"
    lua_isinteger :: Lua.State -> StackIndex -> IO LuaBool
  
  -- | Returns @'Lua.TRUE'@ if the value at the given index is a
  -- light userdata, and @'Lua.FALSE'@ otherwise.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_islightuserdata>
  foreign import capi unsafe "lua.h lua_islightuserdata"
    lua_islightuserdata :: Lua.State -> StackIndex -> IO LuaBool
  
  -- | Returns @'Lua.TRUE'@ if the value at the given index is
  -- __nil__, and @'Lua.FALSE'@ otherwise.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_isnil>
  foreign import capi unsafe "lua.h lua_isnil"
    lua_isnil :: Lua.State -> StackIndex -> IO LuaBool
  
  -- | Returns @'Lua.TRUE'@ if the given index is not valid, and
  -- @'Lua.FALSE'@ otherwise.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_isnone>
  foreign import capi unsafe "lua.h lua_isnone"
    lua_isnone :: Lua.State -> StackIndex -> IO LuaBool
  
  -- | Returns @'Lua.TRUE'@ if the given index is not valid or if
  -- the value at the given index is __nil__, and @'Lua.FALSE'@
  -- otherwise.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_isnoneornil>
  foreign import capi unsafe "lua.h lua_isnoneornil"
    lua_isnoneornil :: Lua.State -> StackIndex -> IO LuaBool
  
  -- | Returns @'Lua.TRUE'@ if the value at the given index is a
  -- number or a string convertible to a number, and @'Lua.FALSE'@
  -- otherwise.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_isnumber>
  foreign import capi unsafe "lua.h lua_isnumber"
    lua_isnumber :: Lua.State -> StackIndex -> IO LuaBool
  
  -- | Returns @'Lua.TRUE'@ if the value at the given index is a
  -- string or a number (which is always convertible to a string), and
  -- @'Lua.FALSE'@ otherwise.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_isstring>
  foreign import capi unsafe "lua.h lua_isstring"
    lua_isstring :: Lua.State -> StackIndex -> IO LuaBool
  
  -- | Returns @'Lua.TRUE'@ if the value at the given index is a
  -- table, and @'Lua.FALSE'@ otherwise.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_istable>
  foreign import capi unsafe "lua.h lua_istable"
    lua_istable :: Lua.State -> StackIndex -> IO LuaBool
  
  -- | Returns @'Lua.TRUE'@ if the value at the given index is a
  -- thread, and @'Lua.FALSE'@ otherwise.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_isthread>
  foreign import capi unsafe "lua.h lua_isthread"
    lua_isthread :: Lua.State -> StackIndex -> IO LuaBool
  
  -- | Returns @'Lua.TRUE'@ if the value at the given index is a
  -- userdata (either full or light), and @'Lua.FALSE'@ otherwise.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_isuserdata>
  foreign import capi unsafe "lua.h lua_isuserdata"
    lua_isuserdata :: Lua.State -> StackIndex -> IO LuaBool
  
  -- | Loads a Lua chunk (without running it). If there are no errors,
  -- @lua_load@ pushes the compiled chunk as a Lua function on top of the
  -- stack. Otherwise, it pushes an error message.
  --
  -- The return values of @lua_load@ are:
  --
  -- - @'Lua.LUA_OK'@: no errors;
  -- - @'Lua.LUA_ERRSYNTAX'@: syntax error during pre-compilation;
  -- - @'Lua.LUA_ERRMEM'@: memory allocation error;
  -- - @'Lua.LUA_ERRGCMM'@: error while running a @__gc@
  --   metamethod. (This error has no relation with the chunk being
  --   loaded. It is generated by the garbage collector.)
  --
  -- This function only loads a chunk; it does not run it.
  --
  -- @lua_load@ automatically detects whether the chunk is text or binary,
  -- and loads it accordingly (see program luac).
  --
  -- The @lua_load@ function uses a user-supplied reader function to
  -- read the chunk (see @'Lua.Reader'@). The data argument is an opaque
  -- value passed to the reader function.
  --
  -- The @chunkname@ argument gives a name to the chunk, which is used for
  -- error messages and in debug information (see
  -- <https://www.lua.org/manual/5.4/manual.html#4.7 §4.7>).
  --
  -- @lua_load@ automatically detects whether the chunk is text or binary
  -- and loads it accordingly (see program @luac@). The string mode works
  -- as in function @load@, with the addition that a @NULL@ value is
  -- equivalent to the string "bt".
  --
  -- @lua_load@ uses the stack internally, so the reader function must
  -- always leave the stack unmodified when returning.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_load>.
  foreign import capi safe "lua.h lua_load"
    lua_load :: Lua.State
             -> Lua.Reader     -- ^ reader
             -> Ptr ()         -- ^ data
             -> CString        -- ^ chunkname
             -> CString        -- ^ mode
             -> IO StatusCode
  
  -- | Creates a new thread, pushes it on the stack, and returns a
  -- 'Lua.State' that represents this new thread. The new thread returned
  -- by this function shares with the original thread its global
  -- environment, but has an independent execution stack.
  --
  -- There is no explicit function to close or to destroy a thread.
  -- Threads are subject to garbage collection, like any Lua object.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_newthread>
  foreign import capi SAFTY "lua.h lua_newthread"
    lua_newthread :: Lua.State -> IO Lua.State
  
  -- | This function creates and pushes on the stack a new full userdata,
  -- with @nuvalue@ associated Lua values, called @user values@, plus an
  -- associated block of raw memory with @size@ bytes. (The user values
  -- can be set and read with the functions 'lua_setiuservalue' and
  -- 'lua_getiuservalue'.)
  --
  -- The function returns the address of the block of memory. Lua ensures
  -- that this address is valid as long as the corresponding userdata is
  -- alive (see <https://www.lua.org/manual/5.4/manual.html#2.5 §2.5>).
  -- Moreover, if the userdata is marked for finalization (see
  -- <https://www.lua.org/manual/5.4/manual.html#2.5.3 §2.5.3>), its
  -- address is valid at least until the call to its finalizer.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_newuserdatauv>.
  foreign import capi SAFTY "lua.h lua_newuserdatauv"
    lua_newuserdatauv :: Lua.State
                      -> CSize       -- ^ size
                      -> CInt        -- ^ nuvalue
                      -> IO (Ptr ())
  
  -- | Pops a key from the stack, and pushes a key–value pair from the
  -- table at the given index (the \"next\" pair after the given key). If
  -- there are no more elements in the table, then
  -- <https://www.lua.org/manual/5.4/manual.html#lua_next lua_next>
  -- returns 'Lua.FALSE' (and pushes nothing).
  --
  -- A typical traversal looks like this:
  --
  -- > -- table is in the stack at index 't'
  -- > lua_pushnil l    -- first key
  -- > let loop = lua_next l t >>= \case
  -- >       FALSE -> return ()
  -- >       _ -> do
  -- >         lua_type l (-2) >>= lua_typename l >>= peekCString >>= putStrLn
  -- >         lua_type l (-1) >>= lua_typename l >>= peekCString >>= putStrLn
  -- >         -- removes 'value'; keeps 'key' for next iteration
  -- >         lua_pop l 1
  -- >         loop
  -- > loop
  --
  -- While traversing a table, do not call 'lua_tolstring' directly on a
  -- key, unless you know that the key is actually a string. Recall that
  -- 'lua_tolstring' may change the value at the given index; this
  -- confuses the next call to
  -- <https://www.lua.org/manual/5.4/manual.html#lua_next lua_next>.
  --
  -- See function
  -- <https://www.lua.org/manual/5.4/manual.html#pdf-next next> for the
  -- caveats of modifying the table during its traversal.
  --
  -- __WARNING__: @lua_next@ is unsafe in Haskell: This function will
  -- cause an unrecoverable crash an error if the given key is neither
  -- @nil@ nor present in the table. Consider using the @'Lua.hslua_next'@
  -- ersatz function instead.
  foreign import capi SAFTY "lua.h lua_next"
    lua_next :: State -> StackIndex {- ^ index -} -> IO LuaBool
  {-# WARNING lua_next
        [ "This is an unsafe function, it will cause a program crash if"
        , "the given key is neither nil nor present in the table."
        , "Consider using hslua_next instead."
        ] #-}
  
  -- | Calls a function in protected mode.
  --
  -- To call a function you must use the following protocol: first, the
  -- function to be called is pushed onto the stack; then, the arguments
  -- to the function are pushed in direct order; that is, the first
  -- argument is pushed first. Finally you call @lua_pcall@; @nargs@ is
  -- the number of arguments that you pushed onto the stack. All arguments
  -- and the function value are popped from the stack when the function is
  -- called. The function results are pushed onto the stack when the
  -- function returns. The number of results is adjusted to @nresults@,
  -- unless @nresults@ is @'Lua.LUA_MULTRET'@. In this case, all
  -- results from the function are pushed. Lua takes care that the
  -- returned values fit into the stack space. The function results are
  -- pushed onto the stack in direct order (the first result is pushed
  -- first), so that after the call the last result is on the top of the
  -- stack.
  --
  -- If there is any error, @lua_pcall@ catches it, pushes a single value
  -- on the stack (the error message), and returns the error code.
  -- @lua_pcall@ always removes the function and its arguments from the
  -- stack.
  --
  -- If @msgh@ is @0@, then the error object returned on the stack is
  -- exactly the original error object. Otherwise, @msgh@ is the location
  -- of a message handler. (This index cannot be a pseudo-index.) In case
  -- of runtime errors, this function will be called with the error object
  -- and its return value will be the object returned on the stack by
  -- @'lua_pcall'@.
  --
  -- Typically, the message handler is used to add more debug information
  -- to the error object, such as a stack traceback. Such information
  -- cannot be gathered after the return of @'lua_pcall'@, since by then
  -- the stack has unwound.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_pcall>.
  foreign import capi safe "lua.h lua_pcall"
    lua_pcall :: Lua.State
              -> NumArgs        -- ^ nargs
              -> NumResults     -- ^ nresults
              -> StackIndex     -- ^ msgh
              -> IO StatusCode
  
  -- | Pops @n@ elements from the stack.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_pop>
  foreign import capi unsafe "lua.h lua_pop"
    lua_pop :: Lua.State -> CInt {- ^ n -} -> IO ()
  
  -- | Pushes a boolean value with the given value onto the stack.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_pushboolean>.
  foreign import capi unsafe "lua.h lua_pushboolean"
    lua_pushboolean :: Lua.State -> LuaBool -> IO ()
  
  -- | Pushes a new C closure onto the stack.
  --
  -- When a C function is created, it is possible to associate some values
  -- with it, thus creating a C closure (see
  -- <https://www.lua.org/manual/5.1/manual.html#3.4 §3.4>); these values
  -- are then accessible to the function whenever it is called. To
  -- associate values with a C function, first these values should be
  -- pushed onto the stack (when there are multiple values, the first
  -- value is pushed first). Then lua_pushcclosure is called to create and
  -- push the C function onto the stack, with the argument @n@ telling how
  -- many values should be associated with the function. lua_pushcclosure
  -- also pops these values from the stack.
  --
  -- The maximum value for @n@ is 255.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_pushcclosure>.
  foreign import capi SAFTY "lua.h lua_pushcclosure"
    lua_pushcclosure :: Lua.State
                     -> CFunction   -- ^ fn
                     -> NumArgs     -- ^ n
                     -> IO ()
  
  -- | Pushes a C function onto the stack. This function receives a
  -- pointer to a C function and pushes onto the stack a Lua value of type
  -- @function@ that, when called, invokes the corresponding C function.
  --
  -- Any function to be callable by Lua must follow the correct protocol
  -- to receive its parameters and return its results (see 'CFunction').
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_pushcfunction>.
  foreign import capi unsafe "lua.h lua_pushcfunction"
    lua_pushcfunction :: Lua.State
                      -> CFunction   -- ^ fn
                      -> IO ()
  
  -- | Pushes the global environment onto the stack.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_pushglobaltable>
  foreign import capi unsafe "lua.h lua_pushglobaltable"
    lua_pushglobaltable :: Lua.State -> IO ()
  
  -- | Pushes an integer with with the given value onto the stack.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_pushinteger>.
  foreign import capi unsafe "lua.h lua_pushinteger"
    lua_pushinteger :: Lua.State -> Lua.Integer -> IO ()
  
  -- | Pushes a light userdata onto the stack.
  --
  -- Userdata represent C values in Lua. A light userdata represents a
  -- pointer, a @Ptr ()@ (i.e., @void*@ in C lingo). It is a value (like a
  -- number): you do not create it, it has no individual metatable, and it
  -- is not collected (as it was never created). A light userdata is equal
  -- to "any" light userdata with the same C address.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_pushlightuserdata>.
  foreign import capi unsafe "lua.h lua_pushlightuserdata"
    lua_pushlightuserdata :: Lua.State -> Ptr a -> IO ()
  
  -- | Pushes the string pointed to by @s@ with size @len@ onto the stack.
  -- Lua makes (or reuses) an internal copy of the given string, so the
  -- memory at s can be freed or reused immediately after the function
  -- returns. The string can contain any binary data, including embedded
  -- zeros.
  --
  -- Returns a pointer to the internal copy of the string.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_pushlstring>.
  foreign import capi SAFTY "lua.h lua_pushlstring"
    lua_pushlstring :: Lua.State
                    -> Ptr CChar    -- ^ s
                    -> CSize        -- ^ len
                    -> IO ()
  
  -- | Pushes a nil value onto the stack.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_pushnil>.
  foreign import capi unsafe "lua.h lua_pushnil"
    lua_pushnil :: Lua.State -> IO ()
  
  -- | Pushes a float with the given value onto the stack.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_pushnumber>.
  foreign import capi unsafe "lua.h lua_pushnumber"
    lua_pushnumber :: Lua.State -> Lua.Number -> IO ()
  
  
  -- | Pushes the zero-terminated string pointed to by @s@ onto the stack.
  -- Lua makes (or reuses) an internal copy of the given string, so the
  -- memory at @s@ can be freed or reused immediately after the function
  -- returns.
  --
  -- Returns a pointer to the internal copy of the string.
  --
  -- If s is NULL, pushes nil and returns NULL.
  foreign import ccall unsafe "lua.h lua_pushstring"
    lua_pushstring :: Lua.State -> CString {- ^ s -} -> IO CString
  
  
  -- | Pushes the current thread onto the stack. Returns @1@ iff this
  -- thread is the main thread of its state.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_pushthread>.
  foreign import capi unsafe "lua.h lua_pushthread"
    lua_pushthread :: Lua.State -> IO CInt
  
  -- | Pushes a copy of the element at the given index onto the stack.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_pushvalue>
  foreign import capi unsafe "lua.h lua_pushvalue"
    lua_pushvalue :: Lua.State -> StackIndex -> IO ()
  
  -- | Returns @True@ if the two values in indices @idx1@ and @idx2@ are
  -- primitively equal (that is, without calling the @__eq@ metamethod).
  -- Otherwise returns @False@. Also returns @False@ if any of the indices
  -- are not valid.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_rawequal>
  foreign import capi unsafe "lua.h lua_rawequal"
    lua_rawequal :: Lua.State
                 -> StackIndex  -- ^ idx1
                 -> StackIndex  -- ^ idx2
                 -> IO LuaBool
  
  -- | Similar to @'lua_gettable'@, but does a raw access (i.e., without
  -- metamethods).
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_rawget>.
  foreign import capi unsafe "lua.h lua_rawget"
    lua_rawget :: Lua.State -> StackIndex -> IO TypeCode
  
  -- | Pushes onto the stack the value @t[n]@, where @t@ is the table at
  -- the given index. The access is raw, that is, it does not invoke the
  -- @__index@ metamethod.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_rawgeti>.
  foreign import capi unsafe "lua.h lua_rawgeti"
    lua_rawgeti :: Lua.State -> StackIndex -> Lua.Integer {- ^ n -}
                -> IO TypeCode
  
  -- | Returns the raw "length" of the value at the given index: for
  -- strings, this is the string length; for tables, this is the result of
  -- the length operator (@#@) with no metamethods; for userdata, this is
  -- the size of the block of memory allocated for the userdata; for other
  -- values, it is 0.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_rawlen>.
  foreign import capi unsafe "lua.h lua_rawlen"
    lua_rawlen :: Lua.State -> StackIndex -> IO CSize
  
  -- | Similar to @'lua_settable'@, but does a raw assignment (i.e.,
  -- without metamethods).
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_rawset>.
  foreign import capi SAFTY "lua.h lua_rawset"
    lua_rawset :: Lua.State -> StackIndex -> IO ()
  
  -- | Does the equivalent of @t[i] = v@, where @t@ is the table at the
  -- given index and @v@ is the value at the top of the stack.
  --
  -- This function pops the value from the stack. The assignment is raw,
  -- that is, it does not invoke the @__newindex@ metamethod.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_rawseti>.
  foreign import capi SAFTY "lua.h lua_rawseti"
    lua_rawseti :: Lua.State -> StackIndex -> Lua.Integer -> IO ()
  
  -- | Removes the element at the given valid index, shifting down the
  -- elements above this index to fill the gap. This function cannot be
  -- called with a pseudo-index, because a pseudo-index is not an actual
  -- stack position.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_remove>
  foreign import capi unsafe "lua.h lua_remove"
    lua_remove :: Lua.State -> StackIndex -> IO ()
  
  -- | Moves the top element into the given valid index without shifting
  -- any element (therefore replacing the value at that given index), and
  -- then pops the top element.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_replace>
  foreign import capi unsafe "lua.h lua_replace"
    lua_replace :: Lua.State -> StackIndex -> IO ()
  
  -- | Rotates the stack elements between the valid index @idx@ and the
  -- top of the stack. The elements are rotated @n@ positions in the
  -- direction of the top, for a positive @n@, or @-n@ positions in the
  -- direction of the bottom, for a negative @n@. The absolute value of
  -- @n@ must not be greater than the size of the slice being rotated.
  -- This function cannot be called with a pseudo-index, because a
  -- pseudo-index is not an actual stack position.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_rotate>
  foreign import capi unsafe "lua.h lua_rotate"
    lua_rotate :: Lua.State
               -> StackIndex  -- ^ idx
               -> CInt        -- ^ n
               -> IO ()
  
  -- | Pops a value from the stack and sets it as the new value of global
  -- @name@.
  --
  -- __WARNING__: @lua_setglobal@ is unsafe in Haskell: if the call to a
  -- metamethod triggers an error, then that error cannot be handled and
  -- will lead to an unrecoverable program crash. Consider using the
  -- @'Lua.hslua_setglobal'@ ersatz function instead. Likewise,
  -- the global metamethod may not call a Haskell function unless the
  -- library was compiled without @allow-unsafe-gc@.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_setglobal>.
  foreign import capi SAFTY "lua.h lua_setglobal"
    lua_setglobal :: State -> CString {- ^ name -} -> IO ()
  {-# WARNING lua_setglobal
        [ "This is an unsafe function, errors will lead to a program crash;"
        , "consider using hslua_getglobal instead."
        ] #-}
  
  -- | Pops a table from the stack and sets it as the new metatable for
  -- the value at the given index.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_setmetatable>.
  foreign import capi unsafe "lua.h lua_setmetatable"
    lua_setmetatable :: Lua.State -> StackIndex -> IO ()
  
  -- | Does the equivalent to @t[k] = v@, where @t@ is the value at the
  -- given index, @v@ is the value at the top of the stack, and @k@ is the
  -- value just below the top.
  --
  -- This function pops both the key and the value from the stack. As in
  -- Lua, this function may trigger a metamethod for the \"newindex\"
  -- event (see <https://www.lua.org/manual/5.4/manual.html#2.4 §2.4>).
  --
  -- __WARNING__: @lua_settable@ is unsafe in Haskell: if the call to a
  -- metamethod triggers an error, then that error cannot be handled and
  -- will lead to an unrecoverable program crash. Consider using the
  -- @'Lua.hslua_settable'@ ersatz function instead. Likewise, the
  -- metamethod may not call a Haskell function unless the library was
  -- compiled without @allow-unsafe-gc@.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_settable>
  foreign import capi SAFTY "lua.h lua_settable"
    lua_settable :: Lua.State -> StackIndex {- ^ index -} -> IO ()
  {-# WARNING lua_settable
        [ "This is an unsafe function, errors will lead to a program crash;"
        , "consider using hslua_settable instead."
        ] #-}
  
  -- | 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 @index@ is 0, then all stack elements are
  -- removed.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_settop>
  foreign import capi unsafe "lua.h lua_settop"
    lua_settop :: Lua.State -> StackIndex {- ^ index -} -> IO ()
  
  -- | Pops a value from the stack and sets it as the new @n@-th user
  -- value associated to the full userdata at the given index. Returns 0
  -- if the userdata does not have that value.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_setiuservalue>
  foreign import capi unsafe "lua.h lua_setiuservalue"
    lua_setiuservalue :: Lua.State
                      -> StackIndex  -- ^ index
                      -> CInt        -- ^ n
                      -> IO LuaBool
  
  -- | Sets the warning function to be used by Lua to emit warnings (see
  -- 'WarnFunction'). The @ud@ parameter sets the value @ud@ passed to the
  -- warning function.
  foreign import capi unsafe "lua.h lua_setwarnf"
    lua_setwarnf :: Lua.State
                 -> Lua.WarnFunction -- ^ f
                 -> Ptr ()           -- ^ ud
                 -> IO ()
  
  -- |  Returns the status of this Lua thread.
  --
  -- The status can be @'Lua.LUA_OK'@ for a normal thread, an
  -- error value if the thread finished the execution of a @lua_resume@
  -- with an error, or @'Lua.LUA_YIELD'@ if the thread is
  -- suspended.
  --
  -- You can only call functions in threads with status
  -- @'Lua.LUA_OK'@. You can resume threads with status
  -- @'Lua.LUA_OK'@ (to start a new coroutine) or
  -- @'Lua.LUA_YIELD'@ (to resume a coroutine).
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_status>.
  foreign import capi unsafe "lua.h lua_status"
    lua_status :: Lua.State -> IO StatusCode
  
  -- | Converts the zero-terminated string @s@ to a number, pushes that
  -- number into the stack, and returns the total size of the string, that
  -- is, its length plus one. The conversion can result in an integer or a
  -- float, according to the lexical conventions of Lua (see
  -- <https://www.lua.org/manual/5.4/manual.html#3.1 §3.1>). The string
  -- may have leading and trailing spaces and a sign. If the string is not
  -- a valid numeral, returns 0 and pushes nothing. (Note that the result
  -- can be used as a boolean, true if the conversion succeeds.)
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_stringtonumber>.
  foreign import capi unsafe "lua.h lua_stringtonumber"
    lua_stringtonumber :: Lua.State -> CString -> IO CSize
  
  -- | Converts the Lua value at the given index to a haskell boolean
  -- value. Like all tests in Lua, @toboolean@ returns @True@ for any Lua
  -- value different from *false* and *nil*; otherwise it returns @False@.
  -- (If you want to accept only actual boolean values, use
  -- @'lua_isboolean'@ to test the value's type.)
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_toboolean>
  foreign import capi unsafe "lua.h lua_toboolean"
    lua_toboolean :: Lua.State -> StackIndex -> IO LuaBool
  
  -- | Converts a value at the given index to a C function. That value
  -- must be a C function; otherwise, returns @Nothing@.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_tocfunction>
  foreign import capi unsafe "lua.h lua_tocfunction"
    lua_tocfunction :: Lua.State -> StackIndex -> IO CFunction
  
  -- | Converts the Lua value at the given acceptable index to the signed
  -- integral type 'Lua.Integer'. The Lua value must be an integer, a
  -- number, or a string convertible to an integer (see
  -- <https://www.lua.org/manual/5.4/manual.html#3.4.3 §3.4.3> of the Lua
  -- 5.4 Reference Manual); otherwise, @lua_tointegerx@ returns @0@.
  --
  -- If the number is not an integer, it is truncated in some
  -- non-specified way.
  --
  -- If @isnum@ is not @NULL@, its referent is assigned a boolean value
  -- that indicates whether the operation succeeded.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_tointegerx>
  foreign import capi unsafe "lua.h lua_tointegerx"
    lua_tointegerx :: Lua.State
                   -> StackIndex       -- ^ index
                   -> Ptr LuaBool      -- ^ isnum
                   -> IO Lua.Integer
  
  -- | Converts the Lua value at the given index to a C string. If @len@
  -- is not @NULL@, it sets the referent with the string length. The Lua
  -- value must be a string or a number; otherwise, the function returns
  -- @NULL@. If the value is a number, then @lua_tolstring@ also changes
  -- the actual value in the stack to a string. (This change confuses
  -- @lua_next@ when @lua_tolstring@ is applied to keys during a table
  -- traversal.)
  --
  -- @lua_tolstring@ returns a pointer to a string inside the Lua state.
  -- This string always has a zero ('\0') after its last character (as in
  -- C), but can contain other zeros in its body.
  --
  -- Because Lua has garbage collection, there is no guarantee that the
  -- pointer returned by @lua_tolstring@ will be valid after the
  -- corresponding Lua value is removed from the stack.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_tolstring>
  foreign import ccall SAFTY "lua.h lua_tolstring"
    lua_tolstring :: Lua.State
                  -> StackIndex        -- ^ index
                  -> Ptr CSize         -- ^ len
                  -> IO (Ptr CChar)
  
  -- | Converts the Lua value at the given index to the C type lua_Number
  -- (see lua_Number). The Lua value must be a number or a string
  -- convertible to a number (see §3.4.3); otherwise, lua_tonumberx
  -- returns 0.
  --
  -- If @isnum@ is not @NULL@, its referent is assigned a boolean value
  -- that indicates whether the operation succeeded.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_tonumberx>
  foreign import ccall unsafe "lua.h lua_tonumberx"
    lua_tonumberx :: Lua.State
                  -> StackIndex        -- ^ index
                  -> Ptr LuaBool       -- ^ isnum
                  -> IO Lua.Number
  
  -- | Converts the value at the given index to a generic C pointer
  -- (@void*@). The value can be a userdata, a table, a thread, or a
  -- function; otherwise, @lua_topointer@ returns @'nullPtr'@. Different
  -- objects will give different pointers. There is no way to convert the
  -- pointer back to its original value.
  --
  -- Typically this function is used only for hashing and debug
  -- information.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_topointer>
  foreign import ccall unsafe "lua.h lua_topointer"
    lua_topointer :: Lua.State -> StackIndex -> IO (Ptr ())
  
  -- | Converts the value at the given index to a Lua thread (represented
  -- as @'Lua.State'@). This value must be a thread; otherwise, the
  -- function returns @'nullPtr'@.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_tothread>
  foreign import capi unsafe "lua.h lua_tothread"
    lua_tothread :: Lua.State -> StackIndex -> IO Lua.State
  
  -- | If the value at the given index is a full userdata, returns its
  -- block address. If the value is a light userdata, returns its pointer.
  -- Otherwise, returns @'nullPtr'@.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_touserdata>
  foreign import capi unsafe "lua.h lua_touserdata"
    lua_touserdata :: Lua.State -> StackIndex -> IO (Ptr a)
  
  -- | Returns the type of the value in the given valid index, or
  -- @'Lua.LUA_TNONE'@ for a non-valid (but acceptable) index.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_type>
  foreign import capi unsafe "lua.h lua_type"
    lua_type :: Lua.State -> StackIndex -> IO TypeCode
  
  -- | Returns the name of the type encoded by the value @tp@, which must
  -- be one the values returned by @'lua_type'@.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_typename>
  foreign import ccall unsafe "lua.h lua_typename"
    lua_typename :: Lua.State -> TypeCode {- ^ tp -} -> IO CString
  
  -- | Returns the address of the version number (a C static variable)
  -- stored in the Lua core. When called with a valid 'Lua.State', returns
  -- the address of the version used to create that state. When called
  -- with @NULL@, returns the address of the version running the call.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_version>
  foreign import ccall unsafe "lua.h lua_version"
    lua_version :: Lua.State -> IO (Ptr Lua.Number)
  
  -- | Emits a warning with the given message. A message in a call with
  -- @tocont@ true should be continued in another call to this function.
  --
  -- See <https://www.lua.org/manual/5.4/manual.html#pdf-warn warn> for
  -- more details about warnings.
  --
  -- <https://www.lua.org/manual/5.4/manual.html#lua_warning>
  foreign import capi safe "lua.h lua_warning"
    lua_warning :: Lua.State
                -> CString   -- ^ message
                -> LuaBool   -- ^ tocont
                -> IO ()
  