libcspm-1.0.0: src/CSPM/DataStructures/Names.hs
{-# LANGUAGE DeriveDataTypeable, FlexibleInstances, MultiParamTypeClasses,
TypeSynonymInstances #-}
-- | Names used by the evaluator. This is heavily inspired by GHC.
module CSPM.DataStructures.Names (
-- * Data Types
OccName(..),
UnRenamedName(..),
Name(..),
NameType(..),
-- * Construction Helpers
mkExternalName, mkInternalName, mkWiredInName, mkFreshInternalName,
-- * Utility Functions
isNameDataConstructor,
) where
import Control.Applicative
import Control.Monad.Trans
import Data.Hashable
import Data.IORef
import Data.Supply
import Data.Typeable
import System.IO.Unsafe
import Util.Annotated
import qualified Util.MonadicPrettyPrint as M
import Util.PrettyPrint
-- | A name that occurs in the source code somewhere.
data OccName =
OccName String
deriving (Eq, Ord, Show, Typeable)
instance PrettyPrintable OccName where
prettyPrint (OccName s) = text s
instance (Applicative m, Monad m) => M.MonadicPrettyPrintable m OccName where
prettyPrint (OccName s) = M.text s
-- | A name that has not yet been renamed. Created by the parser.
data UnRenamedName =
UnQual OccName
| Qual {
unRenamedNameModuleName :: OccName,
unRenamedNameMemberName :: UnRenamedName
}
deriving (Eq, Ord, Show, Typeable)
instance PrettyPrintable UnRenamedName where
prettyPrint (UnQual n) = prettyPrint n
prettyPrint (Qual mn n) = prettyPrint mn <> text "::" <> prettyPrint n
instance (Applicative m, Monad m) => M.MonadicPrettyPrintable m UnRenamedName where
prettyPrint (UnQual n) = M.prettyPrint n
prettyPrint (Qual mn n) = M.prettyPrint mn M.<> M.text "::" M.<> M.prettyPrint n
-- | A renamed name and is the exclusive type used after the renamer. Names
-- are guaranteed to be unique, meaning that two names are equal iff they
-- refer to the same binding instance. For example, consider the following CSPM
-- code:
--
-- @
-- f = 1
-- g = let f = 2 within (f, f)
-- @
--
-- This will be renamed to:
--
-- @
-- f0 = 1
-- g = let f1 = 2 within (f1, f1)
-- @
--
data Name =
Name {
-- | The type of this name.
nameType :: NameType,
-- | The original occurence of this name (used for error messages).
nameFullyQualified :: !UnRenamedName,
-- | Where this name was defined. If this occurs in a pattern, then it
-- will be equal to the location of the pattern, otherwise it will be
-- equal to the location of the definition that this name binds to.
nameDefinition :: !SrcSpan,
-- | The unique identifier for this name. Inserted by the renamer.
nameUnique :: !Int,
-- | Is this name a type constructor, i.e. a datatype or a channel?
nameIsConstructor :: Bool
}
deriving Typeable
data NameType =
-- | An externally visible name (like a top level definition).
ExternalName
-- | A name created by the renamer, but from the users' source (e.g. from
-- a lambda).
| InternalName
-- | A built in name.
| WiredInName
deriving Eq
instance Eq Name where
n1 == n2 = nameUnique n1 == nameUnique n2
instance Hashable Name where
hash n = nameUnique n
instance Ord Name where
compare n1 n2 = compare (nameUnique n1) (nameUnique n2)
instance PrettyPrintable Name where
prettyPrint n = prettyPrint (nameFullyQualified n)
instance (Applicative m, Monad m) => M.MonadicPrettyPrintable m Name where
prettyPrint n = M.prettyPrint (nameFullyQualified n)
instance Show Name where
show n = show (prettyPrint n)
nameUniqueSupply :: IORef (Supply Int)
nameUniqueSupply = unsafePerformIO $ do
s <- newNumSupply
newIORef s
{-# NOINLINE nameUniqueSupply #-}
takeNameUnique :: MonadIO m => m Int
takeNameUnique = do
s <- liftIO $ atomicModifyIORef nameUniqueSupply split2
return $ supplyValue s
mkExternalName :: MonadIO m => UnRenamedName -> SrcSpan -> Bool -> m Name
mkExternalName o s b = do
u <- takeNameUnique
return $ Name ExternalName o s u b
mkInternalName :: MonadIO m => UnRenamedName -> SrcSpan -> m Name
mkInternalName o s = do
u <- takeNameUnique
return $ Name InternalName o s u False
mkFreshInternalName :: MonadIO m => m Name
mkFreshInternalName = do
u <- takeNameUnique
let s = 'i':show u
return $ Name InternalName (UnQual (OccName s)) Unknown u False
mkWiredInName :: MonadIO m => UnRenamedName -> Bool -> m Name
mkWiredInName o b = do
u <- takeNameUnique
return $ Name WiredInName o BuiltIn u b
-- | Does the given Name correspond to a data type or a channel definition.
isNameDataConstructor :: Name -> Bool
isNameDataConstructor n = nameIsConstructor n