{- |
    Module      :  $Header$
    Description :  Identifiers
    Copyright   :  (c) 1999 - 2004, Wolfgang Lux
                       2011 - 2013, Björn Peemöller
                       2016       , Finn Teegen
    License     :  BSD-3-clause

    Maintainer  :  bjp@informatik.uni-kiel.de
    Stability   :  experimental
    Portability :  portable

    This module provides the implementation of identifiers and some
    utility functions for identifiers.

    Identifiers comprise the name of the denoted entity and an /id/,
    which can be used for renaming identifiers, e.g., in order to resolve
    name conflicts between identifiers from different scopes. An
    identifier with an /id/ @0@ is considered as not being renamed
    and, hence, its /id/ will not be shown.

    Qualified identifiers may optionally be prefixed by a module name.
-}
{-# LANGUAGE CPP #-}
module Curry.Base.Ident
  ( -- * Module identifiers
    ModuleIdent (..), mkMIdent, moduleName, escModuleName
  , fromModuleName, isValidModuleName, addPositionModuleIdent, mIdentLength

    -- * Local identifiers
  , Ident (..), mkIdent, showIdent, escName, identSupply
  , globalScope, hasGlobalScope, isRenamed, renameIdent, unRenameIdent
  , updIdentName, addPositionIdent, isInfixOp, identLength

    -- * Qualified identifiers
  , QualIdent (..), qualName, escQualName, isQInfixOp, qualify
  , qualifyWith, qualQualify, qualifyLike, isQualified, unqualify, qualUnqualify
  , localIdent, isLocalIdent, updQualIdent, qIdentLength

    -- * Predefined simple identifiers
    -- ** Identifiers for modules
  , emptyMIdent, mainMIdent, preludeMIdent
    -- ** Identifiers for types
  , arrowId, unitId, boolId, charId, intId, floatId, listId, ioId, successId
    -- ** Identifiers for type classes
  , eqId, ordId, enumId, boundedId, readId, showId
  , numId, fractionalId
  , monadId, monadFailId
  , dataId
    -- ** Identifiers for constructors
  , trueId, falseId, nilId, consId, tupleId, isTupleId, tupleArity
    -- ** Identifiers for values
  , mainId, minusId, fminusId, applyId, errorId, failedId, idId
  , succId, predId, toEnumId, fromEnumId, enumFromId, enumFromThenId
  , enumFromToId, enumFromThenToId
  , maxBoundId, minBoundId
  , lexId, readsPrecId, readParenId
  , showsPrecId, showParenId, showStringId
  , andOpId, eqOpId, leqOpId, ltOpId, orOpId, appendOpId, dotOpId
  , aValueId, dataEqId
  , anonId, isAnonId

    -- * Predefined qualified identifiers
    -- ** Identifiers for types
  , qArrowId, qUnitId, qBoolId, qCharId, qIntId, qFloatId, qListId, qIOId
  , qSuccessId, isPrimTypeId
    -- ** Identifiers for type classes
  , qEqId, qOrdId, qEnumId, qBoundedId, qReadId, qShowId
  , qNumId, qFractionalId
  , qMonadId, qMonadFailId
  , qDataId
    -- ** Identifiers for constructors
  , qTrueId, qFalseId, qNilId, qConsId, qTupleId, isQTupleId, qTupleArity
    -- ** Identifiers for values
  , qApplyId, qErrorId, qFailedId, qIdId
  , qFromEnumId, qEnumFromId, qEnumFromThenId, qEnumFromToId, qEnumFromThenToId
  , qMaxBoundId, qMinBoundId
  , qLexId, qReadsPrecId, qReadParenId
  , qShowsPrecId, qShowParenId, qShowStringId
  , qAndOpId, qEqOpId, qLeqOpId, qLtOpId, qOrOpId, qAppendOpId, qDotOpId
  , qAValueId, qDataEqId

    -- * Extended functionality
    -- ** Functional patterns
  , fpSelectorId, isFpSelectorId, isQualFpSelectorId
    -- ** Records
  , recSelectorId, qualRecSelectorId, recUpdateId, qualRecUpdateId
  , recordExt, recordExtId, isRecordExtId, fromRecordExtId
  , labelExt, labelExtId, isLabelExtId, fromLabelExtId
  , renameLabel, mkLabelIdent
  ) where

import Prelude hiding ((<>))
import Data.Char           (isAlpha, isAlphaNum)
import Data.Function       (on)
import Data.List           (intercalate, isInfixOf, isPrefixOf)
import Data.Maybe          (isJust, fromMaybe)
import Data.Binary
import Control.Monad

import Curry.Base.Position
import Curry.Base.Span hiding (file)
import Curry.Base.SpanInfo
import Curry.Base.Pretty

-- ---------------------------------------------------------------------------
-- Module identifier
-- ---------------------------------------------------------------------------

-- | Module identifier
data ModuleIdent = ModuleIdent
  { ModuleIdent -> SpanInfo
midSpanInfo   :: SpanInfo -- ^ source code 'SpanInfo'
  , ModuleIdent -> [String]
midQualifiers :: [String] -- ^ hierarchical idenfiers
  } deriving (ReadPrec [ModuleIdent]
ReadPrec ModuleIdent
Int -> ReadS ModuleIdent
ReadS [ModuleIdent]
(Int -> ReadS ModuleIdent)
-> ReadS [ModuleIdent]
-> ReadPrec ModuleIdent
-> ReadPrec [ModuleIdent]
-> Read ModuleIdent
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [ModuleIdent]
$creadListPrec :: ReadPrec [ModuleIdent]
readPrec :: ReadPrec ModuleIdent
$creadPrec :: ReadPrec ModuleIdent
readList :: ReadS [ModuleIdent]
$creadList :: ReadS [ModuleIdent]
readsPrec :: Int -> ReadS ModuleIdent
$creadsPrec :: Int -> ReadS ModuleIdent
Read, Int -> ModuleIdent -> ShowS
[ModuleIdent] -> ShowS
ModuleIdent -> String
(Int -> ModuleIdent -> ShowS)
-> (ModuleIdent -> String)
-> ([ModuleIdent] -> ShowS)
-> Show ModuleIdent
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ModuleIdent] -> ShowS
$cshowList :: [ModuleIdent] -> ShowS
show :: ModuleIdent -> String
$cshow :: ModuleIdent -> String
showsPrec :: Int -> ModuleIdent -> ShowS
$cshowsPrec :: Int -> ModuleIdent -> ShowS
Show)

instance Eq ModuleIdent where
  == :: ModuleIdent -> ModuleIdent -> Bool
(==) = [String] -> [String] -> Bool
forall a. Eq a => a -> a -> Bool
(==) ([String] -> [String] -> Bool)
-> (ModuleIdent -> [String]) -> ModuleIdent -> ModuleIdent -> Bool
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` ModuleIdent -> [String]
midQualifiers

instance Ord ModuleIdent where
  compare :: ModuleIdent -> ModuleIdent -> Ordering
compare = [String] -> [String] -> Ordering
forall a. Ord a => a -> a -> Ordering
compare ([String] -> [String] -> Ordering)
-> (ModuleIdent -> [String])
-> ModuleIdent
-> ModuleIdent
-> Ordering
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` ModuleIdent -> [String]
midQualifiers

instance HasSpanInfo ModuleIdent where
  getSpanInfo :: ModuleIdent -> SpanInfo
getSpanInfo = ModuleIdent -> SpanInfo
midSpanInfo
  setSpanInfo :: SpanInfo -> ModuleIdent -> ModuleIdent
setSpanInfo spi :: SpanInfo
spi a :: ModuleIdent
a = ModuleIdent
a { midSpanInfo :: SpanInfo
midSpanInfo = SpanInfo
spi }
  updateEndPos :: ModuleIdent -> ModuleIdent
updateEndPos i :: ModuleIdent
i =
    Position -> ModuleIdent -> ModuleIdent
forall a. HasSpanInfo a => Position -> a -> a
setEndPosition (Position -> Int -> Position
incr (ModuleIdent -> Position
forall a. HasPosition a => a -> Position
getPosition ModuleIdent
i) (ModuleIdent -> Int
mIdentLength ModuleIdent
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- 1)) ModuleIdent
i

instance HasPosition ModuleIdent where
  getPosition :: ModuleIdent -> Position
getPosition = ModuleIdent -> Position
forall a. HasSpanInfo a => a -> Position
getStartPosition
  setPosition :: Position -> ModuleIdent -> ModuleIdent
setPosition = Position -> ModuleIdent -> ModuleIdent
forall a. HasSpanInfo a => Position -> a -> a
setStartPosition

instance Pretty ModuleIdent where
  pPrint :: ModuleIdent -> Doc
