{- | Machine Fortran LOGICAL values.

Fortran compilers usually store LOGICALs as INTEGERs (they former is tied to the
latter in the specifications). To more accurately simulate their behaviour, we
represent them directly as integers, and simply provide a handful of definitions
for using them as booleans.
-}

module Language.Fortran.Repr.Value.Scalar.Logical.Machine where

import Language.Fortran.Repr.Value.Scalar.Int.Machine

-- | Retrieve the boolean value stored by a @LOGICAL(x)@.
fLogicalToBool :: FInt -> Bool
fLogicalToBool :: FInt -> Bool
fLogicalToBool = forall r. (forall a. FKindedC FInt a => a -> r) -> FInt -> r
fIntUOp forall a b. (a -> b) -> a -> b
$ forall a r. (Num a, Eq a) => r -> r -> a -> r
consumeFLogicalNumeric Bool
True Bool
False

-- | Convert a bool to its Fortran machine representation in any numeric type.
fLogicalNumericFromBool :: Num a => Bool -> a
fLogicalNumericFromBool :: forall a. Num a => Bool -> a
fLogicalNumericFromBool = \case Bool
True -> a
1; Bool
False -> a
0

-- | Consume some Fortran logical stored using an integer.
consumeFLogicalNumeric :: (Num a, Eq a) => r -> r -> a -> r
consumeFLogicalNumeric :: forall a r. (Num a, Eq a) => r -> r -> a -> r
consumeFLogicalNumeric r
whenTrue r
whenFalse a
bi =
    if a
bi forall a. Eq a => a -> a -> Bool
== a
1 then r
whenTrue else r
whenFalse

fLogicalNot :: FInt -> FInt
fLogicalNot :: FInt -> FInt
fLogicalNot = (forall a. FKindedC FInt a => a -> a) -> FInt -> FInt
fIntUOpInplace (forall a r. (Num a, Eq a) => r -> r -> a -> r
consumeFLogicalNumeric a
0 a
1)