packages feed

fortran-vars-0.3.1: src/Language/Fortran/Vars/PureExpression.hs

module Language.Fortran.Vars.PureExpression
  ( isPureExpression
  )
where
import           Data.Maybe                     ( catMaybes )

import           Language.Fortran.AST           ( Expression(..)
                                                , Index(..)
                                                , Value(..)
                                                , aStrip
                                                )
import           Language.Fortran.AST.Literal.Complex
                                                ( ComplexLit(..)
                                                , ComplexPart(..)
                                                )
import           Language.Fortran.Vars.Call
                                                ( functionArguments )

-- | Given an 'Expression', determine whether it is a pure expression. 
-- A pure expression does not have side effect.
-- return true if the expression is guaranteed to be pure,
-- return false if the expression can not be guaranteed to be pure. 
isPureExpression :: Expression a -> Bool
isPureExpression (ExpValue _ _ v) = isPureValue v
isPureExpression (ExpBinary _ _ _ e1 e2) =
  isPureExpression e1 && isPureExpression e2
isPureExpression (ExpUnary _ _ _ e) = isPureExpression e
isPureExpression (ExpSubscript _ _ _ indices) =
  all isPureIndex (aStrip indices)
isPureExpression e@ExpFunctionCall{} =
  isIntrinsicFunctionCall e && all isPureExpression (functionArguments e)
isPureExpression (ExpInitialisation _ _ exprs) =
  all isPureExpression (aStrip exprs)
isPureExpression ExpReturnSpec{} = False
isPureExpression ExpImpliedDo{}  = False
isPureExpression ExpDataRef{}    = False


-- | Given a 'Value', determine whether it is pure
isPureValue :: Value a -> Bool
isPureValue ValInteger{}       = True
isPureValue ValReal{}          = True
isPureValue (ValComplex c)     = complexLitIsPure c
isPureValue ValString{}        = True
isPureValue ValHollerith{}     = True
isPureValue ValVariable{}      = True
isPureValue ValIntrinsic{}     = True
isPureValue ValLogical{}       = True
isPureValue ValStar            = True
isPureValue _                  = False

-- | Is the given COMPLEX literal "pure", i.e. does it have no named constant
--   components?
complexLitIsPure :: ComplexLit a -> Bool
complexLitIsPure c =
    check (complexLitRealPart c) && check (complexLitImagPart c)
  where check = \case ComplexPartNamed{} -> False
                      _                  -> True

-- | Given an 'Index', determine whether it is pure
isPureIndex :: Index a -> Bool
isPureIndex (IxSingle _ _ _ e) = isPureExpression e
isPureIndex (IxRange _ _ me1 me2 me3) =
  all isPureExpression $ catMaybes [me1, me2, me3]

-- | Given an expression determine whether it is intrinsic function call
isIntrinsicFunctionCall :: Expression a -> Bool
isIntrinsicFunctionCall (ExpFunctionCall _ _ (ExpValue _ _ (ValIntrinsic _)) _)
  = True
isIntrinsicFunctionCall _ = False