pPrint = [Doc] -> Doc
hcat ([Doc] -> Doc) -> (ModuleIdent -> [Doc]) -> ModuleIdent -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Doc -> [Doc] -> [Doc]
punctuate Doc
dot ([Doc] -> [Doc]) -> (ModuleIdent -> [Doc]) -> ModuleIdent -> [Doc]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> Doc) -> [String] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map String -> Doc
text ([String] -> [Doc])
-> (ModuleIdent -> [String]) -> ModuleIdent -> [Doc]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ModuleIdent -> [String]
midQualifiers

instance Binary ModuleIdent where
  put :: ModuleIdent -> Put
put (ModuleIdent sp :: SpanInfo
sp qs :: [String]
qs) = SpanInfo -> Put
forall t. Binary t => t -> Put
put SpanInfo
sp Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> [String] -> Put
forall t. Binary t => t -> Put
put [String]
qs
  get :: Get ModuleIdent
get = (SpanInfo -> [String] -> ModuleIdent)
-> Get SpanInfo -> Get [String] -> Get ModuleIdent
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 SpanInfo -> [String] -> ModuleIdent
ModuleIdent Get SpanInfo
forall t. Binary t => Get t
get Get [String]
forall t. Binary t => Get t
get

mIdentLength :: ModuleIdent -> Int
mIdentLength :: ModuleIdent -> Int
mIdentLength a :: ModuleIdent
a = String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat (ModuleIdent -> [String]
midQualifiers ModuleIdent
a))
               Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (ModuleIdent -> [String]
midQualifiers ModuleIdent
a)

-- |Construct a 'ModuleIdent' from a list of 'String's forming the
--  the hierarchical module name.
mkMIdent :: [String] -> ModuleIdent
mkMIdent :: [String] -> ModuleIdent
mkMIdent = SpanInfo -> [String] -> ModuleIdent
ModuleIdent SpanInfo
NoSpanInfo

-- |Retrieve the hierarchical name of a module
moduleName :: ModuleIdent -> String
moduleName :: ModuleIdent -> String
moduleName = String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate "." ([String] -> String)
-> (ModuleIdent -> [String]) -> ModuleIdent -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ModuleIdent -> [String]
midQualifiers

-- |Show the name of an 'ModuleIdent' escaped by ticks
escModuleName :: ModuleIdent -> String
escModuleName :: ModuleIdent -> String
escModuleName m :: ModuleIdent
m = '`' Char -> ShowS
forall a. a -> [a] -> [a]
: ModuleIdent -> String
moduleName ModuleIdent
m String -> ShowS
forall a. [a] -> [a] -> [a]
++ "'"

-- |Add a source code 'Position' to a 'ModuleIdent'
addPositionModuleIdent :: Position -> ModuleIdent -> ModuleIdent
addPositionModuleIdent :: Position -> ModuleIdent -> ModuleIdent
addPositionModuleIdent = Position -> ModuleIdent -> ModuleIdent
forall a. HasPosition a => Position -> a -> a
setPosition

-- |Check whether a 'String' is a valid module name.
--
-- Valid module names must satisfy the following conditions:
--
--  * The name must not be empty
--  * The name must consist of one or more single identifiers,
--    seperated by dots
--  * Each single identifier must be non-empty, start with a letter and
--    consist of letter, digits, single quotes or underscores only
isValidModuleName :: String -> Bool
isValidModuleName :: String -> Bool
isValidModuleName [] = Bool
False -- Module names may not be empty
isValidModuleName qs :: String
qs = (String -> Bool) -> [String] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all String -> Bool
isModuleIdentifier ([String] -> Bool) -> [String] -> Bool
forall a b. (a -> b) -> a -> b
$ String -> [String]
splitIdentifiers String
qs
  where
  -- components of a module identifier may not be null
  isModuleIdentifier :: String -> Bool
isModuleIdentifier []     = Bool
False
  -- components of a module identifier must start with a letter and consist
  -- of letter, digits, underscores or single quotes
  isModuleIdentifier (c :: Char
c:cs :: String
cs) = Char -> Bool
isAlpha Char
c Bool -> Bool -> Bool
&& (Char -> Bool) -> String -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Char -> Bool
isIdent String
cs
  isIdent :: Char -> Bool
isIdent c :: Char
c                 = Char -> Bool
isAlphaNum Char
c Bool -> Bool -> Bool
|| Char
c Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` "'_"

-- |Resemble the hierarchical module name from a 'String' by splitting
-- the 'String' at inner dots.
--
-- /Note:/ This function does not check the 'String' to be a valid module
-- identifier, use isValidModuleName for this purpose.
fromModuleName :: String -> ModuleIdent
fromModuleName :: String -> ModuleIdent
fromModuleName = [String] -> ModuleIdent
mkMIdent ([String] -> ModuleIdent)
-> (String -> [String]) -> String -> ModuleIdent
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
splitIdentifiers

-- Auxiliary function to split a hierarchical module identifier at the dots
splitIdentifiers :: String -> [String]
splitIdentifiers :: String -> [String]
splitIdentifiers s :: String
s = let (pref :: String
pref, rest :: String
rest) = (Char -> Bool) -> String -> (String, String)
forall a. (a -> Bool) -> [a] -> ([a], [a])
break (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== '.') String
s in
  String
pref String -> [String] -> [String]
forall a. a -> [a] -> [a]
: case String
rest of
    []     -> []
    (_:s' :: String
s') -> String -> [String]
splitIdentifiers String
s'

-- ---------------------------------------------------------------------------
-- Simple identifier
-- ---------------------------------------------------------------------------

-- |Simple identifier
data Ident = Ident
  { Ident -> SpanInfo
idSpanInfo :: SpanInfo -- ^ Source code 'SpanInfo'
  , Ident -> String
idName     :: String   -- ^ Name of the identifier
  , Ident -> Integer
idUnique   :: Integer  -- ^ Unique number of the identifier
  } deriving (ReadPrec [Ident]
ReadPrec Ident
Int -> ReadS Ident
ReadS [Ident]
(Int -> ReadS Ident)
-> ReadS [Ident]
-> ReadPrec Ident
-> ReadPrec [Ident]
-> Read Ident
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Ident]
$creadListPrec :: ReadPrec [Ident]
readPrec :: ReadPrec Ident
$creadPrec :: ReadPrec Ident
readList :: ReadS [Ident]
$creadList :: ReadS [Ident]
readsPrec :: Int -> ReadS Ident
$creadsPrec :: Int -> ReadS Ident
Read, Int -> Ident -> ShowS
[Ident] -> ShowS
Ident -> String
(Int -> Ident -> ShowS)
-> (Ident -> String) -> ([Ident] -> ShowS) -> Show Ident
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Ident] -> ShowS
$cshowList :: [Ident] -> ShowS
show :: Ident -> String
$cshow :: Ident -> String
showsPrec :: Int -> Ident -> ShowS
$cshowsPrec :: Int -> Ident -> ShowS
Show)

instance Eq Ident where
  Ident _ m :: String
m i :: Integer
i == :: Ident -> Ident -> Bool
== Ident _ n :: String
n j :: Integer
j = (String
m, Integer
i) (String, Integer) -> (String, Integer) -> Bool
forall a. Eq a => a -> a -> Bool
== (String
n, Integer
j)

instance Ord Ident where
  Ident _ m :: String
m i :: Integer
i compare :: Ident -> Ident -> Ordering
`compare` Ident _ n :: String
n j :: Integer
j = (String
m, Integer
i) (String, Integer) -> (String, Integer) -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare` (String
n, Integer
j)

instance HasSpanInfo Ident where
  getSpanInfo :: Ident -> SpanInfo
getSpanInfo = Ident -> SpanInfo
idSpanInfo
  setSpanInfo :: SpanInfo -> Ident -> Ident
setSpanInfo spi :: SpanInfo
spi a :: Ident
a = Ident
a { idSpanInfo :: SpanInfo
idSpanInfo = SpanInfo
spi }
  updateEndPos :: Ident -> Ident
updateEndPos i :: Ident
i@(Ident (SpanInfo _ [_,ss :: Span
ss]) _ _) =
    Position -> Ident -> Ident
forall a. HasSpanInfo a => Position -> a -> a
setEndPosition (Span -> Position
end Span
ss) Ident
i
  updateEndPos i :: Ident
i =
    Position -> Ident -> Ident
forall a. HasSpanInfo a => Position -> a -> a
setEndPosition (Position -> Int -> Position
incr (Ident -> Position
forall a. HasPosition a => a -> Position
getPosition Ident
i) (Ident -> Int
identLength Ident
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- 1)) Ident
i

instance HasPosition Ident where
  getPosition :: Ident -> Position
getPosition = Ident -> Position
forall a. HasSpanInfo a => a -> Position
getStartPosition
  setPosition :: Position -> Ident -> Ident
setPosition = Position -> Ident -> Ident
forall a. HasSpanInfo a => Position -> a -> a
setStartPosition

