module Data.IsEvaluated(isEvaluated) where

import RtClosureInspect

-- |Checks whether Control.Exception.evaluate (or rwhnf) would do no work
-- when applied to the value. May produce false negatives (where isEvaluated
-- thinks it would, but it actually wouldn't) in some cases.
--
-- Use case: if isEvaluated foo returns True, then evaluate foo will never
-- throw an exception, or indeed take more than constant (small) time.
isEvaluated :: a -> IO Bool
isEvaluated a = (discriminate . tipe) `fmap` getClosureData a
    where
      discriminate Constr          = True
      discriminate Fun             = True
      discriminate (Indirection _) = True
      discriminate (MutVar _)      = True
      discriminate (MVar _)        = True
      discriminate PAP             = True
      -- It might be possible to handle THUNK_SELECTOR specially
      discriminate _               = False