    {-# LANGUAGE FlexibleInstances     #-}
    {-# LANGUAGE MultiParamTypeClasses #-}
    {-# LANGUAGE ScopedTypeVariables   #-}
    {-|
    Module      : HsLua.ObjectOrientation
    Copyright   : © 2021-2026 Albert Krewinkel
    License     : MIT
    Maintainer  : Albert Krewinkel <tarleb@hslua.org>

    This module provides types and functions to use Haskell values as
    userdata objects in Lua. These objects wrap a Haskell value and provide
    methods and properties to interact with the Haskell value.

    The terminology in this module refers to the userdata values as /UD
    objects/, and to their type as /UD type/.
    -}
    module HsLua.ObjectOrientation
      ( UDType
      , deftypeGeneric
      , module HsLua.ObjectOrientation.Generic
      , module HsLua.ObjectOrientation.ListType
      ) where

    import HsLua.Core (Name)
    import HsLua.Marshalling (Pusher)
    import HsLua.ObjectOrientation.Generic
    import HsLua.ObjectOrientation.ListType

    -- | A userdata type, capturing the behavior of Lua objects that wrap
    -- Haskell values. The type name must be unique; once the type has been
    -- used to push or retrieve a value, the behavior can no longer be
    -- modified through this type.
    type UDType e fn a = UDTypeGeneric e fn a

    -- | Defines a new type, defining the behavior of objects in Lua.
    -- Note that the type name must be unique.
    deftypeGeneric :: Pusher e fn           -- ^ function pusher
                   -> Name                  -- ^ type name
                   -> [(Operation, fn)]     -- ^ operations
                   -> [Member e fn a]       -- ^ methods
                   -> UDType e fn a
    deftypeGeneric :: forall e fn a.
    Pusher e fn
    -> Name -> [(Operation, fn)] -> [Member e fn a] -> UDType e fn a
    deftypeGeneric Pusher e fn
    pushFunction Name
    name [(Operation, fn)]
    ops [Member e fn a]
    members =
      Pusher e fn
    -> Name
    -> [(Operation, fn)]
    -> [Member e fn a]
    -> UDTypeHooks e fn a
    -> UDTypeGeneric e fn a
    forall e fn a.
    Pusher e fn
    -> Name
    -> [(Operation, fn)]
    -> [Member e fn a]
    -> UDTypeHooks e fn a
    -> UDTypeGeneric e fn a
    deftypeGeneric' Pusher e fn
    pushFunction Name
    name [(Operation, fn)]
    ops [Member e fn a]
    members UDTypeHooks e fn a
    forall e fn a. UDTypeHooks e fn a
    emptyHooks