instance Pretty Ident where
  pPrint :: Ident -> Doc
pPrint (Ident _ x :: String
x n :: Integer
n) | Integer
n Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
globalScope = String -> Doc
text String
x
                       | Bool
otherwise        = String -> Doc
text String
x Doc -> Doc -> Doc
<> Doc
dot Doc -> Doc -> Doc
<> Integer -> Doc
integer Integer
n

instance Binary Ident where
  put :: Ident -> Put
put (Ident sp :: SpanInfo
sp qs :: String
qs i :: Integer
i) = SpanInfo -> Put
forall t. Binary t => t -> Put
put SpanInfo
sp Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> String -> Put
forall t. Binary t => t -> Put
put String
qs Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Integer -> Put
forall t. Binary t => t -> Put
put Integer
i
  get :: Get Ident
get = (SpanInfo -> String -> Integer -> Ident)
-> Get SpanInfo -> Get String -> Get Integer -> Get Ident
forall (m :: * -> *) a1 a2 a3 r.
Monad m =>
(a1 -> a2 -> a3 -> r) -> m a1 -> m a2 -> m a3 -> m r
liftM3 SpanInfo -> String -> Integer -> Ident
Ident Get SpanInfo
forall t. Binary t => Get t
get Get String
forall t. Binary t => Get t
get Get Integer
forall t. Binary t => Get t
get

identLength :: Ident -> Int
identLength :: Ident -> Int
identLength a :: Ident
a = String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (Ident -> String
idName Ident
a)

-- |Global scope for renaming
globalScope :: Integer
globalScope :: Integer
globalScope = 0

-- |Construct an 'Ident' from a 'String'
mkIdent :: String -> Ident
mkIdent :: String -> Ident
mkIdent x :: String
x = SpanInfo -> String -> Integer -> Ident
Ident SpanInfo
NoSpanInfo String
x Integer
globalScope

-- |Infinite list of different 'Ident's
identSupply :: [Ident]
identSupply :: [Ident]
identSupply = [ Char -> Integer -> Ident
forall a. (Eq a, Num a, Show a) => Char -> a -> Ident
mkNewIdent Char
c Integer
i | Integer
i <- [0 ..] :: [Integer], Char
c <- ['a'..'z'] ]
  where mkNewIdent :: Char -> a -> Ident
mkNewIdent c :: Char
c 0 = String -> Ident
mkIdent [Char
c]
        mkNewIdent c :: Char
c n :: a
n = String -> Ident
mkIdent (String -> Ident) -> String -> Ident
forall a b. (a -> b) -> a -> b
$ Char
c Char -> ShowS
forall a. a -> [a] -> [a]
: a -> String
forall a. Show a => a -> String
show a
n

-- |Show function for an 'Ident'
showIdent :: Ident -> String
showIdent :: Ident -> String
showIdent (Ident _ x :: String
x n :: Integer
n) | Integer
n Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
globalScope = String
x
                        | Bool
otherwise        = String
x String -> ShowS
forall a. [a] -> [a] -> [a]
++ '.' Char -> ShowS
forall a. a -> [a] -> [a]
: Integer -> String
forall a. Show a => a -> String
show Integer
n

-- |Show the name of an 'Ident' escaped by ticks
escName :: Ident -> String
escName :: Ident -> String
escName i :: Ident
i = '`' Char -> ShowS
forall a. a -> [a] -> [a]
: Ident -> String
idName Ident
i String -> ShowS
forall a. [a] -> [a] -> [a]
++ "'"

-- |Has the identifier global scope?
hasGlobalScope :: Ident -> Bool
hasGlobalScope :: Ident -> Bool
hasGlobalScope = (Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
globalScope) (Integer -> Bool) -> (Ident -> Integer) -> Ident -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ident -> Integer
idUnique

-- |Is the 'Ident' renamed?
isRenamed :: Ident -> Bool
isRenamed :: Ident -> Bool
isRenamed = (Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
/= Integer
globalScope) (Integer -> Bool) -> (Ident -> Integer) -> Ident -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ident -> Integer
idUnique

-- |Rename an 'Ident' by changing its unique number
renameIdent :: Ident -> Integer -> Ident
renameIdent :: Ident -> Integer -> Ident
renameIdent ident :: Ident
ident n :: Integer
n = Ident
ident { idUnique :: Integer
idUnique = Integer
n }

-- |Revert the renaming of an 'Ident' by resetting its unique number
unRenameIdent :: Ident -> Ident
unRenameIdent :: Ident -> Ident
unRenameIdent ident :: Ident
ident = Ident -> Integer -> Ident
renameIdent Ident
ident Integer
globalScope

-- |Change the name of an 'Ident' using a renaming function
updIdentName :: (String -> String) -> Ident -> Ident
updIdentName :: ShowS -> Ident -> Ident
updIdentName f :: ShowS
f (Ident p :: SpanInfo
p n :: String
n i :: Integer
i) = SpanInfo -> String -> Integer -> Ident
Ident SpanInfo
p (ShowS
f String
n) Integer
i

-- |Add a 'Position' to an 'Ident'
addPositionIdent :: Position -> Ident -> Ident
addPositionIdent :: Position -> Ident -> Ident
addPositionIdent = Position -> Ident -> Ident
forall a. HasPosition a => Position -> a -> a
setPosition

-- |Check whether an 'Ident' identifies an infix operation
isInfixOp :: Ident -> Bool
isInfixOp :: Ident -> Bool
isInfixOp (Ident _ ('<' : c :: Char
c : cs :: String
cs) _) =
  String -> Char
forall a. [a] -> a
last (Char
c Char -> ShowS
forall a. a -> [a] -> [a]
: String
cs) Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= '>' Bool -> Bool -> Bool
|| Bool -> Bool
not (Char -> Bool
isAlphaNum Char
c) Bool -> Bool -> Bool
&& Char
c Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` "_(["
isInfixOp (Ident _ (c :: Char
c : _) _)    = Bool -> Bool
not (Char -> Bool
isAlphaNum Char
c) Bool -> Bool -> Bool
&& Char
c Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` "_(["
isInfixOp Ident{}                = Bool
False -- error "Zero-length identifier"

-- ---------------------------------------------------------------------------
-- Qualified identifier
-- ---------------------------------------------------------------------------

-- |Qualified identifier
data QualIdent = QualIdent
  { QualIdent -> SpanInfo
qidSpanInfo :: SpanInfo          -- ^ Source code 'SpanInfo'
  , QualIdent -> Maybe ModuleIdent
qidModule   :: Maybe ModuleIdent -- ^ optional module identifier
  , QualIdent -> Ident
qidIdent    :: Ident             -- ^ identifier itself
  } deriving (ReadPrec [QualIdent]
ReadPrec QualIdent
Int -> ReadS QualIdent
ReadS [QualIdent]
(Int -> ReadS QualIdent)
-> ReadS [QualIdent]
-> ReadPrec QualIdent
-> ReadPrec [QualIdent]
-> Read QualIdent
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [QualIdent]
$creadListPrec :: ReadPrec [QualIdent]
readPrec :: ReadPrec QualIdent
$creadPrec :: ReadPrec QualIdent
readList :: ReadS [QualIdent]
$creadList :: ReadS [QualIdent]
readsPrec :: Int -> ReadS QualIdent
$creadsPrec :: Int -> ReadS QualIdent
Read, Int -> QualIdent -> ShowS
[QualIdent] -> ShowS
QualIdent -> String
(Int -> QualIdent -> ShowS)
-> (QualIdent -> String)
-> ([QualIdent] -> ShowS)
-> Show QualIdent
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [QualIdent] -> ShowS
$cshowList :: [QualIdent] -> ShowS
show :: QualIdent -> String
$cshow :: QualIdent -> String
showsPrec :: Int -> QualIdent -> ShowS
$cshowsPrec :: Int -> QualIdent -> ShowS
Show)

instance Eq QualIdent where
  QualIdent _ m :: Maybe ModuleIdent
m i :: Ident
i == :: QualIdent -> QualIdent -> Bool
== QualIdent _ n :: Maybe ModuleIdent
n j :: Ident
j = (Maybe ModuleIdent
m, Ident
i) (Maybe ModuleIdent, Ident) -> (Maybe ModuleIdent, Ident) -> Bool
forall a. Eq a => a -> a -> Bool
== (Maybe ModuleIdent
n, Ident
j)

instance Ord QualIdent where
  QualIdent _ m :: Maybe ModuleIdent
