packages feed

sdl3-bindgen-sys-0.0.0.1: runtime/HsBindgen/Runtime/CBool.hs

{-# LANGUAGE NoImplicitPrelude #-}

-- | C boolean semantics
--
-- In C, boolean types are numeric, where value @0@ is considered false and any
-- other value is considered true.  They are implemented differently across
-- different C projects:
--
-- * Since C23, there is a @bool@ type and predefined constants @true@ and
--   @false@.
-- * Since C99, standard header @stdbool.h@ defines (implementation-dependent)
--   type @_Bool@ and macros @true@ and @false@.  This header is deprecated
--   since C23.
-- * Before C99, users defined boolean types and values, following the common
--   conventions.  Some projects still define their own boolean type, perhaps
--   for compatibility with old C standards.  Common implementations include the
--   following, where @bool@ may be spelled differently (such as @Bool@ or
--   @BOOL@):
--
--     * An @enum@ type:
--
--         @
--         typedef enum { false, true } bool;
--         @
--
--     * A @typedef@ and /separate/ @enum@ values:
--
--         @
--         typedef int bool;
--         enum { false, true };
--         @
--
--     * A @typedef@ and macro values:
--
--         @
--         typedef int bool;
--         #define true 1
--         #define false 0
--         @
--
--     * A macro alias and macro values:
--
--         @
--         #define bool int
--         #define true 1
--         #define false 0
--         @
--
-- This module provides an API that is compatible with bindings generated for
-- any of these possible implementations.  Note that the implementation only
-- requires 'Eq' and 'Num' instances.  Conversion follows C23 semantics: /only/
-- value @0@ is considered false, and any other value is considered true.
--
-- Intended for qualified import.
--
-- > import HsBindgen.Runtime.CBool qualified as CBool
module HsBindgen.Runtime.CBool (
  -- * Values
  true,
  false,

  -- * Predicates
  isTrue,
  isFalse,

  -- * Conversion
  fromBool,
  toBool,

  -- * Operations
  (&&),
  (||),
  not,
  bool,
  if_,
  when,
  unless,
) where

import Prelude hiding (not, (&&), (||))
import Prelude qualified

{-------------------------------------------------------------------------------
  Values
-------------------------------------------------------------------------------}

-- | Standard true value: @1@
true :: (Num b) => b
true = 1

-- | Standard false value: @0@
false :: (Num b) => b
false = 0

{-------------------------------------------------------------------------------
  Predicates
-------------------------------------------------------------------------------}

-- | 'True' if the value is not @0@
isTrue :: (Eq b, Num b) => b -> Bool
isTrue = (/= false)

-- | 'True' if the value is @0@
isFalse :: (Eq b, Num b) => b -> Bool
isFalse = (== false)

{-------------------------------------------------------------------------------
  Conversion
-------------------------------------------------------------------------------}

-- | Convert from 'Bool' to 'true' or 'false'
fromBool :: (Num b) => Bool -> b
fromBool True = true
fromBool False = false

-- | Convert to 'Bool' using 'isTrue'
toBool :: (Eq b, Num b) => b -> Bool
toBool = isTrue

{-------------------------------------------------------------------------------
  Operations
-------------------------------------------------------------------------------}

-- | Boolean /and/, lazy in the second argument
--
-- This function returns one of the standard values.
(&&) :: (Eq b, Num b) => b -> b -> b
l && r = fromBool $ toBool l Prelude.&& toBool r

-- | Boolean /or/, lazy in the second argument
--
-- This function returns one of the standard values.
(||) :: (Eq b, Num b) => b -> b -> b
l || r = fromBool $ toBool l Prelude.|| toBool r

-- | Boolean /not/
--
-- This function returns one of the standard values.
not :: (Eq b, Num b) => b -> b
not = fromBool . Prelude.not . toBool

-- | Boolean case analysis, implemented using 'isTrue'
--
-- See 'Data.Bool.bool' for details.
bool :: (Eq b, Num b) => a -> a -> b -> a
bool f t b = if isTrue b then t else f

-- | Boolean case analysis, implemented using 'isTrue'
if_ :: (Eq b, Num b) => b -> a -> a -> a
if_ b t f = if isTrue b then t else f

-- | Execute an applicative expression when the condition 'isTrue'
when :: (Eq b, Num b, Applicative f) => b -> f () -> f ()
when b e = if isTrue b then e else pure ()
{-# ANN when ("HLint: ignore Use when" :: String) #-}

-- | Execute an applicative expression when the condition 'isFalse'
unless :: (Eq b, Num b, Applicative f) => b -> f () -> f ()
unless b e = if isFalse b then e else pure ()
{-# ANN unless ("HLint: ignore Use when" :: String) #-}