    {-# LANGUAGE LambdaCase           #-}
    {- |
    Copyright  : © 2021-2024 Albert Krewinkel
    License    : MIT
    Maintainer : Albert Krewinkel <tarleb@hslua.org>

    Lua lists with additional methods.
    -}
    module HsLua.List
      ( luaopen_list_ptr
      , pushListModule
      , newListMetatable
      ) where

    import Data.ByteString (useAsCString)
    import Foreign.C
    import HsLua.Core

    -- | Pointer to the function that opens the List module and pushes it to the
    -- stack.
    foreign import ccall unsafe "listmod.c &luaopen_list"
      luaopen_list_ptr :: CFunction

    -- | Opens the List module and pushes it to the stack.
    pushListModule :: LuaError e => LuaE e ()
    pushListModule :: forall e. LuaError e => LuaE e ()
    pushListModule = do
      CFunction -> LuaE e ()
    forall e. CFunction -> LuaE e ()
    pushcfunction CFunction
    luaopen_list_ptr
      NumArgs -> NumResults -> LuaE e ()
    forall e. LuaError e => NumArgs -> NumResults -> LuaE e ()
    call NumArgs
    0 NumResults
    1

    -- | Creates a new list metatable with the given name.
    foreign import ccall "listmod.c lualist_newmetatable"
      lualist_newmetatable :: State -> CString -> IO CInt

    -- | Pushes the metatable of the given List type, creating it if
    -- necessary. The @setup@ operation is run when the metatable did not
    -- exists, was created, and is then at the top of the stack. The
    -- operation may modify the table but must be balanced, and must leave
    -- the stack as it found it.
    newListMetatable :: Name -> LuaE e () {-^ setup -} -> LuaE e ()
    newListMetatable :: forall e. Name -> LuaE e () -> LuaE e ()
    newListMetatable (Name ByteString
    name) LuaE e ()
    setup = do
      l <- LuaE e State
    forall e. LuaE e State
    state
      liftIO (useAsCString name (lualist_newmetatable l)) >>= \case
        CInt
    0 -> () -> LuaE e ()
    forall a. a -> LuaE e a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ()   -- metatable already registered; no need to setup again
        CInt
    _ -> LuaE e ()
    setup