m i :: Ident
i compare :: QualIdent -> QualIdent -> Ordering
`compare` QualIdent _ n :: Maybe ModuleIdent
n j :: Ident
j = (Maybe ModuleIdent
m, Ident
i) (Maybe ModuleIdent, Ident)
-> (Maybe ModuleIdent, Ident) -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare` (Maybe ModuleIdent
n, Ident
j)

instance HasSpanInfo QualIdent where
  getSpanInfo :: QualIdent -> SpanInfo
getSpanInfo = QualIdent -> SpanInfo
qidSpanInfo
  setSpanInfo :: SpanInfo -> QualIdent -> QualIdent
setSpanInfo spi :: SpanInfo
spi a :: QualIdent
a = QualIdent
a { qidSpanInfo :: SpanInfo
qidSpanInfo = SpanInfo
spi }
  updateEndPos :: QualIdent -> QualIdent
updateEndPos i :: QualIdent
i@(QualIdent (SpanInfo _ [_,ss :: Span
ss]) _ _) =
    Position -> QualIdent -> QualIdent
forall a. HasSpanInfo a => Position -> a -> a
setEndPosition (Span -> Position
end Span
ss) QualIdent
i
  updateEndPos i :: QualIdent
i =
    Position -> QualIdent -> QualIdent
forall a. HasSpanInfo a => Position -> a -> a
setEndPosition (Position -> Int -> Position
incr (QualIdent -> Position
forall a. HasPosition a => a -> Position
getPosition QualIdent
i) (QualIdent -> Int
qIdentLength QualIdent
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- 1)) QualIdent
i

instance HasPosition QualIdent where
  getPosition :: QualIdent -> Position
getPosition = QualIdent -> Position
forall a. HasSpanInfo a => a -> Position
getStartPosition
  setPosition :: Position -> QualIdent -> QualIdent
setPosition = Position -> QualIdent -> QualIdent
forall a. HasSpanInfo a => Position -> a -> a
setStartPosition

instance Pretty QualIdent where
  pPrint :: QualIdent -> Doc
pPrint = String -> Doc
text (String -> Doc) -> (QualIdent -> String) -> QualIdent -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. QualIdent -> String
qualName

instance Binary QualIdent where
  put :: QualIdent -> Put
put (QualIdent sp :: SpanInfo
sp mid :: Maybe ModuleIdent
mid idt :: Ident
idt) = SpanInfo -> Put
forall t. Binary t => t -> Put
put SpanInfo
sp Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Maybe ModuleIdent -> Put
forall t. Binary t => t -> Put
put Maybe ModuleIdent
mid Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Ident -> Put
forall t. Binary t => t -> Put
put Ident
idt
  get :: Get QualIdent
get = (SpanInfo -> Maybe ModuleIdent -> Ident -> QualIdent)
-> Get SpanInfo
-> Get (Maybe ModuleIdent)
-> Get Ident
-> Get QualIdent
forall (m :: * -> *) a1 a2 a3 r.
Monad m =>
(a1 -> a2 -> a3 -> r) -> m a1 -> m a2 -> m a3 -> m r
liftM3 SpanInfo -> Maybe ModuleIdent -> Ident -> QualIdent
QualIdent Get SpanInfo
forall t. Binary t => Get t
get Get (Maybe ModuleIdent)
forall t. Binary t => Get t
get Get Ident
forall t. Binary t => Get t
get

qIdentLength :: QualIdent -> Int
qIdentLength :: QualIdent -> Int
qIdentLength (QualIdent _ (Just m :: ModuleIdent
m) i :: Ident
i) = Ident -> Int
identLength Ident
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ ModuleIdent -> Int
mIdentLength ModuleIdent
m
qIdentLength (QualIdent _ Nothing  i :: Ident
i) = Ident -> Int
identLength Ident
i

-- |show function for qualified identifiers)=
qualName :: QualIdent -> String
qualName :: QualIdent -> String
qualName (QualIdent _ Nothing  x :: Ident
x) = Ident -> String
idName Ident
x
qualName (QualIdent _ (Just m :: ModuleIdent
m) x :: Ident
x) = ModuleIdent -> String
moduleName ModuleIdent
m String -> ShowS
forall a. [a] -> [a] -> [a]
++ "." String -> ShowS
forall a. [a] -> [a] -> [a]
++ Ident -> String
idName Ident
x

-- |Show the name of an 'QualIdent' escaped by ticks
escQualName :: QualIdent -> String
escQualName :: QualIdent -> String
escQualName qn :: QualIdent
qn = '`' Char -> ShowS
forall a. a -> [a] -> [a]
: QualIdent -> String
qualName QualIdent
qn String -> ShowS
forall a. [a] -> [a] -> [a]
++ "'"

-- |Check whether an 'QualIdent' identifies an infix operation
isQInfixOp :: QualIdent -> Bool
isQInfixOp :: QualIdent -> Bool
isQInfixOp = Ident -> Bool
isInfixOp (Ident -> Bool) -> (QualIdent -> Ident) -> QualIdent -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. QualIdent -> Ident
qidIdent

-- ---------------------------------------------------------------------------
-- The functions \texttt{qualify} and \texttt{qualifyWith} convert an
-- unqualified identifier into a qualified identifier (without and with a
-- given module prefix, respectively).
-- ---------------------------------------------------------------------------

-- | Convert an 'Ident' to a 'QualIdent'
qualify :: Ident -> QualIdent
qualify :: Ident -> QualIdent
qualify i :: Ident
i = SpanInfo -> Maybe ModuleIdent -> Ident -> QualIdent
QualIdent (Span -> SpanInfo
fromSrcSpan (Ident -> Span
forall a. HasSpanInfo a => a -> Span
getSrcSpan Ident
i)) Maybe ModuleIdent
forall a. Maybe a
Nothing Ident
i

-- | Convert an 'Ident' to a 'QualIdent' with a given 'ModuleIdent'
qualifyWith :: ModuleIdent -> Ident -> QualIdent
qualifyWith :: ModuleIdent -> Ident -> QualIdent
qualifyWith mid :: ModuleIdent
mid i :: Ident
i = QualIdent -> QualIdent
forall a. HasSpanInfo a => a -> a
updateEndPos (QualIdent -> QualIdent) -> QualIdent -> QualIdent
forall a b. (a -> b) -> a -> b
$
  SpanInfo -> Maybe ModuleIdent -> Ident -> QualIdent
QualIdent (Span -> SpanInfo
fromSrcSpan (ModuleIdent -> Span
forall a. HasSpanInfo a => a -> Span
getSrcSpan ModuleIdent
mid)) (ModuleIdent -> Maybe ModuleIdent
forall a. a -> Maybe a
Just ModuleIdent
mid) Ident
i

-- | Convert an 'QualIdent' to a new 'QualIdent' with a given 'ModuleIdent'.
--   If the original 'QualIdent' already contains an 'ModuleIdent' it
--   remains unchanged.
qualQualify :: ModuleIdent -> QualIdent -> QualIdent
qualQualify :: ModuleIdent -> QualIdent -> QualIdent
qualQualify m :: ModuleIdent
m (QualIdent _ Nothing x :: Ident
x) = ModuleIdent -> Ident -> QualIdent
qualifyWith ModuleIdent
m Ident
x
qualQualify _ x :: QualIdent
x = QualIdent
x

-- |Qualify an 'Ident' with the 'ModuleIdent' of the given 'QualIdent',
-- if present.
qualifyLike :: QualIdent -> Ident -> QualIdent
qualifyLike :: QualIdent -> Ident -> QualIdent
qualifyLike (QualIdent _ Nothing  _) x :: Ident
x = Ident -> QualIdent
qualify Ident
x
qualifyLike (QualIdent _ (Just m :: ModuleIdent
m) _) x :: Ident
x = ModuleIdent -> Ident -> QualIdent
qualifyWith ModuleIdent
m Ident
x

-- | Check whether a 'QualIdent' contains a 'ModuleIdent'
isQualified :: QualIdent -> Bool
isQualified :: QualIdent -> Bool
isQualified = Maybe ModuleIdent -> Bool
forall a. Maybe a -> Bool
isJust (Maybe ModuleIdent -> Bool)
-> (QualIdent -> Maybe ModuleIdent) -> QualIdent -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. QualIdent -> Maybe ModuleIdent
qidModule

-- | Remove the qualification of an 'QualIdent'
unqualify :: QualIdent -> Ident
unqualify :: QualIdent -> Ident
unqualify = QualIdent -> Ident
qidIdent

