never executed always true always false
    1 {-# LANGUAGE BangPatterns #-}
    2 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
    3 
    4 module Conjure.Language.NameGen (
    5     NameGen,
    6     NameGenM,
    7     NameGenState,
    8     nextName,
    9     exportNameGenState,
   10     importNameGenState,
   11     runNameGen,
   12 ) where
   13 
   14 -- conjure
   15 
   16 import Conjure.Language.Name
   17 import Conjure.Prelude
   18 import Conjure.UserError
   19 
   20 -- containers
   21 import Data.Map.Strict as M
   22 import Data.Set as S
   23 
   24 -- pipes
   25 import qualified Pipes
   26 
   27 
   28 type NameGenState = ( M.Map NameKind Int        -- next int to use
   29                     , S.Set Name                -- set of names to avoid
   30                     )
   31 
   32 type NameKind = Text
   33 
   34 newtype NameGenM m a = NameGenM (StateT NameGenState m a)
   35     deriving ( Functor, Applicative, Monad
   36              , MonadUserError
   37              , MonadLog
   38              , MonadTrans
   39              , MonadState NameGenState
   40              , MonadIO
   41              )
   42 instance (MonadFail m) => MonadFail (NameGenM m) where
   43     fail = lift . fail
   44 
   45 
   46 instance (Functor m, Applicative m, MonadFail m) => MonadFailDoc (NameGenM m) where
   47     failDoc = lift . fail . show
   48 class (Functor m, Applicative m, Monad m) => NameGen m where
   49     nextName :: NameKind -> m Name
   50     exportNameGenState :: m [(NameKind, Int)]
   51     importNameGenState :: [(NameKind, Int)] -> m ()
   52 
   53 instance NameGen m => NameGen (StateT st m) where
   54     nextName = lift . nextName
   55     exportNameGenState = lift exportNameGenState
   56     importNameGenState = lift . importNameGenState
   57 
   58 instance (NameGen m, Monoid w) => NameGen (WriterT w m) where
   59     nextName = lift . nextName
   60     exportNameGenState = lift exportNameGenState
   61     importNameGenState = lift . importNameGenState
   62 
   63 instance NameGen m => NameGen (ReaderT r m) where
   64     nextName = lift . nextName
   65     exportNameGenState = lift exportNameGenState
   66     importNameGenState = lift . importNameGenState
   67 
   68 instance NameGen m => NameGen (IdentityT m) where
   69     nextName = lift . nextName
   70     exportNameGenState = lift exportNameGenState
   71     importNameGenState = lift . importNameGenState
   72 
   73 instance NameGen m => NameGen (ExceptT m) where
   74     nextName = lift . nextName
   75     exportNameGenState = lift exportNameGenState
   76     importNameGenState = lift . importNameGenState
   77 
   78 instance NameGen m => NameGen (MaybeT m) where
   79     nextName = lift . nextName
   80     exportNameGenState = lift exportNameGenState
   81     importNameGenState = lift . importNameGenState
   82 
   83 instance NameGen m => NameGen (Pipes.Proxy a b c d m) where
   84     nextName = lift . nextName
   85     exportNameGenState = lift exportNameGenState
   86     importNameGenState = lift . importNameGenState
   87 
   88 instance (Functor m, MonadFail m) => NameGen (NameGenM m) where
   89     nextName k = do
   90         mi <- gets (M.lookup k . fst)
   91         out <- case mi of
   92             Nothing -> do
   93                 modify $ \(st, avoid) -> (M.insert k 2 st, avoid)
   94                 return $ MachineName k 1 []
   95             Just !i -> do
   96                 modify $ \(st, avoid) -> (M.insert k (i + 1) st, avoid)
   97                 return $ MachineName k i []
   98         avoid <- gets snd
   99         if out `S.member` avoid
  100             then nextName k
  101             else return out
  102     exportNameGenState = gets (M.toList . fst)
  103     importNameGenState st = modify $ \(_, avoid) -> (M.fromList st, avoid)
  104 
  105 instance NameGen (Either Doc) where
  106     nextName _ = failDoc "nextName{Either Doc}"
  107     exportNameGenState = failDoc "exportNameGenState{Either Doc}"
  108     importNameGenState _ = failDoc "importNameGenState{Either Doc}"
  109 
  110 instance NameGen Identity where
  111     nextName _ = failDoc "nextName{Identity}"
  112     exportNameGenState = failDoc "exportNameGenState{Identity}"
  113     importNameGenState _ = failDoc "importNameGenState{Identity}"
  114 
  115 runNameGen :: (MonadFailDoc m, Data x) => x -> NameGenM m a -> m a
  116 runNameGen avoid (NameGenM comp) =
  117     let initState = (M.empty, S.fromList (universeBi avoid))
  118      in evalStateT comp initState