-- | Module for generating unique names which correspond to given names
-- (of type ref).
module Util.NameMangle(
   NameMangler,
   newNameMangler, -- :: IO (NameMangler ref)
   MangledName, -- synonym for String.  MangledNames are generated by
      -- UniqueString.
   newMangledName, -- :: NameMangler ref -> ref -> IO MangledName
   readMangledName, -- :: NameMangler ref -> MangledName -> IO ref
   ) where

import Util.Registry
import Util.UniqueString

-- ---------------------------------------------------------------------
-- Data types
-- ---------------------------------------------------------------------

type MangledName = String

-- | For now we just do this naively, with a Registry.  Since the names are
-- generated sequentially a dynamic array would be more efficient, perhaps.
data NameMangler ref = NameMangler {
   nameSource :: UniqueStringSource,
   fromMangledName :: Registry MangledName ref
   }

-- ---------------------------------------------------------------------
-- Functions
-- ---------------------------------------------------------------------

newNameMangler :: IO (NameMangler ref)
newNameMangler =
   do
      nameSource <- newUniqueStringSource
      fromMangledName <- newRegistry
      return (NameMangler {nameSource = nameSource,
         fromMangledName = fromMangledName})

newMangledName :: NameMangler ref -> ref -> IO MangledName
newMangledName (NameMangler {nameSource = nameSource,
      fromMangledName = fromMangledName}) str =
   do
      name <- newUniqueString nameSource
      setValue fromMangledName name str
      return name

readMangledName :: NameMangler ref -> MangledName -> IO ref
readMangledName (NameMangler {fromMangledName = fromMangledName}) name =
   do
      refOpt <- getValueOpt fromMangledName name
      case refOpt of
         Nothing -> error ("NameMangle: couldn't retrieve "++name)
         Just ref -> return ref