content: {-# LANGUAGE PatternGuards #-}
  
  -- | A Ninja style environment, equivalent to a non-empty list of mutable hash tables.
  module Development.Ninja.Env(
      Env, newEnv, scopeEnv, addEnv, askEnv, fromEnv
      ) where
  
  import qualified Data.HashMap.Strict as Map
  import Data.Hashable
  import Data.IORef
  
  
  data Env k v = Env (IORef (Map.HashMap k v)) (Maybe (Env k v))
  
  instance Show (Env k v) where show _ = "Env"
  
  
  newEnv :: IO (Env k v)
  newEnv = do ref <- newIORef Map.empty; pure $ Env ref Nothing
  
  
  scopeEnv :: Env k v -> IO (Env k v)
  scopeEnv e = do ref <- newIORef Map.empty; pure $ Env ref $ Just e
  
  
  addEnv :: (Eq k, Hashable k) => Env k v -> k -> v -> IO ()
  addEnv (Env ref _) k v = modifyIORef ref $ Map.insert k v
  
  
  askEnv :: (Eq k, Hashable k) => Env k v -> k -> IO (Maybe v)
  askEnv (Env ref e) k = do
      mp <- readIORef ref
      case Map.lookup k mp of
          Just v -> pure $ Just v
          Nothing | Just e <- e -> askEnv e k
          _ -> pure Nothing
  
  fromEnv :: Env k v -> IO (Map.HashMap k v)
  fromEnv (Env ref _) = readIORef ref
  