-- | Remove the qualification with a specific 'ModuleIdent'. If the
--   original 'QualIdent' has no 'ModuleIdent' or a different one, it
--   remains unchanged.
qualUnqualify :: ModuleIdent -> QualIdent -> QualIdent
qualUnqualify :: ModuleIdent -> QualIdent -> QualIdent
qualUnqualify _ qid :: QualIdent
qid@(QualIdent _   Nothing   _) = QualIdent
qid
qualUnqualify m :: ModuleIdent
m     (QualIdent spi :: SpanInfo
spi (Just m' :: ModuleIdent
m') x :: Ident
x) = SpanInfo -> Maybe ModuleIdent -> Ident -> QualIdent
QualIdent SpanInfo
spi Maybe ModuleIdent
m'' Ident
x
  where m'' :: Maybe ModuleIdent
m'' | ModuleIdent
m ModuleIdent -> ModuleIdent -> Bool
forall a. Eq a => a -> a -> Bool
== ModuleIdent
m'   = Maybe ModuleIdent
forall a. Maybe a
Nothing
            | Bool
otherwise = ModuleIdent -> Maybe ModuleIdent
forall a. a -> Maybe a
Just ModuleIdent
m'

-- | Extract the 'Ident' of an 'QualIdent' if it is local to the
--   'ModuleIdent', i.e. if the 'Ident' is either unqualified or qualified
--   with the given 'ModuleIdent'.
localIdent :: ModuleIdent -> QualIdent -> Maybe Ident
localIdent :: ModuleIdent -> QualIdent -> Maybe Ident
localIdent _ (QualIdent _ Nothing   x :: Ident
x) = Ident -> Maybe Ident
forall a. a -> Maybe a
Just Ident
x
localIdent m :: ModuleIdent
m (QualIdent _ (Just m' :: ModuleIdent
m') x :: Ident
x)
  | ModuleIdent
m ModuleIdent -> ModuleIdent -> Bool
forall a. Eq a => a -> a -> Bool
== ModuleIdent
m'   = Ident -> Maybe Ident
forall a. a -> Maybe a
Just Ident
x
  | Bool
otherwise = Maybe Ident
forall a. Maybe a
Nothing

-- |Check whether the given 'QualIdent' is local to the given 'ModuleIdent'.
isLocalIdent :: ModuleIdent -> QualIdent -> Bool
isLocalIdent :: ModuleIdent -> QualIdent -> Bool
isLocalIdent mid :: ModuleIdent
mid qid :: QualIdent
qid = Maybe Ident -> Bool
forall a. Maybe a -> Bool
isJust (ModuleIdent -> QualIdent -> Maybe Ident
localIdent ModuleIdent
mid QualIdent
qid)

-- | Update a 'QualIdent' by applying functions to its components
updQualIdent :: (ModuleIdent -> ModuleIdent) -> (Ident -> Ident)
             -> QualIdent -> QualIdent
updQualIdent :: (ModuleIdent -> ModuleIdent)
-> (Ident -> Ident) -> QualIdent -> QualIdent
updQualIdent f :: ModuleIdent -> ModuleIdent
f g :: Ident -> Ident
g (QualIdent spi :: SpanInfo
spi m :: Maybe ModuleIdent
m x :: Ident
x) = SpanInfo -> Maybe ModuleIdent -> Ident -> QualIdent
QualIdent SpanInfo
spi ((ModuleIdent -> ModuleIdent)
-> Maybe ModuleIdent -> Maybe ModuleIdent
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ModuleIdent -> ModuleIdent
f Maybe ModuleIdent
m) (Ident -> Ident
g Ident
x)

-- ---------------------------------------------------------------------------
-- A few identifiers are predefined here.
-- ---------------------------------------------------------------------------
-- | 'ModuleIdent' for the empty module
emptyMIdent :: ModuleIdent
emptyMIdent :: ModuleIdent
emptyMIdent = SpanInfo -> [String] -> ModuleIdent
ModuleIdent SpanInfo
NoSpanInfo []

-- | 'ModuleIdent' for the main module
mainMIdent :: ModuleIdent
mainMIdent :: ModuleIdent
mainMIdent = SpanInfo -> [String] -> ModuleIdent
ModuleIdent SpanInfo
NoSpanInfo ["main"]

-- | 'ModuleIdent' for the Prelude
preludeMIdent :: ModuleIdent
preludeMIdent :: ModuleIdent
preludeMIdent = SpanInfo -> [String] -> ModuleIdent
ModuleIdent SpanInfo
NoSpanInfo ["Prelude"]

-- ---------------------------------------------------------------------------
-- Identifiers for types
-- ---------------------------------------------------------------------------

-- | 'Ident' for the type '(->)'
arrowId :: Ident
arrowId :: Ident
arrowId = String -> Ident
mkIdent "(->)"

-- | 'Ident' for the type/value unit ('()')
unitId :: Ident
unitId :: Ident
unitId = String -> Ident
mkIdent "()"

-- | 'Ident' for the type 'Bool'
boolId :: Ident
boolId :: Ident
boolId = String -> Ident
mkIdent "Bool"

-- | 'Ident' for the type 'Char'
charId :: Ident
charId :: Ident
charId = String -> Ident
mkIdent "Char"

-- | 'Ident' for the type 'Int'
intId :: Ident
intId :: Ident
intId = String -> Ident
mkIdent "Int"

-- | 'Ident' for the type 'Float'
floatId :: Ident
floatId :: Ident
floatId = String -> Ident
mkIdent "Float"

-- | 'Ident' for the type '[]'
listId :: Ident
listId :: Ident
listId = String -> Ident
mkIdent "[]"

-- | 'Ident' for the type 'IO'
ioId :: Ident
ioId :: Ident
ioId = String -> Ident
mkIdent "IO"

-- | 'Ident' for the type 'Success'
successId :: Ident
successId :: Ident
successId = String -> Ident
mkIdent "Success"

-- | Construct an 'Ident' for an n-ary tuple where n > 1
tupleId :: Int -> Ident
tupleId :: Int -> Ident
tupleId n :: Int
n
  | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> 1     = String -> Ident
mkIdent (String -> Ident) -> String -> Ident
forall a b. (a -> b) -> a -> b
$ '(' Char -> ShowS
forall a. a -> [a] -> [a]
: Int -> Char -> String
forall a. Int -> a -> [a]
replicate (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- 1) ',' String -> ShowS
forall a. [a] -> [a] -> [a]
++ ")"
  | Bool
otherwise = String -> Ident
forall a. HasCallStack => String -> a
error (String -> Ident) -> String -> Ident
forall a b. (a -> b) -> a -> b
$ "Curry.Base.Ident.tupleId: wrong arity " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
n

-- | Check whether an 'Ident' is an identifier for an tuple type
isTupleId :: Ident -> Bool
isTupleId :: Ident -> Bool
isTupleId (Ident _ x :: String
x _) = Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> 1 Bool -> Bool -> Bool
&& String
x String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== Ident -> String
idName (Int -> Ident
tupleId Int
n)
  where n :: Int
n = String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
x Int -> Int -> Int
forall a. Num a => a -> a -> a
- 1

-- | Compute the arity of a tuple identifier
tupleArity :: Ident -> Int
tupleArity :: Ident -> Int
tupleArity i :: Ident
i@(Ident _ x :: String
x _)
  | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> 1 Bool -> Bool -> Bool
&& String
x String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== Ident -> String
idName (Int -> Ident
tupleId Int
n) = Int
n
  | Bool
otherwise                        = String -> Int
forall a. HasCallStack => String -> a
error (String -> Int) -> String -> Int
forall a b. (a -> b) -> a -> b
$
      "Curry.Base.Ident.tupleArity: no tuple identifier: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Ident -> String
showIdent Ident
i
  where n :: Int
n = String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
x Int -> Int -> Int
forall a. Num a => a -> a -> a
- 1

-- ---------------------------------------------------------------------------
-- Identifiers for type classes
-- ---------------------------------------------------------------------------

-- | 'Ident' for the 'Eq' class
eqId :: Ident
eqId :: Ident
eqId = String -> Ident
mkIdent "Eq"

-- | 'Ident' for the 'Ord' class
ordId :: Ident
ordId :: Ident
ordId = String -> Ident
mkIdent "Ord"

-- | 'Ident' for the 'Enum' class
enumId :: Ident
enumId :: Ident
enumId = String -> Ident
mkIdent "Enum"

-- | 'Ident' for the 'Bounded' class
boundedId :: Ident
boundedId :: Ident
boundedId = String -> Ident
mkIdent "Bounded"

-- | 'Ident' for the 'Read' class
readId :: Ident
readId :: Ident
readId = String -> Ident
mkIdent "Read"

-- | 'Ident' for the 'Show' class
showId :: Ident
showId :: Ident
showId = String -> Ident
mkIdent "Show"

-- | 'Ident' for the 'Num' class
numId :: Ident
numId :: Ident
numId = String -> Ident
mkIdent "Num"

-- | 'Ident' for the 'Fractional' class
fractionalId :: Ident
fractionalId :: Ident
fractionalId = String -> Ident
mkIdent "Fractional"

-- | 'Ident' for the 'Monad' class
monadId :: Ident
monadId :: Ident
monadId = String -> Ident
mkIdent "Monad"

-- | 'Ident' for the 'MonadFail' class
monadFailId :: Ident
monadFailId :: Ident
monadFailId = String -> Ident
mkIdent "MonadFail"

-- | 'Ident' for the 'Data' class
dataId :: Ident
dataId :: Ident
dataId = String -> Ident
mkIdent "Data"

-- ---------------------------------------------------------------------------
-- Identifiers for constructors
-- ---------------------------------------------------------------------------

-- | 'Ident' for the value 'True'
trueId :: Ident
trueId :: Ident
trueId = String -> Ident
mkIdent "True"

-- | 'Ident' for the value 'False'
falseId :: Ident
falseId :: Ident
falseId = String -> Ident
mkIdent "False"

-- | 'Ident' for the value '[]'
nilId :: Ident
nilId :: Ident
nilId = String -> Ident
mkIdent "[]"

-- | 'Ident' for the function ':'
consId :: Ident
consId :: Ident
consId = String -> Ident
mkIdent ":"

-- ---------------------------------------------------------------------------
-- Identifiers for values
-- ---------------------------------------------------------------------------

-- | 'Ident' for the main function
mainId :: Ident
mainId :: Ident
mainId = String -> Ident
mkIdent "main"

-- | 'Ident' for the minus function
minusId :: Ident
minusId :: Ident
minusId = String -> Ident
mkIdent "-"

-- | 'Ident' for the minus function for Floats
fminusId :: Ident
fminusId :: Ident
fminusId = String -> Ident
mkIdent "-."

-- | 'Ident' for the apply function
applyId :: Ident
applyId :: Ident
applyId = String -> Ident
mkIdent "apply"

-- | 'Ident' for the error function
errorId :: Ident
errorId :: Ident
errorId = String -> Ident
mkIdent "error"

-- | 'Ident' for the failed function
failedId :: Ident
failedId :: Ident
failedId = String -> Ident
mkIdent "failed"

-- | 'Ident' for the id function
idId :: Ident
idId :: Ident
idId = String -> Ident
mkIdent "id"

-- | 'Ident' for the maxBound function
maxBoundId :: Ident
maxBoundId :: Ident
maxBoundId = String -> Ident
mkIdent "maxBound"

-- | 'Ident' for the minBound function
minBoundId :: Ident
minBoundId :: Ident
minBoundId = String -> Ident
mkIdent "minBound"

-- | 'Ident' for the pred function
predId :: Ident
predId :: Ident
predId = String -> Ident
mkIdent "pred"

-- | 'Ident' for the succ function
succId :: Ident
succId :: Ident
succId = String -> Ident
mkIdent "succ"

-- | 'Ident' for the toEnum function
toEnumId :: Ident
toEnumId :: Ident
toEnumId = String -> Ident
mkIdent "toEnum"

-- | 'Ident' for the fromEnum function
fromEnumId :: Ident
fromEnumId :: Ident
fromEnumId = String -> Ident
mkIdent "fromEnum"

-- | 'Ident' for the enumFrom function
enumFromId :: Ident
enumFromId :: Ident
enumFromId = String -> Ident
mkIdent "enumFrom"

-- | 'Ident' for the enumFromThen function
enumFromThenId :: Ident
enumFromThenId :: Ident
enumFromThenId = String -> Ident
mkIdent "enumFromThen"

-- | 'Ident' for the enumFromTo function
enumFromToId :: Ident
enumFromToId :: Ident
enumFromToId = String -> Ident
mkIdent "enumFromTo"

-- | 'Ident' for the enumFromThenTo function
enumFromThenToId :: Ident
enumFromThenToId :: Ident
enumFromThenToId = String -> Ident
mkIdent "enumFromThenTo"

-- | 'Ident' for the lex function
lexId :: Ident
lexId :: Ident
lexId = String -> Ident
mkIdent "lex"

-- | 'Ident' for the readsPrec function
readsPrecId :: Ident
readsPrecId :: Ident
readsPrecId = String -> Ident
mkIdent "readsPrec"

-- | 'Ident' for the readParen function
readParenId :: Ident
readParenId :: Ident
readParenId = String -> Ident
mkIdent "readParen"

-- | 'Ident' for the showsPrec function
showsPrecId :: Ident
showsPrecId :: Ident
showsPrecId = String -> Ident
mkIdent "showsPrec"

-- | 'Ident' for the showParen function
showParenId :: Ident
showParenId :: Ident
showParenId = String -> Ident
mkIdent "showParen"

-- | 'Ident' for the showString function
showStringId :: Ident
showStringId :: Ident
showStringId = String -> Ident
mkIdent "showString"

-- | 'Ident' for the '&&' operator
andOpId :: Ident
andOpId :: Ident
andOpId = String -> Ident
mkIdent "&&"

-- | 'Ident' for the '==' operator
eqOpId :: Ident
eqOpId :: Ident
eqOpId = String -> Ident
mkIdent "=="

-- | 'Ident' for the '<=' operator
leqOpId :: Ident
leqOpId :: Ident
leqOpId = String -> Ident
mkIdent "<="

-- | 'Ident' for the '<' operator
ltOpId :: Ident
ltOpId :: Ident
ltOpId = String -> Ident
mkIdent "<"

-- | 'Ident' for the '||' operator
orOpId :: Ident
orOpId :: Ident
orOpId = String -> Ident
mkIdent "||"

-- | 'Ident' for the '++' operator
appendOpId :: Ident
appendOpId :: Ident
appendOpId = String -> Ident
mkIdent "++"

-- | 'Ident' for the '.' operator
dotOpId :: Ident
dotOpId :: Ident
dotOpId = String -> Ident
mkIdent "."

aValueId :: Ident
aValueId :: Ident
aValueId = String -> Ident
mkIdent "aValue"

dataEqId :: Ident
dataEqId :: Ident
dataEqId = String -> Ident
mkIdent "==="

-- | 'Ident' for anonymous variable
anonId :: Ident
anonId :: Ident
anonId = String -> Ident
mkIdent "_"

-- |Check whether an 'Ident' represents an anonymous identifier ('anonId')
isAnonId :: Ident -> Bool
isAnonId :: Ident -> Bool
isAnonId = (Ident -> Ident -> Bool
forall a. Eq a => a -> a -> Bool
== Ident
anonId) (Ident -> Bool) -> (Ident -> Ident) -> Ident -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ident -> Ident
unRenameIdent

-- ---------------------------------------------------------------------------
-- Qualified Identifiers for types
-- ---------------------------------------------------------------------------

-- | Construct a 'QualIdent' for an 'Ident' using the module prelude
qPreludeIdent :: Ident -> QualIdent
qPreludeIdent :: Ident -> QualIdent
qPreludeIdent = ModuleIdent -> Ident -> QualIdent
qualifyWith ModuleIdent
preludeMIdent

-- | 'QualIdent' for the type '(->)'
qArrowId :: QualIdent
qArrowId :: QualIdent
qArrowId = Ident -> QualIdent
qualify Ident
arrowId

-- | 'QualIdent' for the type/value unit ('()')
qUnitId :: QualIdent
qUnitId :: QualIdent
qUnitId = Ident -> QualIdent
qualify Ident
unitId

-- | 'QualIdent' for the type '[]'
qListId :: QualIdent
qListId :: QualIdent
qListId = Ident -> QualIdent
qualify Ident
listId

-- | 'QualIdent' for the type 'Bool'
qBoolId :: QualIdent
qBoolId :: QualIdent
qBoolId = Ident -> QualIdent
qPreludeIdent Ident
boolId

-- | 'QualIdent' for the type 'Char'
qCharId :: QualIdent
qCharId :: QualIdent
qCharId = Ident -> QualIdent
qPreludeIdent Ident
charId

-- | 'QualIdent' for the type 'Int'
qIntId :: QualIdent
qIntId :: QualIdent
qIntId = Ident -> QualIdent
qPreludeIdent Ident
intId

-- | 'QualIdent' for the type 'Float'
qFloatId :: QualIdent
qFloatId :: QualIdent
qFloatId = Ident -> QualIdent
qPreludeIdent Ident
floatId

-- | 'QualIdent' for the type 'IO'
qIOId :: QualIdent
qIOId :: QualIdent
qIOId = Ident -> QualIdent
qPreludeIdent Ident
ioId

-- | 'QualIdent' for the type 'Success'
qSuccessId :: QualIdent
qSuccessId :: QualIdent
qSuccessId = Ident -> QualIdent
qPreludeIdent Ident
successId

-- | Check whether an 'QualIdent' is an primary type constructor
isPrimTypeId :: QualIdent -> Bool
isPrimTypeId :: QualIdent -> Bool
isPrimTypeId tc :: QualIdent
tc = QualIdent
tc QualIdent -> [QualIdent] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [QualIdent
qArrowId, QualIdent
qUnitId, QualIdent
qListId] Bool -> Bool -> Bool
|| QualIdent -> Bool
isQTupleId QualIdent
tc

-- ---------------------------------------------------------------------------
-- Qualified Identifiers for type classes
-- ---------------------------------------------------------------------------

-- | 'QualIdent' for the 'Eq' class
qEqId :: QualIdent
qEqId :: QualIdent
qEqId = Ident -> QualIdent
qPreludeIdent Ident
eqId

-- | 'QualIdent' for the 'Ord' class
qOrdId :: QualIdent
qOrdId :: QualIdent
qOrdId = Ident -> QualIdent
qPreludeIdent Ident
ordId

-- | 'QualIdent' for the 'Enum' class
qEnumId :: QualIdent
qEnumId :: QualIdent
qEnumId = Ident -> QualIdent
qPreludeIdent Ident
enumId

-- | 'QualIdent' for the 'Bounded' class
qBoundedId :: QualIdent
qBoundedId :: QualIdent
qBoundedId = Ident -> QualIdent
qPreludeIdent Ident
boundedId

-- | 'QualIdent' for the 'Read' class
qReadId :: QualIdent
qReadId :: QualIdent
qReadId = Ident -> QualIdent
qPreludeIdent Ident
readId

-- | 'QualIdent' for the 'Show' class
qShowId :: QualIdent
qShowId :: QualIdent
qShowId = Ident -> QualIdent
qPreludeIdent Ident
showId

-- | 'QualIdent' for the 'Num' class
qNumId :: QualIdent
qNumId :: QualIdent
qNumId = Ident -> QualIdent
qPreludeIdent Ident
numId

-- | 'QualIdent' for the 'Fractional' class
qFractionalId :: QualIdent
qFractionalId :: QualIdent
qFractionalId = Ident -> QualIdent
qPreludeIdent Ident
fractionalId

-- | 'QualIdent' for the 'Monad' class
qMonadId :: QualIdent
qMonadId :: QualIdent
qMonadId = Ident -> QualIdent
qPreludeIdent Ident
monadId

-- | 'QualIdent' for the 'MonadFail' class
qMonadFailId :: QualIdent
qMonadFailId :: QualIdent
qMonadFailId = Ident -> QualIdent
qPreludeIdent Ident
monadFailId

-- | 'QualIdent' for the 'Data' class
qDataId :: QualIdent
qDataId :: QualIdent
qDataId = Ident -> QualIdent
qPreludeIdent Ident
dataId

-- ---------------------------------------------------------------------------
-- Qualified Identifiers for constructors
-- ---------------------------------------------------------------------------

-- | 'QualIdent' for the constructor 'True'
qTrueId :: QualIdent
qTrueId :: QualIdent
qTrueId = Ident -> QualIdent
qPreludeIdent Ident
trueId

-- | 'QualIdent' for the constructor 'False'
qFalseId :: QualIdent
qFalseId :: QualIdent
qFalseId = Ident -> QualIdent
qPreludeIdent Ident
falseId

-- | 'QualIdent' for the constructor '[]'
qNilId :: QualIdent
qNilId :: QualIdent
qNilId = Ident -> QualIdent
qualify Ident
nilId

-- | 'QualIdent' for the constructor ':'
qConsId :: QualIdent
qConsId :: QualIdent
qConsId = Ident -> QualIdent
qualify Ident
consId

-- | 'QualIdent' for the type of n-ary tuples
qTupleId :: Int -> QualIdent
qTupleId :: Int -> QualIdent
qTupleId = Ident -> QualIdent
qualify (Ident -> QualIdent) -> (Int -> Ident) -> Int -> QualIdent
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Ident
tupleId

-- | Check whether an 'QualIdent' is an identifier for an tuple type
isQTupleId :: QualIdent -> Bool
isQTupleId :: QualIdent -> Bool
isQTupleId = Ident -> Bool
isTupleId (Ident -> Bool) -> (QualIdent -> Ident) -> QualIdent -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. QualIdent -> Ident
unqualify

-- | Compute the arity of an qualified tuple identifier
qTupleArity :: QualIdent -> Int
qTupleArity :: QualIdent -> Int
qTupleArity = Ident -> Int
tupleArity (Ident -> Int) -> (QualIdent -> Ident) -> QualIdent -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. QualIdent -> Ident
unqualify

-- ---------------------------------------------------------------------------
-- Qualified Identifiers for values
-- ---------------------------------------------------------------------------

-- | 'QualIdent' for the apply function
qApplyId :: QualIdent
qApplyId :: QualIdent
qApplyId = Ident -> QualIdent
qPreludeIdent Ident
applyId

-- | 'QualIdent' for the error function
qErrorId :: QualIdent
qErrorId :: QualIdent
qErrorId = Ident -> QualIdent
qPreludeIdent Ident
errorId

-- | 'QualIdent' for the failed function
qFailedId :: QualIdent
qFailedId :: QualIdent
qFailedId = Ident -> QualIdent
qPreludeIdent Ident
failedId

-- | 'QualIdent' for the id function
qIdId :: QualIdent
qIdId :: QualIdent
qIdId = Ident -> QualIdent
qPreludeIdent Ident
idId

-- | 'QualIdent' for the maxBound function
qMaxBoundId :: QualIdent
qMaxBoundId :: QualIdent
qMaxBoundId = Ident -> QualIdent
qPreludeIdent Ident
maxBoundId

-- | 'QualIdent' for the minBound function
qMinBoundId :: QualIdent
qMinBoundId :: QualIdent
qMinBoundId = Ident -> QualIdent
qPreludeIdent Ident
minBoundId

-- | 'QualIdent' for the fromEnum function
qFromEnumId :: QualIdent
qFromEnumId :: QualIdent
qFromEnumId = Ident -> QualIdent
qPreludeIdent Ident
fromEnumId

-- | 'QualIdent' for the enumFrom function
qEnumFromId :: QualIdent
qEnumFromId :: QualIdent
qEnumFromId = Ident -> QualIdent
qPreludeIdent Ident
enumFromId

-- | 'QualIdent' for the enumFromThen function
qEnumFromThenId :: QualIdent
qEnumFromThenId :: QualIdent
qEnumFromThenId = Ident -> QualIdent
qPreludeIdent Ident
enumFromThenId

-- | 'QualIdent' for the enumFromTo function
qEnumFromToId :: QualIdent
qEnumFromToId :: QualIdent
qEnumFromToId = Ident -> QualIdent
qPreludeIdent Ident
enumFromToId

-- | 'QualIdent' for the enumFromThenTo function
qEnumFromThenToId :: QualIdent
qEnumFromThenToId :: QualIdent
qEnumFromThenToId = Ident -> QualIdent
qPreludeIdent Ident
enumFromThenToId

-- | 'QualIdent' for the lex function
qLexId :: QualIdent
qLexId :: QualIdent
qLexId = Ident -> QualIdent
qPreludeIdent Ident
lexId

-- | 'QualIdent' for the readsPrec function
qReadsPrecId :: QualIdent
qReadsPrecId :: QualIdent
qReadsPrecId = Ident -> QualIdent
qPreludeIdent Ident
readsPrecId

-- | 'QualIdent' for the readParen function
qReadParenId :: QualIdent
qReadParenId :: QualIdent
qReadParenId = Ident -> QualIdent
qPreludeIdent Ident
readParenId

-- | 'QualIdent' for the showsPrec function
qShowsPrecId :: QualIdent
qShowsPrecId :: QualIdent
qShowsPrecId = Ident -> QualIdent
qPreludeIdent Ident
showsPrecId

-- | 'QualIdent' for the showParen function
qShowParenId :: QualIdent
qShowParenId :: QualIdent
qShowParenId = Ident -> QualIdent
qPreludeIdent Ident
showParenId

-- | 'QualIdent' for the showString function
qShowStringId :: QualIdent
qShowStringId :: QualIdent
qShowStringId = Ident -> QualIdent
qPreludeIdent Ident
showStringId

-- | 'QualIdent' for the '&&' operator
qAndOpId :: QualIdent
qAndOpId :: QualIdent
qAndOpId = Ident -> QualIdent
qPreludeIdent Ident
andOpId

-- | 'QualIdent' for the '==' operator
qEqOpId :: QualIdent
qEqOpId :: QualIdent
qEqOpId = Ident -> QualIdent
qPreludeIdent Ident
eqOpId

-- | 'QualIdent' for the '<=' operator
qLeqOpId :: QualIdent
qLeqOpId :: QualIdent
qLeqOpId = Ident -> QualIdent
qPreludeIdent Ident
leqOpId

-- | 'QualIdent' for the '<' operator
qLtOpId :: QualIdent
qLtOpId :: QualIdent
qLtOpId = Ident -> QualIdent
qPreludeIdent Ident
ltOpId

-- | 'QualIdent' for the '||' operator
qOrOpId :: QualIdent
qOrOpId :: QualIdent
qOrOpId = Ident -> QualIdent
qPreludeIdent Ident
orOpId

-- | 'QualIdent' for the '.' operator
qDotOpId :: QualIdent
qDotOpId :: QualIdent
qDotOpId = Ident -> QualIdent
qPreludeIdent Ident
dotOpId

qAValueId :: QualIdent
qAValueId :: QualIdent
qAValueId = Ident -> QualIdent
qPreludeIdent Ident
aValueId

qDataEqId :: QualIdent
qDataEqId :: QualIdent
qDataEqId = Ident -> QualIdent
qPreludeIdent Ident
dataEqId

-- | 'QualIdent' for the '++' operator
qAppendOpId :: QualIdent
qAppendOpId :: QualIdent
qAppendOpId = Ident -> QualIdent
qPreludeIdent Ident
appendOpId

-- ---------------------------------------------------------------------------
-- Micellaneous functions for generating and testing extended identifiers
-- ---------------------------------------------------------------------------

-- Functional patterns

-- | Annotation for function pattern identifiers
fpSelExt :: String
fpSelExt :: String
fpSelExt = "_#selFP"

-- | Construct an 'Ident' for a functional pattern
fpSelectorId :: Int -> Ident
fpSelectorId :: Int -> Ident
fpSelectorId n :: Int
n = String -> Ident
mkIdent (String -> Ident) -> String -> Ident
forall a b. (a -> b) -> a -> b
$ String
fpSelExt String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
n

-- | Check whether an 'Ident' is an identifier for a functional pattern
isFpSelectorId :: Ident -> Bool
isFpSelectorId :: Ident -> Bool
isFpSelectorId = (String
fpSelExt String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isInfixOf`) (String -> Bool) -> (Ident -> String) -> Ident -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ident -> String
idName

-- | Check whether an 'QualIdent' is an identifier for a function pattern
isQualFpSelectorId :: QualIdent -> Bool
isQualFpSelectorId :: QualIdent -> Bool
isQualFpSelectorId = Ident -> Bool
isFpSelectorId (Ident -> Bool) -> (QualIdent -> Ident) -> QualIdent -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. QualIdent -> Ident
unqualify

-- Record selection

-- | Annotation for record selection identifiers
recSelExt :: String
recSelExt :: String
recSelExt = "_#selR@"

-- | Construct an 'Ident' for a record selection pattern
recSelectorId :: QualIdent -- ^ identifier of the record
              -> Ident     -- ^ identifier of the label
              -> Ident
recSelectorId :: QualIdent -> Ident -> Ident
recSelectorId = String -> QualIdent -> Ident -> Ident
mkRecordId String
recSelExt

-- | Construct a 'QualIdent' for a record selection pattern
qualRecSelectorId :: ModuleIdent -- ^ default module
                  -> QualIdent   -- ^ record identifier
                  -> Ident       -- ^ label identifier
                  -> QualIdent
qualRecSelectorId :: ModuleIdent -> QualIdent -> Ident -> QualIdent
qualRecSelectorId m :: ModuleIdent
m r :: QualIdent
r l :: Ident
l = ModuleIdent -> QualIdent -> Ident -> QualIdent
qualRecordId ModuleIdent
m QualIdent
r (Ident -> QualIdent) -> Ident -> QualIdent
forall a b. (a -> b) -> a -> b
$ QualIdent -> Ident -> Ident
recSelectorId QualIdent
r Ident
l

-- Record update

-- | Annotation for record update identifiers
recUpdExt :: String
recUpdExt :: String
recUpdExt = "_#updR@"

-- | Construct an 'Ident' for a record update pattern
recUpdateId :: QualIdent -- ^ record identifier
            -> Ident     -- ^ label identifier
            -> Ident
recUpdateId :: QualIdent -> Ident -> Ident
recUpdateId = String -> QualIdent -> Ident -> Ident
mkRecordId String
recUpdExt

-- | Construct a 'QualIdent' for a record update pattern
qualRecUpdateId :: ModuleIdent -- ^ default module
                -> QualIdent   -- ^ record identifier
                -> Ident       -- ^ label identifier
                -> QualIdent
qualRecUpdateId :: ModuleIdent -> QualIdent -> Ident -> QualIdent
qualRecUpdateId m :: ModuleIdent
m r :: QualIdent
r l :: Ident
l = ModuleIdent -> QualIdent -> Ident -> QualIdent
qualRecordId ModuleIdent
m QualIdent
r (Ident -> QualIdent) -> Ident -> QualIdent
forall a b. (a -> b) -> a -> b
$ QualIdent -> Ident -> Ident
recUpdateId QualIdent
r Ident
l

-- Auxiliary function to construct a selector/update identifier
mkRecordId :: String -> QualIdent -> Ident -> Ident
mkRecordId :: String -> QualIdent -> Ident -> Ident
mkRecordId ann :: String
ann r :: QualIdent
r l :: Ident
l = String -> Ident
mkIdent (String -> Ident) -> String -> Ident
forall a b. (a -> b) -> a -> b
$ [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
  [String
ann, Ident -> String
idName (QualIdent -> Ident
unqualify QualIdent
r), ".", Ident -> String
idName Ident
l]

-- Auxiliary function to qualify a selector/update identifier
qualRecordId :: ModuleIdent -> QualIdent -> Ident -> QualIdent
qualRecordId :: ModuleIdent -> QualIdent -> Ident -> QualIdent
qualRecordId m :: ModuleIdent
m r :: QualIdent
r = ModuleIdent -> Ident -> QualIdent
qualifyWith (ModuleIdent -> Maybe ModuleIdent -> ModuleIdent
forall a. a -> Maybe a -> a
fromMaybe ModuleIdent
m (Maybe ModuleIdent -> ModuleIdent)
-> Maybe ModuleIdent -> ModuleIdent
forall a b. (a -> b) -> a -> b
$ QualIdent -> Maybe ModuleIdent
qidModule QualIdent
r)

-- Record tyes

-- | Annotation for record identifiers
recordExt :: String
recordExt :: String
recordExt = "_#Rec:"

-- | Construct an 'Ident' for a record
recordExtId :: Ident -> Ident
recordExtId :: Ident -> Ident
recordExtId r :: Ident
r = String -> Ident
mkIdent (String -> Ident) -> String -> Ident
forall a b. (a -> b) -> a -> b
$ String
recordExt String -> ShowS
forall a. [a] -> [a] -> [a]
++ Ident -> String
idName Ident
r

-- | Check whether an 'Ident' is an identifier for a record
isRecordExtId :: Ident -> Bool
isRecordExtId :: Ident -> Bool
isRecordExtId = (String
recordExt String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf`) (String -> Bool) -> (Ident -> String) -> Ident -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ident -> String
idName

-- | Retrieve the 'Ident' from a record identifier
fromRecordExtId :: Ident -> Ident
fromRecordExtId :: Ident -> Ident
fromRecordExtId r :: Ident
r
  | String
p String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
recordExt = String -> Ident
mkIdent String
r'
  | Bool
otherwise      = Ident
r
 where (p :: String
p, r' :: String
r') = Int -> String -> (String, String)
forall a. Int -> [a] -> ([a], [a])
splitAt (String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
recordExt) (Ident -> String
idName Ident
r)

-- Record labels

-- | Annotation for record label identifiers
labelExt :: String
labelExt :: String
labelExt = "_#Lab:"

-- | Construct an 'Ident' for a record label
labelExtId :: Ident -> Ident
labelExtId :: Ident -> Ident
labelExtId l :: Ident
l = String -> Ident
mkIdent (String -> Ident) -> String -> Ident
forall a b. (a -> b) -> a -> b
$ String
labelExt String -> ShowS
forall a. [a] -> [a] -> [a]
++ Ident -> String
idName Ident
l

-- | Check whether an 'Ident' is an identifier for a record label
isLabelExtId :: Ident -> Bool
isLabelExtId :: Ident -> Bool
isLabelExtId = (String
labelExt String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf`) (String -> Bool) -> (Ident -> String) -> Ident -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ident -> String
idName

-- | Retrieve the 'Ident' from a record label identifier
fromLabelExtId :: Ident -> Ident
fromLabelExtId :: Ident -> Ident
fromLabelExtId l :: Ident
l
  | String
p String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
labelExt = String -> Ident
mkIdent String
l'
  | Bool
otherwise     = Ident
l
 where (p :: String
p, l' :: String
l') = Int -> String -> (String, String)
forall a. Int -> [a] -> ([a], [a])
splitAt (String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
labelExt) (Ident -> String
idName Ident
l)

-- | Construct an 'Ident' for a record label
mkLabelIdent :: String -> Ident
mkLabelIdent :: String -> Ident
mkLabelIdent c :: String
c = Ident -> Integer -> Ident
renameIdent (String -> Ident
mkIdent String
c) (-1)

-- | Rename an 'Ident' for a record label
renameLabel :: Ident -> Ident
renameLabel :: Ident -> Ident
renameLabel l :: Ident
l = Ident -> Integer -> Ident
renameIdent Ident
l (-1)