content: -- |
  -- Module      :  Cryptol.TypeCheck.PP
  -- Copyright   :  (c) 2013-2016 Galois, Inc.
  -- License     :  BSD3
  -- Maintainer  :  cryptol@galois.com
  -- Stability   :  provisional
  -- Portability :  portable
  
  {-# LANGUAGE Safe #-}
  {-# LANGUAGE FlexibleInstances, FlexibleContexts #-}
  module Cryptol.TypeCheck.PP
    ( NameMap, WithNames(..)
    , emptyNameMap
    , ppWithNamesPrec, ppWithNames
    , nameList
    , dump
    , module Cryptol.Utils.PP
    ) where
  
  import           Data.IntMap (IntMap)
  import qualified Data.IntMap as IntMap
  import           Data.List(transpose)
  import           Cryptol.Utils.PP
  
  
  type NameMap = IntMap Doc
  
  emptyNameMap :: NameMap
  emptyNameMap = IntMap.empty
  
  -- | This packages together a type with some names to be used to display
  -- the variables.  It is used for pretty printing types.
  data WithNames a = WithNames a NameMap
  
  ppWithNamesPrec :: PP (WithNames a) => NameMap -> Int -> a -> Doc
  ppWithNamesPrec names prec t = ppPrec prec (WithNames t names)
  
  ppWithNames :: PP (WithNames a) => NameMap -> a -> Doc
  ppWithNames names t = ppWithNamesPrec names 0 t
  
  dump :: PP (WithNames a) => a -> String
  dump x = show (ppWithNames IntMap.empty x)
  
  -- | Compute the n-th variant of a name (e.g., @a5@).
  nameVariant :: Int -> String -> String
  nameVariant 0 x   = x
  nameVariant n x   = x ++ show n
  
  -- | Compute all variants of a name: @a, a1, a2, a3, ...@
  nameVariants :: String -> [String]
  nameVariants x = map (`nameVariant` x) [ 0 .. ]
  
  -- | Expand a list of base names into an infinite list of variations.
  nameList :: [String] -> [String]
  nameList names = concat $ transpose $ map nameVariants baseNames
    where
    baseNames | null names = map (:[]) [ 'a' .. 'z' ]
              | otherwise  = names
  
  
  