content: {-# LANGUAGE OverloadedStrings #-}
  {-|
  Module      : HsLua.ObjectOrientation.Operation
  Copyright   : © 2020-2024 Albert Krewinkel
  License     : MIT
  Maintainer  : Albert Krewinkel <tarleb@hslua.org>
  
  Binary and unary object operations.
  -}
  module HsLua.ObjectOrientation.Operation
    ( Operation (..)
    , metamethodName
    ) where
  
  import HsLua.Core (Name)
  
  -- | Lua metadata operation types.
  data Operation
    = Add   -- ^ the addition (@+@) operation. If any operand for an
            -- addition is not a number (nor a string coercible to a
            -- number), Lua will try to call a metamethod. First, Lua will
            -- check the first operand (even if it is valid). If that
            -- operand does not define a metamethod for @__add@, then Lua
            -- will check the second operand. If Lua can find a
            -- metamethod, it calls the metamethod with the two operands
            -- as arguments, and the result of the call (adjusted to one
            -- value) is the result of the operation. Otherwise, it raises
            -- an error.
    | Sub   -- ^ the subtraction (@-@) operation. Behavior similar to the
            -- addition operation.
    | Mul   -- ^ the multiplication (@*@) operation. Behavior similar to the
            -- addition operation.
    | Div   -- ^ the division (@/@) operation. Behavior similar to the
            -- addition operation.
    | Mod   -- ^ the modulo (@%@) operation. Behavior similar to the
            -- addition operation.
    | Pow   -- ^ the exponentiation (@^@) operation. Behavior similar to the
            -- addition operation.
    | Unm   -- ^ the negation (unary @-@) operation. Behavior similar to the
            -- addition operation.
    | Idiv  -- ^ the floor division (@//@) operation. Behavior similar to
            -- the addition operation.
    | Band  -- ^ the bitwise AND (@&@) operation. Behavior similar to the
            -- addition operation, except that Lua will try a metamethod
            -- if any operand is neither an integer nor a value coercible
            -- to an integer (see §3.4.3).
    | Bor   -- ^ the bitwise OR (@|@) operation. Behavior similar to the
            -- bitwise AND operation.
    | Bxor  -- ^ the bitwise exclusive OR (binary @~@) operation. Behavior
            -- similar to the bitwise AND operation.
    | Bnot  -- ^ the bitwise NOT (unary @~@) operation. Behavior similar to
            -- the bitwise AND operation.
    | Shl   -- ^ the bitwise left shift (@<<@) operation. Behavior similar
            -- to the bitwise AND operation.
    | Shr   -- ^ the bitwise right shift (@>>@) operation. Behavior
            -- similar to the bitwise AND operation.
    | Concat
            -- ^ the concatenation (@..@) operation. Behavior similar to
            -- the addition operation, except that Lua will try a
            -- metamethod if any operand is neither a string nor a number
            -- (which is always coercible to a string).
    | Len   -- ^ the length (@#@) operation. If the object is not a string,
            -- Lua will try its metamethod. If there is a metamethod, Lua
            -- calls it with the object as argument, and the result of the
            -- call (always adjusted to one value) is the result of the
            -- operation. If there is no metamethod but the object is a
            -- table, then Lua uses the table length operation (see
            -- §3.4.7). Otherwise, Lua raises an error.
    | Eq    -- ^ the equal (@==@) operation. Behavior similar to the
            -- addition operation, except that Lua will try a metamethod
            -- only when the values being compared are either both tables
            -- or both full userdata and they are not primitively equal.
            -- The result of the call is always converted to a boolean.
    | Lt    -- ^ the less than (@<@) operation. Behavior similar to the
            -- addition operation, except that Lua will try a metamethod
            -- only when the values being compared are neither both
            -- numbers nor both strings. The result of the call is always
            -- converted to a boolean.
    | Le    -- ^ the less equal (@<=@) operation. Unlike other operations,
            -- the less-equal operation can use two different events.
            -- First, Lua looks for the @__le@ metamethod in both
            -- operands, like in the less than operation. If it cannot
            -- find such a metamethod, then it will try the @__lt@
            -- metamethod, assuming that a <= b is equivalent to not (b <
            -- a). As with the other comparison operators, the result is
            -- always a boolean. (This use of the @__lt@ event can be
            -- removed in future versions; it is also slower than a real
            -- __le metamethod.)
    | Index -- ^ The indexing access operation @table[key]@. This event
            -- happens when table is not a table or when key is not
            -- present in table. The metamethod is looked up in table.
    | Newindex
            -- ^ The indexing assignment @table[key] = value@. Like the
            -- index event, this event happens when table is not a table
            -- or when key is not present in table. The metamethod is
            -- looked up in table.
    | Call  -- ^ The call operation @func(args)@. This event happens when
            -- Lua tries to call a non-function value (that is, func is
            -- not a function). The metamethod is looked up in func. If
            -- present, the metamethod is called with func as its first
            -- argument, followed by the arguments of the original call
            -- (args). All results of the call are the result of the
            -- operation. (This is the only metamethod that allows
            -- multiple results.)
    | Tostring
            -- ^ The operation used to create a string representation of
            -- the object.
    | Pairs -- ^ the operation of iterating over the object's key-value
            -- pairs.
    | CustomOperation Name
            -- ^ a custom operation, with the metamethod name as
            -- parameter.
    deriving (Eq, Ord, Show)
  
  -- | Returns the metamethod name used to control this operation.
  metamethodName :: Operation -> Name
  metamethodName = \case
    Add      -> "__add"
    Sub      -> "__sub"
    Mul      -> "__mul"
    Div      -> "__div"
    Mod      -> "__mod"
    Pow      -> "__pow"
    Unm      -> "__unm"
    Idiv     -> "__idiv"
    Band     -> "__band"
    Bor      -> "__bor"
    Bxor     -> "__bxor"
    Bnot     -> "__bnot"
    Shl      -> "__shl"
    Shr      -> "__shr"
    Concat   -> "__concat"
    Len      -> "__len"
    Eq       -> "__eq"
    Lt       -> "__lt"
    Le       -> "__le"
    Index    -> "__index"
    Newindex -> "__newindex"
    Call     -> "__call"
    Tostring -> "__tostring"
    Pairs    -> "__pairs"
    CustomOperation x -> x
  