summaryrefslogtreecommitdiff
path: root/compiler/basicTypes
diff options
context:
space:
mode:
authorSimon Marlow <simonmar@microsoft.com>2006-04-07 02:05:11 +0000
committerSimon Marlow <simonmar@microsoft.com>2006-04-07 02:05:11 +0000
commit0065d5ab628975892cea1ec7303f968c3338cbe1 (patch)
tree8e2afe0ab48ee33cf95009809d67c9649573ef92 /compiler/basicTypes
parent28a464a75e14cece5db40f2765a29348273ff2d2 (diff)
downloadhaskell-0065d5ab628975892cea1ec7303f968c3338cbe1.tar.gz
Reorganisation of the source tree
Most of the other users of the fptools build system have migrated to Cabal, and with the move to darcs we can now flatten the source tree without losing history, so here goes. The main change is that the ghc/ subdir is gone, and most of what it contained is now at the top level. The build system now makes no pretense at being multi-project, it is just the GHC build system. No doubt this will break many things, and there will be a period of instability while we fix the dependencies. A straightforward build should work, but I haven't yet fixed binary/source distributions. Changes to the Building Guide will follow, too.
Diffstat (limited to 'compiler/basicTypes')
-rw-r--r--compiler/basicTypes/BasicTypes.lhs508
-rw-r--r--compiler/basicTypes/DataCon.hi-boot-55
-rw-r--r--compiler/basicTypes/DataCon.hi-boot-65
-rw-r--r--compiler/basicTypes/DataCon.lhs632
-rw-r--r--compiler/basicTypes/DataCon.lhs-boot8
-rw-r--r--compiler/basicTypes/Demand.lhs208
-rw-r--r--compiler/basicTypes/FieldLabel.lhs71
-rw-r--r--compiler/basicTypes/Id.lhs529
-rw-r--r--compiler/basicTypes/IdInfo.hi-boot-58
-rw-r--r--compiler/basicTypes/IdInfo.hi-boot-68
-rw-r--r--compiler/basicTypes/IdInfo.lhs699
-rw-r--r--compiler/basicTypes/IdInfo.lhs-boot9
-rw-r--r--compiler/basicTypes/Literal.lhs405
-rw-r--r--compiler/basicTypes/MkId.hi-boot-53
-rw-r--r--compiler/basicTypes/MkId.hi-boot-65
-rw-r--r--compiler/basicTypes/MkId.lhs1044
-rw-r--r--compiler/basicTypes/MkId.lhs-boot9
-rw-r--r--compiler/basicTypes/Module.hi-boot-54
-rw-r--r--compiler/basicTypes/Module.hi-boot-63
-rw-r--r--compiler/basicTypes/Module.lhs216
-rw-r--r--compiler/basicTypes/Module.lhs-boot6
-rw-r--r--compiler/basicTypes/Name.hi-boot-53
-rw-r--r--compiler/basicTypes/Name.hi-boot-63
-rw-r--r--compiler/basicTypes/Name.lhs384
-rw-r--r--compiler/basicTypes/Name.lhs-boot5
-rw-r--r--compiler/basicTypes/NameEnv.lhs72
-rw-r--r--compiler/basicTypes/NameSet.lhs190
-rw-r--r--compiler/basicTypes/NewDemand.lhs318
-rw-r--r--compiler/basicTypes/OccName.hi-boot-64
-rw-r--r--compiler/basicTypes/OccName.lhs676
-rw-r--r--compiler/basicTypes/OccName.lhs-boot5
-rw-r--r--compiler/basicTypes/RdrName.lhs540
-rw-r--r--compiler/basicTypes/SrcLoc.lhs386
-rw-r--r--compiler/basicTypes/UniqSupply.lhs203
-rw-r--r--compiler/basicTypes/Unique.lhs330
-rw-r--r--compiler/basicTypes/Var.lhs337
-rw-r--r--compiler/basicTypes/VarEnv.lhs344
-rw-r--r--compiler/basicTypes/VarSet.lhs105
38 files changed, 8290 insertions, 0 deletions
diff --git a/compiler/basicTypes/BasicTypes.lhs b/compiler/basicTypes/BasicTypes.lhs
new file mode 100644
index 0000000000..6b662bd6a6
--- /dev/null
+++ b/compiler/basicTypes/BasicTypes.lhs
@@ -0,0 +1,508 @@
+%
+% (c) The GRASP/AQUA Project, Glasgow University, 1997-1998
+%
+\section[BasicTypes]{Miscellanous types}
+
+This module defines a miscellaneously collection of very simple
+types that
+
+\begin{itemize}
+\item have no other obvious home
+\item don't depend on any other complicated types
+\item are used in more than one "part" of the compiler
+\end{itemize}
+
+\begin{code}
+module BasicTypes(
+ Version, bumpVersion, initialVersion,
+
+ Arity,
+
+ DeprecTxt,
+
+ Fixity(..), FixityDirection(..),
+ defaultFixity, maxPrecedence,
+ negateFixity, funTyFixity,
+ compareFixity,
+
+ IPName(..), ipNameName, mapIPName,
+
+ RecFlag(..), isRec, isNonRec, boolToRecFlag,
+
+ TopLevelFlag(..), isTopLevel, isNotTopLevel,
+
+ Boxity(..), isBoxed,
+
+ TupCon(..), tupleParens,
+
+ OccInfo(..), seqOccInfo, isFragileOcc, isOneOcc,
+ isDeadOcc, isLoopBreaker, isNoOcc,
+
+ InsideLam, insideLam, notInsideLam,
+ OneBranch, oneBranch, notOneBranch,
+ InterestingCxt,
+
+ EP(..),
+
+ StrictnessMark(..), isMarkedUnboxed, isMarkedStrict,
+
+ CompilerPhase,
+ Activation(..), isActive, isNeverActive, isAlwaysActive,
+ InlineSpec(..), defaultInlineSpec, alwaysInlineSpec, neverInlineSpec,
+
+ SuccessFlag(..), succeeded, failed, successIf
+ ) where
+
+#include "HsVersions.h"
+
+import FastString( FastString )
+import Outputable
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[Arity]{Arity}
+%* *
+%************************************************************************
+
+\begin{code}
+type Arity = Int
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection[Version]{Module and identifier version numbers}
+%* *
+%************************************************************************
+
+\begin{code}
+type Version = Int
+
+bumpVersion :: Version -> Version
+bumpVersion v = v+1
+
+initialVersion :: Version
+initialVersion = 1
+\end{code}
+
+%************************************************************************
+%* *
+ Deprecations
+%* *
+%************************************************************************
+
+
+\begin{code}
+type DeprecTxt = FastString -- reason/explanation for deprecation
+\end{code}
+
+%************************************************************************
+%* *
+\subsection{Implicit parameter identity}
+%* *
+%************************************************************************
+
+The @IPName@ type is here because it is used in TypeRep (i.e. very
+early in the hierarchy), but also in HsSyn.
+
+\begin{code}
+data IPName name
+ = Dupable name -- ?x: you can freely duplicate this implicit parameter
+ | Linear name -- %x: you must use the splitting function to duplicate it
+ deriving( Eq, Ord ) -- Ord is used in the IP name cache finite map
+ -- (used in HscTypes.OrigIParamCache)
+
+
+ipNameName :: IPName name -> name
+ipNameName (Dupable n) = n
+ipNameName (Linear n) = n
+
+mapIPName :: (a->b) -> IPName a -> IPName b
+mapIPName f (Dupable n) = Dupable (f n)
+mapIPName f (Linear n) = Linear (f n)
+
+instance Outputable name => Outputable (IPName name) where
+ ppr (Dupable n) = char '?' <> ppr n -- Ordinary implicit parameters
+ ppr (Linear n) = char '%' <> ppr n -- Splittable implicit parameters
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection[Fixity]{Fixity info}
+%* *
+%************************************************************************
+
+\begin{code}
+------------------------
+data Fixity = Fixity Int FixityDirection
+
+instance Outputable Fixity where
+ ppr (Fixity prec dir) = hcat [ppr dir, space, int prec]
+
+instance Eq Fixity where -- Used to determine if two fixities conflict
+ (Fixity p1 dir1) == (Fixity p2 dir2) = p1==p2 && dir1 == dir2
+
+------------------------
+data FixityDirection = InfixL | InfixR | InfixN
+ deriving(Eq)
+
+instance Outputable FixityDirection where
+ ppr InfixL = ptext SLIT("infixl")
+ ppr InfixR = ptext SLIT("infixr")
+ ppr InfixN = ptext SLIT("infix")
+
+------------------------
+maxPrecedence = (9::Int)
+defaultFixity = Fixity maxPrecedence InfixL
+
+negateFixity, funTyFixity :: Fixity
+-- Wired-in fixities
+negateFixity = Fixity 6 InfixL -- Fixity of unary negate
+funTyFixity = Fixity 0 InfixR -- Fixity of '->'
+\end{code}
+
+Consider
+
+\begin{verbatim}
+ a `op1` b `op2` c
+\end{verbatim}
+@(compareFixity op1 op2)@ tells which way to arrange appication, or
+whether there's an error.
+
+\begin{code}
+compareFixity :: Fixity -> Fixity
+ -> (Bool, -- Error please
+ Bool) -- Associate to the right: a op1 (b op2 c)
+compareFixity (Fixity prec1 dir1) (Fixity prec2 dir2)
+ = case prec1 `compare` prec2 of
+ GT -> left
+ LT -> right
+ EQ -> case (dir1, dir2) of
+ (InfixR, InfixR) -> right
+ (InfixL, InfixL) -> left
+ _ -> error_please
+ where
+ right = (False, True)
+ left = (False, False)
+ error_please = (True, False)
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection[Top-level/local]{Top-level/not-top level flag}
+%* *
+%************************************************************************
+
+\begin{code}
+data TopLevelFlag
+ = TopLevel
+ | NotTopLevel
+
+isTopLevel, isNotTopLevel :: TopLevelFlag -> Bool
+
+isNotTopLevel NotTopLevel = True
+isNotTopLevel TopLevel = False
+
+isTopLevel TopLevel = True
+isTopLevel NotTopLevel = False
+
+instance Outputable TopLevelFlag where
+ ppr TopLevel = ptext SLIT("<TopLevel>")
+ ppr NotTopLevel = ptext SLIT("<NotTopLevel>")
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection[Top-level/local]{Top-level/not-top level flag}
+%* *
+%************************************************************************
+
+\begin{code}
+data Boxity
+ = Boxed
+ | Unboxed
+ deriving( Eq )
+
+isBoxed :: Boxity -> Bool
+isBoxed Boxed = True
+isBoxed Unboxed = False
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection[Recursive/Non-Recursive]{Recursive/Non-Recursive flag}
+%* *
+%************************************************************************
+
+\begin{code}
+data RecFlag = Recursive
+ | NonRecursive
+ deriving( Eq )
+
+isRec :: RecFlag -> Bool
+isRec Recursive = True
+isRec NonRecursive = False
+
+isNonRec :: RecFlag -> Bool
+isNonRec Recursive = False
+isNonRec NonRecursive = True
+
+boolToRecFlag :: Bool -> RecFlag
+boolToRecFlag True = Recursive
+boolToRecFlag False = NonRecursive
+
+instance Outputable RecFlag where
+ ppr Recursive = ptext SLIT("Recursive")
+ ppr NonRecursive = ptext SLIT("NonRecursive")
+\end{code}
+
+%************************************************************************
+%* *
+ Tuples
+%* *
+%************************************************************************
+
+\begin{code}
+data TupCon = TupCon Boxity Arity
+
+instance Eq TupCon where
+ (TupCon b1 a1) == (TupCon b2 a2) = b1==b2 && a1==a2
+
+tupleParens :: Boxity -> SDoc -> SDoc
+tupleParens Boxed p = parens p
+tupleParens Unboxed p = ptext SLIT("(#") <+> p <+> ptext SLIT("#)")
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[Generic]{Generic flag}
+%* *
+%************************************************************************
+
+This is the "Embedding-Projection pair" datatype, it contains
+two pieces of code (normally either RenamedExpr's or Id's)
+If we have a such a pair (EP from to), the idea is that 'from' and 'to'
+represents functions of type
+
+ from :: T -> Tring
+ to :: Tring -> T
+
+And we should have
+
+ to (from x) = x
+
+T and Tring are arbitrary, but typically T is the 'main' type while
+Tring is the 'representation' type. (This just helps us remember
+whether to use 'from' or 'to'.
+
+\begin{code}
+data EP a = EP { fromEP :: a, -- :: T -> Tring
+ toEP :: a } -- :: Tring -> T
+\end{code}
+
+Embedding-projection pairs are used in several places:
+
+First of all, each type constructor has an EP associated with it, the
+code in EP converts (datatype T) from T to Tring and back again.
+
+Secondly, when we are filling in Generic methods (in the typechecker,
+tcMethodBinds), we are constructing bimaps by induction on the structure
+of the type of the method signature.
+
+
+%************************************************************************
+%* *
+\subsection{Occurrence information}
+%* *
+%************************************************************************
+
+This data type is used exclusively by the simplifier, but it appears in a
+SubstResult, which is currently defined in VarEnv, which is pretty near
+the base of the module hierarchy. So it seemed simpler to put the
+defn of OccInfo here, safely at the bottom
+
+\begin{code}
+data OccInfo
+ = NoOccInfo
+
+ | IAmDead -- Marks unused variables. Sometimes useful for
+ -- lambda and case-bound variables.
+
+ | OneOcc !InsideLam
+ !OneBranch
+ !InterestingCxt
+
+ | IAmALoopBreaker -- Used by the occurrence analyser to mark loop-breakers
+ -- in a group of recursive definitions
+
+isNoOcc :: OccInfo -> Bool
+isNoOcc NoOccInfo = True
+isNoOcc other = False
+
+seqOccInfo :: OccInfo -> ()
+seqOccInfo occ = occ `seq` ()
+
+-----------------
+type InterestingCxt = Bool -- True <=> Function: is applied
+ -- Data value: scrutinised by a case with
+ -- at least one non-DEFAULT branch
+
+-----------------
+type InsideLam = Bool -- True <=> Occurs inside a non-linear lambda
+ -- Substituting a redex for this occurrence is
+ -- dangerous because it might duplicate work.
+insideLam = True
+notInsideLam = False
+
+-----------------
+type OneBranch = Bool -- True <=> Occurs in only one case branch
+ -- so no code-duplication issue to worry about
+oneBranch = True
+notOneBranch = False
+
+isLoopBreaker :: OccInfo -> Bool
+isLoopBreaker IAmALoopBreaker = True
+isLoopBreaker other = False
+
+isDeadOcc :: OccInfo -> Bool
+isDeadOcc IAmDead = True
+isDeadOcc other = False
+
+isOneOcc (OneOcc _ _ _) = True
+isOneOcc other = False
+
+isFragileOcc :: OccInfo -> Bool
+isFragileOcc (OneOcc _ _ _) = True
+isFragileOcc other = False
+\end{code}
+
+\begin{code}
+instance Outputable OccInfo where
+ -- only used for debugging; never parsed. KSW 1999-07
+ ppr NoOccInfo = empty
+ ppr IAmALoopBreaker = ptext SLIT("LoopBreaker")
+ ppr IAmDead = ptext SLIT("Dead")
+ ppr (OneOcc inside_lam one_branch int_cxt)
+ = ptext SLIT("Once") <> pp_lam <> pp_br <> pp_args
+ where
+ pp_lam | inside_lam = char 'L'
+ | otherwise = empty
+ pp_br | one_branch = empty
+ | otherwise = char '*'
+ pp_args | int_cxt = char '!'
+ | otherwise = empty
+
+instance Show OccInfo where
+ showsPrec p occ = showsPrecSDoc p (ppr occ)
+\end{code}
+
+%************************************************************************
+%* *
+\subsection{Strictness indication}
+%* *
+%************************************************************************
+
+The strictness annotations on types in data type declarations
+e.g. data T = MkT !Int !(Bool,Bool)
+
+\begin{code}
+data StrictnessMark -- Used in interface decls only
+ = MarkedStrict
+ | MarkedUnboxed
+ | NotMarkedStrict
+ deriving( Eq )
+
+isMarkedUnboxed MarkedUnboxed = True
+isMarkedUnboxed other = False
+
+isMarkedStrict NotMarkedStrict = False
+isMarkedStrict other = True -- All others are strict
+
+instance Outputable StrictnessMark where
+ ppr MarkedStrict = ptext SLIT("!")
+ ppr MarkedUnboxed = ptext SLIT("!!")
+ ppr NotMarkedStrict = ptext SLIT("_")
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Success flag}
+%* *
+%************************************************************************
+
+\begin{code}
+data SuccessFlag = Succeeded | Failed
+
+successIf :: Bool -> SuccessFlag
+successIf True = Succeeded
+successIf False = Failed
+
+succeeded, failed :: SuccessFlag -> Bool
+succeeded Succeeded = True
+succeeded Failed = False
+
+failed Succeeded = False
+failed Failed = True
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Activation}
+%* *
+%************************************************************************
+
+When a rule or inlining is active
+
+\begin{code}
+type CompilerPhase = Int -- Compilation phase
+ -- Phases decrease towards zero
+ -- Zero is the last phase
+
+data Activation = NeverActive
+ | AlwaysActive
+ | ActiveBefore CompilerPhase -- Active only *before* this phase
+ | ActiveAfter CompilerPhase -- Active in this phase and later
+ deriving( Eq ) -- Eq used in comparing rules in HsDecls
+
+data InlineSpec
+ = Inline
+ Activation -- Says during which phases inlining is allowed
+ Bool -- True <=> make the RHS look small, so that when inlining
+ -- is enabled, it will definitely actually happen
+ deriving( Eq )
+
+defaultInlineSpec = Inline AlwaysActive False -- Inlining is OK, but not forced
+alwaysInlineSpec = Inline AlwaysActive True -- INLINE always
+neverInlineSpec = Inline NeverActive False -- NOINLINE
+
+instance Outputable Activation where
+ ppr AlwaysActive = empty -- The default
+ ppr (ActiveBefore n) = brackets (char '~' <> int n)
+ ppr (ActiveAfter n) = brackets (int n)
+ ppr NeverActive = ptext SLIT("NEVER")
+
+instance Outputable InlineSpec where
+ ppr (Inline act True) = ptext SLIT("INLINE") <> ppr act
+ ppr (Inline act False) = ptext SLIT("NOINLINE") <> ppr act
+
+isActive :: CompilerPhase -> Activation -> Bool
+isActive p NeverActive = False
+isActive p AlwaysActive = True
+isActive p (ActiveAfter n) = p <= n
+isActive p (ActiveBefore n) = p > n
+
+isNeverActive, isAlwaysActive :: Activation -> Bool
+isNeverActive NeverActive = True
+isNeverActive act = False
+
+isAlwaysActive AlwaysActive = True
+isAlwaysActive other = False
+\end{code}
+
diff --git a/compiler/basicTypes/DataCon.hi-boot-5 b/compiler/basicTypes/DataCon.hi-boot-5
new file mode 100644
index 0000000000..f5a8a2d6a8
--- /dev/null
+++ b/compiler/basicTypes/DataCon.hi-boot-5
@@ -0,0 +1,5 @@
+__interface DataCon 1 0 where
+__export DataCon DataCon isExistentialDataCon dataConName ;
+1 data DataCon ;
+1 isExistentialDataCon :: DataCon -> PrelBase.Bool ;
+1 dataConName :: DataCon -> Name.Name ;
diff --git a/compiler/basicTypes/DataCon.hi-boot-6 b/compiler/basicTypes/DataCon.hi-boot-6
new file mode 100644
index 0000000000..7882469bce
--- /dev/null
+++ b/compiler/basicTypes/DataCon.hi-boot-6
@@ -0,0 +1,5 @@
+module DataCon where
+
+data DataCon
+dataConName :: DataCon -> Name.Name
+isVanillaDataCon :: DataCon -> GHC.Base.Bool
diff --git a/compiler/basicTypes/DataCon.lhs b/compiler/basicTypes/DataCon.lhs
new file mode 100644
index 0000000000..805ef73c59
--- /dev/null
+++ b/compiler/basicTypes/DataCon.lhs
@@ -0,0 +1,632 @@
+%
+% (c) The GRASP/AQUA Project, Glasgow University, 1998
+%
+\section[DataCon]{@DataCon@: Data Constructors}
+
+\begin{code}
+module DataCon (
+ DataCon, DataConIds(..),
+ ConTag, fIRST_TAG,
+ mkDataCon,
+ dataConRepType, dataConSig, dataConName, dataConTag, dataConTyCon,
+ dataConTyVars, dataConResTys,
+ dataConStupidTheta,
+ dataConInstArgTys, dataConOrigArgTys, dataConInstResTy,
+ dataConInstOrigArgTys, dataConRepArgTys,
+ dataConFieldLabels, dataConFieldType,
+ dataConStrictMarks, dataConExStricts,
+ dataConSourceArity, dataConRepArity,
+ dataConIsInfix,
+ dataConWorkId, dataConWrapId, dataConWrapId_maybe, dataConImplicitIds,
+ dataConRepStrictness,
+ isNullarySrcDataCon, isNullaryRepDataCon, isTupleCon, isUnboxedTupleCon,
+ isVanillaDataCon, classDataCon,
+
+ splitProductType_maybe, splitProductType,
+ ) where
+
+#include "HsVersions.h"
+
+import Type ( Type, ThetaType, substTyWith, substTy, zipOpenTvSubst,
+ mkForAllTys, mkFunTys, mkTyConApp,
+ splitTyConApp_maybe,
+ mkPredTys, isStrictPred, pprType
+ )
+import TyCon ( TyCon, FieldLabel, tyConDataCons,
+ isProductTyCon, isTupleTyCon, isUnboxedTupleTyCon )
+import Class ( Class, classTyCon )
+import Name ( Name, NamedThing(..), nameUnique )
+import Var ( TyVar, Id )
+import BasicTypes ( Arity, StrictnessMark(..) )
+import Outputable
+import Unique ( Unique, Uniquable(..) )
+import ListSetOps ( assoc )
+import Util ( zipEqual, zipWithEqual )
+import Maybes ( expectJust )
+\end{code}
+
+
+Data constructor representation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Consider the following Haskell data type declaration
+
+ data T = T !Int ![Int]
+
+Using the strictness annotations, GHC will represent this as
+
+ data T = T Int# [Int]
+
+That is, the Int has been unboxed. Furthermore, the Haskell source construction
+
+ T e1 e2
+
+is translated to
+
+ case e1 of { I# x ->
+ case e2 of { r ->
+ T x r }}
+
+That is, the first argument is unboxed, and the second is evaluated. Finally,
+pattern matching is translated too:
+
+ case e of { T a b -> ... }
+
+becomes
+
+ case e of { T a' b -> let a = I# a' in ... }
+
+To keep ourselves sane, we name the different versions of the data constructor
+differently, as follows.
+
+
+Note [Data Constructor Naming]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Each data constructor C has two, and possibly three, Names associated with it:
+
+ OccName Name space Used for
+ ---------------------------------------------------------------------------
+ * The "source data con" C DataName The DataCon itself
+ * The "real data con" C VarName Its worker Id
+ * The "wrapper data con" $WC VarName Wrapper Id (optional)
+
+Each of these three has a distinct Unique. The "source data con" name
+appears in the output of the renamer, and names the Haskell-source
+data constructor. The type checker translates it into either the wrapper Id
+(if it exists) or worker Id (otherwise).
+
+The data con has one or two Ids associated with it:
+
+ The "worker Id", is the actual data constructor.
+ Its type may be different to the Haskell source constructor
+ because:
+ - useless dict args are dropped
+ - strict args may be flattened
+ The worker is very like a primop, in that it has no binding.
+
+ Newtypes have no worker Id
+
+
+ The "wrapper Id", $WC, whose type is exactly what it looks like
+ in the source program. It is an ordinary function,
+ and it gets a top-level binding like any other function.
+
+ The wrapper Id isn't generated for a data type if the worker
+ and wrapper are identical. It's always generated for a newtype.
+
+
+
+A note about the stupid context
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Data types can have a context:
+
+ data (Eq a, Ord b) => T a b = T1 a b | T2 a
+
+and that makes the constructors have a context too
+(notice that T2's context is "thinned"):
+
+ T1 :: (Eq a, Ord b) => a -> b -> T a b
+ T2 :: (Eq a) => a -> T a b
+
+Furthermore, this context pops up when pattern matching
+(though GHC hasn't implemented this, but it is in H98, and
+I've fixed GHC so that it now does):
+
+ f (T2 x) = x
+gets inferred type
+ f :: Eq a => T a b -> a
+
+I say the context is "stupid" because the dictionaries passed
+are immediately discarded -- they do nothing and have no benefit.
+It's a flaw in the language.
+
+ Up to now [March 2002] I have put this stupid context into the
+ type of the "wrapper" constructors functions, T1 and T2, but
+ that turned out to be jolly inconvenient for generics, and
+ record update, and other functions that build values of type T
+ (because they don't have suitable dictionaries available).
+
+ So now I've taken the stupid context out. I simply deal with
+ it separately in the type checker on occurrences of a
+ constructor, either in an expression or in a pattern.
+
+ [May 2003: actually I think this decision could evasily be
+ reversed now, and probably should be. Generics could be
+ disabled for types with a stupid context; record updates now
+ (H98) needs the context too; etc. It's an unforced change, so
+ I'm leaving it for now --- but it does seem odd that the
+ wrapper doesn't include the stupid context.]
+
+[July 04] With the advent of generalised data types, it's less obvious
+what the "stupid context" is. Consider
+ C :: forall a. Ord a => a -> a -> T (Foo a)
+Does the C constructor in Core contain the Ord dictionary? Yes, it must:
+
+ f :: T b -> Ordering
+ f = /\b. \x:T b.
+ case x of
+ C a (d:Ord a) (p:a) (q:a) -> compare d p q
+
+Note that (Foo a) might not be an instance of Ord.
+
+%************************************************************************
+%* *
+\subsection{Data constructors}
+%* *
+%************************************************************************
+
+\begin{code}
+data DataCon
+ = MkData {
+ dcName :: Name, -- This is the name of the *source data con*
+ -- (see "Note [Data Constructor Naming]" above)
+ dcUnique :: Unique, -- Cached from Name
+ dcTag :: ConTag,
+
+ -- Running example:
+ --
+ -- data Eq a => T a = forall b. Ord b => MkT a [b]
+
+ -- The next six fields express the type of the constructor, in pieces
+ -- e.g.
+ --
+ -- dcTyVars = [a,b]
+ -- dcStupidTheta = [Eq a]
+ -- dcTheta = [Ord b]
+ -- dcOrigArgTys = [a,List b]
+ -- dcTyCon = T
+ -- dcTyArgs = [a,b]
+
+ dcVanilla :: Bool, -- True <=> This is a vanilla Haskell 98 data constructor
+ -- Its type is of form
+ -- forall a1..an . t1 -> ... tm -> T a1..an
+ -- No existentials, no GADTs, nothing.
+ --
+ -- NB1: the order of the forall'd variables does matter;
+ -- for a vanilla constructor, we assume that if the result
+ -- type is (T t1 ... tn) then we can instantiate the constr
+ -- at types [t1, ..., tn]
+ --
+ -- NB2: a vanilla constructor can still be declared in GADT-style
+ -- syntax, provided its type looks like the above.
+
+ dcTyVars :: [TyVar], -- Universally-quantified type vars
+ -- for the data constructor.
+ -- See NB1 on dcVanilla for the conneciton between dcTyVars and dcResTys
+ --
+ -- In general, the dcTyVars are NOT NECESSARILY THE SAME AS THE TYVARS
+ -- FOR THE PARENT TyCon. With GADTs the data con might not even have
+ -- the same number of type variables.
+ -- [This is a change (Oct05): previously, vanilla datacons guaranteed to
+ -- have the same type variables as their parent TyCon, but that seems ugly.]
+
+ dcStupidTheta :: ThetaType, -- This is a "thinned" version of
+ -- the context of the data decl.
+ -- "Thinned", because the Report says
+ -- to eliminate any constraints that don't mention
+ -- tyvars free in the arg types for this constructor
+ --
+ -- "Stupid", because the dictionaries aren't used for anything.
+ --
+ -- Indeed, [as of March 02] they are no
+ -- longer in the type of the wrapper Id, because
+ -- that makes it harder to use the wrap-id to rebuild
+ -- values after record selection or in generics.
+ --
+ -- Fact: the free tyvars of dcStupidTheta are a subset of
+ -- the free tyvars of dcResTys
+ -- Reason: dcStupidTeta is gotten by instantiating the
+ -- stupid theta from the tycon (see BuildTyCl.mkDataConStupidTheta)
+
+ dcTheta :: ThetaType, -- The existentially quantified stuff
+
+ dcOrigArgTys :: [Type], -- Original argument types
+ -- (before unboxing and flattening of
+ -- strict fields)
+
+ -- Result type of constructor is T t1..tn
+ dcTyCon :: TyCon, -- Result tycon, T
+ dcResTys :: [Type], -- Result type args, t1..tn
+
+ -- Now the strictness annotations and field labels of the constructor
+ dcStrictMarks :: [StrictnessMark],
+ -- Strictness annotations as decided by the compiler.
+ -- Does *not* include the existential dictionaries
+ -- length = dataConSourceArity dataCon
+
+ dcFields :: [FieldLabel],
+ -- Field labels for this constructor, in the
+ -- same order as the argument types;
+ -- length = 0 (if not a record) or dataConSourceArity.
+
+ -- Constructor representation
+ dcRepArgTys :: [Type], -- Final, representation argument types,
+ -- after unboxing and flattening,
+ -- and *including* existential dictionaries
+
+ dcRepStrictness :: [StrictnessMark], -- One for each *representation* argument
+
+ dcRepType :: Type, -- Type of the constructor
+ -- forall a b . Ord b => a -> [b] -> MkT a
+ -- (this is *not* of the constructor wrapper Id:
+ -- see notes after this data type declaration)
+ --
+ -- Notice that the existential type parameters come *second*.
+ -- Reason: in a case expression we may find:
+ -- case (e :: T t) of { MkT b (d:Ord b) (x:t) (xs:[b]) -> ... }
+ -- It's convenient to apply the rep-type of MkT to 't', to get
+ -- forall b. Ord b => ...
+ -- and use that to check the pattern. Mind you, this is really only
+ -- use in CoreLint.
+
+
+ -- Finally, the curried worker function that corresponds to the constructor
+ -- It doesn't have an unfolding; the code generator saturates these Ids
+ -- and allocates a real constructor when it finds one.
+ --
+ -- An entirely separate wrapper function is built in TcTyDecls
+ dcIds :: DataConIds,
+
+ dcInfix :: Bool -- True <=> declared infix
+ -- Used for Template Haskell and 'deriving' only
+ -- The actual fixity is stored elsewhere
+ }
+
+data DataConIds
+ = NewDC Id -- Newtypes have only a wrapper, but no worker
+ | AlgDC (Maybe Id) Id -- Algebraic data types always have a worker, and
+ -- may or may not have a wrapper, depending on whether
+ -- the wrapper does anything.
+
+ -- _Neither_ the worker _nor_ the wrapper take the dcStupidTheta dicts as arguments
+
+ -- The wrapper takes dcOrigArgTys as its arguments
+ -- The worker takes dcRepArgTys as its arguments
+ -- If the worker is absent, dcRepArgTys is the same as dcOrigArgTys
+
+ -- The 'Nothing' case of AlgDC is important
+ -- Not only is this efficient,
+ -- but it also ensures that the wrapper is replaced
+ -- by the worker (becuase it *is* the wroker)
+ -- even when there are no args. E.g. in
+ -- f (:) x
+ -- the (:) *is* the worker.
+ -- This is really important in rule matching,
+ -- (We could match on the wrappers,
+ -- but that makes it less likely that rules will match
+ -- when we bring bits of unfoldings together.)
+
+type ConTag = Int
+
+fIRST_TAG :: ConTag
+fIRST_TAG = 1 -- Tags allocated from here for real constructors
+\end{code}
+
+The dcRepType field contains the type of the representation of a contructor
+This may differ from the type of the contructor *Id* (built
+by MkId.mkDataConId) for two reasons:
+ a) the constructor Id may be overloaded, but the dictionary isn't stored
+ e.g. data Eq a => T a = MkT a a
+
+ b) the constructor may store an unboxed version of a strict field.
+
+Here's an example illustrating both:
+ data Ord a => T a = MkT Int! a
+Here
+ T :: Ord a => Int -> a -> T a
+but the rep type is
+ Trep :: Int# -> a -> T a
+Actually, the unboxed part isn't implemented yet!
+
+
+%************************************************************************
+%* *
+\subsection{Instances}
+%* *
+%************************************************************************
+
+\begin{code}
+instance Eq DataCon where
+ a == b = getUnique a == getUnique b
+ a /= b = getUnique a /= getUnique b
+
+instance Ord DataCon where
+ a <= b = getUnique a <= getUnique b
+ a < b = getUnique a < getUnique b
+ a >= b = getUnique a >= getUnique b
+ a > b = getUnique a > getUnique b
+ compare a b = getUnique a `compare` getUnique b
+
+instance Uniquable DataCon where
+ getUnique = dcUnique
+
+instance NamedThing DataCon where
+ getName = dcName
+
+instance Outputable DataCon where
+ ppr con = ppr (dataConName con)
+
+instance Show DataCon where
+ showsPrec p con = showsPrecSDoc p (ppr con)
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Construction}
+%* *
+%************************************************************************
+
+\begin{code}
+mkDataCon :: Name
+ -> Bool -- Declared infix
+ -> Bool -- Vanilla (see notes with dcVanilla)
+ -> [StrictnessMark] -> [FieldLabel]
+ -> [TyVar] -> ThetaType -> ThetaType
+ -> [Type] -> TyCon -> [Type]
+ -> DataConIds
+ -> DataCon
+ -- Can get the tag from the TyCon
+
+mkDataCon name declared_infix vanilla
+ arg_stricts -- Must match orig_arg_tys 1-1
+ fields
+ tyvars stupid_theta theta orig_arg_tys tycon res_tys
+ ids
+ = con
+ where
+ con = MkData {dcName = name,
+ dcUnique = nameUnique name, dcVanilla = vanilla,
+ dcTyVars = tyvars, dcStupidTheta = stupid_theta, dcTheta = theta,
+ dcOrigArgTys = orig_arg_tys, dcTyCon = tycon, dcResTys = res_tys,
+ dcRepArgTys = rep_arg_tys,
+ dcStrictMarks = arg_stricts, dcRepStrictness = rep_arg_stricts,
+ dcFields = fields, dcTag = tag, dcRepType = ty,
+ dcIds = ids, dcInfix = declared_infix}
+
+ -- Strictness marks for source-args
+ -- *after unboxing choices*,
+ -- but *including existential dictionaries*
+ --
+ -- The 'arg_stricts' passed to mkDataCon are simply those for the
+ -- source-language arguments. We add extra ones for the
+ -- dictionary arguments right here.
+ dict_tys = mkPredTys theta
+ real_arg_tys = dict_tys ++ orig_arg_tys
+ real_stricts = map mk_dict_strict_mark theta ++ arg_stricts
+
+ -- Representation arguments and demands
+ (rep_arg_stricts, rep_arg_tys) = computeRep real_stricts real_arg_tys
+
+ tag = assoc "mkDataCon" (tyConDataCons tycon `zip` [fIRST_TAG..]) con
+ ty = mkForAllTys tyvars (mkFunTys rep_arg_tys result_ty)
+ -- NB: the existential dict args are already in rep_arg_tys
+
+ result_ty = mkTyConApp tycon res_tys
+
+mk_dict_strict_mark pred | isStrictPred pred = MarkedStrict
+ | otherwise = NotMarkedStrict
+\end{code}
+
+\begin{code}
+dataConName :: DataCon -> Name
+dataConName = dcName
+
+dataConTag :: DataCon -> ConTag
+dataConTag = dcTag
+
+dataConTyCon :: DataCon -> TyCon
+dataConTyCon = dcTyCon
+
+dataConRepType :: DataCon -> Type
+dataConRepType = dcRepType
+
+dataConIsInfix :: DataCon -> Bool
+dataConIsInfix = dcInfix
+
+dataConTyVars :: DataCon -> [TyVar]
+dataConTyVars = dcTyVars
+
+dataConWorkId :: DataCon -> Id
+dataConWorkId dc = case dcIds dc of
+ AlgDC _ wrk_id -> wrk_id
+ NewDC _ -> pprPanic "dataConWorkId" (ppr dc)
+
+dataConWrapId_maybe :: DataCon -> Maybe Id
+dataConWrapId_maybe dc = case dcIds dc of
+ AlgDC mb_wrap _ -> mb_wrap
+ NewDC wrap -> Just wrap
+
+dataConWrapId :: DataCon -> Id
+-- Returns an Id which looks like the Haskell-source constructor
+dataConWrapId dc = case dcIds dc of
+ AlgDC (Just wrap) _ -> wrap
+ AlgDC Nothing wrk -> wrk -- worker=wrapper
+ NewDC wrap -> wrap
+
+dataConImplicitIds :: DataCon -> [Id]
+dataConImplicitIds dc = case dcIds dc of
+ AlgDC (Just wrap) work -> [wrap,work]
+ AlgDC Nothing work -> [work]
+ NewDC wrap -> [wrap]
+
+dataConFieldLabels :: DataCon -> [FieldLabel]
+dataConFieldLabels = dcFields
+
+dataConFieldType :: DataCon -> FieldLabel -> Type
+dataConFieldType con label = expectJust "unexpected label" $
+ lookup label (dcFields con `zip` dcOrigArgTys con)
+
+dataConStrictMarks :: DataCon -> [StrictnessMark]
+dataConStrictMarks = dcStrictMarks
+
+dataConExStricts :: DataCon -> [StrictnessMark]
+-- Strictness of *existential* arguments only
+-- Usually empty, so we don't bother to cache this
+dataConExStricts dc = map mk_dict_strict_mark (dcTheta dc)
+
+dataConSourceArity :: DataCon -> Arity
+ -- Source-level arity of the data constructor
+dataConSourceArity dc = length (dcOrigArgTys dc)
+
+-- dataConRepArity gives the number of actual fields in the
+-- {\em representation} of the data constructor. This may be more than appear
+-- in the source code; the extra ones are the existentially quantified
+-- dictionaries
+dataConRepArity (MkData {dcRepArgTys = arg_tys}) = length arg_tys
+
+isNullarySrcDataCon, isNullaryRepDataCon :: DataCon -> Bool
+isNullarySrcDataCon dc = null (dcOrigArgTys dc)
+isNullaryRepDataCon dc = null (dcRepArgTys dc)
+
+dataConRepStrictness :: DataCon -> [StrictnessMark]
+ -- Give the demands on the arguments of a
+ -- Core constructor application (Con dc args)
+dataConRepStrictness dc = dcRepStrictness dc
+
+dataConSig :: DataCon -> ([TyVar], ThetaType,
+ [Type], TyCon, [Type])
+
+dataConSig (MkData {dcTyVars = tyvars, dcTheta = theta,
+ dcOrigArgTys = arg_tys, dcTyCon = tycon, dcResTys = res_tys})
+ = (tyvars, theta, arg_tys, tycon, res_tys)
+
+dataConStupidTheta :: DataCon -> ThetaType
+dataConStupidTheta dc = dcStupidTheta dc
+
+dataConResTys :: DataCon -> [Type]
+dataConResTys dc = dcResTys dc
+
+dataConInstArgTys :: DataCon
+ -> [Type] -- Instantiated at these types
+ -- NB: these INCLUDE the existentially quantified arg types
+ -> [Type] -- Needs arguments of these types
+ -- NB: these INCLUDE the existentially quantified dict args
+ -- but EXCLUDE the data-decl context which is discarded
+ -- It's all post-flattening etc; this is a representation type
+dataConInstArgTys (MkData {dcRepArgTys = arg_tys, dcTyVars = tyvars}) inst_tys
+ = ASSERT( length tyvars == length inst_tys )
+ map (substTyWith tyvars inst_tys) arg_tys
+
+dataConInstResTy :: DataCon -> [Type] -> Type
+dataConInstResTy (MkData {dcTyVars = tyvars, dcTyCon = tc, dcResTys = res_tys}) inst_tys
+ = ASSERT( length tyvars == length inst_tys )
+ substTy (zipOpenTvSubst tyvars inst_tys) (mkTyConApp tc res_tys)
+ -- res_tys can't currently contain any foralls,
+ -- but might in future; hence zipOpenTvSubst
+
+-- And the same deal for the original arg tys
+dataConInstOrigArgTys :: DataCon -> [Type] -> [Type]
+dataConInstOrigArgTys (MkData {dcOrigArgTys = arg_tys, dcTyVars = tyvars}) inst_tys
+ = ASSERT( length tyvars == length inst_tys )
+ map (substTyWith tyvars inst_tys) arg_tys
+\end{code}
+
+These two functions get the real argument types of the constructor,
+without substituting for any type variables.
+
+dataConOrigArgTys returns the arg types of the wrapper, excluding all dictionary args.
+
+dataConRepArgTys retuns the arg types of the worker, including all dictionaries, and
+after any flattening has been done.
+
+\begin{code}
+dataConOrigArgTys :: DataCon -> [Type]
+dataConOrigArgTys dc = dcOrigArgTys dc
+
+dataConRepArgTys :: DataCon -> [Type]
+dataConRepArgTys dc = dcRepArgTys dc
+\end{code}
+
+
+\begin{code}
+isTupleCon :: DataCon -> Bool
+isTupleCon (MkData {dcTyCon = tc}) = isTupleTyCon tc
+
+isUnboxedTupleCon :: DataCon -> Bool
+isUnboxedTupleCon (MkData {dcTyCon = tc}) = isUnboxedTupleTyCon tc
+
+isVanillaDataCon :: DataCon -> Bool
+isVanillaDataCon dc = dcVanilla dc
+\end{code}
+
+
+\begin{code}
+classDataCon :: Class -> DataCon
+classDataCon clas = case tyConDataCons (classTyCon clas) of
+ (dict_constr:no_more) -> ASSERT( null no_more ) dict_constr
+\end{code}
+
+%************************************************************************
+%* *
+\subsection{Splitting products}
+%* *
+%************************************************************************
+
+\begin{code}
+splitProductType_maybe
+ :: Type -- A product type, perhaps
+ -> Maybe (TyCon, -- The type constructor
+ [Type], -- Type args of the tycon
+ DataCon, -- The data constructor
+ [Type]) -- Its *representation* arg types
+
+ -- Returns (Just ...) for any
+ -- concrete (i.e. constructors visible)
+ -- single-constructor
+ -- not existentially quantified
+ -- type whether a data type or a new type
+ --
+ -- Rejecing existentials is conservative. Maybe some things
+ -- could be made to work with them, but I'm not going to sweat
+ -- it through till someone finds it's important.
+
+splitProductType_maybe ty
+ = case splitTyConApp_maybe ty of
+ Just (tycon,ty_args)
+ | isProductTyCon tycon -- Includes check for non-existential,
+ -- and for constructors visible
+ -> Just (tycon, ty_args, data_con, dataConInstArgTys data_con ty_args)
+ where
+ data_con = head (tyConDataCons tycon)
+ other -> Nothing
+
+splitProductType str ty
+ = case splitProductType_maybe ty of
+ Just stuff -> stuff
+ Nothing -> pprPanic (str ++ ": not a product") (pprType ty)
+
+
+computeRep :: [StrictnessMark] -- Original arg strictness
+ -> [Type] -- and types
+ -> ([StrictnessMark], -- Representation arg strictness
+ [Type]) -- And type
+
+computeRep stricts tys
+ = unzip $ concat $ zipWithEqual "computeRep" unbox stricts tys
+ where
+ unbox NotMarkedStrict ty = [(NotMarkedStrict, ty)]
+ unbox MarkedStrict ty = [(MarkedStrict, ty)]
+ unbox MarkedUnboxed ty = zipEqual "computeRep" (dataConRepStrictness arg_dc) arg_tys
+ where
+ (_, _, arg_dc, arg_tys) = splitProductType "unbox_strict_arg_ty" ty
+\end{code}
diff --git a/compiler/basicTypes/DataCon.lhs-boot b/compiler/basicTypes/DataCon.lhs-boot
new file mode 100644
index 0000000000..c5e05c9ecd
--- /dev/null
+++ b/compiler/basicTypes/DataCon.lhs-boot
@@ -0,0 +1,8 @@
+\begin{code}
+module DataCon where
+import Name( Name )
+
+data DataCon
+dataConName :: DataCon -> Name
+isVanillaDataCon :: DataCon -> Bool
+\end{code}
diff --git a/compiler/basicTypes/Demand.lhs b/compiler/basicTypes/Demand.lhs
new file mode 100644
index 0000000000..50bb0c6ffa
--- /dev/null
+++ b/compiler/basicTypes/Demand.lhs
@@ -0,0 +1,208 @@
+%
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
+%
+\section[Demand]{@Demand@: the amount of demand on a value}
+
+\begin{code}
+#ifndef OLD_STRICTNESS
+module Demand () where
+#else
+
+module Demand(
+ Demand(..),
+
+ wwLazy, wwStrict, wwUnpack, wwPrim, wwEnum,
+ isStrict, isLazy, isPrim,
+
+ pprDemands, seqDemand, seqDemands,
+
+ StrictnessInfo(..),
+ mkStrictnessInfo,
+ noStrictnessInfo,
+ ppStrictnessInfo, seqStrictnessInfo,
+ isBottomingStrictness, appIsBottom,
+
+ ) where
+
+#include "HsVersions.h"
+
+import Outputable
+import Util ( listLengthCmp )
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{The @Demand@ data type}
+%* *
+%************************************************************************
+
+\begin{code}
+data Demand
+ = WwLazy -- Argument is lazy as far as we know
+ MaybeAbsent -- (does not imply worker's existence [etc]).
+ -- If MaybeAbsent == True, then it is
+ -- *definitely* lazy. (NB: Absence implies
+ -- a worker...)
+
+ | WwStrict -- Argument is strict but that's all we know
+ -- (does not imply worker's existence or any
+ -- calling-convention magic)
+
+ | WwUnpack -- Argument is strict & a single-constructor type
+ Bool -- True <=> wrapper unpacks it; False <=> doesn't
+ [Demand] -- Its constituent parts (whose StrictInfos
+ -- are in the list) should be passed
+ -- as arguments to the worker.
+
+ | WwPrim -- Argument is of primitive type, therefore
+ -- strict; doesn't imply existence of a worker;
+ -- argument should be passed as is to worker.
+
+ | WwEnum -- Argument is strict & an enumeration type;
+ -- an Int# representing the tag (start counting
+ -- at zero) should be passed to the worker.
+ deriving( Eq )
+
+type MaybeAbsent = Bool -- True <=> not even used
+
+-- versions that don't worry about Absence:
+wwLazy = WwLazy False
+wwStrict = WwStrict
+wwUnpack xs = WwUnpack False xs
+wwPrim = WwPrim
+wwEnum = WwEnum
+
+seqDemand :: Demand -> ()
+seqDemand (WwLazy a) = a `seq` ()
+seqDemand (WwUnpack b ds) = b `seq` seqDemands ds
+seqDemand other = ()
+
+seqDemands [] = ()
+seqDemands (d:ds) = seqDemand d `seq` seqDemands ds
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Functions over @Demand@}
+%* *
+%************************************************************************
+
+\begin{code}
+isLazy :: Demand -> Bool
+isLazy (WwLazy _) = True
+isLazy _ = False
+
+isStrict :: Demand -> Bool
+isStrict d = not (isLazy d)
+
+isPrim :: Demand -> Bool
+isPrim WwPrim = True
+isPrim other = False
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Instances}
+%* *
+%************************************************************************
+
+
+\begin{code}
+pprDemands demands bot = hcat (map pprDemand demands) <> pp_bot
+ where
+ pp_bot | bot = ptext SLIT("B")
+ | otherwise = empty
+
+
+pprDemand (WwLazy False) = char 'L'
+pprDemand (WwLazy True) = char 'A'
+pprDemand WwStrict = char 'S'
+pprDemand WwPrim = char 'P'
+pprDemand WwEnum = char 'E'
+pprDemand (WwUnpack wu args) = char ch <> parens (hcat (map pprDemand args))
+ where
+ ch = if wu then 'U' else 'u'
+
+instance Outputable Demand where
+ ppr (WwLazy False) = empty
+ ppr other_demand = ptext SLIT("__D") <+> pprDemand other_demand
+
+instance Show Demand where
+ showsPrec p d = showsPrecSDoc p (ppr d)
+
+-- Reading demands is done in Lex.lhs
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection[strictness-IdInfo]{Strictness info about an @Id@}
+%* *
+%************************************************************************
+
+We specify the strictness of a function by giving information about
+each of the ``wrapper's'' arguments (see the description about
+worker/wrapper-style transformations in the PJ/Launchbury paper on
+unboxed types).
+
+The list of @Demands@ specifies: (a)~the strictness properties of a
+function's arguments; and (b)~the type signature of that worker (if it
+exists); i.e. its calling convention.
+
+Note that the existence of a worker function is now denoted by the Id's
+workerInfo field.
+
+\begin{code}
+data StrictnessInfo
+ = NoStrictnessInfo
+
+ | StrictnessInfo [Demand] -- Demands on the arguments.
+
+ Bool -- True <=> the function diverges regardless of its arguments
+ -- Useful for "error" and other disguised variants thereof.
+ -- BUT NB: f = \x y. error "urk"
+ -- will have info SI [SS] True
+ -- but still (f) and (f 2) are not bot; only (f 3 2) is bot
+ deriving( Eq )
+
+ -- NOTA BENE: if the arg demands are, say, [S,L], this means that
+ -- (f bot) is not necy bot, only (f bot x) is bot
+ -- We simply cannot express accurately the strictness of a function
+ -- like f = \x -> case x of (a,b) -> \y -> ...
+ -- The up-side is that we don't need to restrict the strictness info
+ -- to the visible arity of the function.
+
+seqStrictnessInfo :: StrictnessInfo -> ()
+seqStrictnessInfo (StrictnessInfo ds b) = b `seq` seqDemands ds
+seqStrictnessInfo other = ()
+\end{code}
+
+\begin{code}
+mkStrictnessInfo :: ([Demand], Bool) -> StrictnessInfo
+
+mkStrictnessInfo (xs, is_bot)
+ | all totally_boring xs && not is_bot = NoStrictnessInfo -- Uninteresting
+ | otherwise = StrictnessInfo xs is_bot
+ where
+ totally_boring (WwLazy False) = True
+ totally_boring other = False
+
+noStrictnessInfo = NoStrictnessInfo
+
+isBottomingStrictness (StrictnessInfo _ bot) = bot
+isBottomingStrictness NoStrictnessInfo = False
+
+-- appIsBottom returns true if an application to n args would diverge
+appIsBottom (StrictnessInfo ds bot) n = bot && (listLengthCmp ds n /=GT) -- not more than 'n' elts in 'ds'.
+appIsBottom NoStrictnessInfo n = False
+
+ppStrictnessInfo NoStrictnessInfo = empty
+ppStrictnessInfo (StrictnessInfo wrapper_args bot) = hsep [pprDemands wrapper_args bot]
+\end{code}
+
+\begin{code}
+#endif /* OLD_STRICTNESS */
+\end{code}
diff --git a/compiler/basicTypes/FieldLabel.lhs b/compiler/basicTypes/FieldLabel.lhs
new file mode 100644
index 0000000000..b388d378d7
--- /dev/null
+++ b/compiler/basicTypes/FieldLabel.lhs
@@ -0,0 +1,71 @@
+%
+% (c) The AQUA Project, Glasgow University, 1996-1998
+%
+\section[FieldLabel]{The @FieldLabel@ type}
+
+\begin{code}
+module FieldLabel(
+ FieldLabel, -- Abstract
+
+ mkFieldLabel,
+ fieldLabelName, fieldLabelTyCon, fieldLabelType, fieldLabelTag,
+
+ FieldLabelTag,
+ firstFieldLabelTag, allFieldLabelTags
+ ) where
+
+#include "HsVersions.h"
+
+import Type( Type )
+import TyCon( TyCon )
+import Name ( Name{-instance Eq/Outputable-}, NamedThing(..), nameUnique )
+import Outputable
+import Unique ( Uniquable(..) )
+\end{code}
+
+\begin{code}
+data FieldLabel
+ = FieldLabel Name -- Also used as the Name of the field selector Id
+
+ TyCon -- Parent type constructor
+
+ Type -- Type of the field; may have free type variables that
+ -- are the tyvars of its parent *data* constructor, and
+ -- those will be the same as the tyvars of its parent *type* constructor
+ -- e.g. data T a = MkT { op1 :: a -> a, op2 :: a -> Int }
+ -- The type in the FieldLabel for op1 will be simply (a->a).
+
+ FieldLabelTag -- Indicates position within constructor
+ -- (starting with firstFieldLabelTag)
+ --
+ -- If the same field occurs in more than one constructor
+ -- then it'll have a separate FieldLabel on each occasion,
+ -- but with a single name (and presumably the same type!)
+
+type FieldLabelTag = Int
+
+mkFieldLabel = FieldLabel
+
+firstFieldLabelTag :: FieldLabelTag
+firstFieldLabelTag = 1
+
+allFieldLabelTags :: [FieldLabelTag]
+allFieldLabelTags = [firstFieldLabelTag..]
+
+fieldLabelName (FieldLabel n _ _ _) = n
+fieldLabelTyCon (FieldLabel _ tc _ _) = tc
+fieldLabelType (FieldLabel _ _ ty _) = ty
+fieldLabelTag (FieldLabel _ _ _ tag) = tag
+
+instance Eq FieldLabel where
+ fl1 == fl2 = fieldLabelName fl1 == fieldLabelName fl2
+
+instance Outputable FieldLabel where
+ ppr fl = ppr (fieldLabelName fl)
+
+instance NamedThing FieldLabel where
+ getName = fieldLabelName
+
+instance Uniquable FieldLabel where
+ getUnique fl = nameUnique (fieldLabelName fl)
+\end{code}
diff --git a/compiler/basicTypes/Id.lhs b/compiler/basicTypes/Id.lhs
new file mode 100644
index 0000000000..c7ce818adb
--- /dev/null
+++ b/compiler/basicTypes/Id.lhs
@@ -0,0 +1,529 @@
+%
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
+%
+\section[Id]{@Ids@: Value and constructor identifiers}
+
+\begin{code}
+module Id (
+ Id, DictId,
+
+ -- Simple construction
+ mkGlobalId, mkLocalId, mkLocalIdWithInfo,
+ mkSysLocal, mkUserLocal, mkVanillaGlobal,
+ mkTemplateLocals, mkTemplateLocalsNum, mkWildId, mkTemplateLocal,
+ mkWorkerId, mkExportedLocalId,
+
+ -- Taking an Id apart
+ idName, idType, idUnique, idInfo,
+ isId, globalIdDetails, idPrimRep,
+ recordSelectorFieldLabel,
+
+ -- Modifying an Id
+ setIdName, setIdUnique, Id.setIdType, setIdExported, setIdNotExported,
+ setIdInfo, lazySetIdInfo, modifyIdInfo, maybeModifyIdInfo,
+ zapLamIdInfo, zapDemandIdInfo,
+
+ -- Predicates
+ isImplicitId, isDeadBinder, isDictId,
+ isExportedId, isLocalId, isGlobalId,
+ isRecordSelector, isNaughtyRecordSelector,
+ isClassOpId_maybe,
+ isPrimOpId, isPrimOpId_maybe,
+ isFCallId, isFCallId_maybe,
+ isDataConWorkId, isDataConWorkId_maybe, isDataConId_maybe, idDataCon,
+ isBottomingId, idIsFrom,
+ hasNoBinding,
+
+ -- Inline pragma stuff
+ idInlinePragma, setInlinePragma, modifyInlinePragma,
+
+
+ -- One shot lambda stuff
+ isOneShotBndr, isOneShotLambda, isStateHackType,
+ setOneShotLambda, clearOneShotLambda,
+
+ -- IdInfo stuff
+ setIdUnfolding,
+ setIdArity,
+ setIdNewDemandInfo,
+ setIdNewStrictness, zapIdNewStrictness,
+ setIdWorkerInfo,
+ setIdSpecialisation,
+ setIdCafInfo,
+ setIdOccInfo,
+
+#ifdef OLD_STRICTNESS
+ idDemandInfo,
+ idStrictness,
+ idCprInfo,
+ setIdStrictness,
+ setIdDemandInfo,
+ setIdCprInfo,
+#endif
+
+ idArity,
+ idNewDemandInfo, idNewDemandInfo_maybe,
+ idNewStrictness, idNewStrictness_maybe,
+ idWorkerInfo,
+ idUnfolding,
+ idSpecialisation, idCoreRules,
+ idCafInfo,
+ idLBVarInfo,
+ idOccInfo,
+
+#ifdef OLD_STRICTNESS
+ newStrictnessFromOld -- Temporary
+#endif
+
+ ) where
+
+#include "HsVersions.h"
+
+
+import CoreSyn ( Unfolding, CoreRule )
+import BasicTypes ( Arity )
+import Var ( Id, DictId,
+ isId, isExportedId, isLocalId,
+ idName, idType, idUnique, idInfo, isGlobalId,
+ setIdName, setIdType, setIdUnique,
+ setIdExported, setIdNotExported,
+ setIdInfo, lazySetIdInfo, modifyIdInfo,
+ maybeModifyIdInfo,
+ globalIdDetails
+ )
+import qualified Var ( mkLocalId, mkGlobalId, mkExportedLocalId )
+import TyCon ( FieldLabel, TyCon )
+import Type ( Type, typePrimRep, addFreeTyVars, seqType,
+ splitTyConApp_maybe, PrimRep )
+import TcType ( isDictTy )
+import TysPrim ( statePrimTyCon )
+import IdInfo
+
+#ifdef OLD_STRICTNESS
+import qualified Demand ( Demand )
+#endif
+import DataCon ( DataCon, isUnboxedTupleCon )
+import NewDemand ( Demand, StrictSig, topDmd, topSig, isBottomingSig )
+import Name ( Name, OccName, nameIsLocalOrFrom,
+ mkSystemVarName, mkInternalName, getOccName,
+ getSrcLoc )
+import Module ( Module )
+import OccName ( mkWorkerOcc )
+import Maybes ( orElse )
+import SrcLoc ( SrcLoc )
+import Outputable
+import Unique ( Unique, mkBuiltinUnique )
+import FastString ( FastString )
+import StaticFlags ( opt_NoStateHack )
+
+-- infixl so you can say (id `set` a `set` b)
+infixl 1 `setIdUnfolding`,
+ `setIdArity`,
+ `setIdNewDemandInfo`,
+ `setIdNewStrictness`,
+ `setIdWorkerInfo`,
+ `setIdSpecialisation`,
+ `setInlinePragma`,
+ `idCafInfo`
+#ifdef OLD_STRICTNESS
+ ,`idCprInfo`
+ ,`setIdStrictness`
+ ,`setIdDemandInfo`
+#endif
+\end{code}
+
+
+
+%************************************************************************
+%* *
+\subsection{Simple Id construction}
+%* *
+%************************************************************************
+
+Absolutely all Ids are made by mkId. It is just like Var.mkId,
+but in addition it pins free-tyvar-info onto the Id's type,
+where it can easily be found.
+
+\begin{code}
+mkLocalIdWithInfo :: Name -> Type -> IdInfo -> Id
+mkLocalIdWithInfo name ty info = Var.mkLocalId name (addFreeTyVars ty) info
+
+mkExportedLocalId :: Name -> Type -> Id
+mkExportedLocalId name ty = Var.mkExportedLocalId name (addFreeTyVars ty) vanillaIdInfo
+
+mkGlobalId :: GlobalIdDetails -> Name -> Type -> IdInfo -> Id
+mkGlobalId details name ty info = Var.mkGlobalId details name (addFreeTyVars ty) info
+\end{code}
+
+\begin{code}
+mkLocalId :: Name -> Type -> Id
+mkLocalId name ty = mkLocalIdWithInfo name ty vanillaIdInfo
+
+-- SysLocal: for an Id being created by the compiler out of thin air...
+-- UserLocal: an Id with a name the user might recognize...
+mkUserLocal :: OccName -> Unique -> Type -> SrcLoc -> Id
+mkSysLocal :: FastString -> Unique -> Type -> Id
+mkVanillaGlobal :: Name -> Type -> IdInfo -> Id
+
+mkSysLocal fs uniq ty = mkLocalId (mkSystemVarName uniq fs) ty
+
+mkUserLocal occ uniq ty loc = mkLocalId (mkInternalName uniq occ loc) ty
+mkVanillaGlobal = mkGlobalId VanillaGlobal
+\end{code}
+
+Make some local @Ids@ for a template @CoreExpr@. These have bogus
+@Uniques@, but that's OK because the templates are supposed to be
+instantiated before use.
+
+\begin{code}
+-- "Wild Id" typically used when you need a binder that you don't expect to use
+mkWildId :: Type -> Id
+mkWildId ty = mkSysLocal FSLIT("wild") (mkBuiltinUnique 1) ty
+
+mkWorkerId :: Unique -> Id -> Type -> Id
+-- A worker gets a local name. CoreTidy will externalise it if necessary.
+mkWorkerId uniq unwrkr ty
+ = mkLocalId wkr_name ty
+ where
+ wkr_name = mkInternalName uniq (mkWorkerOcc (getOccName unwrkr)) (getSrcLoc unwrkr)
+
+-- "Template locals" typically used in unfoldings
+mkTemplateLocals :: [Type] -> [Id]
+mkTemplateLocals tys = zipWith mkTemplateLocal [1..] tys
+
+mkTemplateLocalsNum :: Int -> [Type] -> [Id]
+-- The Int gives the starting point for unique allocation
+mkTemplateLocalsNum n tys = zipWith mkTemplateLocal [n..] tys
+
+mkTemplateLocal :: Int -> Type -> Id
+mkTemplateLocal i ty = mkSysLocal FSLIT("tpl") (mkBuiltinUnique i) ty
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection[Id-general-funs]{General @Id@-related functions}
+%* *
+%************************************************************************
+
+\begin{code}
+setIdType :: Id -> Type -> Id
+ -- Add free tyvar info to the type
+setIdType id ty = seqType ty `seq` Var.setIdType id (addFreeTyVars ty)
+
+idPrimRep :: Id -> PrimRep
+idPrimRep id = typePrimRep (idType id)
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Special Ids}
+%* *
+%************************************************************************
+
+\begin{code}
+recordSelectorFieldLabel :: Id -> (TyCon, FieldLabel)
+recordSelectorFieldLabel id = case globalIdDetails id of
+ RecordSelId tycon lbl _ -> (tycon,lbl)
+ other -> panic "recordSelectorFieldLabel"
+
+isRecordSelector id = case globalIdDetails id of
+ RecordSelId {} -> True
+ other -> False
+
+isNaughtyRecordSelector id = case globalIdDetails id of
+ RecordSelId { sel_naughty = n } -> n
+ other -> False
+
+isClassOpId_maybe id = case globalIdDetails id of
+ ClassOpId cls -> Just cls
+ _other -> Nothing
+
+isPrimOpId id = case globalIdDetails id of
+ PrimOpId op -> True
+ other -> False
+
+isPrimOpId_maybe id = case globalIdDetails id of
+ PrimOpId op -> Just op
+ other -> Nothing
+
+isFCallId id = case globalIdDetails id of
+ FCallId call -> True
+ other -> False
+
+isFCallId_maybe id = case globalIdDetails id of
+ FCallId call -> Just call
+ other -> Nothing
+
+isDataConWorkId id = case globalIdDetails id of
+ DataConWorkId _ -> True
+ other -> False
+
+isDataConWorkId_maybe id = case globalIdDetails id of
+ DataConWorkId con -> Just con
+ other -> Nothing
+
+isDataConId_maybe :: Id -> Maybe DataCon
+isDataConId_maybe id = case globalIdDetails id of
+ DataConWorkId con -> Just con
+ DataConWrapId con -> Just con
+ other -> Nothing
+
+idDataCon :: Id -> DataCon
+-- Get from either the worker or the wrapper to the DataCon
+-- Currently used only in the desugarer
+-- INVARIANT: idDataCon (dataConWrapId d) = d
+-- (Remember, dataConWrapId can return either the wrapper or the worker.)
+idDataCon id = case globalIdDetails id of
+ DataConWorkId con -> con
+ DataConWrapId con -> con
+ other -> pprPanic "idDataCon" (ppr id)
+
+
+isDictId :: Id -> Bool
+isDictId id = isDictTy (idType id)
+
+-- hasNoBinding returns True of an Id which may not have a
+-- binding, even though it is defined in this module.
+-- Data constructor workers used to be things of this kind, but
+-- they aren't any more. Instead, we inject a binding for
+-- them at the CorePrep stage.
+-- EXCEPT: unboxed tuples, which definitely have no binding
+hasNoBinding id = case globalIdDetails id of
+ PrimOpId _ -> True
+ FCallId _ -> True
+ DataConWorkId dc -> isUnboxedTupleCon dc
+ other -> False
+
+isImplicitId :: Id -> Bool
+ -- isImplicitId tells whether an Id's info is implied by other
+ -- declarations, so we don't need to put its signature in an interface
+ -- file, even if it's mentioned in some other interface unfolding.
+isImplicitId id
+ = case globalIdDetails id of
+ RecordSelId {} -> True
+ FCallId _ -> True
+ PrimOpId _ -> True
+ ClassOpId _ -> True
+ DataConWorkId _ -> True
+ DataConWrapId _ -> True
+ -- These are are implied by their type or class decl;
+ -- remember that all type and class decls appear in the interface file.
+ -- The dfun id is not an implicit Id; it must *not* be omitted, because
+ -- it carries version info for the instance decl
+ other -> False
+
+idIsFrom :: Module -> Id -> Bool
+idIsFrom mod id = nameIsLocalOrFrom mod (idName id)
+\end{code}
+
+\begin{code}
+isDeadBinder :: Id -> Bool
+isDeadBinder bndr | isId bndr = isDeadOcc (idOccInfo bndr)
+ | otherwise = False -- TyVars count as not dead
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{IdInfo stuff}
+%* *
+%************************************************************************
+
+\begin{code}
+ ---------------------------------
+ -- ARITY
+idArity :: Id -> Arity
+idArity id = arityInfo (idInfo id)
+
+setIdArity :: Id -> Arity -> Id
+setIdArity id arity = modifyIdInfo (`setArityInfo` arity) id
+
+#ifdef OLD_STRICTNESS
+ ---------------------------------
+ -- (OLD) STRICTNESS
+idStrictness :: Id -> StrictnessInfo
+idStrictness id = strictnessInfo (idInfo id)
+
+setIdStrictness :: Id -> StrictnessInfo -> Id
+setIdStrictness id strict_info = modifyIdInfo (`setStrictnessInfo` strict_info) id
+#endif
+
+-- isBottomingId returns true if an application to n args would diverge
+isBottomingId :: Id -> Bool
+isBottomingId id = isBottomingSig (idNewStrictness id)
+
+idNewStrictness_maybe :: Id -> Maybe StrictSig
+idNewStrictness :: Id -> StrictSig
+
+idNewStrictness_maybe id = newStrictnessInfo (idInfo id)
+idNewStrictness id = idNewStrictness_maybe id `orElse` topSig
+
+setIdNewStrictness :: Id -> StrictSig -> Id
+setIdNewStrictness id sig = modifyIdInfo (`setNewStrictnessInfo` Just sig) id
+
+zapIdNewStrictness :: Id -> Id
+zapIdNewStrictness id = modifyIdInfo (`setNewStrictnessInfo` Nothing) id
+
+ ---------------------------------
+ -- WORKER ID
+idWorkerInfo :: Id -> WorkerInfo
+idWorkerInfo id = workerInfo (idInfo id)
+
+setIdWorkerInfo :: Id -> WorkerInfo -> Id
+setIdWorkerInfo id work_info = modifyIdInfo (`setWorkerInfo` work_info) id
+
+ ---------------------------------
+ -- UNFOLDING
+idUnfolding :: Id -> Unfolding
+idUnfolding id = unfoldingInfo (idInfo id)
+
+setIdUnfolding :: Id -> Unfolding -> Id
+setIdUnfolding id unfolding = modifyIdInfo (`setUnfoldingInfo` unfolding) id
+
+#ifdef OLD_STRICTNESS
+ ---------------------------------
+ -- (OLD) DEMAND
+idDemandInfo :: Id -> Demand.Demand
+idDemandInfo id = demandInfo (idInfo id)
+
+setIdDemandInfo :: Id -> Demand.Demand -> Id
+setIdDemandInfo id demand_info = modifyIdInfo (`setDemandInfo` demand_info) id
+#endif
+
+idNewDemandInfo_maybe :: Id -> Maybe NewDemand.Demand
+idNewDemandInfo :: Id -> NewDemand.Demand
+
+idNewDemandInfo_maybe id = newDemandInfo (idInfo id)
+idNewDemandInfo id = newDemandInfo (idInfo id) `orElse` NewDemand.topDmd
+
+setIdNewDemandInfo :: Id -> NewDemand.Demand -> Id
+setIdNewDemandInfo id dmd = modifyIdInfo (`setNewDemandInfo` Just dmd) id
+
+ ---------------------------------
+ -- SPECIALISATION
+idSpecialisation :: Id -> SpecInfo
+idSpecialisation id = specInfo (idInfo id)
+
+idCoreRules :: Id -> [CoreRule]
+idCoreRules id = specInfoRules (idSpecialisation id)
+
+setIdSpecialisation :: Id -> SpecInfo -> Id
+setIdSpecialisation id spec_info = modifyIdInfo (`setSpecInfo` spec_info) id
+
+ ---------------------------------
+ -- CAF INFO
+idCafInfo :: Id -> CafInfo
+#ifdef OLD_STRICTNESS
+idCafInfo id = case cgInfo (idInfo id) of
+ NoCgInfo -> pprPanic "idCafInfo" (ppr id)
+ info -> cgCafInfo info
+#else
+idCafInfo id = cafInfo (idInfo id)
+#endif
+
+setIdCafInfo :: Id -> CafInfo -> Id
+setIdCafInfo id caf_info = modifyIdInfo (`setCafInfo` caf_info) id
+
+ ---------------------------------
+ -- CPR INFO
+#ifdef OLD_STRICTNESS
+idCprInfo :: Id -> CprInfo
+idCprInfo id = cprInfo (idInfo id)
+
+setIdCprInfo :: Id -> CprInfo -> Id
+setIdCprInfo id cpr_info = modifyIdInfo (`setCprInfo` cpr_info) id
+#endif
+
+ ---------------------------------
+ -- Occcurrence INFO
+idOccInfo :: Id -> OccInfo
+idOccInfo id = occInfo (idInfo id)
+
+setIdOccInfo :: Id -> OccInfo -> Id
+setIdOccInfo id occ_info = modifyIdInfo (`setOccInfo` occ_info) id
+\end{code}
+
+
+ ---------------------------------
+ -- INLINING
+The inline pragma tells us to be very keen to inline this Id, but it's still
+OK not to if optimisation is switched off.
+
+\begin{code}
+idInlinePragma :: Id -> InlinePragInfo
+idInlinePragma id = inlinePragInfo (idInfo id)
+
+setInlinePragma :: Id -> InlinePragInfo -> Id
+setInlinePragma id prag = modifyIdInfo (`setInlinePragInfo` prag) id
+
+modifyInlinePragma :: Id -> (InlinePragInfo -> InlinePragInfo) -> Id
+modifyInlinePragma id fn = modifyIdInfo (\info -> info `setInlinePragInfo` (fn (inlinePragInfo info))) id
+\end{code}
+
+
+ ---------------------------------
+ -- ONE-SHOT LAMBDAS
+\begin{code}
+idLBVarInfo :: Id -> LBVarInfo
+idLBVarInfo id = lbvarInfo (idInfo id)
+
+isOneShotBndr :: Id -> Bool
+-- This one is the "business end", called externally.
+-- Its main purpose is to encapsulate the Horrible State Hack
+isOneShotBndr id = isOneShotLambda id || (isStateHackType (idType id))
+
+isStateHackType :: Type -> Bool
+isStateHackType ty
+ | opt_NoStateHack
+ = False
+ | otherwise
+ = case splitTyConApp_maybe ty of
+ Just (tycon,_) -> tycon == statePrimTyCon
+ other -> False
+ -- This is a gross hack. It claims that
+ -- every function over realWorldStatePrimTy is a one-shot
+ -- function. This is pretty true in practice, and makes a big
+ -- difference. For example, consider
+ -- a `thenST` \ r -> ...E...
+ -- The early full laziness pass, if it doesn't know that r is one-shot
+ -- will pull out E (let's say it doesn't mention r) to give
+ -- let lvl = E in a `thenST` \ r -> ...lvl...
+ -- When `thenST` gets inlined, we end up with
+ -- let lvl = E in \s -> case a s of (r, s') -> ...lvl...
+ -- and we don't re-inline E.
+ --
+ -- It would be better to spot that r was one-shot to start with, but
+ -- I don't want to rely on that.
+ --
+ -- Another good example is in fill_in in PrelPack.lhs. We should be able to
+ -- spot that fill_in has arity 2 (and when Keith is done, we will) but we can't yet.
+
+
+-- The OneShotLambda functions simply fiddle with the IdInfo flag
+isOneShotLambda :: Id -> Bool
+isOneShotLambda id = case idLBVarInfo id of
+ IsOneShotLambda -> True
+ NoLBVarInfo -> False
+
+setOneShotLambda :: Id -> Id
+setOneShotLambda id = modifyIdInfo (`setLBVarInfo` IsOneShotLambda) id
+
+clearOneShotLambda :: Id -> Id
+clearOneShotLambda id
+ | isOneShotLambda id = modifyIdInfo (`setLBVarInfo` NoLBVarInfo) id
+ | otherwise = id
+
+-- But watch out: this may change the type of something else
+-- f = \x -> e
+-- If we change the one-shot-ness of x, f's type changes
+\end{code}
+
+\begin{code}
+zapLamIdInfo :: Id -> Id
+zapLamIdInfo id = maybeModifyIdInfo zapLamInfo id
+
+zapDemandIdInfo id = maybeModifyIdInfo zapDemandInfo id
+\end{code}
+
diff --git a/compiler/basicTypes/IdInfo.hi-boot-5 b/compiler/basicTypes/IdInfo.hi-boot-5
new file mode 100644
index 0000000000..4a326cad6f
--- /dev/null
+++ b/compiler/basicTypes/IdInfo.hi-boot-5
@@ -0,0 +1,8 @@
+__interface IdInfo 1 0 where
+__export IdInfo IdInfo GlobalIdDetails notGlobalId seqIdInfo vanillaIdInfo ;
+1 data IdInfo ;
+1 data GlobalIdDetails ;
+1 notGlobalId :: GlobalIdDetails ;
+1 seqIdInfo :: IdInfo -> PrelBase.Z0T ;
+1 vanillaIdInfo :: IdInfo ;
+
diff --git a/compiler/basicTypes/IdInfo.hi-boot-6 b/compiler/basicTypes/IdInfo.hi-boot-6
new file mode 100644
index 0000000000..e090800d61
--- /dev/null
+++ b/compiler/basicTypes/IdInfo.hi-boot-6
@@ -0,0 +1,8 @@
+module IdInfo where
+
+data IdInfo
+data GlobalIdDetails
+
+notGlobalId :: GlobalIdDetails
+seqIdInfo :: IdInfo -> ()
+vanillaIdInfo :: IdInfo
diff --git a/compiler/basicTypes/IdInfo.lhs b/compiler/basicTypes/IdInfo.lhs
new file mode 100644
index 0000000000..d53bf5627d
--- /dev/null
+++ b/compiler/basicTypes/IdInfo.lhs
@@ -0,0 +1,699 @@
+%
+% (c) The GRASP/AQUA Project, Glasgow University, 1993-1998
+%
+\section[IdInfo]{@IdInfos@: Non-essential information about @Ids@}
+
+(And a pretty good illustration of quite a few things wrong with
+Haskell. [WDP 94/11])
+
+\begin{code}
+module IdInfo (
+ GlobalIdDetails(..), notGlobalId, -- Not abstract
+
+ IdInfo, -- Abstract
+ vanillaIdInfo, noCafIdInfo,
+ seqIdInfo, megaSeqIdInfo,
+
+ -- Zapping
+ zapLamInfo, zapDemandInfo,
+
+ -- Arity
+ ArityInfo,
+ unknownArity,
+ arityInfo, setArityInfo, ppArityInfo,
+
+ -- New demand and strictness info
+ newStrictnessInfo, setNewStrictnessInfo,
+ newDemandInfo, setNewDemandInfo, pprNewStrictness,
+ setAllStrictnessInfo,
+
+#ifdef OLD_STRICTNESS
+ -- Strictness; imported from Demand
+ StrictnessInfo(..),
+ mkStrictnessInfo, noStrictnessInfo,
+ ppStrictnessInfo,isBottomingStrictness,
+#endif
+
+ -- Worker
+ WorkerInfo(..), workerExists, wrapperArity, workerId,
+ workerInfo, setWorkerInfo, ppWorkerInfo,
+
+ -- Unfolding
+ unfoldingInfo, setUnfoldingInfo, setUnfoldingInfoLazily,
+
+#ifdef OLD_STRICTNESS
+ -- Old DemandInfo and StrictnessInfo
+ demandInfo, setDemandInfo,
+ strictnessInfo, setStrictnessInfo,
+ cprInfoFromNewStrictness,
+ oldStrictnessFromNew, newStrictnessFromOld,
+ oldDemand, newDemand,
+
+ -- Constructed Product Result Info
+ CprInfo(..), cprInfo, setCprInfo, ppCprInfo, noCprInfo,
+#endif
+
+ -- Inline prags
+ InlinePragInfo,
+ inlinePragInfo, setInlinePragInfo,
+
+ -- Occurrence info
+ OccInfo(..), isFragileOcc, isDeadOcc, isLoopBreaker,
+ InsideLam, OneBranch, insideLam, notInsideLam, oneBranch, notOneBranch,
+ occInfo, setOccInfo,
+
+ -- Specialisation
+ SpecInfo(..), specInfo, setSpecInfo, isEmptySpecInfo,
+ specInfoFreeVars, specInfoRules, seqSpecInfo,
+
+ -- CAF info
+ CafInfo(..), cafInfo, ppCafInfo, setCafInfo, mayHaveCafRefs,
+
+ -- Lambda-bound variable info
+ LBVarInfo(..), lbvarInfo, setLBVarInfo, noLBVarInfo, hasNoLBVarInfo
+ ) where
+
+#include "HsVersions.h"
+
+
+import CoreSyn
+import Class ( Class )
+import PrimOp ( PrimOp )
+import Var ( Id )
+import VarSet ( VarSet, emptyVarSet, seqVarSet )
+import BasicTypes ( OccInfo(..), isFragileOcc, isDeadOcc, seqOccInfo, isLoopBreaker,
+ InsideLam, insideLam, notInsideLam,
+ OneBranch, oneBranch, notOneBranch,
+ Arity,
+ Activation(..)
+ )
+import DataCon ( DataCon )
+import TyCon ( TyCon, FieldLabel )
+import ForeignCall ( ForeignCall )
+import NewDemand
+import Outputable
+import Maybe ( isJust )
+
+#ifdef OLD_STRICTNESS
+import Name ( Name )
+import Demand hiding( Demand, seqDemand )
+import qualified Demand
+import Util ( listLengthCmp )
+import List ( replicate )
+#endif
+
+-- infixl so you can say (id `set` a `set` b)
+infixl 1 `setSpecInfo`,
+ `setArityInfo`,
+ `setInlinePragInfo`,
+ `setUnfoldingInfo`,
+ `setWorkerInfo`,
+ `setLBVarInfo`,
+ `setOccInfo`,
+ `setCafInfo`,
+ `setNewStrictnessInfo`,
+ `setAllStrictnessInfo`,
+ `setNewDemandInfo`
+#ifdef OLD_STRICTNESS
+ , `setCprInfo`
+ , `setDemandInfo`
+ , `setStrictnessInfo`
+#endif
+\end{code}
+
+%************************************************************************
+%* *
+\subsection{New strictness info}
+%* *
+%************************************************************************
+
+To be removed later
+
+\begin{code}
+-- setAllStrictnessInfo :: IdInfo -> Maybe StrictSig -> IdInfo
+-- Set old and new strictness info
+setAllStrictnessInfo info Nothing
+ = info { newStrictnessInfo = Nothing
+#ifdef OLD_STRICTNESS
+ , strictnessInfo = NoStrictnessInfo
+ , cprInfo = NoCPRInfo
+#endif
+ }
+
+setAllStrictnessInfo info (Just sig)
+ = info { newStrictnessInfo = Just sig
+#ifdef OLD_STRICTNESS
+ , strictnessInfo = oldStrictnessFromNew sig
+ , cprInfo = cprInfoFromNewStrictness sig
+#endif
+ }
+
+seqNewStrictnessInfo Nothing = ()
+seqNewStrictnessInfo (Just ty) = seqStrictSig ty
+
+pprNewStrictness Nothing = empty
+pprNewStrictness (Just sig) = ftext FSLIT("Str:") <+> ppr sig
+
+#ifdef OLD_STRICTNESS
+oldStrictnessFromNew :: StrictSig -> Demand.StrictnessInfo
+oldStrictnessFromNew sig = mkStrictnessInfo (map oldDemand dmds, isBotRes res_info)
+ where
+ (dmds, res_info) = splitStrictSig sig
+
+cprInfoFromNewStrictness :: StrictSig -> CprInfo
+cprInfoFromNewStrictness sig = case strictSigResInfo sig of
+ RetCPR -> ReturnsCPR
+ other -> NoCPRInfo
+
+newStrictnessFromOld :: Name -> Arity -> Demand.StrictnessInfo -> CprInfo -> StrictSig
+newStrictnessFromOld name arity (Demand.StrictnessInfo ds res) cpr
+ | listLengthCmp ds arity /= GT -- length ds <= arity
+ -- Sometimes the old strictness analyser has more
+ -- demands than the arity justifies
+ = mk_strict_sig name arity $
+ mkTopDmdType (map newDemand ds) (newRes res cpr)
+
+newStrictnessFromOld name arity other cpr
+ = -- Either no strictness info, or arity is too small
+ -- In either case we can't say anything useful
+ mk_strict_sig name arity $
+ mkTopDmdType (replicate arity lazyDmd) (newRes False cpr)
+
+mk_strict_sig name arity dmd_ty
+ = WARN( arity /= dmdTypeDepth dmd_ty, ppr name <+> (ppr arity $$ ppr dmd_ty) )
+ mkStrictSig dmd_ty
+
+newRes True _ = BotRes
+newRes False ReturnsCPR = retCPR
+newRes False NoCPRInfo = TopRes
+
+newDemand :: Demand.Demand -> NewDemand.Demand
+newDemand (WwLazy True) = Abs
+newDemand (WwLazy False) = lazyDmd
+newDemand WwStrict = evalDmd
+newDemand (WwUnpack unpk ds) = Eval (Prod (map newDemand ds))
+newDemand WwPrim = lazyDmd
+newDemand WwEnum = evalDmd
+
+oldDemand :: NewDemand.Demand -> Demand.Demand
+oldDemand Abs = WwLazy True
+oldDemand Top = WwLazy False
+oldDemand Bot = WwStrict
+oldDemand (Box Bot) = WwStrict
+oldDemand (Box Abs) = WwLazy False
+oldDemand (Box (Eval _)) = WwStrict -- Pass box only
+oldDemand (Defer d) = WwLazy False
+oldDemand (Eval (Prod ds)) = WwUnpack True (map oldDemand ds)
+oldDemand (Eval (Poly _)) = WwStrict
+oldDemand (Call _) = WwStrict
+
+#endif /* OLD_STRICTNESS */
+\end{code}
+
+
+\begin{code}
+seqNewDemandInfo Nothing = ()
+seqNewDemandInfo (Just dmd) = seqDemand dmd
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{GlobalIdDetails
+%* *
+%************************************************************************
+
+This type is here (rather than in Id.lhs) mainly because there's
+an IdInfo.hi-boot, but no Id.hi-boot, and GlobalIdDetails is imported
+(recursively) by Var.lhs.
+
+\begin{code}
+data GlobalIdDetails
+ = VanillaGlobal -- Imported from elsewhere, a default method Id.
+
+ | RecordSelId -- The Id for a record selector
+ { sel_tycon :: TyCon
+ , sel_label :: FieldLabel
+ , sel_naughty :: Bool -- True <=> naughty
+ } -- See Note [Naughty record selectors]
+ -- with MkId.mkRecordSelectorId
+
+ | DataConWorkId DataCon -- The Id for a data constructor *worker*
+ | DataConWrapId DataCon -- The Id for a data constructor *wrapper*
+ -- [the only reasons we need to know is so that
+ -- a) to support isImplicitId
+ -- b) when desugaring a RecordCon we can get
+ -- from the Id back to the data con]
+
+ | ClassOpId Class -- An operation of a class
+
+ | PrimOpId PrimOp -- The Id for a primitive operator
+ | FCallId ForeignCall -- The Id for a foreign call
+
+ | NotGlobalId -- Used as a convenient extra return value from globalIdDetails
+
+notGlobalId = NotGlobalId
+
+instance Outputable GlobalIdDetails where
+ ppr NotGlobalId = ptext SLIT("[***NotGlobalId***]")
+ ppr VanillaGlobal = ptext SLIT("[GlobalId]")
+ ppr (DataConWorkId _) = ptext SLIT("[DataCon]")
+ ppr (DataConWrapId _) = ptext SLIT("[DataConWrapper]")
+ ppr (ClassOpId _) = ptext SLIT("[ClassOp]")
+ ppr (PrimOpId _) = ptext SLIT("[PrimOp]")
+ ppr (FCallId _) = ptext SLIT("[ForeignCall]")
+ ppr (RecordSelId {}) = ptext SLIT("[RecSel]")
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{The main IdInfo type}
+%* *
+%************************************************************************
+
+An @IdInfo@ gives {\em optional} information about an @Id@. If
+present it never lies, but it may not be present, in which case there
+is always a conservative assumption which can be made.
+
+Two @Id@s may have different info even though they have the same
+@Unique@ (and are hence the same @Id@); for example, one might lack
+the properties attached to the other.
+
+The @IdInfo@ gives information about the value, or definition, of the
+@Id@. It does {\em not} contain information about the @Id@'s usage
+(except for @DemandInfo@? ToDo). (@lbvarInfo@ is also a marginal
+case. KSW 1999-04).
+
+\begin{code}
+data IdInfo
+ = IdInfo {
+ arityInfo :: !ArityInfo, -- Its arity
+ specInfo :: SpecInfo, -- Specialisations of this function which exist
+#ifdef OLD_STRICTNESS
+ cprInfo :: CprInfo, -- Function always constructs a product result
+ demandInfo :: Demand.Demand, -- Whether or not it is definitely demanded
+ strictnessInfo :: StrictnessInfo, -- Strictness properties
+#endif
+ workerInfo :: WorkerInfo, -- Pointer to Worker Function
+ -- Within one module this is irrelevant; the
+ -- inlining of a worker is handled via the Unfolding
+ -- WorkerInfo is used *only* to indicate the form of
+ -- the RHS, so that interface files don't actually
+ -- need to contain the RHS; it can be derived from
+ -- the strictness info
+
+ unfoldingInfo :: Unfolding, -- Its unfolding
+ cafInfo :: CafInfo, -- CAF info
+ lbvarInfo :: LBVarInfo, -- Info about a lambda-bound variable
+ inlinePragInfo :: InlinePragInfo, -- Inline pragma
+ occInfo :: OccInfo, -- How it occurs
+
+ newStrictnessInfo :: Maybe StrictSig, -- Reason for Maybe: the DmdAnal phase needs to
+ -- know whether whether this is the first visit,
+ -- so it can assign botSig. Other customers want
+ -- topSig. So Nothing is good.
+
+ newDemandInfo :: Maybe Demand -- Similarly we want to know if there's no
+ -- known demand yet, for when we are looking for
+ -- CPR info
+ }
+
+seqIdInfo :: IdInfo -> ()
+seqIdInfo (IdInfo {}) = ()
+
+megaSeqIdInfo :: IdInfo -> ()
+megaSeqIdInfo info
+ = seqSpecInfo (specInfo info) `seq`
+ seqWorker (workerInfo info) `seq`
+
+-- Omitting this improves runtimes a little, presumably because
+-- some unfoldings are not calculated at all
+-- seqUnfolding (unfoldingInfo info) `seq`
+
+ seqNewDemandInfo (newDemandInfo info) `seq`
+ seqNewStrictnessInfo (newStrictnessInfo info) `seq`
+
+#ifdef OLD_STRICTNESS
+ Demand.seqDemand (demandInfo info) `seq`
+ seqStrictnessInfo (strictnessInfo info) `seq`
+ seqCpr (cprInfo info) `seq`
+#endif
+
+ seqCaf (cafInfo info) `seq`
+ seqLBVar (lbvarInfo info) `seq`
+ seqOccInfo (occInfo info)
+\end{code}
+
+Setters
+
+\begin{code}
+setWorkerInfo info wk = wk `seq` info { workerInfo = wk }
+setSpecInfo info sp = sp `seq` info { specInfo = sp }
+setInlinePragInfo info pr = pr `seq` info { inlinePragInfo = pr }
+setOccInfo info oc = oc `seq` info { occInfo = oc }
+#ifdef OLD_STRICTNESS
+setStrictnessInfo info st = st `seq` info { strictnessInfo = st }
+#endif
+ -- Try to avoid spack leaks by seq'ing
+
+setUnfoldingInfoLazily info uf -- Lazy variant to avoid looking at the
+ = -- unfolding of an imported Id unless necessary
+ info { unfoldingInfo = uf } -- (In this case the demand-zapping is redundant.)
+
+setUnfoldingInfo info uf
+ -- We do *not* seq on the unfolding info, For some reason, doing so
+ -- actually increases residency significantly.
+ = info { unfoldingInfo = uf }
+
+#ifdef OLD_STRICTNESS
+setDemandInfo info dd = info { demandInfo = dd }
+setCprInfo info cp = info { cprInfo = cp }
+#endif
+
+setArityInfo info ar = info { arityInfo = ar }
+setCafInfo info caf = info { cafInfo = caf }
+
+setLBVarInfo info lb = {-lb `seq`-} info { lbvarInfo = lb }
+
+setNewDemandInfo info dd = dd `seq` info { newDemandInfo = dd }
+setNewStrictnessInfo info dd = dd `seq` info { newStrictnessInfo = dd }
+\end{code}
+
+
+\begin{code}
+vanillaIdInfo :: IdInfo
+vanillaIdInfo
+ = IdInfo {
+ cafInfo = vanillaCafInfo,
+ arityInfo = unknownArity,
+#ifdef OLD_STRICTNESS
+ cprInfo = NoCPRInfo,
+ demandInfo = wwLazy,
+ strictnessInfo = NoStrictnessInfo,
+#endif
+ specInfo = emptySpecInfo,
+ workerInfo = NoWorker,
+ unfoldingInfo = noUnfolding,
+ lbvarInfo = NoLBVarInfo,
+ inlinePragInfo = AlwaysActive,
+ occInfo = NoOccInfo,
+ newDemandInfo = Nothing,
+ newStrictnessInfo = Nothing
+ }
+
+noCafIdInfo = vanillaIdInfo `setCafInfo` NoCafRefs
+ -- Used for built-in type Ids in MkId.
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection[arity-IdInfo]{Arity info about an @Id@}
+%* *
+%************************************************************************
+
+For locally-defined Ids, the code generator maintains its own notion
+of their arities; so it should not be asking... (but other things
+besides the code-generator need arity info!)
+
+\begin{code}
+type ArityInfo = Arity
+ -- A partial application of this Id to up to n-1 value arguments
+ -- does essentially no work. That is not necessarily the
+ -- same as saying that it has n leading lambdas, because coerces
+ -- may get in the way.
+
+ -- The arity might increase later in the compilation process, if
+ -- an extra lambda floats up to the binding site.
+
+unknownArity = 0 :: Arity
+
+ppArityInfo 0 = empty
+ppArityInfo n = hsep [ptext SLIT("Arity"), int n]
+\end{code}
+
+%************************************************************************
+%* *
+\subsection{Inline-pragma information}
+%* *
+%************************************************************************
+
+\begin{code}
+type InlinePragInfo = Activation
+ -- Tells when the inlining is active
+ -- When it is active the thing may be inlined, depending on how
+ -- big it is.
+ --
+ -- If there was an INLINE pragma, then as a separate matter, the
+ -- RHS will have been made to look small with a CoreSyn Inline Note
+
+ -- The default InlinePragInfo is AlwaysActive, so the info serves
+ -- entirely as a way to inhibit inlining until we want it
+\end{code}
+
+
+%************************************************************************
+%* *
+ SpecInfo
+%* *
+%************************************************************************
+
+\begin{code}
+-- CoreRules is used only in an idSpecialisation (move to IdInfo?)
+data SpecInfo
+ = SpecInfo [CoreRule] VarSet -- Locally-defined free vars of RHSs
+
+emptySpecInfo :: SpecInfo
+emptySpecInfo = SpecInfo [] emptyVarSet
+
+isEmptySpecInfo :: SpecInfo -> Bool
+isEmptySpecInfo (SpecInfo rs _) = null rs
+
+specInfoFreeVars :: SpecInfo -> VarSet
+specInfoFreeVars (SpecInfo _ fvs) = fvs
+
+specInfoRules :: SpecInfo -> [CoreRule]
+specInfoRules (SpecInfo rules _) = rules
+
+seqSpecInfo (SpecInfo rules fvs) = seqRules rules `seq` seqVarSet fvs
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection[worker-IdInfo]{Worker info about an @Id@}
+%* *
+%************************************************************************
+
+If this Id has a worker then we store a reference to it. Worker
+functions are generated by the worker/wrapper pass. This uses
+information from strictness analysis.
+
+There might not be a worker, even for a strict function, because:
+(a) the function might be small enough to inline, so no need
+ for w/w split
+(b) the strictness info might be "SSS" or something, so no w/w split.
+
+Sometimes the arity of a wrapper changes from the original arity from
+which it was generated, so we always emit the "original" arity into
+the interface file, as part of the worker info.
+
+How can this happen? Sometimes we get
+ f = coerce t (\x y -> $wf x y)
+at the moment of w/w split; but the eta reducer turns it into
+ f = coerce t $wf
+which is perfectly fine except that the exposed arity so far as
+the code generator is concerned (zero) differs from the arity
+when we did the split (2).
+
+All this arises because we use 'arity' to mean "exactly how many
+top level lambdas are there" in interface files; but during the
+compilation of this module it means "how many things can I apply
+this to".
+
+\begin{code}
+
+data WorkerInfo = NoWorker
+ | HasWorker Id Arity
+ -- The Arity is the arity of the *wrapper* at the moment of the
+ -- w/w split. See notes above.
+
+seqWorker :: WorkerInfo -> ()
+seqWorker (HasWorker id a) = id `seq` a `seq` ()
+seqWorker NoWorker = ()
+
+ppWorkerInfo NoWorker = empty
+ppWorkerInfo (HasWorker wk_id _) = ptext SLIT("Worker") <+> ppr wk_id
+
+workerExists :: WorkerInfo -> Bool
+workerExists NoWorker = False
+workerExists (HasWorker _ _) = True
+
+workerId :: WorkerInfo -> Id
+workerId (HasWorker id _) = id
+
+wrapperArity :: WorkerInfo -> Arity
+wrapperArity (HasWorker _ a) = a
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection[CG-IdInfo]{Code generator-related information}
+%* *
+%************************************************************************
+
+\begin{code}
+-- CafInfo is used to build Static Reference Tables (see simplStg/SRT.lhs).
+
+data CafInfo
+ = MayHaveCafRefs -- either:
+ -- (1) A function or static constructor
+ -- that refers to one or more CAFs,
+ -- (2) A real live CAF
+
+ | NoCafRefs -- A function or static constructor
+ -- that refers to no CAFs.
+
+vanillaCafInfo = MayHaveCafRefs -- Definitely safe
+
+mayHaveCafRefs MayHaveCafRefs = True
+mayHaveCafRefs _ = False
+
+seqCaf c = c `seq` ()
+
+ppCafInfo NoCafRefs = ptext SLIT("NoCafRefs")
+ppCafInfo MayHaveCafRefs = empty
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[cpr-IdInfo]{Constructed Product Result info about an @Id@}
+%* *
+%************************************************************************
+
+If the @Id@ is a function then it may have CPR info. A CPR analysis
+phase detects whether:
+
+\begin{enumerate}
+\item
+The function's return value has a product type, i.e. an algebraic type
+with a single constructor. Examples of such types are tuples and boxed
+primitive values.
+\item
+The function always 'constructs' the value that it is returning. It
+must do this on every path through, and it's OK if it calls another
+function which constructs the result.
+\end{enumerate}
+
+If this is the case then we store a template which tells us the
+function has the CPR property and which components of the result are
+also CPRs.
+
+\begin{code}
+#ifdef OLD_STRICTNESS
+data CprInfo
+ = NoCPRInfo
+ | ReturnsCPR -- Yes, this function returns a constructed product
+ -- Implicitly, this means "after the function has been applied
+ -- to all its arguments", so the worker/wrapper builder in
+ -- WwLib.mkWWcpr checks that that it is indeed saturated before
+ -- making use of the CPR info
+
+ -- We used to keep nested info about sub-components, but
+ -- we never used it so I threw it away
+
+seqCpr :: CprInfo -> ()
+seqCpr ReturnsCPR = ()
+seqCpr NoCPRInfo = ()
+
+noCprInfo = NoCPRInfo
+
+ppCprInfo NoCPRInfo = empty
+ppCprInfo ReturnsCPR = ptext SLIT("__M")
+
+instance Outputable CprInfo where
+ ppr = ppCprInfo
+
+instance Show CprInfo where
+ showsPrec p c = showsPrecSDoc p (ppr c)
+#endif
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection[lbvar-IdInfo]{Lambda-bound var info about an @Id@}
+%* *
+%************************************************************************
+
+If the @Id@ is a lambda-bound variable then it may have lambda-bound
+var info. Sometimes we know whether the lambda binding this var is a
+``one-shot'' lambda; that is, whether it is applied at most once.
+
+This information may be useful in optimisation, as computations may
+safely be floated inside such a lambda without risk of duplicating
+work.
+
+\begin{code}
+data LBVarInfo = NoLBVarInfo
+ | IsOneShotLambda -- The lambda is applied at most once).
+
+seqLBVar l = l `seq` ()
+\end{code}
+
+\begin{code}
+hasNoLBVarInfo NoLBVarInfo = True
+hasNoLBVarInfo IsOneShotLambda = False
+
+noLBVarInfo = NoLBVarInfo
+
+pprLBVarInfo NoLBVarInfo = empty
+pprLBVarInfo IsOneShotLambda = ptext SLIT("OneShot")
+
+instance Outputable LBVarInfo where
+ ppr = pprLBVarInfo
+
+instance Show LBVarInfo where
+ showsPrec p c = showsPrecSDoc p (ppr c)
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Bulk operations on IdInfo}
+%* *
+%************************************************************************
+
+@zapLamInfo@ is used for lambda binders that turn out to to be
+part of an unsaturated lambda
+
+\begin{code}
+zapLamInfo :: IdInfo -> Maybe IdInfo
+zapLamInfo info@(IdInfo {occInfo = occ, newDemandInfo = demand})
+ | is_safe_occ occ && is_safe_dmd demand
+ = Nothing
+ | otherwise
+ = Just (info {occInfo = safe_occ, newDemandInfo = Nothing})
+ where
+ -- The "unsafe" occ info is the ones that say I'm not in a lambda
+ -- because that might not be true for an unsaturated lambda
+ is_safe_occ (OneOcc in_lam _ _) = in_lam
+ is_safe_occ other = True
+
+ safe_occ = case occ of
+ OneOcc _ once int_cxt -> OneOcc insideLam once int_cxt
+ other -> occ
+
+ is_safe_dmd Nothing = True
+ is_safe_dmd (Just dmd) = not (isStrictDmd dmd)
+\end{code}
+
+\begin{code}
+zapDemandInfo :: IdInfo -> Maybe IdInfo
+zapDemandInfo info@(IdInfo {newDemandInfo = dmd})
+ | isJust dmd = Just (info {newDemandInfo = Nothing})
+ | otherwise = Nothing
+\end{code}
+
diff --git a/compiler/basicTypes/IdInfo.lhs-boot b/compiler/basicTypes/IdInfo.lhs-boot
new file mode 100644
index 0000000000..90cf36f90b
--- /dev/null
+++ b/compiler/basicTypes/IdInfo.lhs-boot
@@ -0,0 +1,9 @@
+\begin{code}
+module IdInfo where
+
+data IdInfo
+data GlobalIdDetails
+
+notGlobalId :: GlobalIdDetails
+seqIdInfo :: IdInfo -> ()
+\end{code} \ No newline at end of file
diff --git a/compiler/basicTypes/Literal.lhs b/compiler/basicTypes/Literal.lhs
new file mode 100644
index 0000000000..e83ea9db74
--- /dev/null
+++ b/compiler/basicTypes/Literal.lhs
@@ -0,0 +1,405 @@
+%
+% (c) The GRASP/AQUA Project, Glasgow University, 1998
+%
+\section[Literal]{@Literal@: Machine literals (unboxed, of course)}
+
+\begin{code}
+module Literal
+ ( Literal(..) -- Exported to ParseIface
+ , mkMachInt, mkMachWord
+ , mkMachInt64, mkMachWord64, mkStringLit
+ , litSize
+ , litIsDupable, litIsTrivial
+ , literalType
+ , hashLiteral
+
+ , inIntRange, inWordRange, tARGET_MAX_INT, inCharRange
+ , isZeroLit
+
+ , word2IntLit, int2WordLit
+ , narrow8IntLit, narrow16IntLit, narrow32IntLit
+ , narrow8WordLit, narrow16WordLit, narrow32WordLit
+ , char2IntLit, int2CharLit
+ , float2IntLit, int2FloatLit, double2IntLit, int2DoubleLit
+ , nullAddrLit, float2DoubleLit, double2FloatLit
+ ) where
+
+#include "HsVersions.h"
+
+import TysPrim ( charPrimTy, addrPrimTy, floatPrimTy, doublePrimTy,
+ intPrimTy, wordPrimTy, int64PrimTy, word64PrimTy
+ )
+import Type ( Type )
+import Outputable
+import FastTypes
+import FastString
+import Binary
+
+import Ratio ( numerator )
+import FastString ( uniqueOfFS, lengthFS )
+import DATA_INT ( Int8, Int16, Int32 )
+import DATA_WORD ( Word8, Word16, Word32 )
+import Char ( ord, chr )
+\end{code}
+
+
+
+%************************************************************************
+%* *
+\subsection{Sizes}
+%* *
+%************************************************************************
+
+If we're compiling with GHC (and we're not cross-compiling), then we
+know that minBound and maxBound :: Int are the right values for the
+target architecture. Otherwise, we assume -2^31 and 2^31-1
+respectively (which will be wrong on a 64-bit machine).
+
+\begin{code}
+tARGET_MIN_INT, tARGET_MAX_INT, tARGET_MAX_WORD :: Integer
+#if __GLASGOW_HASKELL__
+tARGET_MIN_INT = toInteger (minBound :: Int)
+tARGET_MAX_INT = toInteger (maxBound :: Int)
+#else
+tARGET_MIN_INT = -2147483648
+tARGET_MAX_INT = 2147483647
+#endif
+tARGET_MAX_WORD = (tARGET_MAX_INT * 2) + 1
+
+tARGET_MAX_CHAR :: Int
+tARGET_MAX_CHAR = 0x10ffff
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Literals}
+%* *
+%************************************************************************
+
+So-called @Literals@ are {\em either}:
+\begin{itemize}
+\item
+An unboxed (``machine'') literal (type: @IntPrim@, @FloatPrim@, etc.),
+which is presumed to be surrounded by appropriate constructors
+(@mKINT@, etc.), so that the overall thing makes sense.
+\item
+An Integer, Rational, or String literal whose representation we are
+{\em uncommitted} about; i.e., the surrounding with constructors,
+function applications, etc., etc., has not yet been done.
+\end{itemize}
+
+\begin{code}
+data Literal
+ = ------------------
+ -- First the primitive guys
+ MachChar Char -- Char# At least 31 bits
+
+ | MachStr FastString -- A string-literal: stored and emitted
+ -- UTF-8 encoded, we'll arrange to decode it
+ -- at runtime. Also emitted with a '\0'
+ -- terminator.
+
+ | MachNullAddr -- the NULL pointer, the only pointer value
+ -- that can be represented as a Literal.
+
+ | MachInt Integer -- Int# At least WORD_SIZE_IN_BITS bits
+ | MachInt64 Integer -- Int64# At least 64 bits
+ | MachWord Integer -- Word# At least WORD_SIZE_IN_BITS bits
+ | MachWord64 Integer -- Word64# At least 64 bits
+
+ | MachFloat Rational
+ | MachDouble Rational
+
+ -- MachLabel is used (only) for the literal derived from a
+ -- "foreign label" declaration.
+ -- string argument is the name of a symbol. This literal
+ -- refers to the *address* of the label.
+ | MachLabel FastString -- always an Addr#
+ (Maybe Int) -- the size (in bytes) of the arguments
+ -- the label expects. Only applicable with
+ -- 'stdcall' labels.
+ -- Just x => "@<x>" will be appended to label
+ -- name when emitting asm.
+\end{code}
+
+Binary instance
+
+\begin{code}
+instance Binary Literal where
+ put_ bh (MachChar aa) = do putByte bh 0; put_ bh aa
+ put_ bh (MachStr ab) = do putByte bh 1; put_ bh ab
+ put_ bh (MachNullAddr) = do putByte bh 2
+ put_ bh (MachInt ad) = do putByte bh 3; put_ bh ad
+ put_ bh (MachInt64 ae) = do putByte bh 4; put_ bh ae
+ put_ bh (MachWord af) = do putByte bh 5; put_ bh af
+ put_ bh (MachWord64 ag) = do putByte bh 6; put_ bh ag
+ put_ bh (MachFloat ah) = do putByte bh 7; put_ bh ah
+ put_ bh (MachDouble ai) = do putByte bh 8; put_ bh ai
+ put_ bh (MachLabel aj mb) = do putByte bh 9; put_ bh aj ; put_ bh mb
+ get bh = do
+ h <- getByte bh
+ case h of
+ 0 -> do
+ aa <- get bh
+ return (MachChar aa)
+ 1 -> do
+ ab <- get bh
+ return (MachStr ab)
+ 2 -> do
+ return (MachNullAddr)
+ 3 -> do
+ ad <- get bh
+ return (MachInt ad)
+ 4 -> do
+ ae <- get bh
+ return (MachInt64 ae)
+ 5 -> do
+ af <- get bh
+ return (MachWord af)
+ 6 -> do
+ ag <- get bh
+ return (MachWord64 ag)
+ 7 -> do
+ ah <- get bh
+ return (MachFloat ah)
+ 8 -> do
+ ai <- get bh
+ return (MachDouble ai)
+ 9 -> do
+ aj <- get bh
+ mb <- get bh
+ return (MachLabel aj mb)
+\end{code}
+
+\begin{code}
+instance Outputable Literal where
+ ppr lit = pprLit lit
+
+instance Show Literal where
+ showsPrec p lit = showsPrecSDoc p (ppr lit)
+
+instance Eq Literal where
+ a == b = case (a `compare` b) of { EQ -> True; _ -> False }
+ a /= b = case (a `compare` b) of { EQ -> False; _ -> True }
+
+instance Ord Literal where
+ a <= b = case (a `compare` b) of { LT -> True; EQ -> True; GT -> False }
+ a < b = case (a `compare` b) of { LT -> True; EQ -> False; GT -> False }
+ a >= b = case (a `compare` b) of { LT -> False; EQ -> True; GT -> True }
+ a > b = case (a `compare` b) of { LT -> False; EQ -> False; GT -> True }
+ compare a b = cmpLit a b
+\end{code}
+
+
+ Construction
+ ~~~~~~~~~~~~
+\begin{code}
+mkMachInt, mkMachWord, mkMachInt64, mkMachWord64 :: Integer -> Literal
+
+mkMachInt x = -- ASSERT2( inIntRange x, integer x )
+ -- Not true: you can write out of range Int# literals
+ -- For example, one can write (intToWord# 0xffff0000) to
+ -- get a particular Word bit-pattern, and there's no other
+ -- convenient way to write such literals, which is why we allow it.
+ MachInt x
+mkMachWord x = -- ASSERT2( inWordRange x, integer x )
+ MachWord x
+mkMachInt64 x = MachInt64 x
+mkMachWord64 x = MachWord64 x
+
+mkStringLit :: String -> Literal
+mkStringLit s = MachStr (mkFastString s) -- stored UTF-8 encoded
+
+inIntRange, inWordRange :: Integer -> Bool
+inIntRange x = x >= tARGET_MIN_INT && x <= tARGET_MAX_INT
+inWordRange x = x >= 0 && x <= tARGET_MAX_WORD
+
+inCharRange :: Char -> Bool
+inCharRange c = c >= '\0' && c <= chr tARGET_MAX_CHAR
+
+isZeroLit :: Literal -> Bool
+isZeroLit (MachInt 0) = True
+isZeroLit (MachInt64 0) = True
+isZeroLit (MachWord 0) = True
+isZeroLit (MachWord64 0) = True
+isZeroLit (MachFloat 0) = True
+isZeroLit (MachDouble 0) = True
+isZeroLit other = False
+\end{code}
+
+ Coercions
+ ~~~~~~~~~
+\begin{code}
+word2IntLit, int2WordLit,
+ narrow8IntLit, narrow16IntLit, narrow32IntLit,
+ narrow8WordLit, narrow16WordLit, narrow32WordLit,
+ char2IntLit, int2CharLit,
+ float2IntLit, int2FloatLit, double2IntLit, int2DoubleLit,
+ float2DoubleLit, double2FloatLit
+ :: Literal -> Literal
+
+word2IntLit (MachWord w)
+ | w > tARGET_MAX_INT = MachInt (w - tARGET_MAX_WORD - 1)
+ | otherwise = MachInt w
+
+int2WordLit (MachInt i)
+ | i < 0 = MachWord (1 + tARGET_MAX_WORD + i) -- (-1) ---> tARGET_MAX_WORD
+ | otherwise = MachWord i
+
+narrow8IntLit (MachInt i) = MachInt (toInteger (fromInteger i :: Int8))
+narrow16IntLit (MachInt i) = MachInt (toInteger (fromInteger i :: Int16))
+narrow32IntLit (MachInt i) = MachInt (toInteger (fromInteger i :: Int32))
+narrow8WordLit (MachWord w) = MachWord (toInteger (fromInteger w :: Word8))
+narrow16WordLit (MachWord w) = MachWord (toInteger (fromInteger w :: Word16))
+narrow32WordLit (MachWord w) = MachWord (toInteger (fromInteger w :: Word32))
+
+char2IntLit (MachChar c) = MachInt (toInteger (ord c))
+int2CharLit (MachInt i) = MachChar (chr (fromInteger i))
+
+float2IntLit (MachFloat f) = MachInt (truncate f)
+int2FloatLit (MachInt i) = MachFloat (fromInteger i)
+
+double2IntLit (MachDouble f) = MachInt (truncate f)
+int2DoubleLit (MachInt i) = MachDouble (fromInteger i)
+
+float2DoubleLit (MachFloat f) = MachDouble f
+double2FloatLit (MachDouble d) = MachFloat d
+
+nullAddrLit :: Literal
+nullAddrLit = MachNullAddr
+\end{code}
+
+ Predicates
+ ~~~~~~~~~~
+\begin{code}
+litIsTrivial :: Literal -> Bool
+-- True if there is absolutely no penalty to duplicating the literal
+-- c.f. CoreUtils.exprIsTrivial
+-- False principally of strings
+litIsTrivial (MachStr _) = False
+litIsTrivial other = True
+
+litIsDupable :: Literal -> Bool
+-- True if code space does not go bad if we duplicate this literal
+-- c.f. CoreUtils.exprIsDupable
+-- Currently we treat it just like litIsTrivial
+litIsDupable (MachStr _) = False
+litIsDupable other = True
+
+litSize :: Literal -> Int
+-- Used by CoreUnfold.sizeExpr
+litSize (MachStr str) = 1 + ((lengthFS str + 3) `div` 4)
+ -- Every literal has size at least 1, otherwise
+ -- f "x"
+ -- might be too small
+ -- [Sept03: make literal strings a bit bigger to avoid fruitless
+ -- duplication of little strings]
+litSize _other = 1
+\end{code}
+
+ Types
+ ~~~~~
+\begin{code}
+literalType :: Literal -> Type
+literalType MachNullAddr = addrPrimTy
+literalType (MachChar _) = charPrimTy
+literalType (MachStr _) = addrPrimTy
+literalType (MachInt _) = intPrimTy
+literalType (MachWord _) = wordPrimTy
+literalType (MachInt64 _) = int64PrimTy
+literalType (MachWord64 _) = word64PrimTy
+literalType (MachFloat _) = floatPrimTy
+literalType (MachDouble _) = doublePrimTy
+literalType (MachLabel _ _) = addrPrimTy
+\end{code}
+
+
+ Comparison
+ ~~~~~~~~~~
+\begin{code}
+cmpLit (MachChar a) (MachChar b) = a `compare` b
+cmpLit (MachStr a) (MachStr b) = a `compare` b
+cmpLit (MachNullAddr) (MachNullAddr) = EQ
+cmpLit (MachInt a) (MachInt b) = a `compare` b
+cmpLit (MachWord a) (MachWord b) = a `compare` b
+cmpLit (MachInt64 a) (MachInt64 b) = a `compare` b
+cmpLit (MachWord64 a) (MachWord64 b) = a `compare` b
+cmpLit (MachFloat a) (MachFloat b) = a `compare` b
+cmpLit (MachDouble a) (MachDouble b) = a `compare` b
+cmpLit (MachLabel a _) (MachLabel b _) = a `compare` b
+cmpLit lit1 lit2 | litTag lit1 <# litTag lit2 = LT
+ | otherwise = GT
+
+litTag (MachChar _) = _ILIT(1)
+litTag (MachStr _) = _ILIT(2)
+litTag (MachNullAddr) = _ILIT(3)
+litTag (MachInt _) = _ILIT(4)
+litTag (MachWord _) = _ILIT(5)
+litTag (MachInt64 _) = _ILIT(6)
+litTag (MachWord64 _) = _ILIT(7)
+litTag (MachFloat _) = _ILIT(8)
+litTag (MachDouble _) = _ILIT(9)
+litTag (MachLabel _ _) = _ILIT(10)
+\end{code}
+
+ Printing
+ ~~~~~~~~
+* MachX (i.e. unboxed) things are printed unadornded (e.g. 3, 'a', "foo")
+ exceptions: MachFloat gets an initial keyword prefix.
+
+\begin{code}
+pprLit (MachChar ch) = pprHsChar ch
+pprLit (MachStr s) = pprHsString s
+pprLit (MachInt i) = pprIntVal i
+pprLit (MachInt64 i) = ptext SLIT("__int64") <+> integer i
+pprLit (MachWord w) = ptext SLIT("__word") <+> integer w
+pprLit (MachWord64 w) = ptext SLIT("__word64") <+> integer w
+pprLit (MachFloat f) = ptext SLIT("__float") <+> rational f
+pprLit (MachDouble d) = rational d
+pprLit (MachNullAddr) = ptext SLIT("__NULL")
+pprLit (MachLabel l mb) = ptext SLIT("__label") <+>
+ case mb of
+ Nothing -> pprHsString l
+ Just x -> doubleQuotes (text (unpackFS l ++ '@':show x))
+
+pprIntVal :: Integer -> SDoc
+-- Print negative integers with parens to be sure it's unambiguous
+pprIntVal i | i < 0 = parens (integer i)
+ | otherwise = integer i
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Hashing}
+%* *
+%************************************************************************
+
+Hash values should be zero or a positive integer. No negatives please.
+(They mess up the UniqFM for some reason.)
+
+\begin{code}
+hashLiteral :: Literal -> Int
+hashLiteral (MachChar c) = ord c + 1000 -- Keep it out of range of common ints
+hashLiteral (MachStr s) = hashFS s
+hashLiteral (MachNullAddr) = 0
+hashLiteral (MachInt i) = hashInteger i
+hashLiteral (MachInt64 i) = hashInteger i
+hashLiteral (MachWord i) = hashInteger i
+hashLiteral (MachWord64 i) = hashInteger i
+hashLiteral (MachFloat r) = hashRational r
+hashLiteral (MachDouble r) = hashRational r
+hashLiteral (MachLabel s _) = hashFS s
+
+hashRational :: Rational -> Int
+hashRational r = hashInteger (numerator r)
+
+hashInteger :: Integer -> Int
+hashInteger i = 1 + abs (fromInteger (i `rem` 10000))
+ -- The 1+ is to avoid zero, which is a Bad Number
+ -- since we use * to combine hash values
+
+hashFS :: FastString -> Int
+hashFS s = iBox (uniqueOfFS s)
+\end{code}
diff --git a/compiler/basicTypes/MkId.hi-boot-5 b/compiler/basicTypes/MkId.hi-boot-5
new file mode 100644
index 0000000000..ff901a5840
--- /dev/null
+++ b/compiler/basicTypes/MkId.hi-boot-5
@@ -0,0 +1,3 @@
+__interface MkId 1 0 where
+__export MkId mkDataConIds ;
+1 mkDataConIds :: Name.Name -> Name.Name -> DataCon.DataCon -> DataCon.DataConIds ;
diff --git a/compiler/basicTypes/MkId.hi-boot-6 b/compiler/basicTypes/MkId.hi-boot-6
new file mode 100644
index 0000000000..d3f22527f3
--- /dev/null
+++ b/compiler/basicTypes/MkId.hi-boot-6
@@ -0,0 +1,5 @@
+module MkId where
+
+mkDataConIds :: Name.Name -> Name.Name -> DataCon.DataCon -> DataCon.DataConIds
+
+
diff --git a/compiler/basicTypes/MkId.lhs b/compiler/basicTypes/MkId.lhs
new file mode 100644
index 0000000000..84b3546e62
--- /dev/null
+++ b/compiler/basicTypes/MkId.lhs
@@ -0,0 +1,1044 @@
+%
+% (c) The AQUA Project, Glasgow University, 1998
+%
+\section[StdIdInfo]{Standard unfoldings}
+
+This module contains definitions for the IdInfo for things that
+have a standard form, namely:
+
+ * data constructors
+ * record selectors
+ * method and superclass selectors
+ * primitive operations
+
+\begin{code}
+module MkId (
+ mkDictFunId, mkDefaultMethodId,
+ mkDictSelId,
+
+ mkDataConIds,
+ mkRecordSelId,
+ mkPrimOpId, mkFCallId,
+
+ mkReboxingAlt, mkNewTypeBody,
+
+ -- And some particular Ids; see below for why they are wired in
+ wiredInIds, ghcPrimIds,
+ unsafeCoerceId, realWorldPrimId, voidArgId, nullAddrId, seqId,
+ lazyId, lazyIdUnfolding, lazyIdKey,
+
+ mkRuntimeErrorApp,
+ rEC_CON_ERROR_ID, iRREFUT_PAT_ERROR_ID, rUNTIME_ERROR_ID,
+ nON_EXHAUSTIVE_GUARDS_ERROR_ID, nO_METHOD_BINDING_ERROR_ID,
+ pAT_ERROR_ID, eRROR_ID,
+
+ unsafeCoerceName
+ ) where
+
+#include "HsVersions.h"
+
+
+import BasicTypes ( Arity, StrictnessMark(..), isMarkedUnboxed, isMarkedStrict )
+import Rules ( mkSpecInfo )
+import TysPrim ( openAlphaTyVars, alphaTyVar, alphaTy,
+ realWorldStatePrimTy, addrPrimTy
+ )
+import TysWiredIn ( charTy, mkListTy )
+import PrelRules ( primOpRules )
+import Type ( TyThing(..), mkForAllTy, tyVarsOfTypes )
+import TcType ( Type, ThetaType, mkDictTy, mkPredTys, mkPredTy,
+ mkTyConApp, mkTyVarTys, mkClassPred,
+ mkFunTys, mkFunTy, mkSigmaTy, tcSplitSigmaTy,
+ isUnLiftedType, mkForAllTys, mkTyVarTy, tyVarsOfType,
+ tcSplitFunTys, tcSplitForAllTys, dataConsStupidTheta
+ )
+import CoreUtils ( exprType )
+import CoreUnfold ( mkTopUnfolding, mkCompulsoryUnfolding )
+import Literal ( nullAddrLit, mkStringLit )
+import TyCon ( TyCon, isNewTyCon, tyConDataCons, FieldLabel,
+ tyConStupidTheta, isProductTyCon, isDataTyCon, isRecursiveTyCon )
+import Class ( Class, classTyCon, classSelIds )
+import Var ( Id, TyVar, Var )
+import VarSet ( isEmptyVarSet, subVarSet, varSetElems )
+import Name ( mkFCallName, mkWiredInName, Name, BuiltInSyntax(..) )
+import OccName ( mkOccNameFS, varName )
+import PrimOp ( PrimOp, primOpSig, primOpOcc, primOpTag )
+import ForeignCall ( ForeignCall )
+import DataCon ( DataCon, DataConIds(..), dataConTyVars,
+ dataConFieldLabels, dataConRepArity, dataConResTys,
+ dataConRepArgTys, dataConRepType,
+ dataConSig, dataConStrictMarks, dataConExStricts,
+ splitProductType, isVanillaDataCon, dataConFieldType,
+ dataConInstOrigArgTys
+ )
+import Id ( idType, mkGlobalId, mkVanillaGlobal, mkSysLocal,
+ mkTemplateLocals, mkTemplateLocalsNum, mkExportedLocalId,
+ mkTemplateLocal, idName
+ )
+import IdInfo ( IdInfo, noCafIdInfo, setUnfoldingInfo,
+ setArityInfo, setSpecInfo, setCafInfo,
+ setAllStrictnessInfo, vanillaIdInfo,
+ GlobalIdDetails(..), CafInfo(..)
+ )
+import NewDemand ( mkStrictSig, DmdResult(..),
+ mkTopDmdType, topDmd, evalDmd, lazyDmd, retCPR,
+ Demand(..), Demands(..) )
+import DmdAnal ( dmdAnalTopRhs )
+import CoreSyn
+import Unique ( mkBuiltinUnique, mkPrimOpIdUnique )
+import Maybes
+import PrelNames
+import Util ( dropList, isSingleton )
+import Outputable
+import FastString
+import ListSetOps ( assoc )
+\end{code}
+
+%************************************************************************
+%* *
+\subsection{Wired in Ids}
+%* *
+%************************************************************************
+
+\begin{code}
+wiredInIds
+ = [ -- These error-y things are wired in because we don't yet have
+ -- a way to express in an interface file that the result type variable
+ -- is 'open'; that is can be unified with an unboxed type
+ --
+ -- [The interface file format now carry such information, but there's
+ -- no way yet of expressing at the definition site for these
+ -- error-reporting functions that they have an 'open'
+ -- result type. -- sof 1/99]
+
+ eRROR_ID, -- This one isn't used anywhere else in the compiler
+ -- But we still need it in wiredInIds so that when GHC
+ -- compiles a program that mentions 'error' we don't
+ -- import its type from the interface file; we just get
+ -- the Id defined here. Which has an 'open-tyvar' type.
+
+ rUNTIME_ERROR_ID,
+ iRREFUT_PAT_ERROR_ID,
+ nON_EXHAUSTIVE_GUARDS_ERROR_ID,
+ nO_METHOD_BINDING_ERROR_ID,
+ pAT_ERROR_ID,
+ rEC_CON_ERROR_ID,
+
+ lazyId
+ ] ++ ghcPrimIds
+
+-- These Ids are exported from GHC.Prim
+ghcPrimIds
+ = [ -- These can't be defined in Haskell, but they have
+ -- perfectly reasonable unfoldings in Core
+ realWorldPrimId,
+ unsafeCoerceId,
+ nullAddrId,
+ seqId
+ ]
+\end{code}
+
+%************************************************************************
+%* *
+\subsection{Data constructors}
+%* *
+%************************************************************************
+
+The wrapper for a constructor is an ordinary top-level binding that evaluates
+any strict args, unboxes any args that are going to be flattened, and calls
+the worker.
+
+We're going to build a constructor that looks like:
+
+ data (Data a, C b) => T a b = T1 !a !Int b
+
+ T1 = /\ a b ->
+ \d1::Data a, d2::C b ->
+ \p q r -> case p of { p ->
+ case q of { q ->
+ Con T1 [a,b] [p,q,r]}}
+
+Notice that
+
+* d2 is thrown away --- a context in a data decl is used to make sure
+ one *could* construct dictionaries at the site the constructor
+ is used, but the dictionary isn't actually used.
+
+* We have to check that we can construct Data dictionaries for
+ the types a and Int. Once we've done that we can throw d1 away too.
+
+* We use (case p of q -> ...) to evaluate p, rather than "seq" because
+ all that matters is that the arguments are evaluated. "seq" is
+ very careful to preserve evaluation order, which we don't need
+ to be here.
+
+ You might think that we could simply give constructors some strictness
+ info, like PrimOps, and let CoreToStg do the let-to-case transformation.
+ But we don't do that because in the case of primops and functions strictness
+ is a *property* not a *requirement*. In the case of constructors we need to
+ do something active to evaluate the argument.
+
+ Making an explicit case expression allows the simplifier to eliminate
+ it in the (common) case where the constructor arg is already evaluated.
+
+
+\begin{code}
+mkDataConIds :: Name -> Name -> DataCon -> DataConIds
+ -- Makes the *worker* for the data constructor; that is, the function
+ -- that takes the reprsentation arguments and builds the constructor.
+mkDataConIds wrap_name wkr_name data_con
+ | isNewTyCon tycon
+ = NewDC nt_wrap_id
+
+ | any isMarkedStrict all_strict_marks -- Algebraic, needs wrapper
+ = AlgDC (Just alg_wrap_id) wrk_id
+
+ | otherwise -- Algebraic, no wrapper
+ = AlgDC Nothing wrk_id
+ where
+ (tyvars, theta, orig_arg_tys, tycon, res_tys) = dataConSig data_con
+
+ dict_tys = mkPredTys theta
+ all_arg_tys = dict_tys ++ orig_arg_tys
+ result_ty = mkTyConApp tycon res_tys
+
+ wrap_ty = mkForAllTys tyvars (mkFunTys all_arg_tys result_ty)
+ -- We used to include the stupid theta in the wrapper's args
+ -- but now we don't. Instead the type checker just injects these
+ -- extra constraints where necessary.
+
+ ----------- Worker (algebraic data types only) --------------
+ wrk_id = mkGlobalId (DataConWorkId data_con) wkr_name
+ (dataConRepType data_con) wkr_info
+
+ wkr_arity = dataConRepArity data_con
+ wkr_info = noCafIdInfo
+ `setArityInfo` wkr_arity
+ `setAllStrictnessInfo` Just wkr_sig
+ `setUnfoldingInfo` evaldUnfolding -- Record that it's evaluated,
+ -- even if arity = 0
+
+ wkr_sig = mkStrictSig (mkTopDmdType (replicate wkr_arity topDmd) cpr_info)
+ -- Notice that we do *not* say the worker is strict
+ -- even if the data constructor is declared strict
+ -- e.g. data T = MkT !(Int,Int)
+ -- Why? Because the *wrapper* is strict (and its unfolding has case
+ -- expresssions that do the evals) but the *worker* itself is not.
+ -- If we pretend it is strict then when we see
+ -- case x of y -> $wMkT y
+ -- the simplifier thinks that y is "sure to be evaluated" (because
+ -- $wMkT is strict) and drops the case. No, $wMkT is not strict.
+ --
+ -- When the simplifer sees a pattern
+ -- case e of MkT x -> ...
+ -- it uses the dataConRepStrictness of MkT to mark x as evaluated;
+ -- but that's fine... dataConRepStrictness comes from the data con
+ -- not from the worker Id.
+
+ cpr_info | isProductTyCon tycon &&
+ isDataTyCon tycon &&
+ wkr_arity > 0 &&
+ wkr_arity <= mAX_CPR_SIZE = retCPR
+ | otherwise = TopRes
+ -- RetCPR is only true for products that are real data types;
+ -- that is, not unboxed tuples or [non-recursive] newtypes
+
+ ----------- Wrappers for newtypes --------------
+ nt_wrap_id = mkGlobalId (DataConWrapId data_con) wrap_name wrap_ty nt_wrap_info
+ nt_wrap_info = noCafIdInfo -- The NoCaf-ness is set by noCafIdInfo
+ `setArityInfo` 1 -- Arity 1
+ `setUnfoldingInfo` newtype_unf
+ newtype_unf = ASSERT( isVanillaDataCon data_con &&
+ isSingleton orig_arg_tys )
+ -- No existentials on a newtype, but it can have a context
+ -- e.g. newtype Eq a => T a = MkT (...)
+ mkTopUnfolding $ Note InlineMe $
+ mkLams tyvars $ Lam id_arg1 $
+ mkNewTypeBody tycon result_ty (Var id_arg1)
+
+ id_arg1 = mkTemplateLocal 1 (head orig_arg_tys)
+
+ ----------- Wrappers for algebraic data types --------------
+ alg_wrap_id = mkGlobalId (DataConWrapId data_con) wrap_name wrap_ty alg_wrap_info
+ alg_wrap_info = noCafIdInfo -- The NoCaf-ness is set by noCafIdInfo
+ `setArityInfo` alg_arity
+ -- It's important to specify the arity, so that partial
+ -- applications are treated as values
+ `setUnfoldingInfo` alg_unf
+ `setAllStrictnessInfo` Just wrap_sig
+
+ all_strict_marks = dataConExStricts data_con ++ dataConStrictMarks data_con
+ wrap_sig = mkStrictSig (mkTopDmdType arg_dmds cpr_info)
+ arg_dmds = map mk_dmd all_strict_marks
+ mk_dmd str | isMarkedStrict str = evalDmd
+ | otherwise = lazyDmd
+ -- The Cpr info can be important inside INLINE rhss, where the
+ -- wrapper constructor isn't inlined.
+ -- And the argument strictness can be important too; we
+ -- may not inline a contructor when it is partially applied.
+ -- For example:
+ -- data W = C !Int !Int !Int
+ -- ...(let w = C x in ...(w p q)...)...
+ -- we want to see that w is strict in its two arguments
+
+ alg_unf = mkTopUnfolding $ Note InlineMe $
+ mkLams tyvars $
+ mkLams dict_args $ mkLams id_args $
+ foldr mk_case con_app
+ (zip (dict_args ++ id_args) all_strict_marks)
+ i3 []
+
+ con_app i rep_ids = mkApps (Var wrk_id)
+ (map varToCoreExpr (tyvars ++ reverse rep_ids))
+
+ (dict_args,i2) = mkLocals 1 dict_tys
+ (id_args,i3) = mkLocals i2 orig_arg_tys
+ alg_arity = i3-1
+
+ mk_case
+ :: (Id, StrictnessMark) -- Arg, strictness
+ -> (Int -> [Id] -> CoreExpr) -- Body
+ -> Int -- Next rep arg id
+ -> [Id] -- Rep args so far, reversed
+ -> CoreExpr
+ mk_case (arg,strict) body i rep_args
+ = case strict of
+ NotMarkedStrict -> body i (arg:rep_args)
+ MarkedStrict
+ | isUnLiftedType (idType arg) -> body i (arg:rep_args)
+ | otherwise ->
+ Case (Var arg) arg result_ty [(DEFAULT,[], body i (arg:rep_args))]
+
+ MarkedUnboxed
+ -> case splitProductType "do_unbox" (idType arg) of
+ (tycon, tycon_args, con, tys) ->
+ Case (Var arg) arg result_ty
+ [(DataAlt con,
+ con_args,
+ body i' (reverse con_args ++ rep_args))]
+ where
+ (con_args, i') = mkLocals i tys
+
+mAX_CPR_SIZE :: Arity
+mAX_CPR_SIZE = 10
+-- We do not treat very big tuples as CPR-ish:
+-- a) for a start we get into trouble because there aren't
+-- "enough" unboxed tuple types (a tiresome restriction,
+-- but hard to fix),
+-- b) more importantly, big unboxed tuples get returned mainly
+-- on the stack, and are often then allocated in the heap
+-- by the caller. So doing CPR for them may in fact make
+-- things worse.
+
+mkLocals i tys = (zipWith mkTemplateLocal [i..i+n-1] tys, i+n)
+ where
+ n = length tys
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Record selectors}
+%* *
+%************************************************************************
+
+We're going to build a record selector unfolding that looks like this:
+
+ data T a b c = T1 { ..., op :: a, ...}
+ | T2 { ..., op :: a, ...}
+ | T3
+
+ sel = /\ a b c -> \ d -> case d of
+ T1 ... x ... -> x
+ T2 ... x ... -> x
+ other -> error "..."
+
+Similarly for newtypes
+
+ newtype N a = MkN { unN :: a->a }
+
+ unN :: N a -> a -> a
+ unN n = coerce (a->a) n
+
+We need to take a little care if the field has a polymorphic type:
+
+ data R = R { f :: forall a. a->a }
+
+Then we want
+
+ f :: forall a. R -> a -> a
+ f = /\ a \ r = case r of
+ R f -> f a
+
+(not f :: R -> forall a. a->a, which gives the type inference mechanism
+problems at call sites)
+
+Similarly for (recursive) newtypes
+
+ newtype N = MkN { unN :: forall a. a->a }
+
+ unN :: forall b. N -> b -> b
+ unN = /\b -> \n:N -> (coerce (forall a. a->a) n)
+
+
+Note [Naughty record selectors]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+A "naughty" field is one for which we can't define a record
+selector, because an existential type variable would escape. For example:
+ data T = forall a. MkT { x,y::a }
+We obviously can't define
+ x (MkT v _) = v
+Nevertheless we *do* put a RecordSelId into the type environment
+so that if the user tries to use 'x' as a selector we can bleat
+helpfully, rather than saying unhelpfully that 'x' is not in scope.
+Hence the sel_naughty flag, to identify record selcectors that don't really exist.
+
+In general, a field is naughty if its type mentions a type variable that
+isn't in the result type of the constructor.
+
+For GADTs, we require that all constructors with a common field 'f' have the same
+result type (modulo alpha conversion). [Checked in TcTyClsDecls.checkValidTyCon]
+E.g.
+ data T where
+ T1 { f :: a } :: T [a]
+ T2 { f :: a, y :: b } :: T [a]
+and now the selector takes that type as its argument:
+ f :: forall a. T [a] -> a
+ f t = case t of
+ T1 { f = v } -> v
+ T2 { f = v } -> v
+Note the forall'd tyvars of the selector are just the free tyvars
+of the result type; there may be other tyvars in the constructor's
+type (e.g. 'b' in T2).
+
+\begin{code}
+
+-- XXX - autrijus -
+-- Plan: 1. Determine naughtiness by comparing field type vs result type
+-- 2. Install naughty ones with selector_ty of type _|_ and fill in mzero for info
+-- 3. If it's not naughty, do the normal plan.
+
+mkRecordSelId :: TyCon -> FieldLabel -> Id
+mkRecordSelId tycon field_label
+ -- Assumes that all fields with the same field label have the same type
+ | is_naughty = naughty_id
+ | otherwise = sel_id
+ where
+ is_naughty = not (tyVarsOfType field_ty `subVarSet` tyvar_set)
+ sel_id_details = RecordSelId tycon field_label is_naughty
+
+ -- Escapist case here for naughty construcotrs
+ -- We give it no IdInfo, and a type of forall a.a (never looked at)
+ naughty_id = mkGlobalId sel_id_details field_label forall_a_a noCafIdInfo
+ forall_a_a = mkForAllTy alphaTyVar (mkTyVarTy alphaTyVar)
+
+ -- Normal case starts here
+ sel_id = mkGlobalId sel_id_details field_label selector_ty info
+ data_cons = tyConDataCons tycon
+ data_cons_w_field = filter has_field data_cons -- Can't be empty!
+ has_field con = field_label `elem` dataConFieldLabels con
+
+ con1 = head data_cons_w_field
+ res_tys = dataConResTys con1
+ tyvar_set = tyVarsOfTypes res_tys
+ tyvars = varSetElems tyvar_set
+ data_ty = mkTyConApp tycon res_tys
+ field_ty = dataConFieldType con1 field_label
+
+ -- *Very* tiresomely, the selectors are (unnecessarily!) overloaded over
+ -- just the dictionaries in the types of the constructors that contain
+ -- the relevant field. [The Report says that pattern matching on a
+ -- constructor gives the same constraints as applying it.] Urgh.
+ --
+ -- However, not all data cons have all constraints (because of
+ -- BuildTyCl.mkDataConStupidTheta). So we need to find all the data cons
+ -- involved in the pattern match and take the union of their constraints.
+ stupid_dict_tys = mkPredTys (dataConsStupidTheta data_cons_w_field)
+ n_stupid_dicts = length stupid_dict_tys
+
+ (field_tyvars,field_theta,field_tau) = tcSplitSigmaTy field_ty
+ field_dict_tys = mkPredTys field_theta
+ n_field_dict_tys = length field_dict_tys
+ -- If the field has a universally quantified type we have to
+ -- be a bit careful. Suppose we have
+ -- data R = R { op :: forall a. Foo a => a -> a }
+ -- Then we can't give op the type
+ -- op :: R -> forall a. Foo a => a -> a
+ -- because the typechecker doesn't understand foralls to the
+ -- right of an arrow. The "right" type to give it is
+ -- op :: forall a. Foo a => R -> a -> a
+ -- But then we must generate the right unfolding too:
+ -- op = /\a -> \dfoo -> \ r ->
+ -- case r of
+ -- R op -> op a dfoo
+ -- Note that this is exactly the type we'd infer from a user defn
+ -- op (R op) = op
+
+ selector_ty :: Type
+ selector_ty = mkForAllTys tyvars $ mkForAllTys field_tyvars $
+ mkFunTys stupid_dict_tys $ mkFunTys field_dict_tys $
+ mkFunTy data_ty field_tau
+
+ arity = 1 + n_stupid_dicts + n_field_dict_tys
+
+ (strict_sig, rhs_w_str) = dmdAnalTopRhs sel_rhs
+ -- Use the demand analyser to work out strictness.
+ -- With all this unpackery it's not easy!
+
+ info = noCafIdInfo
+ `setCafInfo` caf_info
+ `setArityInfo` arity
+ `setUnfoldingInfo` mkTopUnfolding rhs_w_str
+ `setAllStrictnessInfo` Just strict_sig
+
+ -- Allocate Ids. We do it a funny way round because field_dict_tys is
+ -- almost always empty. Also note that we use max_dict_tys
+ -- rather than n_dict_tys, because the latter gives an infinite loop:
+ -- n_dict tys depends on the_alts, which depens on arg_ids, which depends
+ -- on arity, which depends on n_dict tys. Sigh! Mega sigh!
+ stupid_dict_ids = mkTemplateLocalsNum 1 stupid_dict_tys
+ max_stupid_dicts = length (tyConStupidTheta tycon)
+ field_dict_base = max_stupid_dicts + 1
+ field_dict_ids = mkTemplateLocalsNum field_dict_base field_dict_tys
+ dict_id_base = field_dict_base + n_field_dict_tys
+ data_id = mkTemplateLocal dict_id_base data_ty
+ arg_base = dict_id_base + 1
+
+ the_alts :: [CoreAlt]
+ the_alts = map mk_alt data_cons_w_field -- Already sorted by data-con
+ no_default = length data_cons == length data_cons_w_field -- No default needed
+
+ default_alt | no_default = []
+ | otherwise = [(DEFAULT, [], error_expr)]
+
+ -- The default branch may have CAF refs, because it calls recSelError etc.
+ caf_info | no_default = NoCafRefs
+ | otherwise = MayHaveCafRefs
+
+ sel_rhs = mkLams tyvars $ mkLams field_tyvars $
+ mkLams stupid_dict_ids $ mkLams field_dict_ids $
+ Lam data_id $ sel_body
+
+ sel_body | isNewTyCon tycon = mk_result (mkNewTypeBody tycon field_ty (Var data_id))
+ | otherwise = Case (Var data_id) data_id field_tau (default_alt ++ the_alts)
+
+ mk_result poly_result = mkVarApps (mkVarApps poly_result field_tyvars) field_dict_ids
+ -- We pull the field lambdas to the top, so we need to
+ -- apply them in the body. For example:
+ -- data T = MkT { foo :: forall a. a->a }
+ --
+ -- foo :: forall a. T -> a -> a
+ -- foo = /\a. \t:T. case t of { MkT f -> f a }
+
+ mk_alt data_con
+ = -- In the non-vanilla case, the pattern must bind type variables and
+ -- the context stuff; hence the arg_prefix binding below
+ mkReboxingAlt uniqs data_con (arg_prefix ++ arg_ids)
+ (mk_result (Var the_arg_id))
+ where
+ (arg_prefix, arg_ids)
+ | isVanillaDataCon data_con -- Instantiate from commmon base
+ = ([], mkTemplateLocalsNum arg_base (dataConInstOrigArgTys data_con res_tys))
+ | otherwise -- The case pattern binds type variables, which are used
+ -- in the types of the arguments of the pattern
+ = (dc_tyvars ++ mkTemplateLocalsNum arg_base (mkPredTys dc_theta),
+ mkTemplateLocalsNum arg_base' dc_arg_tys)
+
+ (dc_tyvars, dc_theta, dc_arg_tys, _, _) = dataConSig data_con
+ arg_base' = arg_base + length dc_theta
+
+ unpack_base = arg_base' + length dc_arg_tys
+ uniqs = map mkBuiltinUnique [unpack_base..]
+
+ the_arg_id = assoc "mkRecordSelId:mk_alt" (field_lbls `zip` arg_ids) field_label
+ field_lbls = dataConFieldLabels data_con
+
+ error_expr = mkRuntimeErrorApp rEC_SEL_ERROR_ID field_tau full_msg
+ full_msg = showSDoc (sep [text "No match in record selector", ppr sel_id])
+
+
+-- (mkReboxingAlt us con xs rhs) basically constructs the case
+-- alternative (con, xs, rhs)
+-- but it does the reboxing necessary to construct the *source*
+-- arguments, xs, from the representation arguments ys.
+-- For example:
+-- data T = MkT !(Int,Int) Bool
+--
+-- mkReboxingAlt MkT [x,b] r
+-- = (DataAlt MkT, [y::Int,z::Int,b], let x = (y,z) in r)
+--
+-- mkDataAlt should really be in DataCon, but it can't because
+-- it manipulates CoreSyn.
+
+mkReboxingAlt
+ :: [Unique] -- Uniques for the new Ids
+ -> DataCon
+ -> [Var] -- Source-level args, including existential dicts
+ -> CoreExpr -- RHS
+ -> CoreAlt
+
+mkReboxingAlt us con args rhs
+ | not (any isMarkedUnboxed stricts)
+ = (DataAlt con, args, rhs)
+
+ | otherwise
+ = let
+ (binds, args') = go args stricts us
+ in
+ (DataAlt con, args', mkLets binds rhs)
+
+ where
+ stricts = dataConExStricts con ++ dataConStrictMarks con
+
+ go [] stricts us = ([], [])
+
+ -- Type variable case
+ go (arg:args) stricts us
+ | isTyVar arg
+ = let (binds, args') = go args stricts us
+ in (binds, arg:args')
+
+ -- Term variable case
+ go (arg:args) (str:stricts) us
+ | isMarkedUnboxed str
+ = let
+ (_, tycon_args, pack_con, con_arg_tys)
+ = splitProductType "mkReboxingAlt" (idType arg)
+
+ unpacked_args = zipWith (mkSysLocal FSLIT("rb")) us con_arg_tys
+ (binds, args') = go args stricts (dropList con_arg_tys us)
+ con_app = mkConApp pack_con (map Type tycon_args ++ map Var unpacked_args)
+ in
+ (NonRec arg con_app : binds, unpacked_args ++ args')
+
+ | otherwise
+ = let (binds, args') = go args stricts us
+ in (binds, arg:args')
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Dictionary selectors}
+%* *
+%************************************************************************
+
+Selecting a field for a dictionary. If there is just one field, then
+there's nothing to do.
+
+Dictionary selectors may get nested forall-types. Thus:
+
+ class Foo a where
+ op :: forall b. Ord b => a -> b -> b
+
+Then the top-level type for op is
+
+ op :: forall a. Foo a =>
+ forall b. Ord b =>
+ a -> b -> b
+
+This is unlike ordinary record selectors, which have all the for-alls
+at the outside. When dealing with classes it's very convenient to
+recover the original type signature from the class op selector.
+
+\begin{code}
+mkDictSelId :: Name -> Class -> Id
+mkDictSelId name clas
+ = mkGlobalId (ClassOpId clas) name sel_ty info
+ where
+ sel_ty = mkForAllTys tyvars (mkFunTy (idType dict_id) (idType the_arg_id))
+ -- We can't just say (exprType rhs), because that would give a type
+ -- C a -> C a
+ -- for a single-op class (after all, the selector is the identity)
+ -- But it's type must expose the representation of the dictionary
+ -- to gat (say) C a -> (a -> a)
+
+ info = noCafIdInfo
+ `setArityInfo` 1
+ `setUnfoldingInfo` mkTopUnfolding rhs
+ `setAllStrictnessInfo` Just strict_sig
+
+ -- We no longer use 'must-inline' on record selectors. They'll
+ -- inline like crazy if they scrutinise a constructor
+
+ -- The strictness signature is of the form U(AAAVAAAA) -> T
+ -- where the V depends on which item we are selecting
+ -- It's worth giving one, so that absence info etc is generated
+ -- even if the selector isn't inlined
+ strict_sig = mkStrictSig (mkTopDmdType [arg_dmd] TopRes)
+ arg_dmd | isNewTyCon tycon = evalDmd
+ | otherwise = Eval (Prod [ if the_arg_id == id then evalDmd else Abs
+ | id <- arg_ids ])
+
+ tycon = classTyCon clas
+ [data_con] = tyConDataCons tycon
+ tyvars = dataConTyVars data_con
+ arg_tys = dataConRepArgTys data_con
+ the_arg_id = assoc "MkId.mkDictSelId" (map idName (classSelIds clas) `zip` arg_ids) name
+
+ pred = mkClassPred clas (mkTyVarTys tyvars)
+ (dict_id:arg_ids) = mkTemplateLocals (mkPredTy pred : arg_tys)
+
+ rhs | isNewTyCon tycon = mkLams tyvars $ Lam dict_id $
+ mkNewTypeBody tycon (head arg_tys) (Var dict_id)
+ | otherwise = mkLams tyvars $ Lam dict_id $
+ Case (Var dict_id) dict_id (idType the_arg_id)
+ [(DataAlt data_con, arg_ids, Var the_arg_id)]
+
+mkNewTypeBody tycon result_ty result_expr
+ -- Adds a coerce where necessary
+ -- Used for both wrapping and unwrapping
+ | isRecursiveTyCon tycon -- Recursive case; use a coerce
+ = Note (Coerce result_ty (exprType result_expr)) result_expr
+ | otherwise -- Normal case
+ = result_expr
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Primitive operations
+%* *
+%************************************************************************
+
+\begin{code}
+mkPrimOpId :: PrimOp -> Id
+mkPrimOpId prim_op
+ = id
+ where
+ (tyvars,arg_tys,res_ty, arity, strict_sig) = primOpSig prim_op
+ ty = mkForAllTys tyvars (mkFunTys arg_tys res_ty)
+ name = mkWiredInName gHC_PRIM (primOpOcc prim_op)
+ (mkPrimOpIdUnique (primOpTag prim_op))
+ Nothing (AnId id) UserSyntax
+ id = mkGlobalId (PrimOpId prim_op) name ty info
+
+ info = noCafIdInfo
+ `setSpecInfo` mkSpecInfo (primOpRules prim_op name)
+ `setArityInfo` arity
+ `setAllStrictnessInfo` Just strict_sig
+
+-- For each ccall we manufacture a separate CCallOpId, giving it
+-- a fresh unique, a type that is correct for this particular ccall,
+-- and a CCall structure that gives the correct details about calling
+-- convention etc.
+--
+-- The *name* of this Id is a local name whose OccName gives the full
+-- details of the ccall, type and all. This means that the interface
+-- file reader can reconstruct a suitable Id
+
+mkFCallId :: Unique -> ForeignCall -> Type -> Id
+mkFCallId uniq fcall ty
+ = ASSERT( isEmptyVarSet (tyVarsOfType ty) )
+ -- A CCallOpId should have no free type variables;
+ -- when doing substitutions won't substitute over it
+ mkGlobalId (FCallId fcall) name ty info
+ where
+ occ_str = showSDoc (braces (ppr fcall <+> ppr ty))
+ -- The "occurrence name" of a ccall is the full info about the
+ -- ccall; it is encoded, but may have embedded spaces etc!
+
+ name = mkFCallName uniq occ_str
+
+ info = noCafIdInfo
+ `setArityInfo` arity
+ `setAllStrictnessInfo` Just strict_sig
+
+ (_, tau) = tcSplitForAllTys ty
+ (arg_tys, _) = tcSplitFunTys tau
+ arity = length arg_tys
+ strict_sig = mkStrictSig (mkTopDmdType (replicate arity evalDmd) TopRes)
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{DictFuns and default methods}
+%* *
+%************************************************************************
+
+Important notes about dict funs and default methods
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Dict funs and default methods are *not* ImplicitIds. Their definition
+involves user-written code, so we can't figure out their strictness etc
+based on fixed info, as we can for constructors and record selectors (say).
+
+We build them as LocalIds, but with External Names. This ensures that
+they are taken to account by free-variable finding and dependency
+analysis (e.g. CoreFVs.exprFreeVars).
+
+Why shouldn't they be bound as GlobalIds? Because, in particular, if
+they are globals, the specialiser floats dict uses above their defns,
+which prevents good simplifications happening. Also the strictness
+analyser treats a occurrence of a GlobalId as imported and assumes it
+contains strictness in its IdInfo, which isn't true if the thing is
+bound in the same module as the occurrence.
+
+It's OK for dfuns to be LocalIds, because we form the instance-env to
+pass on to the next module (md_insts) in CoreTidy, afer tidying
+and globalising the top-level Ids.
+
+BUT make sure they are *exported* LocalIds (mkExportedLocalId) so
+that they aren't discarded by the occurrence analyser.
+
+\begin{code}
+mkDefaultMethodId dm_name ty = mkExportedLocalId dm_name ty
+
+mkDictFunId :: Name -- Name to use for the dict fun;
+ -> [TyVar]
+ -> ThetaType
+ -> Class
+ -> [Type]
+ -> Id
+
+mkDictFunId dfun_name inst_tyvars dfun_theta clas inst_tys
+ = mkExportedLocalId dfun_name dfun_ty
+ where
+ dfun_ty = mkSigmaTy inst_tyvars dfun_theta (mkDictTy clas inst_tys)
+
+{- 1 dec 99: disable the Mark Jones optimisation for the sake
+ of compatibility with Hugs.
+ See `types/InstEnv' for a discussion related to this.
+
+ (class_tyvars, sc_theta, _, _) = classBigSig clas
+ not_const (clas, tys) = not (isEmptyVarSet (tyVarsOfTypes tys))
+ sc_theta' = substClasses (zipTopTvSubst class_tyvars inst_tys) sc_theta
+ dfun_theta = case inst_decl_theta of
+ [] -> [] -- If inst_decl_theta is empty, then we don't
+ -- want to have any dict arguments, so that we can
+ -- expose the constant methods.
+
+ other -> nub (inst_decl_theta ++ filter not_const sc_theta')
+ -- Otherwise we pass the superclass dictionaries to
+ -- the dictionary function; the Mark Jones optimisation.
+ --
+ -- NOTE the "nub". I got caught by this one:
+ -- class Monad m => MonadT t m where ...
+ -- instance Monad m => MonadT (EnvT env) m where ...
+ -- Here, the inst_decl_theta has (Monad m); but so
+ -- does the sc_theta'!
+ --
+ -- NOTE the "not_const". I got caught by this one too:
+ -- class Foo a => Baz a b where ...
+ -- instance Wob b => Baz T b where..
+ -- Now sc_theta' has Foo T
+-}
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Un-definable}
+%* *
+%************************************************************************
+
+These Ids can't be defined in Haskell. They could be defined in
+unfoldings in the wired-in GHC.Prim interface file, but we'd have to
+ensure that they were definitely, definitely inlined, because there is
+no curried identifier for them. That's what mkCompulsoryUnfolding
+does. If we had a way to get a compulsory unfolding from an interface
+file, we could do that, but we don't right now.
+
+unsafeCoerce# isn't so much a PrimOp as a phantom identifier, that
+just gets expanded into a type coercion wherever it occurs. Hence we
+add it as a built-in Id with an unfolding here.
+
+The type variables we use here are "open" type variables: this means
+they can unify with both unlifted and lifted types. Hence we provide
+another gun with which to shoot yourself in the foot.
+
+\begin{code}
+mkWiredInIdName mod fs uniq id
+ = mkWiredInName mod (mkOccNameFS varName fs) uniq Nothing (AnId id) UserSyntax
+
+unsafeCoerceName = mkWiredInIdName gHC_PRIM FSLIT("unsafeCoerce#") unsafeCoerceIdKey unsafeCoerceId
+nullAddrName = mkWiredInIdName gHC_PRIM FSLIT("nullAddr#") nullAddrIdKey nullAddrId
+seqName = mkWiredInIdName gHC_PRIM FSLIT("seq") seqIdKey seqId
+realWorldName = mkWiredInIdName gHC_PRIM FSLIT("realWorld#") realWorldPrimIdKey realWorldPrimId
+lazyIdName = mkWiredInIdName pREL_BASE FSLIT("lazy") lazyIdKey lazyId
+
+errorName = mkWiredInIdName pREL_ERR FSLIT("error") errorIdKey eRROR_ID
+recSelErrorName = mkWiredInIdName pREL_ERR FSLIT("recSelError") recSelErrorIdKey rEC_SEL_ERROR_ID
+runtimeErrorName = mkWiredInIdName pREL_ERR FSLIT("runtimeError") runtimeErrorIdKey rUNTIME_ERROR_ID
+irrefutPatErrorName = mkWiredInIdName pREL_ERR FSLIT("irrefutPatError") irrefutPatErrorIdKey iRREFUT_PAT_ERROR_ID
+recConErrorName = mkWiredInIdName pREL_ERR FSLIT("recConError") recConErrorIdKey rEC_CON_ERROR_ID
+patErrorName = mkWiredInIdName pREL_ERR FSLIT("patError") patErrorIdKey pAT_ERROR_ID
+noMethodBindingErrorName = mkWiredInIdName pREL_ERR FSLIT("noMethodBindingError")
+ noMethodBindingErrorIdKey nO_METHOD_BINDING_ERROR_ID
+nonExhaustiveGuardsErrorName
+ = mkWiredInIdName pREL_ERR FSLIT("nonExhaustiveGuardsError")
+ nonExhaustiveGuardsErrorIdKey nON_EXHAUSTIVE_GUARDS_ERROR_ID
+\end{code}
+
+\begin{code}
+-- unsafeCoerce# :: forall a b. a -> b
+unsafeCoerceId
+ = pcMiscPrelId unsafeCoerceName ty info
+ where
+ info = noCafIdInfo `setUnfoldingInfo` mkCompulsoryUnfolding rhs
+
+
+ ty = mkForAllTys [openAlphaTyVar,openBetaTyVar]
+ (mkFunTy openAlphaTy openBetaTy)
+ [x] = mkTemplateLocals [openAlphaTy]
+ rhs = mkLams [openAlphaTyVar,openBetaTyVar,x] $
+ Note (Coerce openBetaTy openAlphaTy) (Var x)
+
+-- nullAddr# :: Addr#
+-- The reason is is here is because we don't provide
+-- a way to write this literal in Haskell.
+nullAddrId
+ = pcMiscPrelId nullAddrName addrPrimTy info
+ where
+ info = noCafIdInfo `setUnfoldingInfo`
+ mkCompulsoryUnfolding (Lit nullAddrLit)
+
+seqId
+ = pcMiscPrelId seqName ty info
+ where
+ info = noCafIdInfo `setUnfoldingInfo` mkCompulsoryUnfolding rhs
+
+
+ ty = mkForAllTys [alphaTyVar,openBetaTyVar]
+ (mkFunTy alphaTy (mkFunTy openBetaTy openBetaTy))
+ [x,y] = mkTemplateLocals [alphaTy, openBetaTy]
+-- gaw 2004
+ rhs = mkLams [alphaTyVar,openBetaTyVar,x,y] (Case (Var x) x openBetaTy [(DEFAULT, [], Var y)])
+
+-- lazy :: forall a?. a? -> a? (i.e. works for unboxed types too)
+-- Used to lazify pseq: pseq a b = a `seq` lazy b
+-- No unfolding: it gets "inlined" by the worker/wrapper pass
+-- Also, no strictness: by being a built-in Id, it overrides all
+-- the info in PrelBase.hi. This is important, because the strictness
+-- analyser will spot it as strict!
+lazyId
+ = pcMiscPrelId lazyIdName ty info
+ where
+ info = noCafIdInfo
+ ty = mkForAllTys [alphaTyVar] (mkFunTy alphaTy alphaTy)
+
+lazyIdUnfolding :: CoreExpr -- Used to expand LazyOp after strictness anal
+lazyIdUnfolding = mkLams [openAlphaTyVar,x] (Var x)
+ where
+ [x] = mkTemplateLocals [openAlphaTy]
+\end{code}
+
+@realWorld#@ used to be a magic literal, \tr{void#}. If things get
+nasty as-is, change it back to a literal (@Literal@).
+
+voidArgId is a Local Id used simply as an argument in functions
+where we just want an arg to avoid having a thunk of unlifted type.
+E.g.
+ x = \ void :: State# RealWorld -> (# p, q #)
+
+This comes up in strictness analysis
+
+\begin{code}
+realWorldPrimId -- :: State# RealWorld
+ = pcMiscPrelId realWorldName realWorldStatePrimTy
+ (noCafIdInfo `setUnfoldingInfo` evaldUnfolding)
+ -- The evaldUnfolding makes it look that realWorld# is evaluated
+ -- which in turn makes Simplify.interestingArg return True,
+ -- which in turn makes INLINE things applied to realWorld# likely
+ -- to be inlined
+
+voidArgId -- :: State# RealWorld
+ = mkSysLocal FSLIT("void") voidArgIdKey realWorldStatePrimTy
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection[PrelVals-error-related]{@error@ and friends; @trace@}
+%* *
+%************************************************************************
+
+GHC randomly injects these into the code.
+
+@patError@ is just a version of @error@ for pattern-matching
+failures. It knows various ``codes'' which expand to longer
+strings---this saves space!
+
+@absentErr@ is a thing we put in for ``absent'' arguments. They jolly
+well shouldn't be yanked on, but if one is, then you will get a
+friendly message from @absentErr@ (rather than a totally random
+crash).
+
+@parError@ is a special version of @error@ which the compiler does
+not know to be a bottoming Id. It is used in the @_par_@ and @_seq_@
+templates, but we don't ever expect to generate code for it.
+
+\begin{code}
+mkRuntimeErrorApp
+ :: Id -- Should be of type (forall a. Addr# -> a)
+ -- where Addr# points to a UTF8 encoded string
+ -> Type -- The type to instantiate 'a'
+ -> String -- The string to print
+ -> CoreExpr
+
+mkRuntimeErrorApp err_id res_ty err_msg
+ = mkApps (Var err_id) [Type res_ty, err_string]
+ where
+ err_string = Lit (mkStringLit err_msg)
+
+rEC_SEL_ERROR_ID = mkRuntimeErrorId recSelErrorName
+rUNTIME_ERROR_ID = mkRuntimeErrorId runtimeErrorName
+iRREFUT_PAT_ERROR_ID = mkRuntimeErrorId irrefutPatErrorName
+rEC_CON_ERROR_ID = mkRuntimeErrorId recConErrorName
+pAT_ERROR_ID = mkRuntimeErrorId patErrorName
+nO_METHOD_BINDING_ERROR_ID = mkRuntimeErrorId noMethodBindingErrorName
+nON_EXHAUSTIVE_GUARDS_ERROR_ID = mkRuntimeErrorId nonExhaustiveGuardsErrorName
+
+-- The runtime error Ids take a UTF8-encoded string as argument
+mkRuntimeErrorId name = pc_bottoming_Id name runtimeErrorTy
+runtimeErrorTy = mkSigmaTy [openAlphaTyVar] [] (mkFunTy addrPrimTy openAlphaTy)
+\end{code}
+
+\begin{code}
+eRROR_ID = pc_bottoming_Id errorName errorTy
+
+errorTy :: Type
+errorTy = mkSigmaTy [openAlphaTyVar] [] (mkFunTys [mkListTy charTy] openAlphaTy)
+ -- Notice the openAlphaTyVar. It says that "error" can be applied
+ -- to unboxed as well as boxed types. This is OK because it never
+ -- returns, so the return type is irrelevant.
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Utilities}
+%* *
+%************************************************************************
+
+\begin{code}
+pcMiscPrelId :: Name -> Type -> IdInfo -> Id
+pcMiscPrelId name ty info
+ = mkVanillaGlobal name ty info
+ -- We lie and say the thing is imported; otherwise, we get into
+ -- a mess with dependency analysis; e.g., core2stg may heave in
+ -- random calls to GHCbase.unpackPS__. If GHCbase is the module
+ -- being compiled, then it's just a matter of luck if the definition
+ -- will be in "the right place" to be in scope.
+
+pc_bottoming_Id name ty
+ = pcMiscPrelId name ty bottoming_info
+ where
+ bottoming_info = vanillaIdInfo `setAllStrictnessInfo` Just strict_sig
+ -- Do *not* mark them as NoCafRefs, because they can indeed have
+ -- CAF refs. For example, pAT_ERROR_ID calls GHC.Err.untangle,
+ -- which has some CAFs
+ -- In due course we may arrange that these error-y things are
+ -- regarded by the GC as permanently live, in which case we
+ -- can give them NoCaf info. As it is, any function that calls
+ -- any pc_bottoming_Id will itself have CafRefs, which bloats
+ -- SRTs.
+
+ strict_sig = mkStrictSig (mkTopDmdType [evalDmd] BotRes)
+ -- These "bottom" out, no matter what their arguments
+
+(openAlphaTyVar:openBetaTyVar:_) = openAlphaTyVars
+openAlphaTy = mkTyVarTy openAlphaTyVar
+openBetaTy = mkTyVarTy openBetaTyVar
+\end{code}
+
diff --git a/compiler/basicTypes/MkId.lhs-boot b/compiler/basicTypes/MkId.lhs-boot
new file mode 100644
index 0000000000..4f9615a061
--- /dev/null
+++ b/compiler/basicTypes/MkId.lhs-boot
@@ -0,0 +1,9 @@
+\begin{code}
+module MkId where
+import Name( Name )
+import DataCon( DataCon, DataConIds )
+
+mkDataConIds :: Name -> Name -> DataCon -> DataConIds
+\end{code}
+
+
diff --git a/compiler/basicTypes/Module.hi-boot-5 b/compiler/basicTypes/Module.hi-boot-5
new file mode 100644
index 0000000000..cdc5fbf581
--- /dev/null
+++ b/compiler/basicTypes/Module.hi-boot-5
@@ -0,0 +1,4 @@
+__interface Module 1 0 where
+__export Module Module ;
+1 data Module ;
+
diff --git a/compiler/basicTypes/Module.hi-boot-6 b/compiler/basicTypes/Module.hi-boot-6
new file mode 100644
index 0000000000..c4d4b5d474
--- /dev/null
+++ b/compiler/basicTypes/Module.hi-boot-6
@@ -0,0 +1,3 @@
+module Module where
+data Module
+
diff --git a/compiler/basicTypes/Module.lhs b/compiler/basicTypes/Module.lhs
new file mode 100644
index 0000000000..69521625b0
--- /dev/null
+++ b/compiler/basicTypes/Module.lhs
@@ -0,0 +1,216 @@
+%
+% (c) The University of Glasgow, 2004
+%
+
+Module
+~~~~~~~~~~
+Simply the name of a module, represented as a FastString.
+These are Uniquable, hence we can build FiniteMaps with ModuleNames as
+the keys.
+
+\begin{code}
+module Module
+ (
+ Module -- Abstract, instance of Eq, Ord, Outputable
+ , pprModule -- :: ModuleName -> SDoc
+
+ , ModLocation(..)
+ , addBootSuffix, addBootSuffix_maybe, addBootSuffixLocn
+
+ , moduleString -- :: ModuleName -> String
+ , moduleFS -- :: ModuleName -> FastString
+
+ , mkModule -- :: String -> ModuleName
+ , mkModuleFS -- :: FastString -> ModuleName
+
+ , ModuleEnv
+ , elemModuleEnv, extendModuleEnv, extendModuleEnvList, plusModuleEnv_C
+ , delModuleEnvList, delModuleEnv, plusModuleEnv, lookupModuleEnv
+ , lookupWithDefaultModuleEnv, mapModuleEnv, mkModuleEnv, emptyModuleEnv
+ , moduleEnvElts, unitModuleEnv, isEmptyModuleEnv, foldModuleEnv
+ , extendModuleEnv_C, filterModuleEnv
+
+ , ModuleSet, emptyModuleSet, mkModuleSet, moduleSetElts, extendModuleSet, elemModuleSet
+
+ ) where
+
+#include "HsVersions.h"
+import Outputable
+import Unique ( Uniquable(..) )
+import UniqFM
+import UniqSet
+import Binary
+import FastString
+\end{code}
+
+%************************************************************************
+%* *
+\subsection{Module locations}
+%* *
+%************************************************************************
+
+\begin{code}
+data ModLocation
+ = ModLocation {
+ ml_hs_file :: Maybe FilePath,
+ -- The source file, if we have one. Package modules
+ -- probably don't have source files.
+
+ ml_hi_file :: FilePath,
+ -- Where the .hi file is, whether or not it exists
+ -- yet. Always of form foo.hi, even if there is an
+ -- hi-boot file (we add the -boot suffix later)
+
+ ml_obj_file :: FilePath
+ -- Where the .o file is, whether or not it exists yet.
+ -- (might not exist either because the module hasn't
+ -- been compiled yet, or because it is part of a
+ -- package with a .a file)
+ } deriving Show
+
+instance Outputable ModLocation where
+ ppr = text . show
+\end{code}
+
+For a module in another package, the hs_file and obj_file
+components of ModLocation are undefined.
+
+The locations specified by a ModLocation may or may not
+correspond to actual files yet: for example, even if the object
+file doesn't exist, the ModLocation still contains the path to
+where the object file will reside if/when it is created.
+
+\begin{code}
+addBootSuffix :: FilePath -> FilePath
+-- Add the "-boot" suffix to .hs, .hi and .o files
+addBootSuffix path = path ++ "-boot"
+
+addBootSuffix_maybe :: Bool -> FilePath -> FilePath
+addBootSuffix_maybe is_boot path
+ | is_boot = addBootSuffix path
+ | otherwise = path
+
+addBootSuffixLocn :: ModLocation -> ModLocation
+addBootSuffixLocn locn
+ = locn { ml_hs_file = fmap addBootSuffix (ml_hs_file locn)
+ , ml_hi_file = addBootSuffix (ml_hi_file locn)
+ , ml_obj_file = addBootSuffix (ml_obj_file locn) }
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{The name of a module}
+%* *
+%************************************************************************
+
+\begin{code}
+newtype Module = Module FastString
+ -- Haskell module names can include the quote character ',
+ -- so the module names have the z-encoding applied to them
+
+instance Binary Module where
+ put_ bh (Module m) = put_ bh m
+ get bh = do m <- get bh; return (Module m)
+
+instance Uniquable Module where
+ getUnique (Module nm) = getUnique nm
+
+instance Eq Module where
+ nm1 == nm2 = getUnique nm1 == getUnique nm2
+
+-- Warning: gives an ordering relation based on the uniques of the
+-- FastStrings which are the (encoded) module names. This is _not_
+-- a lexicographical ordering.
+instance Ord Module where
+ nm1 `compare` nm2 = getUnique nm1 `compare` getUnique nm2
+
+instance Outputable Module where
+ ppr = pprModule
+
+pprModule :: Module -> SDoc
+pprModule (Module nm) =
+ getPprStyle $ \ sty ->
+ if codeStyle sty
+ then ftext (zEncodeFS nm)
+ else ftext nm
+
+moduleFS :: Module -> FastString
+moduleFS (Module mod) = mod
+
+moduleString :: Module -> String
+moduleString (Module mod) = unpackFS mod
+
+-- used to be called mkSrcModule
+mkModule :: String -> Module
+mkModule s = Module (mkFastString s)
+
+-- used to be called mkSrcModuleFS
+mkModuleFS :: FastString -> Module
+mkModuleFS s = Module s
+\end{code}
+
+%************************************************************************
+%* *
+\subsection{@ModuleEnv@s}
+%* *
+%************************************************************************
+
+\begin{code}
+type ModuleEnv elt = UniqFM elt
+
+emptyModuleEnv :: ModuleEnv a
+mkModuleEnv :: [(Module, a)] -> ModuleEnv a
+unitModuleEnv :: Module -> a -> ModuleEnv a
+extendModuleEnv :: ModuleEnv a -> Module -> a -> ModuleEnv a
+extendModuleEnv_C :: (a->a->a) -> ModuleEnv a -> Module -> a -> ModuleEnv a
+plusModuleEnv :: ModuleEnv a -> ModuleEnv a -> ModuleEnv a
+extendModuleEnvList :: ModuleEnv a -> [(Module, a)] -> ModuleEnv a
+
+delModuleEnvList :: ModuleEnv a -> [Module] -> ModuleEnv a
+delModuleEnv :: ModuleEnv a -> Module -> ModuleEnv a
+plusModuleEnv_C :: (a -> a -> a) -> ModuleEnv a -> ModuleEnv a -> ModuleEnv a
+mapModuleEnv :: (a -> b) -> ModuleEnv a -> ModuleEnv b
+moduleEnvElts :: ModuleEnv a -> [a]
+
+isEmptyModuleEnv :: ModuleEnv a -> Bool
+lookupModuleEnv :: ModuleEnv a -> Module -> Maybe a
+lookupWithDefaultModuleEnv :: ModuleEnv a -> a -> Module -> a
+elemModuleEnv :: Module -> ModuleEnv a -> Bool
+foldModuleEnv :: (a -> b -> b) -> b -> ModuleEnv a -> b
+filterModuleEnv :: (a -> Bool) -> ModuleEnv a -> ModuleEnv a
+
+filterModuleEnv = filterUFM
+elemModuleEnv = elemUFM
+extendModuleEnv = addToUFM
+extendModuleEnv_C = addToUFM_C
+extendModuleEnvList = addListToUFM
+plusModuleEnv_C = plusUFM_C
+delModuleEnvList = delListFromUFM
+delModuleEnv = delFromUFM
+plusModuleEnv = plusUFM
+lookupModuleEnv = lookupUFM
+lookupWithDefaultModuleEnv = lookupWithDefaultUFM
+mapModuleEnv = mapUFM
+mkModuleEnv = listToUFM
+emptyModuleEnv = emptyUFM
+moduleEnvElts = eltsUFM
+unitModuleEnv = unitUFM
+isEmptyModuleEnv = isNullUFM
+foldModuleEnv = foldUFM
+\end{code}
+
+\begin{code}
+type ModuleSet = UniqSet Module
+mkModuleSet :: [Module] -> ModuleSet
+extendModuleSet :: ModuleSet -> Module -> ModuleSet
+emptyModuleSet :: ModuleSet
+moduleSetElts :: ModuleSet -> [Module]
+elemModuleSet :: Module -> ModuleSet -> Bool
+
+emptyModuleSet = emptyUniqSet
+mkModuleSet = mkUniqSet
+extendModuleSet = addOneToUniqSet
+moduleSetElts = uniqSetToList
+elemModuleSet = elementOfUniqSet
+\end{code}
diff --git a/compiler/basicTypes/Module.lhs-boot b/compiler/basicTypes/Module.lhs-boot
new file mode 100644
index 0000000000..d75c032d45
--- /dev/null
+++ b/compiler/basicTypes/Module.lhs-boot
@@ -0,0 +1,6 @@
+\begin{code}
+module Module where
+
+data Module
+\end{code}
+
diff --git a/compiler/basicTypes/Name.hi-boot-5 b/compiler/basicTypes/Name.hi-boot-5
new file mode 100644
index 0000000000..634d95433c
--- /dev/null
+++ b/compiler/basicTypes/Name.hi-boot-5
@@ -0,0 +1,3 @@
+__interface Name 1 0 where
+__export Name Name;
+1 data Name ;
diff --git a/compiler/basicTypes/Name.hi-boot-6 b/compiler/basicTypes/Name.hi-boot-6
new file mode 100644
index 0000000000..c4eeca4d68
--- /dev/null
+++ b/compiler/basicTypes/Name.hi-boot-6
@@ -0,0 +1,3 @@
+module Name where
+
+data Name
diff --git a/compiler/basicTypes/Name.lhs b/compiler/basicTypes/Name.lhs
new file mode 100644
index 0000000000..1e1fb31f84
--- /dev/null
+++ b/compiler/basicTypes/Name.lhs
@@ -0,0 +1,384 @@
+%
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
+%
+\section[Name]{@Name@: to transmit name info from renamer to typechecker}
+
+\begin{code}
+module Name (
+ -- Re-export the OccName stuff
+ module OccName,
+
+ -- The Name type
+ Name, -- Abstract
+ BuiltInSyntax(..),
+ mkInternalName, mkSystemName,
+ mkSystemVarName, mkSysTvName,
+ mkFCallName, mkIPName,
+ mkExternalName, mkWiredInName,
+
+ nameUnique, setNameUnique,
+ nameOccName, nameModule, nameModule_maybe,
+ tidyNameOcc,
+ hashName, localiseName,
+
+ nameSrcLoc, nameParent, nameParent_maybe, isImplicitName,
+
+ isSystemName, isInternalName, isExternalName,
+ isTyVarName, isWiredInName, isBuiltInSyntax,
+ wiredInNameTyThing_maybe,
+ nameIsLocalOrFrom,
+
+ -- Class NamedThing and overloaded friends
+ NamedThing(..),
+ getSrcLoc, getOccString
+ ) where
+
+#include "HsVersions.h"
+
+import {-# SOURCE #-} TypeRep( TyThing )
+
+import OccName -- All of it
+import Module ( Module, moduleFS )
+import SrcLoc ( noSrcLoc, wiredInSrcLoc, SrcLoc )
+import Unique ( Unique, Uniquable(..), getKey, pprUnique )
+import Maybes ( orElse, isJust )
+import FastString ( FastString, zEncodeFS )
+import Outputable
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[Name-datatype]{The @Name@ datatype, and name construction}
+%* *
+%************************************************************************
+
+\begin{code}
+data Name = Name {
+ n_sort :: NameSort, -- What sort of name it is
+ n_occ :: !OccName, -- Its occurrence name
+ n_uniq :: Unique,
+ n_loc :: !SrcLoc -- Definition site
+ }
+
+-- NOTE: we make the n_loc field strict to eliminate some potential
+-- (and real!) space leaks, due to the fact that we don't look at
+-- the SrcLoc in a Name all that often.
+
+data NameSort
+ = External Module (Maybe Name)
+ -- (Just parent) => this Name is a subordinate name of 'parent'
+ -- e.g. data constructor of a data type, method of a class
+ -- Nothing => not a subordinate
+
+ | WiredIn Module (Maybe Name) TyThing BuiltInSyntax
+ -- A variant of External, for wired-in things
+
+ | Internal -- A user-defined Id or TyVar
+ -- defined in the module being compiled
+
+ | System -- A system-defined Id or TyVar. Typically the
+ -- OccName is very uninformative (like 's')
+
+data BuiltInSyntax = BuiltInSyntax | UserSyntax
+-- BuiltInSyntax is for things like (:), [], tuples etc,
+-- which have special syntactic forms. They aren't "in scope"
+-- as such.
+\end{code}
+
+Notes about the NameSorts:
+
+1. Initially, top-level Ids (including locally-defined ones) get External names,
+ and all other local Ids get Internal names
+
+2. Things with a External name are given C static labels, so they finally
+ appear in the .o file's symbol table. They appear in the symbol table
+ in the form M.n. If originally-local things have this property they
+ must be made @External@ first.
+
+3. In the tidy-core phase, a External that is not visible to an importer
+ is changed to Internal, and a Internal that is visible is changed to External
+
+4. A System Name differs in the following ways:
+ a) has unique attached when printing dumps
+ b) unifier eliminates sys tyvars in favour of user provs where possible
+
+ Before anything gets printed in interface files or output code, it's
+ fed through a 'tidy' processor, which zaps the OccNames to have
+ unique names; and converts all sys-locals to user locals
+ If any desugarer sys-locals have survived that far, they get changed to
+ "ds1", "ds2", etc.
+
+Built-in syntax => It's a syntactic form, not "in scope" (e.g. [])
+
+Wired-in thing => The thing (Id, TyCon) is fully known to the compiler,
+ not read from an interface file.
+ E.g. Bool, True, Int, Float, and many others
+
+All built-in syntax is for wired-in things.
+
+\begin{code}
+nameUnique :: Name -> Unique
+nameOccName :: Name -> OccName
+nameModule :: Name -> Module
+nameSrcLoc :: Name -> SrcLoc
+
+nameUnique name = n_uniq name
+nameOccName name = n_occ name
+nameSrcLoc name = n_loc name
+\end{code}
+
+\begin{code}
+nameIsLocalOrFrom :: Module -> Name -> Bool
+isInternalName :: Name -> Bool
+isExternalName :: Name -> Bool
+isSystemName :: Name -> Bool
+isWiredInName :: Name -> Bool
+
+isWiredInName (Name {n_sort = WiredIn _ _ _ _}) = True
+isWiredInName other = False
+
+wiredInNameTyThing_maybe :: Name -> Maybe TyThing
+wiredInNameTyThing_maybe (Name {n_sort = WiredIn _ _ thing _}) = Just thing
+wiredInNameTyThing_maybe other = Nothing
+
+isBuiltInSyntax (Name {n_sort = WiredIn _ _ _ BuiltInSyntax}) = True
+isBuiltInSyntax other = False
+
+isExternalName (Name {n_sort = External _ _}) = True
+isExternalName (Name {n_sort = WiredIn _ _ _ _}) = True
+isExternalName other = False
+
+isInternalName name = not (isExternalName name)
+
+nameParent_maybe :: Name -> Maybe Name
+nameParent_maybe (Name {n_sort = External _ p}) = p
+nameParent_maybe (Name {n_sort = WiredIn _ p _ _}) = p
+nameParent_maybe other = Nothing
+
+nameParent :: Name -> Name
+nameParent name = case nameParent_maybe name of
+ Just parent -> parent
+ Nothing -> name
+
+isImplicitName :: Name -> Bool
+-- An Implicit Name is one has a parent; that is, one whose definition
+-- derives from the parent thing
+isImplicitName name = isJust (nameParent_maybe name)
+
+nameModule name = nameModule_maybe name `orElse` pprPanic "nameModule" (ppr name)
+nameModule_maybe (Name { n_sort = External mod _}) = Just mod
+nameModule_maybe (Name { n_sort = WiredIn mod _ _ _}) = Just mod
+nameModule_maybe name = Nothing
+
+nameIsLocalOrFrom from name
+ | isExternalName name = from == nameModule name
+ | otherwise = True
+
+isTyVarName :: Name -> Bool
+isTyVarName name = isTvOcc (nameOccName name)
+
+isSystemName (Name {n_sort = System}) = True
+isSystemName other = False
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Making names}
+%* *
+%************************************************************************
+
+\begin{code}
+mkInternalName :: Unique -> OccName -> SrcLoc -> Name
+mkInternalName uniq occ loc = Name { n_uniq = uniq, n_sort = Internal, n_occ = occ, n_loc = loc }
+ -- NB: You might worry that after lots of huffing and
+ -- puffing we might end up with two local names with distinct
+ -- uniques, but the same OccName. Indeed we can, but that's ok
+ -- * the insides of the compiler don't care: they use the Unique
+ -- * when printing for -ddump-xxx you can switch on -dppr-debug to get the
+ -- uniques if you get confused
+ -- * for interface files we tidyCore first, which puts the uniques
+ -- into the print name (see setNameVisibility below)
+
+mkExternalName :: Unique -> Module -> OccName -> Maybe Name -> SrcLoc -> Name
+mkExternalName uniq mod occ mb_parent loc
+ = Name { n_uniq = uniq, n_sort = External mod mb_parent,
+ n_occ = occ, n_loc = loc }
+
+mkWiredInName :: Module -> OccName -> Unique
+ -> Maybe Name -> TyThing -> BuiltInSyntax -> Name
+mkWiredInName mod occ uniq mb_parent thing built_in
+ = Name { n_uniq = uniq,
+ n_sort = WiredIn mod mb_parent thing built_in,
+ n_occ = occ, n_loc = wiredInSrcLoc }
+
+mkSystemName :: Unique -> OccName -> Name
+mkSystemName uniq occ = Name { n_uniq = uniq, n_sort = System,
+ n_occ = occ, n_loc = noSrcLoc }
+
+mkSystemVarName :: Unique -> FastString -> Name
+mkSystemVarName uniq fs = mkSystemName uniq (mkVarOccFS fs)
+
+mkSysTvName :: Unique -> FastString -> Name
+mkSysTvName uniq fs = mkSystemName uniq (mkOccNameFS tvName fs)
+
+mkFCallName :: Unique -> String -> Name
+ -- The encoded string completely describes the ccall
+mkFCallName uniq str = Name { n_uniq = uniq, n_sort = Internal,
+ n_occ = mkVarOcc str, n_loc = noSrcLoc }
+
+mkIPName :: Unique -> OccName -> Name
+mkIPName uniq occ
+ = Name { n_uniq = uniq,
+ n_sort = Internal,
+ n_occ = occ,
+ n_loc = noSrcLoc }
+\end{code}
+
+\begin{code}
+-- When we renumber/rename things, we need to be
+-- able to change a Name's Unique to match the cached
+-- one in the thing it's the name of. If you know what I mean.
+setNameUnique name uniq = name {n_uniq = uniq}
+
+tidyNameOcc :: Name -> OccName -> Name
+-- We set the OccName of a Name when tidying
+-- In doing so, we change System --> Internal, so that when we print
+-- it we don't get the unique by default. It's tidy now!
+tidyNameOcc name@(Name { n_sort = System }) occ = name { n_occ = occ, n_sort = Internal}
+tidyNameOcc name occ = name { n_occ = occ }
+
+localiseName :: Name -> Name
+localiseName n = n { n_sort = Internal }
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Predicates and selectors}
+%* *
+%************************************************************************
+
+\begin{code}
+hashName :: Name -> Int
+hashName name = getKey (nameUnique name)
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection[Name-instances]{Instance declarations}
+%* *
+%************************************************************************
+
+\begin{code}
+cmpName n1 n2 = n_uniq n1 `compare` n_uniq n2
+\end{code}
+
+\begin{code}
+instance Eq Name where
+ a == b = case (a `compare` b) of { EQ -> True; _ -> False }
+ a /= b = case (a `compare` b) of { EQ -> False; _ -> True }
+
+instance Ord Name where
+ a <= b = case (a `compare` b) of { LT -> True; EQ -> True; GT -> False }
+ a < b = case (a `compare` b) of { LT -> True; EQ -> False; GT -> False }
+ a >= b = case (a `compare` b) of { LT -> False; EQ -> True; GT -> True }
+ a > b = case (a `compare` b) of { LT -> False; EQ -> False; GT -> True }
+ compare a b = cmpName a b
+
+instance Uniquable Name where
+ getUnique = nameUnique
+
+instance NamedThing Name where
+ getName n = n
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Pretty printing}
+%* *
+%************************************************************************
+
+\begin{code}
+instance Outputable Name where
+ ppr name = pprName name
+
+instance OutputableBndr Name where
+ pprBndr _ name = pprName name
+
+pprName (Name {n_sort = sort, n_uniq = uniq, n_occ = occ})
+ = getPprStyle $ \ sty ->
+ case sort of
+ WiredIn mod _ _ builtin -> pprExternal sty uniq mod occ True builtin
+ External mod _ -> pprExternal sty uniq mod occ False UserSyntax
+ System -> pprSystem sty uniq occ
+ Internal -> pprInternal sty uniq occ
+
+pprExternal sty uniq mod occ is_wired is_builtin
+ | codeStyle sty = ppr_z_module mod <> char '_' <> ppr_z_occ_name occ
+ -- In code style, always qualify
+ -- ToDo: maybe we could print all wired-in things unqualified
+ -- in code style, to reduce symbol table bloat?
+ | debugStyle sty = ppr mod <> dot <> ppr_occ_name occ
+ <> braces (hsep [if is_wired then ptext SLIT("(w)") else empty,
+ pprNameSpaceBrief (occNameSpace occ),
+ pprUnique uniq])
+ | BuiltInSyntax <- is_builtin = ppr_occ_name occ
+ -- never qualify builtin syntax
+ | unqualStyle sty mod occ = ppr_occ_name occ
+ | otherwise = ppr mod <> dot <> ppr_occ_name occ
+
+pprInternal sty uniq occ
+ | codeStyle sty = pprUnique uniq
+ | debugStyle sty = ppr_occ_name occ <> braces (hsep [pprNameSpaceBrief (occNameSpace occ),
+ pprUnique uniq])
+ | dumpStyle sty = ppr_occ_name occ <> char '_' <> pprUnique uniq
+ -- For debug dumps, we're not necessarily dumping
+ -- tidied code, so we need to print the uniques.
+ | otherwise = ppr_occ_name occ -- User style
+
+-- Like Internal, except that we only omit the unique in Iface style
+pprSystem sty uniq occ
+ | codeStyle sty = pprUnique uniq
+ | debugStyle sty = ppr_occ_name occ <> char '_' <> pprUnique uniq
+ <> braces (pprNameSpaceBrief (occNameSpace occ))
+ | otherwise = ppr_occ_name occ <> char '_' <> pprUnique uniq
+ -- If the tidy phase hasn't run, the OccName
+ -- is unlikely to be informative (like 's'),
+ -- so print the unique
+
+ppr_occ_name occ = ftext (occNameFS occ)
+ -- Don't use pprOccName; instead, just print the string of the OccName;
+ -- we print the namespace in the debug stuff above
+
+-- In code style, we Z-encode the strings. The results of Z-encoding each FastString are
+-- cached behind the scenes in the FastString implementation.
+ppr_z_occ_name occ = ftext (zEncodeFS (occNameFS occ))
+ppr_z_module mod = ftext (zEncodeFS (moduleFS mod))
+
+\end{code}
+
+%************************************************************************
+%* *
+\subsection{Overloaded functions related to Names}
+%* *
+%************************************************************************
+
+\begin{code}
+class NamedThing a where
+ getOccName :: a -> OccName
+ getName :: a -> Name
+
+ getOccName n = nameOccName (getName n) -- Default method
+\end{code}
+
+\begin{code}
+getSrcLoc :: NamedThing a => a -> SrcLoc
+getOccString :: NamedThing a => a -> String
+
+getSrcLoc = nameSrcLoc . getName
+getOccString = occNameString . getOccName
+\end{code}
+
diff --git a/compiler/basicTypes/Name.lhs-boot b/compiler/basicTypes/Name.lhs-boot
new file mode 100644
index 0000000000..167ce4242d
--- /dev/null
+++ b/compiler/basicTypes/Name.lhs-boot
@@ -0,0 +1,5 @@
+\begin{code}
+module Name where
+
+data Name
+\end{code}
diff --git a/compiler/basicTypes/NameEnv.lhs b/compiler/basicTypes/NameEnv.lhs
new file mode 100644
index 0000000000..ff637010aa
--- /dev/null
+++ b/compiler/basicTypes/NameEnv.lhs
@@ -0,0 +1,72 @@
+%
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
+%
+\section[NameEnv]{@NameEnv@: name environments}
+
+\begin{code}
+module NameEnv (
+ NameEnv, mkNameEnv,
+ emptyNameEnv, unitNameEnv, nameEnvElts,
+ extendNameEnv_C, extendNameEnv_Acc, extendNameEnv, extendNameEnvList,
+ foldNameEnv, filterNameEnv,
+ plusNameEnv, plusNameEnv_C,
+ lookupNameEnv, lookupNameEnv_NF, delFromNameEnv, delListFromNameEnv,
+ elemNameEnv, mapNameEnv
+ ) where
+
+#include "HsVersions.h"
+
+import Name ( Name )
+import UniqFM
+import Maybes ( expectJust )
+\end{code}
+
+%************************************************************************
+%* *
+\subsection{Name environment}
+%* *
+%************************************************************************
+
+\begin{code}
+type NameEnv a = UniqFM a -- Domain is Name
+
+emptyNameEnv :: NameEnv a
+mkNameEnv :: [(Name,a)] -> NameEnv a
+nameEnvElts :: NameEnv a -> [a]
+extendNameEnv_C :: (a->a->a) -> NameEnv a -> Name -> a -> NameEnv a
+extendNameEnv_Acc :: (a->b->b) -> (a->b) -> NameEnv b -> Name -> a -> NameEnv b
+extendNameEnv :: NameEnv a -> Name -> a -> NameEnv a
+plusNameEnv :: NameEnv a -> NameEnv a -> NameEnv a
+plusNameEnv_C :: (a->a->a) -> NameEnv a -> NameEnv a -> NameEnv a
+extendNameEnvList :: NameEnv a -> [(Name,a)] -> NameEnv a
+delFromNameEnv :: NameEnv a -> Name -> NameEnv a
+delListFromNameEnv :: NameEnv a -> [Name] -> NameEnv a
+elemNameEnv :: Name -> NameEnv a -> Bool
+unitNameEnv :: Name -> a -> NameEnv a
+lookupNameEnv :: NameEnv a -> Name -> Maybe a
+lookupNameEnv_NF :: NameEnv a -> Name -> a
+foldNameEnv :: (a -> b -> b) -> b -> NameEnv a -> b
+filterNameEnv :: (elt -> Bool) -> NameEnv elt -> NameEnv elt
+mapNameEnv :: (elt1 -> elt2) -> NameEnv elt1 -> NameEnv elt2
+
+emptyNameEnv = emptyUFM
+foldNameEnv = foldUFM
+mkNameEnv = listToUFM
+nameEnvElts = eltsUFM
+extendNameEnv_C = addToUFM_C
+extendNameEnv_Acc = addToUFM_Acc
+extendNameEnv = addToUFM
+plusNameEnv = plusUFM
+plusNameEnv_C = plusUFM_C
+extendNameEnvList = addListToUFM
+delFromNameEnv = delFromUFM
+delListFromNameEnv = delListFromUFM
+elemNameEnv = elemUFM
+unitNameEnv = unitUFM
+filterNameEnv = filterUFM
+mapNameEnv = mapUFM
+
+lookupNameEnv = lookupUFM
+lookupNameEnv_NF env n = expectJust "lookupNameEnv_NF" (lookupUFM env n)
+\end{code}
+
diff --git a/compiler/basicTypes/NameSet.lhs b/compiler/basicTypes/NameSet.lhs
new file mode 100644
index 0000000000..d0e55dec68
--- /dev/null
+++ b/compiler/basicTypes/NameSet.lhs
@@ -0,0 +1,190 @@
+%
+% (c) The GRASP/AQUA Project, Glasgow University, 1998
+%
+\section[NameSet]{@NameSets@}
+
+\begin{code}
+module NameSet (
+ -- Sets of Names
+ NameSet,
+ emptyNameSet, unitNameSet, mkNameSet, unionNameSets, unionManyNameSets,
+ minusNameSet, elemNameSet, nameSetToList, addOneToNameSet, addListToNameSet,
+ delFromNameSet, delListFromNameSet, isEmptyNameSet, foldNameSet, filterNameSet,
+ intersectsNameSet, intersectNameSet,
+
+ -- Free variables
+ FreeVars, isEmptyFVs, emptyFVs, plusFVs, plusFV,
+ mkFVs, addOneFV, unitFV, delFV, delFVs,
+
+ -- Defs and uses
+ Defs, Uses, DefUse, DefUses,
+ emptyDUs, usesOnly, mkDUs, plusDU,
+ findUses, duDefs, duUses, allUses
+ ) where
+
+#include "HsVersions.h"
+
+import Name
+import UniqSet
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection[Sets of names}
+%* *
+%************************************************************************
+
+\begin{code}
+type NameSet = UniqSet Name
+emptyNameSet :: NameSet
+unitNameSet :: Name -> NameSet
+addListToNameSet :: NameSet -> [Name] -> NameSet
+addOneToNameSet :: NameSet -> Name -> NameSet
+mkNameSet :: [Name] -> NameSet
+unionNameSets :: NameSet -> NameSet -> NameSet
+unionManyNameSets :: [NameSet] -> NameSet
+minusNameSet :: NameSet -> NameSet -> NameSet
+elemNameSet :: Name -> NameSet -> Bool
+nameSetToList :: NameSet -> [Name]
+isEmptyNameSet :: NameSet -> Bool
+delFromNameSet :: NameSet -> Name -> NameSet
+delListFromNameSet :: NameSet -> [Name] -> NameSet
+foldNameSet :: (Name -> b -> b) -> b -> NameSet -> b
+filterNameSet :: (Name -> Bool) -> NameSet -> NameSet
+intersectNameSet :: NameSet -> NameSet -> NameSet
+intersectsNameSet :: NameSet -> NameSet -> Bool -- True if non-empty intersection
+ -- (s1 `intersectsVarSet` s2) doesn't compute s2 if s1 is empty
+
+isEmptyNameSet = isEmptyUniqSet
+emptyNameSet = emptyUniqSet
+unitNameSet = unitUniqSet
+mkNameSet = mkUniqSet
+addListToNameSet = addListToUniqSet
+addOneToNameSet = addOneToUniqSet
+unionNameSets = unionUniqSets
+unionManyNameSets = unionManyUniqSets
+minusNameSet = minusUniqSet
+elemNameSet = elementOfUniqSet
+nameSetToList = uniqSetToList
+delFromNameSet = delOneFromUniqSet
+foldNameSet = foldUniqSet
+filterNameSet = filterUniqSet
+intersectNameSet = intersectUniqSets
+
+delListFromNameSet set ns = foldl delFromNameSet set ns
+
+intersectsNameSet s1 s2 = not (isEmptyNameSet (s1 `intersectNameSet` s2))
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Free variables}
+%* *
+%************************************************************************
+
+These synonyms are useful when we are thinking of free variables
+
+\begin{code}
+type FreeVars = NameSet
+
+plusFV :: FreeVars -> FreeVars -> FreeVars
+addOneFV :: FreeVars -> Name -> FreeVars
+unitFV :: Name -> FreeVars
+emptyFVs :: FreeVars
+plusFVs :: [FreeVars] -> FreeVars
+mkFVs :: [Name] -> FreeVars
+delFV :: Name -> FreeVars -> FreeVars
+delFVs :: [Name] -> FreeVars -> FreeVars
+
+isEmptyFVs = isEmptyNameSet
+emptyFVs = emptyNameSet
+plusFVs = unionManyNameSets
+plusFV = unionNameSets
+mkFVs = mkNameSet
+addOneFV = addOneToNameSet
+unitFV = unitNameSet
+delFV n s = delFromNameSet s n
+delFVs ns s = delListFromNameSet s ns
+\end{code}
+
+
+%************************************************************************
+%* *
+ Defs and uses
+%* *
+%************************************************************************
+
+\begin{code}
+type Defs = NameSet
+type Uses = NameSet
+
+type DefUses = [DefUse]
+ -- In dependency order: earlier Defs scope over later Uses
+
+type DefUse = (Maybe Defs, Uses)
+ -- For items (Just ds, us), the use of any member
+ -- of the ds implies that all the us are used too
+ --
+ -- Also, us may mention ds
+ --
+ -- Nothing => Nothing defined in this group, but
+ -- nevertheless all the uses are essential.
+ -- Used for instance declarations, for example
+
+emptyDUs :: DefUses
+emptyDUs = []
+
+usesOnly :: Uses -> DefUses
+usesOnly uses = [(Nothing, uses)]
+
+mkDUs :: [(Defs,Uses)] -> DefUses
+mkDUs pairs = [(Just defs, uses) | (defs,uses) <- pairs]
+
+plusDU :: DefUses -> DefUses -> DefUses
+plusDU = (++)
+
+duDefs :: DefUses -> Defs
+duDefs dus = foldr get emptyNameSet dus
+ where
+ get (Nothing, u1) d2 = d2
+ get (Just d1, u1) d2 = d1 `unionNameSets` d2
+
+duUses :: DefUses -> Uses
+-- Just like allUses, but defs are not eliminated
+duUses dus = foldr get emptyNameSet dus
+ where
+ get (d1, u1) u2 = u1 `unionNameSets` u2
+
+allUses :: DefUses -> Uses
+-- Collect all uses, regardless of
+-- whether the group is itself used,
+-- but remove defs on the way
+allUses dus
+ = foldr get emptyNameSet dus
+ where
+ get (Nothing, rhs_uses) uses = rhs_uses `unionNameSets` uses
+ get (Just defs, rhs_uses) uses = (rhs_uses `unionNameSets` uses)
+ `minusNameSet` defs
+
+findUses :: DefUses -> Uses -> Uses
+-- Given some DefUses and some Uses,
+-- find all the uses, transitively.
+-- The result is a superset of the input uses;
+-- and includes things defined in the input DefUses
+-- (but only if they are used)
+findUses dus uses
+ = foldr get uses dus
+ where
+ get (Nothing, rhs_uses) uses
+ = rhs_uses `unionNameSets` uses
+ get (Just defs, rhs_uses) uses
+ | defs `intersectsNameSet` uses -- Used
+ || not (all (reportIfUnused . nameOccName) (nameSetToList defs))
+ -- At least one starts with an "_",
+ -- so treat the group as used
+ = rhs_uses `unionNameSets` uses
+ | otherwise -- No def is used
+ = uses
+\end{code} \ No newline at end of file
diff --git a/compiler/basicTypes/NewDemand.lhs b/compiler/basicTypes/NewDemand.lhs
new file mode 100644
index 0000000000..8e68fd87d2
--- /dev/null
+++ b/compiler/basicTypes/NewDemand.lhs
@@ -0,0 +1,318 @@
+%
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
+%
+\section[Demand]{@Demand@: the amount of demand on a value}
+
+\begin{code}
+module NewDemand(
+ Demand(..),
+ topDmd, lazyDmd, seqDmd, evalDmd, errDmd, isStrictDmd,
+ isTop, isAbsent, seqDemand,
+
+ DmdType(..), topDmdType, botDmdType, mkDmdType, mkTopDmdType,
+ dmdTypeDepth, seqDmdType,
+ DmdEnv, emptyDmdEnv,
+ DmdResult(..), retCPR, isBotRes, returnsCPR, resTypeArgDmd,
+
+ Demands(..), mapDmds, zipWithDmds, allTop, seqDemands,
+
+ StrictSig(..), mkStrictSig, topSig, botSig, cprSig,
+ isTopSig,
+ splitStrictSig,
+ pprIfaceStrictSig, appIsBottom, isBottomingSig, seqStrictSig,
+ ) where
+
+#include "HsVersions.h"
+
+import StaticFlags ( opt_CprOff )
+import BasicTypes ( Arity )
+import VarEnv ( VarEnv, emptyVarEnv, isEmptyVarEnv )
+import UniqFM ( ufmToList )
+import Util ( listLengthCmp, zipWithEqual )
+import Outputable
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Demands}
+%* *
+%************************************************************************
+
+\begin{code}
+data Demand
+ = Top -- T; used for unlifted types too, so that
+ -- A `lub` T = T
+ | Abs -- A
+
+ | Call Demand -- C(d)
+
+ | Eval Demands -- U(ds)
+
+ | Defer Demands -- D(ds)
+
+ | Box Demand -- B(d)
+
+ | Bot -- B
+ deriving( Eq )
+ -- Equality needed for fixpoints in DmdAnal
+
+data Demands = Poly Demand -- Polymorphic case
+ | Prod [Demand] -- Product case
+ deriving( Eq )
+
+allTop (Poly d) = isTop d
+allTop (Prod ds) = all isTop ds
+
+isTop Top = True
+isTop d = False
+
+isAbsent Abs = True
+isAbsent d = False
+
+mapDmds :: (Demand -> Demand) -> Demands -> Demands
+mapDmds f (Poly d) = Poly (f d)
+mapDmds f (Prod ds) = Prod (map f ds)
+
+zipWithDmds :: (Demand -> Demand -> Demand)
+ -> Demands -> Demands -> Demands
+zipWithDmds f (Poly d1) (Poly d2) = Poly (d1 `f` d2)
+zipWithDmds f (Prod ds1) (Poly d2) = Prod [d1 `f` d2 | d1 <- ds1]
+zipWithDmds f (Poly d1) (Prod ds2) = Prod [d1 `f` d2 | d2 <- ds2]
+zipWithDmds f (Prod ds1) (Prod ds2) = Prod (zipWithEqual "zipWithDmds" f ds1 ds2)
+
+topDmd, lazyDmd, seqDmd :: Demand
+topDmd = Top -- The most uninformative demand
+lazyDmd = Box Abs
+seqDmd = Eval (Poly Abs) -- Polymorphic seq demand
+evalDmd = Box seqDmd -- Evaluate and return
+errDmd = Box Bot -- This used to be called X
+
+isStrictDmd :: Demand -> Bool
+isStrictDmd Bot = True
+isStrictDmd (Eval _) = True
+isStrictDmd (Call _) = True
+isStrictDmd (Box d) = isStrictDmd d
+isStrictDmd other = False
+
+seqDemand :: Demand -> ()
+seqDemand (Call d) = seqDemand d
+seqDemand (Eval ds) = seqDemands ds
+seqDemand (Defer ds) = seqDemands ds
+seqDemand (Box d) = seqDemand d
+seqDemand _ = ()
+
+seqDemands :: Demands -> ()
+seqDemands (Poly d) = seqDemand d
+seqDemands (Prod ds) = seqDemandList ds
+
+seqDemandList :: [Demand] -> ()
+seqDemandList [] = ()
+seqDemandList (d:ds) = seqDemand d `seq` seqDemandList ds
+
+instance Outputable Demand where
+ ppr Top = char 'T'
+ ppr Abs = char 'A'
+ ppr Bot = char 'B'
+
+ ppr (Defer ds) = char 'D' <> ppr ds
+ ppr (Eval ds) = char 'U' <> ppr ds
+
+ ppr (Box (Eval ds)) = char 'S' <> ppr ds
+ ppr (Box Abs) = char 'L'
+ ppr (Box Bot) = char 'X'
+
+ ppr (Call d) = char 'C' <> parens (ppr d)
+
+
+instance Outputable Demands where
+ ppr (Poly Abs) = empty
+ ppr (Poly d) = parens (ppr d <> char '*')
+ ppr (Prod ds) = parens (hcat (map ppr ds))
+ -- At one time I printed U(AAA) as U, but that
+ -- confuses (Poly Abs) with (Prod AAA), and the
+ -- worker/wrapper generation differs slightly for these two
+ -- [Reason: in the latter case we can avoid passing the arg;
+ -- see notes with WwLib.mkWWstr_one.]
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Demand types}
+%* *
+%************************************************************************
+
+\begin{code}
+data DmdType = DmdType
+ DmdEnv -- Demand on explicitly-mentioned
+ -- free variables
+ [Demand] -- Demand on arguments
+ DmdResult -- Nature of result
+
+ -- IMPORTANT INVARIANT
+ -- The default demand on free variables not in the DmdEnv is:
+ -- DmdResult = BotRes <=> Bot
+ -- DmdResult = TopRes/ResCPR <=> Abs
+
+ -- ANOTHER IMPORTANT INVARIANT
+ -- The Demands in the argument list are never
+ -- Bot, Defer d
+ -- Handwavey reason: these don't correspond to calling conventions
+ -- See DmdAnal.funArgDemand for details
+
+
+-- This guy lets us switch off CPR analysis
+-- by making sure that everything uses TopRes instead of RetCPR
+-- Assuming, of course, that they don't mention RetCPR by name.
+-- They should onlyu use retCPR
+retCPR | opt_CprOff = TopRes
+ | otherwise = RetCPR
+
+seqDmdType (DmdType env ds res) =
+ {- ??? env `seq` -} seqDemandList ds `seq` res `seq` ()
+
+type DmdEnv = VarEnv Demand
+
+data DmdResult = TopRes -- Nothing known
+ | RetCPR -- Returns a constructed product
+ | BotRes -- Diverges or errors
+ deriving( Eq, Show )
+ -- Equality for fixpoints
+ -- Show needed for Show in Lex.Token (sigh)
+
+-- Equality needed for fixpoints in DmdAnal
+instance Eq DmdType where
+ (==) (DmdType fv1 ds1 res1)
+ (DmdType fv2 ds2 res2) = ufmToList fv1 == ufmToList fv2
+ && ds1 == ds2 && res1 == res2
+
+instance Outputable DmdType where
+ ppr (DmdType fv ds res)
+ = hsep [text "DmdType",
+ hcat (map ppr ds) <> ppr res,
+ if null fv_elts then empty
+ else braces (fsep (map pp_elt fv_elts))]
+ where
+ pp_elt (uniq, dmd) = ppr uniq <> text "->" <> ppr dmd
+ fv_elts = ufmToList fv
+
+instance Outputable DmdResult where
+ ppr TopRes = empty -- Keep these distinct from Demand letters
+ ppr RetCPR = char 'm' -- so that we can print strictness sigs as
+ ppr BotRes = char 'b' -- dddr
+ -- without ambiguity
+
+emptyDmdEnv = emptyVarEnv
+
+topDmdType = DmdType emptyDmdEnv [] TopRes
+botDmdType = DmdType emptyDmdEnv [] BotRes
+cprDmdType = DmdType emptyVarEnv [] retCPR
+
+isTopDmdType :: DmdType -> Bool
+-- Only used on top-level types, hence the assert
+isTopDmdType (DmdType env [] TopRes) = ASSERT( isEmptyVarEnv env) True
+isTopDmdType other = False
+
+isBotRes :: DmdResult -> Bool
+isBotRes BotRes = True
+isBotRes other = False
+
+resTypeArgDmd :: DmdResult -> Demand
+-- TopRes and BotRes are polymorphic, so that
+-- BotRes = Bot -> BotRes
+-- TopRes = Top -> TopRes
+-- This function makes that concrete
+-- We can get a RetCPR, because of the way in which we are (now)
+-- giving CPR info to strict arguments. On the first pass, when
+-- nothing has demand info, we optimistically give CPR info or RetCPR to all args
+resTypeArgDmd TopRes = Top
+resTypeArgDmd RetCPR = Top
+resTypeArgDmd BotRes = Bot
+
+returnsCPR :: DmdResult -> Bool
+returnsCPR RetCPR = True
+returnsCPR other = False
+
+mkDmdType :: DmdEnv -> [Demand] -> DmdResult -> DmdType
+mkDmdType fv ds res = DmdType fv ds res
+
+mkTopDmdType :: [Demand] -> DmdResult -> DmdType
+mkTopDmdType ds res = DmdType emptyDmdEnv ds res
+
+dmdTypeDepth :: DmdType -> Arity
+dmdTypeDepth (DmdType _ ds _) = length ds
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Strictness signature
+%* *
+%************************************************************************
+
+In a let-bound Id we record its strictness info.
+In principle, this strictness info is a demand transformer, mapping
+a demand on the Id into a DmdType, which gives
+ a) the free vars of the Id's value
+ b) the Id's arguments
+ c) an indication of the result of applying
+ the Id to its arguments
+
+However, in fact we store in the Id an extremely emascuated demand transfomer,
+namely
+ a single DmdType
+(Nevertheless we dignify StrictSig as a distinct type.)
+
+This DmdType gives the demands unleashed by the Id when it is applied
+to as many arguments as are given in by the arg demands in the DmdType.
+
+For example, the demand transformer described by the DmdType
+ DmdType {x -> U(LL)} [V,A] Top
+says that when the function is applied to two arguments, it
+unleashes demand U(LL) on the free var x, V on the first arg,
+and A on the second.
+
+If this same function is applied to one arg, all we can say is
+that it uses x with U*(LL), and its arg with demand L.
+
+\begin{code}
+newtype StrictSig = StrictSig DmdType
+ deriving( Eq )
+
+instance Outputable StrictSig where
+ ppr (StrictSig ty) = ppr ty
+
+instance Show StrictSig where
+ show (StrictSig ty) = showSDoc (ppr ty)
+
+mkStrictSig :: DmdType -> StrictSig
+mkStrictSig dmd_ty = StrictSig dmd_ty
+
+splitStrictSig :: StrictSig -> ([Demand], DmdResult)
+splitStrictSig (StrictSig (DmdType _ dmds res)) = (dmds, res)
+
+isTopSig (StrictSig ty) = isTopDmdType ty
+
+topSig, botSig, cprSig :: StrictSig
+topSig = StrictSig topDmdType
+botSig = StrictSig botDmdType
+cprSig = StrictSig cprDmdType
+
+
+-- appIsBottom returns true if an application to n args would diverge
+appIsBottom (StrictSig (DmdType _ ds BotRes)) n = listLengthCmp ds n /= GT
+appIsBottom _ _ = False
+
+isBottomingSig (StrictSig (DmdType _ _ BotRes)) = True
+isBottomingSig _ = False
+
+seqStrictSig (StrictSig ty) = seqDmdType ty
+
+pprIfaceStrictSig :: StrictSig -> SDoc
+-- Used for printing top-level strictness pragmas in interface files
+pprIfaceStrictSig (StrictSig (DmdType _ dmds res))
+ = hcat (map ppr dmds) <> ppr res
+\end{code}
+
+
diff --git a/compiler/basicTypes/OccName.hi-boot-6 b/compiler/basicTypes/OccName.hi-boot-6
new file mode 100644
index 0000000000..705f9b1bd0
--- /dev/null
+++ b/compiler/basicTypes/OccName.hi-boot-6
@@ -0,0 +1,4 @@
+module OccName where
+
+data OccName
+
diff --git a/compiler/basicTypes/OccName.lhs b/compiler/basicTypes/OccName.lhs
new file mode 100644
index 0000000000..a3661a9ab0
--- /dev/null
+++ b/compiler/basicTypes/OccName.lhs
@@ -0,0 +1,676 @@
+{-% DrIFT (Automatic class derivations for Haskell) v1.1 %-}
+%
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
+%
+
+\section[OccName]{@OccName@}
+
+\begin{code}
+module OccName (
+ -- * The NameSpace type; abstact
+ NameSpace, tcName, clsName, tcClsName, dataName, varName,
+ tvName, srcDataName,
+
+ -- ** Printing
+ pprNameSpace, pprNonVarNameSpace, pprNameSpaceBrief,
+
+ -- * The OccName type
+ OccName, -- Abstract, instance of Outputable
+ pprOccName,
+
+ -- ** Construction
+ mkOccName, mkOccNameFS,
+ mkVarOcc, mkVarOccFS,
+ mkTyVarOcc,
+ mkDFunOcc,
+ mkTupleOcc,
+ setOccNameSpace,
+
+ -- ** Derived OccNames
+ mkDataConWrapperOcc, mkWorkerOcc, mkDefaultMethodOcc, mkDerivedTyConOcc,
+ mkClassTyConOcc, mkClassDataConOcc, mkDictOcc, mkIPOcc,
+ mkSpecOcc, mkForeignExportOcc, mkGenOcc1, mkGenOcc2,
+ mkDataTOcc, mkDataCOcc, mkDataConWorkerOcc,
+ mkSuperDictSelOcc, mkLocalOcc, mkMethodOcc,
+
+ -- ** Deconstruction
+ occNameFS, occNameString, occNameSpace,
+
+ isVarOcc, isTvOcc, isTcOcc, isDataOcc, isDataSymOcc, isSymOcc, isValOcc,
+ parenSymOcc, reportIfUnused, isTcClsName, isVarName,
+
+ isTupleOcc_maybe,
+
+ -- The OccEnv type
+ OccEnv, emptyOccEnv, unitOccEnv, extendOccEnv, mapOccEnv,
+ lookupOccEnv, mkOccEnv, extendOccEnvList, elemOccEnv,
+ occEnvElts, foldOccEnv, plusOccEnv, plusOccEnv_C, extendOccEnv_C,
+
+ -- The OccSet type
+ OccSet, emptyOccSet, unitOccSet, mkOccSet, extendOccSet,
+ extendOccSetList,
+ unionOccSets, unionManyOccSets, minusOccSet, elemOccSet, occSetElts,
+ foldOccSet, isEmptyOccSet, intersectOccSet, intersectsOccSet,
+
+ -- Tidying up
+ TidyOccEnv, emptyTidyOccEnv, tidyOccName, initTidyOccEnv,
+
+ -- The basic form of names
+ isLexCon, isLexVar, isLexId, isLexSym,
+ isLexConId, isLexConSym, isLexVarId, isLexVarSym,
+ startsVarSym, startsVarId, startsConSym, startsConId
+ ) where
+
+#include "HsVersions.h"
+
+import Util ( thenCmp )
+import Unique ( Unique, mkUnique, Uniquable(..) )
+import BasicTypes ( Boxity(..), Arity )
+import StaticFlags ( opt_PprStyle_Debug )
+import UniqFM
+import UniqSet
+import FastString
+import Outputable
+import Binary
+
+import GLAEXTS
+
+import Data.Char ( isUpper, isLower, ord )
+
+-- Unicode TODO: put isSymbol in libcompat
+#if __GLASGOW_HASKELL__ > 604
+import Data.Char ( isSymbol )
+#else
+isSymbol = const False
+#endif
+
+\end{code}
+
+%************************************************************************
+%* *
+\subsection{Name space}
+%* *
+%************************************************************************
+
+\begin{code}
+data NameSpace = VarName -- Variables, including "source" data constructors
+ | DataName -- "Real" data constructors
+ | TvName -- Type variables
+ | TcClsName -- Type constructors and classes; Haskell has them
+ -- in the same name space for now.
+ deriving( Eq, Ord )
+ {-! derive: Binary !-}
+
+-- Note [Data Constructors]
+-- see also: Note [Data Constructor Naming] in DataCon.lhs
+--
+-- "Source" data constructors are the data constructors mentioned
+-- in Haskell source code
+--
+-- "Real" data constructors are the data constructors of the
+-- representation type, which may not be the same as the source
+-- type
+
+-- Example:
+-- data T = T !(Int,Int)
+--
+-- The source datacon has type (Int,Int) -> T
+-- The real datacon has type Int -> Int -> T
+-- GHC chooses a representation based on the strictness etc.
+
+
+-- Though type constructors and classes are in the same name space now,
+-- the NameSpace type is abstract, so we can easily separate them later
+tcName = TcClsName -- Type constructors
+clsName = TcClsName -- Classes
+tcClsName = TcClsName -- Not sure which!
+
+dataName = DataName
+srcDataName = DataName -- Haskell-source data constructors should be
+ -- in the Data name space
+
+tvName = TvName
+varName = VarName
+
+isTcClsName :: NameSpace -> Bool
+isTcClsName TcClsName = True
+isTcClsName _ = False
+
+isVarName :: NameSpace -> Bool -- Variables or type variables, but not constructors
+isVarName TvName = True
+isVarName VarName = True
+isVarName other = False
+
+pprNameSpace :: NameSpace -> SDoc
+pprNameSpace DataName = ptext SLIT("data constructor")
+pprNameSpace VarName = ptext SLIT("variable")
+pprNameSpace TvName = ptext SLIT("type variable")
+pprNameSpace TcClsName = ptext SLIT("type constructor or class")
+
+pprNonVarNameSpace :: NameSpace -> SDoc
+pprNonVarNameSpace VarName = empty
+pprNonVarNameSpace ns = pprNameSpace ns
+
+pprNameSpaceBrief DataName = char 'd'
+pprNameSpaceBrief VarName = char 'v'
+pprNameSpaceBrief TvName = ptext SLIT("tv")
+pprNameSpaceBrief TcClsName = ptext SLIT("tc")
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection[Name-pieces-datatypes]{The @OccName@ datatypes}
+%* *
+%************************************************************************
+
+\begin{code}
+data OccName = OccName
+ { occNameSpace :: !NameSpace
+ , occNameFS :: !FastString
+ }
+\end{code}
+
+
+\begin{code}
+instance Eq OccName where
+ (OccName sp1 s1) == (OccName sp2 s2) = s1 == s2 && sp1 == sp2
+
+instance Ord OccName where
+ compare (OccName sp1 s1) (OccName sp2 s2) = (s1 `compare` s2) `thenCmp`
+ (sp1 `compare` sp2)
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Printing}
+%* *
+%************************************************************************
+
+\begin{code}
+instance Outputable OccName where
+ ppr = pprOccName
+
+pprOccName :: OccName -> SDoc
+pprOccName (OccName sp occ)
+ = getPprStyle $ \ sty ->
+ if codeStyle sty
+ then ftext (zEncodeFS occ)
+ else ftext occ <> if debugStyle sty
+ then braces (pprNameSpaceBrief sp)
+ else empty
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Construction}
+%* *
+%************************************************************************
+
+\begin{code}
+mkOccName :: NameSpace -> String -> OccName
+mkOccName occ_sp str = OccName occ_sp (mkFastString str)
+
+mkOccNameFS :: NameSpace -> FastString -> OccName
+mkOccNameFS occ_sp fs = OccName occ_sp fs
+
+mkVarOcc :: String -> OccName
+mkVarOcc s = mkOccName varName s
+
+mkVarOccFS :: FastString -> OccName
+mkVarOccFS fs = mkOccNameFS varName fs
+
+mkTyVarOcc :: FastString -> OccName
+mkTyVarOcc fs = mkOccNameFS tvName fs
+\end{code}
+
+
+%************************************************************************
+%* *
+ Environments
+%* *
+%************************************************************************
+
+OccEnvs are used mainly for the envts in ModIfaces.
+
+They are efficient, because FastStrings have unique Int# keys. We assume
+this key is less than 2^24, so we can make a Unique using
+ mkUnique ns key :: Unique
+where 'ns' is a Char reprsenting the name space. This in turn makes it
+easy to build an OccEnv.
+
+\begin{code}
+instance Uniquable OccName where
+ getUnique (OccName ns fs)
+ = mkUnique char (I# (uniqueOfFS fs))
+ where -- See notes above about this getUnique function
+ char = case ns of
+ VarName -> 'i'
+ DataName -> 'd'
+ TvName -> 'v'
+ TcClsName -> 't'
+
+type OccEnv a = UniqFM a
+
+emptyOccEnv :: OccEnv a
+unitOccEnv :: OccName -> a -> OccEnv a
+extendOccEnv :: OccEnv a -> OccName -> a -> OccEnv a
+extendOccEnvList :: OccEnv a -> [(OccName, a)] -> OccEnv a
+lookupOccEnv :: OccEnv a -> OccName -> Maybe a
+mkOccEnv :: [(OccName,a)] -> OccEnv a
+elemOccEnv :: OccName -> OccEnv a -> Bool
+foldOccEnv :: (a -> b -> b) -> b -> OccEnv a -> b
+occEnvElts :: OccEnv a -> [a]
+extendOccEnv_C :: (a->a->a) -> OccEnv a -> OccName -> a -> OccEnv a
+plusOccEnv :: OccEnv a -> OccEnv a -> OccEnv a
+plusOccEnv_C :: (a->a->a) -> OccEnv a -> OccEnv a -> OccEnv a
+mapOccEnv :: (a->b) -> OccEnv a -> OccEnv b
+
+emptyOccEnv = emptyUFM
+unitOccEnv = unitUFM
+extendOccEnv = addToUFM
+extendOccEnvList = addListToUFM
+lookupOccEnv = lookupUFM
+mkOccEnv = listToUFM
+elemOccEnv = elemUFM
+foldOccEnv = foldUFM
+occEnvElts = eltsUFM
+plusOccEnv = plusUFM
+plusOccEnv_C = plusUFM_C
+extendOccEnv_C = addToUFM_C
+mapOccEnv = mapUFM
+
+type OccSet = UniqFM OccName
+
+emptyOccSet :: OccSet
+unitOccSet :: OccName -> OccSet
+mkOccSet :: [OccName] -> OccSet
+extendOccSet :: OccSet -> OccName -> OccSet
+extendOccSetList :: OccSet -> [OccName] -> OccSet
+unionOccSets :: OccSet -> OccSet -> OccSet
+unionManyOccSets :: [OccSet] -> OccSet
+minusOccSet :: OccSet -> OccSet -> OccSet
+elemOccSet :: OccName -> OccSet -> Bool
+occSetElts :: OccSet -> [OccName]
+foldOccSet :: (OccName -> b -> b) -> b -> OccSet -> b
+isEmptyOccSet :: OccSet -> Bool
+intersectOccSet :: OccSet -> OccSet -> OccSet
+intersectsOccSet :: OccSet -> OccSet -> Bool
+
+emptyOccSet = emptyUniqSet
+unitOccSet = unitUniqSet
+mkOccSet = mkUniqSet
+extendOccSet = addOneToUniqSet
+extendOccSetList = addListToUniqSet
+unionOccSets = unionUniqSets
+unionManyOccSets = unionManyUniqSets
+minusOccSet = minusUniqSet
+elemOccSet = elementOfUniqSet
+occSetElts = uniqSetToList
+foldOccSet = foldUniqSet
+isEmptyOccSet = isEmptyUniqSet
+intersectOccSet = intersectUniqSets
+intersectsOccSet s1 s2 = not (isEmptyOccSet (s1 `intersectOccSet` s2))
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Predicates and taking them apart}
+%* *
+%************************************************************************
+
+\begin{code}
+occNameString :: OccName -> String
+occNameString (OccName _ s) = unpackFS s
+
+setOccNameSpace :: NameSpace -> OccName -> OccName
+setOccNameSpace sp (OccName _ occ) = OccName sp occ
+
+isVarOcc, isTvOcc, isDataSymOcc, isSymOcc, isTcOcc :: OccName -> Bool
+
+isVarOcc (OccName VarName _) = True
+isVarOcc other = False
+
+isTvOcc (OccName TvName _) = True
+isTvOcc other = False
+
+isTcOcc (OccName TcClsName _) = True
+isTcOcc other = False
+
+isValOcc (OccName VarName _) = True
+isValOcc (OccName DataName _) = True
+isValOcc other = False
+
+-- Data constructor operator (starts with ':', or '[]')
+-- Pretty inefficient!
+isDataSymOcc (OccName DataName s) = isLexConSym s
+isDataSymOcc (OccName VarName s)
+ | isLexConSym s = pprPanic "isDataSymOcc: check me" (ppr s)
+ -- Jan06: I don't think this should happen
+isDataSymOcc other = False
+
+isDataOcc (OccName DataName _) = True
+isDataOcc (OccName VarName s)
+ | isLexCon s = pprPanic "isDataOcc: check me" (ppr s)
+ -- Jan06: I don't think this should happen
+isDataOcc other = False
+
+-- Any operator (data constructor or variable)
+-- Pretty inefficient!
+isSymOcc (OccName DataName s) = isLexConSym s
+isSymOcc (OccName TcClsName s) = isLexConSym s
+isSymOcc (OccName VarName s) = isLexSym s
+isSymOcc other = False
+
+parenSymOcc :: OccName -> SDoc -> SDoc
+-- Wrap parens around an operator
+parenSymOcc occ doc | isSymOcc occ = parens doc
+ | otherwise = doc
+\end{code}
+
+
+\begin{code}
+reportIfUnused :: OccName -> Bool
+ -- Haskell 98 encourages compilers to suppress warnings about
+ -- unused names in a pattern if they start with "_".
+reportIfUnused occ = case occNameString occ of
+ ('_' : _) -> False
+ _other -> True
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Making system names}
+%* *
+%************************************************************************
+
+Here's our convention for splitting up the interface file name space:
+
+ d... dictionary identifiers
+ (local variables, so no name-clash worries)
+
+ $f... dict-fun identifiers (from inst decls)
+ $dm... default methods
+ $p... superclass selectors
+ $w... workers
+ :T... compiler-generated tycons for dictionaries
+ :D... ...ditto data cons
+ $sf.. specialised version of f
+
+ in encoded form these appear as Zdfxxx etc
+
+ :... keywords (export:, letrec: etc.)
+--- I THINK THIS IS WRONG!
+
+This knowledge is encoded in the following functions.
+
+
+@mk_deriv@ generates an @OccName@ from the prefix and a string.
+NB: The string must already be encoded!
+
+\begin{code}
+mk_deriv :: NameSpace
+ -> String -- Distinguishes one sort of derived name from another
+ -> String
+ -> OccName
+
+mk_deriv occ_sp sys_prefix str = mkOccName occ_sp (sys_prefix ++ str)
+\end{code}
+
+\begin{code}
+mkDataConWrapperOcc, mkWorkerOcc, mkDefaultMethodOcc, mkDerivedTyConOcc,
+ mkClassTyConOcc, mkClassDataConOcc, mkDictOcc, mkIPOcc,
+ mkSpecOcc, mkForeignExportOcc, mkGenOcc1, mkGenOcc2,
+ mkDataTOcc, mkDataCOcc, mkDataConWorkerOcc
+ :: OccName -> OccName
+
+-- These derived variables have a prefix that no Haskell value could have
+mkDataConWrapperOcc = mk_simple_deriv varName "$W"
+mkWorkerOcc = mk_simple_deriv varName "$w"
+mkDefaultMethodOcc = mk_simple_deriv varName "$dm"
+mkDerivedTyConOcc = mk_simple_deriv tcName ":" -- The : prefix makes sure it classifies
+mkClassTyConOcc = mk_simple_deriv tcName ":T" -- as a tycon/datacon
+mkClassDataConOcc = mk_simple_deriv dataName ":D" -- We go straight to the "real" data con
+ -- for datacons from classes
+mkDictOcc = mk_simple_deriv varName "$d"
+mkIPOcc = mk_simple_deriv varName "$i"
+mkSpecOcc = mk_simple_deriv varName "$s"
+mkForeignExportOcc = mk_simple_deriv varName "$f"
+
+-- Generic derivable classes
+mkGenOcc1 = mk_simple_deriv varName "$gfrom"
+mkGenOcc2 = mk_simple_deriv varName "$gto"
+
+-- data T = MkT ... deriving( Data ) needs defintions for
+-- $tT :: Data.Generics.Basics.DataType
+-- $cMkT :: Data.Generics.Basics.Constr
+mkDataTOcc = mk_simple_deriv varName "$t"
+mkDataCOcc = mk_simple_deriv varName "$c"
+
+mk_simple_deriv sp px occ = mk_deriv sp px (occNameString occ)
+
+-- Data constructor workers are made by setting the name space
+-- of the data constructor OccName (which should be a DataName)
+-- to VarName
+mkDataConWorkerOcc datacon_occ = setOccNameSpace varName datacon_occ
+\end{code}
+
+\begin{code}
+mkSuperDictSelOcc :: Int -- Index of superclass, eg 3
+ -> OccName -- Class, eg "Ord"
+ -> OccName -- eg "$p3Ord"
+mkSuperDictSelOcc index cls_occ
+ = mk_deriv varName "$p" (show index ++ occNameString cls_occ)
+
+mkLocalOcc :: Unique -- Unique
+ -> OccName -- Local name (e.g. "sat")
+ -> OccName -- Nice unique version ("$L23sat")
+mkLocalOcc uniq occ
+ = mk_deriv varName ("$L" ++ show uniq) (occNameString occ)
+ -- The Unique might print with characters
+ -- that need encoding (e.g. 'z'!)
+\end{code}
+
+
+\begin{code}
+mkDFunOcc :: String -- Typically the class and type glommed together e.g. "OrdMaybe"
+ -- Only used in debug mode, for extra clarity
+ -> Bool -- True <=> hs-boot instance dfun
+ -> Int -- Unique index
+ -> OccName -- "$f3OrdMaybe"
+
+-- In hs-boot files we make dict funs like $fx7ClsTy, which get bound to the real
+-- thing when we compile the mother module. Reason: we don't know exactly
+-- what the mother module will call it.
+
+mkDFunOcc info_str is_boot index
+ = mk_deriv VarName prefix string
+ where
+ prefix | is_boot = "$fx"
+ | otherwise = "$f"
+ string | opt_PprStyle_Debug = show index ++ info_str
+ | otherwise = show index
+\end{code}
+
+We used to add a '$m' to indicate a method, but that gives rise to bad
+error messages from the type checker when we print the function name or pattern
+of an instance-decl binding. Why? Because the binding is zapped
+to use the method name in place of the selector name.
+(See TcClassDcl.tcMethodBind)
+
+The way it is now, -ddump-xx output may look confusing, but
+you can always say -dppr-debug to get the uniques.
+
+However, we *do* have to zap the first character to be lower case,
+because overloaded constructors (blarg) generate methods too.
+And convert to VarName space
+
+e.g. a call to constructor MkFoo where
+ data (Ord a) => Foo a = MkFoo a
+
+If this is necessary, we do it by prefixing '$m'. These
+guys never show up in error messages. What a hack.
+
+\begin{code}
+mkMethodOcc :: OccName -> OccName
+mkMethodOcc occ@(OccName VarName fs) = occ
+mkMethodOcc occ = mk_simple_deriv varName "$m" occ
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Tidying them up}
+%* *
+%************************************************************************
+
+Before we print chunks of code we like to rename it so that
+we don't have to print lots of silly uniques in it. But we mustn't
+accidentally introduce name clashes! So the idea is that we leave the
+OccName alone unless it accidentally clashes with one that is already
+in scope; if so, we tack on '1' at the end and try again, then '2', and
+so on till we find a unique one.
+
+There's a wrinkle for operators. Consider '>>='. We can't use '>>=1'
+because that isn't a single lexeme. So we encode it to 'lle' and *then*
+tack on the '1', if necessary.
+
+\begin{code}
+type TidyOccEnv = OccEnv Int -- The in-scope OccNames
+ -- Range gives a plausible starting point for new guesses
+
+emptyTidyOccEnv = emptyOccEnv
+
+initTidyOccEnv :: [OccName] -> TidyOccEnv -- Initialise with names to avoid!
+initTidyOccEnv = foldl (\env occ -> extendOccEnv env occ 1) emptyTidyOccEnv
+
+tidyOccName :: TidyOccEnv -> OccName -> (TidyOccEnv, OccName)
+
+tidyOccName in_scope occ@(OccName occ_sp fs)
+ = case lookupOccEnv in_scope occ of
+ Nothing -> -- Not already used: make it used
+ (extendOccEnv in_scope occ 1, occ)
+
+ Just n -> -- Already used: make a new guess,
+ -- change the guess base, and try again
+ tidyOccName (extendOccEnv in_scope occ (n+1))
+ (mkOccName occ_sp (unpackFS fs ++ show n))
+\end{code}
+
+%************************************************************************
+%* *
+ Stuff for dealing with tuples
+%* *
+%************************************************************************
+
+\begin{code}
+mkTupleOcc :: NameSpace -> Boxity -> Arity -> OccName
+mkTupleOcc ns bx ar = OccName ns (mkFastString str)
+ where
+ -- no need to cache these, the caching is done in the caller
+ -- (TysWiredIn.mk_tuple)
+ str = case bx of
+ Boxed -> '(' : commas ++ ")"
+ Unboxed -> '(' : '#' : commas ++ "#)"
+
+ commas = take (ar-1) (repeat ',')
+
+isTupleOcc_maybe :: OccName -> Maybe (NameSpace, Boxity, Arity)
+-- Tuples are special, because there are so many of them!
+isTupleOcc_maybe (OccName ns fs)
+ = case unpackFS fs of
+ '(':'#':',':rest -> Just (ns, Unboxed, 2 + count_commas rest)
+ '(':',':rest -> Just (ns, Boxed, 2 + count_commas rest)
+ _other -> Nothing
+ where
+ count_commas (',':rest) = 1 + count_commas rest
+ count_commas _ = 0
+\end{code}
+
+%************************************************************************
+%* *
+\subsection{Lexical categories}
+%* *
+%************************************************************************
+
+These functions test strings to see if they fit the lexical categories
+defined in the Haskell report.
+
+\begin{code}
+isLexCon, isLexVar, isLexId, isLexSym :: FastString -> Bool
+isLexConId, isLexConSym, isLexVarId, isLexVarSym :: FastString -> Bool
+
+isLexCon cs = isLexConId cs || isLexConSym cs
+isLexVar cs = isLexVarId cs || isLexVarSym cs
+
+isLexId cs = isLexConId cs || isLexVarId cs
+isLexSym cs = isLexConSym cs || isLexVarSym cs
+
+-------------
+
+isLexConId cs -- Prefix type or data constructors
+ | nullFS cs = False -- e.g. "Foo", "[]", "(,)"
+ | cs == FSLIT("[]") = True
+ | otherwise = startsConId (headFS cs)
+
+isLexVarId cs -- Ordinary prefix identifiers
+ | nullFS cs = False -- e.g. "x", "_x"
+ | otherwise = startsVarId (headFS cs)
+
+isLexConSym cs -- Infix type or data constructors
+ | nullFS cs = False -- e.g. ":-:", ":", "->"
+ | cs == FSLIT("->") = True
+ | otherwise = startsConSym (headFS cs)
+
+isLexVarSym cs -- Infix identifiers
+ | nullFS cs = False -- e.g. "+"
+ | otherwise = startsVarSym (headFS cs)
+
+-------------
+startsVarSym, startsVarId, startsConSym, startsConId :: Char -> Bool
+startsVarSym c = isSymbolASCII c || (ord c > 0x7f && isSymbol c) -- Infix Ids
+startsConSym c = c == ':' -- Infix data constructors
+startsVarId c = isLower c || c == '_' -- Ordinary Ids
+startsConId c = isUpper c || c == '(' -- Ordinary type constructors and data constructors
+
+isSymbolASCII c = c `elem` "!#$%&*+./<=>?@\\^|~-"
+\end{code}
+
+%************************************************************************
+%* *
+ Binary instance
+ Here rather than BinIface because OccName is abstract
+%* *
+%************************************************************************
+
+\begin{code}
+instance Binary NameSpace where
+ put_ bh VarName = do
+ putByte bh 0
+ put_ bh DataName = do
+ putByte bh 1
+ put_ bh TvName = do
+ putByte bh 2
+ put_ bh TcClsName = do
+ putByte bh 3
+ get bh = do
+ h <- getByte bh
+ case h of
+ 0 -> do return VarName
+ 1 -> do return DataName
+ 2 -> do return TvName
+ _ -> do return TcClsName
+
+instance Binary OccName where
+ put_ bh (OccName aa ab) = do
+ put_ bh aa
+ put_ bh ab
+ get bh = do
+ aa <- get bh
+ ab <- get bh
+ return (OccName aa ab)
+\end{code}
diff --git a/compiler/basicTypes/OccName.lhs-boot b/compiler/basicTypes/OccName.lhs-boot
new file mode 100644
index 0000000000..d9c7fcd141
--- /dev/null
+++ b/compiler/basicTypes/OccName.lhs-boot
@@ -0,0 +1,5 @@
+\begin{code}
+module OccName where
+
+data OccName
+\end{code}
diff --git a/compiler/basicTypes/RdrName.lhs b/compiler/basicTypes/RdrName.lhs
new file mode 100644
index 0000000000..030aa1f609
--- /dev/null
+++ b/compiler/basicTypes/RdrName.lhs
@@ -0,0 +1,540 @@
+%
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
+%
+
+\section[RdrName]{@RdrName@}
+
+\begin{code}
+module RdrName (
+ RdrName(..), -- Constructors exported only to BinIface
+
+ -- Construction
+ mkRdrUnqual, mkRdrQual,
+ mkUnqual, mkVarUnqual, mkQual, mkOrig,
+ nameRdrName, getRdrName,
+ mkDerivedRdrName,
+
+ -- Destruction
+ rdrNameModule, rdrNameOcc, setRdrNameSpace,
+ isRdrDataCon, isRdrTyVar, isRdrTc, isQual, isUnqual,
+ isOrig, isOrig_maybe, isExact, isExact_maybe, isSrcRdrName,
+
+ -- Printing; instance Outputable RdrName
+
+ -- LocalRdrEnv
+ LocalRdrEnv, emptyLocalRdrEnv, extendLocalRdrEnv,
+ lookupLocalRdrEnv, elemLocalRdrEnv,
+
+ -- GlobalRdrEnv
+ GlobalRdrEnv, emptyGlobalRdrEnv, mkGlobalRdrEnv, plusGlobalRdrEnv,
+ lookupGlobalRdrEnv, extendGlobalRdrEnv,
+ pprGlobalRdrEnv, globalRdrEnvElts,
+ lookupGRE_RdrName, lookupGRE_Name,
+
+ -- GlobalRdrElt, Provenance, ImportSpec
+ GlobalRdrElt(..), isLocalGRE, unQualOK,
+ Provenance(..), pprNameProvenance,
+ ImportSpec(..), ImpDeclSpec(..), ImpItemSpec(..),
+ importSpecLoc, importSpecModule
+ ) where
+
+#include "HsVersions.h"
+
+import OccName
+import Module ( Module, mkModuleFS )
+import Name ( Name, NamedThing(getName), nameModule, nameParent_maybe,
+ nameOccName, isExternalName, nameSrcLoc )
+import Maybes ( mapCatMaybes )
+import SrcLoc ( isGoodSrcLoc, SrcSpan )
+import FastString ( FastString )
+import Outputable
+import Util ( thenCmp )
+\end{code}
+
+%************************************************************************
+%* *
+\subsection{The main data type}
+%* *
+%************************************************************************
+
+\begin{code}
+data RdrName
+ = Unqual OccName
+ -- Used for ordinary, unqualified occurrences
+
+ | Qual Module OccName
+ -- A qualified name written by the user in
+ -- *source* code. The module isn't necessarily
+ -- the module where the thing is defined;
+ -- just the one from which it is imported
+
+ | Orig Module OccName
+ -- An original name; the module is the *defining* module.
+ -- This is used when GHC generates code that will be fed
+ -- into the renamer (e.g. from deriving clauses), but where
+ -- we want to say "Use Prelude.map dammit".
+
+ | Exact Name
+ -- We know exactly the Name. This is used
+ -- (a) when the parser parses built-in syntax like "[]"
+ -- and "(,)", but wants a RdrName from it
+ -- (b) when converting names to the RdrNames in IfaceTypes
+ -- Here an Exact RdrName always contains an External Name
+ -- (Internal Names are converted to simple Unquals)
+ -- (c) by Template Haskell, when TH has generated a unique name
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Simple functions}
+%* *
+%************************************************************************
+
+\begin{code}
+rdrNameModule :: RdrName -> Module
+rdrNameModule (Qual m _) = m
+rdrNameModule (Orig m _) = m
+rdrNameModule (Exact n) = nameModule n
+rdrNameModule (Unqual n) = pprPanic "rdrNameModule" (ppr n)
+
+rdrNameOcc :: RdrName -> OccName
+rdrNameOcc (Qual _ occ) = occ
+rdrNameOcc (Unqual occ) = occ
+rdrNameOcc (Orig _ occ) = occ
+rdrNameOcc (Exact name) = nameOccName name
+
+setRdrNameSpace :: RdrName -> NameSpace -> RdrName
+-- This rather gruesome function is used mainly by the parser
+-- When parsing data T a = T | T1 Int
+-- we parse the data constructors as *types* because of parser ambiguities,
+-- so then we need to change the *type constr* to a *data constr*
+--
+-- The original-name case *can* occur when parsing
+-- data [] a = [] | a : [a]
+-- For the orig-name case we return an unqualified name.
+setRdrNameSpace (Unqual occ) ns = Unqual (setOccNameSpace ns occ)
+setRdrNameSpace (Qual m occ) ns = Qual m (setOccNameSpace ns occ)
+setRdrNameSpace (Orig m occ) ns = Orig m (setOccNameSpace ns occ)
+setRdrNameSpace (Exact n) ns = Orig (nameModule n)
+ (setOccNameSpace ns (nameOccName n))
+\end{code}
+
+\begin{code}
+ -- These two are the basic constructors
+mkRdrUnqual :: OccName -> RdrName
+mkRdrUnqual occ = Unqual occ
+
+mkRdrQual :: Module -> OccName -> RdrName
+mkRdrQual mod occ = Qual mod occ
+
+mkOrig :: Module -> OccName -> RdrName
+mkOrig mod occ = Orig mod occ
+
+---------------
+mkDerivedRdrName :: Name -> (OccName -> OccName) -> (RdrName)
+mkDerivedRdrName parent mk_occ
+ = mkOrig (nameModule parent) (mk_occ (nameOccName parent))
+
+---------------
+ -- These two are used when parsing source files
+ -- They do encode the module and occurrence names
+mkUnqual :: NameSpace -> FastString -> RdrName
+mkUnqual sp n = Unqual (mkOccNameFS sp n)
+
+mkVarUnqual :: FastString -> RdrName
+mkVarUnqual n = Unqual (mkVarOccFS n)
+
+mkQual :: NameSpace -> (FastString, FastString) -> RdrName
+mkQual sp (m, n) = Qual (mkModuleFS m) (mkOccNameFS sp n)
+
+getRdrName :: NamedThing thing => thing -> RdrName
+getRdrName name = nameRdrName (getName name)
+
+nameRdrName :: Name -> RdrName
+nameRdrName name = Exact name
+-- Keep the Name even for Internal names, so that the
+-- unique is still there for debug printing, particularly
+-- of Types (which are converted to IfaceTypes before printing)
+
+nukeExact :: Name -> RdrName
+nukeExact n
+ | isExternalName n = Orig (nameModule n) (nameOccName n)
+ | otherwise = Unqual (nameOccName n)
+\end{code}
+
+\begin{code}
+isRdrDataCon rn = isDataOcc (rdrNameOcc rn)
+isRdrTyVar rn = isTvOcc (rdrNameOcc rn)
+isRdrTc rn = isTcOcc (rdrNameOcc rn)
+
+isSrcRdrName (Unqual _) = True
+isSrcRdrName (Qual _ _) = True
+isSrcRdrName _ = False
+
+isUnqual (Unqual _) = True
+isUnqual other = False
+
+isQual (Qual _ _) = True
+isQual _ = False
+
+isOrig (Orig _ _) = True
+isOrig _ = False
+
+isOrig_maybe (Orig m n) = Just (m,n)
+isOrig_maybe _ = Nothing
+
+isExact (Exact _) = True
+isExact other = False
+
+isExact_maybe (Exact n) = Just n
+isExact_maybe other = Nothing
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Instances}
+%* *
+%************************************************************************
+
+\begin{code}
+instance Outputable RdrName where
+ ppr (Exact name) = ppr name
+ ppr (Unqual occ) = ppr occ <+> ppr_name_space occ
+ ppr (Qual mod occ) = ppr mod <> dot <> ppr occ <+> ppr_name_space occ
+ ppr (Orig mod occ) = ppr mod <> dot <> ppr occ <+> ppr_name_space occ
+
+ppr_name_space occ = ifPprDebug (parens (pprNonVarNameSpace (occNameSpace occ)))
+
+instance OutputableBndr RdrName where
+ pprBndr _ n
+ | isTvOcc (rdrNameOcc n) = char '@' <+> ppr n
+ | otherwise = ppr n
+
+instance Eq RdrName where
+ (Exact n1) == (Exact n2) = n1==n2
+ -- Convert exact to orig
+ (Exact n1) == r2@(Orig _ _) = nukeExact n1 == r2
+ r1@(Orig _ _) == (Exact n2) = r1 == nukeExact n2
+
+ (Orig m1 o1) == (Orig m2 o2) = m1==m2 && o1==o2
+ (Qual m1 o1) == (Qual m2 o2) = m1==m2 && o1==o2
+ (Unqual o1) == (Unqual o2) = o1==o2
+ r1 == r2 = False
+
+instance Ord RdrName where
+ a <= b = case (a `compare` b) of { LT -> True; EQ -> True; GT -> False }
+ a < b = case (a `compare` b) of { LT -> True; EQ -> False; GT -> False }
+ a >= b = case (a `compare` b) of { LT -> False; EQ -> True; GT -> True }
+ a > b = case (a `compare` b) of { LT -> False; EQ -> False; GT -> True }
+
+ -- Exact < Unqual < Qual < Orig
+ -- [Note: Apr 2004] We used to use nukeExact to convert Exact to Orig
+ -- before comparing so that Prelude.map == the exact Prelude.map, but
+ -- that meant that we reported duplicates when renaming bindings
+ -- generated by Template Haskell; e.g
+ -- do { n1 <- newName "foo"; n2 <- newName "foo";
+ -- <decl involving n1,n2> }
+ -- I think we can do without this conversion
+ compare (Exact n1) (Exact n2) = n1 `compare` n2
+ compare (Exact n1) n2 = LT
+
+ compare (Unqual _) (Exact _) = GT
+ compare (Unqual o1) (Unqual o2) = o1 `compare` o2
+ compare (Unqual _) _ = LT
+
+ compare (Qual _ _) (Exact _) = GT
+ compare (Qual _ _) (Unqual _) = GT
+ compare (Qual m1 o1) (Qual m2 o2) = (o1 `compare` o2) `thenCmp` (m1 `compare` m2)
+ compare (Qual _ _) (Orig _ _) = LT
+
+ compare (Orig m1 o1) (Orig m2 o2) = (o1 `compare` o2) `thenCmp` (m1 `compare` m2)
+ compare (Orig _ _) _ = GT
+\end{code}
+
+
+
+%************************************************************************
+%* *
+ LocalRdrEnv
+%* *
+%************************************************************************
+
+A LocalRdrEnv is used for local bindings (let, where, lambda, case)
+It is keyed by OccName, because we never use it for qualified names.
+
+\begin{code}
+type LocalRdrEnv = OccEnv Name
+
+emptyLocalRdrEnv = emptyOccEnv
+
+extendLocalRdrEnv :: LocalRdrEnv -> [Name] -> LocalRdrEnv
+extendLocalRdrEnv env names
+ = extendOccEnvList env [(nameOccName n, n) | n <- names]
+
+lookupLocalRdrEnv :: LocalRdrEnv -> RdrName -> Maybe Name
+lookupLocalRdrEnv env (Exact name) = Just name
+lookupLocalRdrEnv env (Unqual occ) = lookupOccEnv env occ
+lookupLocalRdrEnv env other = Nothing
+
+elemLocalRdrEnv :: RdrName -> LocalRdrEnv -> Bool
+elemLocalRdrEnv rdr_name env
+ | isUnqual rdr_name = rdrNameOcc rdr_name `elemOccEnv` env
+ | otherwise = False
+\end{code}
+
+
+%************************************************************************
+%* *
+ GlobalRdrEnv
+%* *
+%************************************************************************
+
+\begin{code}
+type GlobalRdrEnv = OccEnv [GlobalRdrElt]
+ -- Keyed by OccName; when looking up a qualified name
+ -- we look up the OccName part, and then check the Provenance
+ -- to see if the appropriate qualification is valid. This
+ -- saves routinely doubling the size of the env by adding both
+ -- qualified and unqualified names to the domain.
+ --
+ -- The list in the range is reqd because there may be name clashes
+ -- These only get reported on lookup, not on construction
+
+ -- INVARIANT: All the members of the list have distinct
+ -- gre_name fields; that is, no duplicate Names
+
+emptyGlobalRdrEnv = emptyOccEnv
+
+globalRdrEnvElts :: GlobalRdrEnv -> [GlobalRdrElt]
+globalRdrEnvElts env = foldOccEnv (++) [] env
+
+data GlobalRdrElt
+ = GRE { gre_name :: Name,
+ gre_prov :: Provenance -- Why it's in scope
+ }
+
+instance Outputable GlobalRdrElt where
+ ppr gre = ppr name <+> pp_parent (nameParent_maybe name)
+ <+> parens (pprNameProvenance gre)
+ where
+ name = gre_name gre
+ pp_parent (Just p) = brackets (text "parent:" <+> ppr p)
+ pp_parent Nothing = empty
+
+pprGlobalRdrEnv :: GlobalRdrEnv -> SDoc
+pprGlobalRdrEnv env
+ = vcat (map pp (occEnvElts env))
+ where
+ pp gres = ppr (nameOccName (gre_name (head gres))) <> colon <+>
+ vcat [ ppr (gre_name gre) <+> pprNameProvenance gre
+ | gre <- gres]
+\end{code}
+
+\begin{code}
+lookupGlobalRdrEnv :: GlobalRdrEnv -> OccName -> [GlobalRdrElt]
+lookupGlobalRdrEnv env rdr_name = case lookupOccEnv env rdr_name of
+ Nothing -> []
+ Just gres -> gres
+
+extendGlobalRdrEnv :: GlobalRdrEnv -> GlobalRdrElt -> GlobalRdrEnv
+extendGlobalRdrEnv env gre = extendOccEnv_C add env occ [gre]
+ where
+ occ = nameOccName (gre_name gre)
+ add gres _ = gre:gres
+
+lookupGRE_RdrName :: RdrName -> GlobalRdrEnv -> [GlobalRdrElt]
+lookupGRE_RdrName rdr_name env
+ = case lookupOccEnv env (rdrNameOcc rdr_name) of
+ Nothing -> []
+ Just gres -> pickGREs rdr_name gres
+
+lookupGRE_Name :: GlobalRdrEnv -> Name -> [GlobalRdrElt]
+lookupGRE_Name env name
+ = [ gre | gre <- lookupGlobalRdrEnv env (nameOccName name),
+ gre_name gre == name ]
+
+
+pickGREs :: RdrName -> [GlobalRdrElt] -> [GlobalRdrElt]
+-- Take a list of GREs which have the right OccName
+-- Pick those GREs that are suitable for this RdrName
+-- And for those, keep only only the Provenances that are suitable
+--
+-- Consider
+-- module A ( f ) where
+-- import qualified Foo( f )
+-- import Baz( f )
+-- f = undefined
+-- Let's suppose that Foo.f and Baz.f are the same entity really.
+-- The export of f is ambiguous because it's in scope from the local def
+-- and the import. The lookup of (Unqual f) should return a GRE for
+-- the locally-defined f, and a GRE for the imported f, with a *single*
+-- provenance, namely the one for Baz(f).
+pickGREs rdr_name gres
+ = mapCatMaybes pick gres
+ where
+ is_unqual = isUnqual rdr_name
+ mod = rdrNameModule rdr_name
+
+ pick :: GlobalRdrElt -> Maybe GlobalRdrElt
+ pick gre@(GRE {gre_prov = LocalDef, gre_name = n}) -- Local def
+ | is_unqual || nameModule n == mod = Just gre
+ | otherwise = Nothing
+ pick gre@(GRE {gre_prov = Imported [is]}) -- Single import (efficiency)
+ | is_unqual = if not (is_qual (is_decl is)) then Just gre
+ else Nothing
+ | otherwise = if mod == is_as (is_decl is) then Just gre
+ else Nothing
+ pick gre@(GRE {gre_prov = Imported is}) -- Multiple import
+ | null filtered_is = Nothing
+ | otherwise = Just (gre {gre_prov = Imported filtered_is})
+ where
+ filtered_is | is_unqual = filter (not . is_qual . is_decl) is
+ | otherwise = filter ((== mod) . is_as . is_decl) is
+
+isLocalGRE :: GlobalRdrElt -> Bool
+isLocalGRE (GRE {gre_prov = LocalDef}) = True
+isLocalGRE other = False
+
+unQualOK :: GlobalRdrElt -> Bool
+-- An unqualifed version of this thing is in scope
+unQualOK (GRE {gre_prov = LocalDef}) = True
+unQualOK (GRE {gre_prov = Imported is}) = not (all (is_qual . is_decl) is)
+
+plusGlobalRdrEnv :: GlobalRdrEnv -> GlobalRdrEnv -> GlobalRdrEnv
+plusGlobalRdrEnv env1 env2 = plusOccEnv_C (foldr insertGRE) env1 env2
+
+mkGlobalRdrEnv :: [GlobalRdrElt] -> GlobalRdrEnv
+mkGlobalRdrEnv gres
+ = foldr add emptyGlobalRdrEnv gres
+ where
+ add gre env = extendOccEnv_C (foldr insertGRE) env
+ (nameOccName (gre_name gre))
+ [gre]
+
+insertGRE :: GlobalRdrElt -> [GlobalRdrElt] -> [GlobalRdrElt]
+insertGRE new_g [] = [new_g]
+insertGRE new_g (old_g : old_gs)
+ | gre_name new_g == gre_name old_g
+ = new_g `plusGRE` old_g : old_gs
+ | otherwise
+ = old_g : insertGRE new_g old_gs
+
+plusGRE :: GlobalRdrElt -> GlobalRdrElt -> GlobalRdrElt
+-- Used when the gre_name fields match
+plusGRE g1 g2
+ = GRE { gre_name = gre_name g1,
+ gre_prov = gre_prov g1 `plusProv` gre_prov g2 }
+\end{code}
+
+
+%************************************************************************
+%* *
+ Provenance
+%* *
+%************************************************************************
+
+The "provenance" of something says how it came to be in scope.
+It's quite elaborate so that we can give accurate unused-name warnings.
+
+\begin{code}
+data Provenance
+ = LocalDef -- Defined locally
+ | Imported -- Imported
+ [ImportSpec] -- INVARIANT: non-empty
+
+data ImportSpec = ImpSpec { is_decl :: ImpDeclSpec,
+ is_item :: ImpItemSpec }
+ deriving( Eq, Ord )
+
+data ImpDeclSpec -- Describes a particular import declaration
+ -- Shared among all the Provenaces for that decl
+ = ImpDeclSpec {
+ is_mod :: Module, -- 'import Muggle'
+ -- Note the Muggle may well not be
+ -- the defining module for this thing!
+ is_as :: Module, -- 'as M' (or 'Muggle' if there is no 'as' clause)
+ is_qual :: Bool, -- True <=> qualified (only)
+ is_dloc :: SrcSpan -- Location of import declaration
+ }
+
+data ImpItemSpec -- Describes import info a particular Name
+ = ImpAll -- The import had no import list,
+ -- or had a hiding list
+
+ | ImpSome { -- The import had an import list
+ is_explicit :: Bool,
+ is_iloc :: SrcSpan -- Location of the import item
+ }
+ -- The is_explicit field is True iff the thing was named
+ -- *explicitly* in the import specs rather
+ -- than being imported as part of a "..." group
+ -- e.g. import C( T(..) )
+ -- Here the constructors of T are not named explicitly;
+ -- only T is named explicitly.
+
+importSpecLoc :: ImportSpec -> SrcSpan
+importSpecLoc (ImpSpec decl ImpAll) = is_dloc decl
+importSpecLoc (ImpSpec _ item) = is_iloc item
+
+importSpecModule :: ImportSpec -> Module
+importSpecModule is = is_mod (is_decl is)
+
+-- Note [Comparing provenance]
+-- Comparison of provenance is just used for grouping
+-- error messages (in RnEnv.warnUnusedBinds)
+instance Eq Provenance where
+ p1 == p2 = case p1 `compare` p2 of EQ -> True; _ -> False
+
+instance Eq ImpDeclSpec where
+ p1 == p2 = case p1 `compare` p2 of EQ -> True; _ -> False
+
+instance Eq ImpItemSpec where
+ p1 == p2 = case p1 `compare` p2 of EQ -> True; _ -> False
+
+instance Ord Provenance where
+ compare LocalDef LocalDef = EQ
+ compare LocalDef (Imported _) = LT
+ compare (Imported _ ) LocalDef = GT
+ compare (Imported is1) (Imported is2) = compare (head is1)
+ {- See Note [Comparing provenance] -} (head is2)
+
+instance Ord ImpDeclSpec where
+ compare is1 is2 = (is_mod is1 `compare` is_mod is2) `thenCmp`
+ (is_dloc is1 `compare` is_dloc is2)
+
+instance Ord ImpItemSpec where
+ compare is1 is2 = is_iloc is1 `compare` is_iloc is2
+\end{code}
+
+\begin{code}
+plusProv :: Provenance -> Provenance -> Provenance
+-- Choose LocalDef over Imported
+-- There is an obscure bug lurking here; in the presence
+-- of recursive modules, something can be imported *and* locally
+-- defined, and one might refer to it with a qualified name from
+-- the import -- but I'm going to ignore that because it makes
+-- the isLocalGRE predicate so much nicer this way
+plusProv LocalDef LocalDef = panic "plusProv"
+plusProv LocalDef p2 = LocalDef
+plusProv p1 LocalDef = LocalDef
+plusProv (Imported is1) (Imported is2) = Imported (is1++is2)
+
+pprNameProvenance :: GlobalRdrElt -> SDoc
+-- Print out the place where the name was imported
+pprNameProvenance (GRE {gre_name = name, gre_prov = LocalDef})
+ = ptext SLIT("defined at") <+> ppr (nameSrcLoc name)
+pprNameProvenance (GRE {gre_name = name, gre_prov = Imported (why:whys)})
+ = sep [ppr why, nest 2 (ppr_defn (nameSrcLoc name))]
+
+-- If we know the exact definition point (which we may do with GHCi)
+-- then show that too. But not if it's just "imported from X".
+ppr_defn loc | isGoodSrcLoc loc = parens (ptext SLIT("defined at") <+> ppr loc)
+ | otherwise = empty
+
+instance Outputable ImportSpec where
+ ppr imp_spec@(ImpSpec imp_decl _)
+ = ptext SLIT("imported from") <+> ppr (is_mod imp_decl)
+ <+> ptext SLIT("at") <+> ppr (importSpecLoc imp_spec)
+\end{code}
diff --git a/compiler/basicTypes/SrcLoc.lhs b/compiler/basicTypes/SrcLoc.lhs
new file mode 100644
index 0000000000..51d4318b0b
--- /dev/null
+++ b/compiler/basicTypes/SrcLoc.lhs
@@ -0,0 +1,386 @@
+%
+% (c) The University of Glasgow, 1992-2003
+%
+%************************************************************************
+%* *
+\section[SrcLoc]{The @SrcLoc@ type}
+%* *
+%************************************************************************
+
+\begin{code}
+module SrcLoc (
+ SrcLoc, -- Abstract
+
+ mkSrcLoc, isGoodSrcLoc, mkGeneralSrcLoc,
+ noSrcLoc, -- "I'm sorry, I haven't a clue"
+ advanceSrcLoc,
+
+ importedSrcLoc, -- Unknown place in an interface
+ wiredInSrcLoc, -- Something wired into the compiler
+ generatedSrcLoc, -- Code generated within the compiler
+ interactiveSrcLoc, -- Code from an interactive session
+
+ srcLocFile, -- return the file name part
+ srcLocLine, -- return the line part
+ srcLocCol, -- return the column part
+ pprDefnLoc,
+
+ SrcSpan, -- Abstract
+ noSrcSpan,
+ mkGeneralSrcSpan,
+ isGoodSrcSpan,
+ mkSrcSpan, srcLocSpan,
+ combineSrcSpans,
+ srcSpanFile,
+ srcSpanStartLine, srcSpanEndLine,
+ srcSpanStartCol, srcSpanEndCol,
+ srcSpanStart, srcSpanEnd,
+
+ Located(..), getLoc, unLoc, noLoc, eqLocated, cmpLocated, combineLocs, addCLoc
+ ) where
+
+#include "HsVersions.h"
+
+import Util ( thenCmp )
+import Outputable
+import FastString
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[SrcLoc-SrcLocations]{Source-location information}
+%* *
+%************************************************************************
+
+We keep information about the {\em definition} point for each entity;
+this is the obvious stuff:
+\begin{code}
+data SrcLoc
+ = SrcLoc FastString -- A precise location (file name)
+ !Int -- line number, begins at 1
+ !Int -- column number, begins at 0
+ -- Don't ask me why lines start at 1 and columns start at
+ -- zero. That's just the way it is, so there. --SDM
+
+ | ImportedLoc String -- Module name
+
+ | UnhelpfulLoc FastString -- Just a general indication
+\end{code}
+
+Note that an entity might be imported via more than one route, and
+there could be more than one ``definition point'' --- in two or more
+\tr{.hi} files. We deemed it probably-unworthwhile to cater for this
+rare case.
+
+%************************************************************************
+%* *
+\subsection[SrcLoc-access-fns]{Access functions for names}
+%* *
+%************************************************************************
+
+Things to make 'em:
+\begin{code}
+mkSrcLoc x line col = SrcLoc x line col
+noSrcLoc = UnhelpfulLoc FSLIT("<no location info>")
+generatedSrcLoc = UnhelpfulLoc FSLIT("<compiler-generated code>")
+wiredInSrcLoc = UnhelpfulLoc FSLIT("<wired into compiler>")
+interactiveSrcLoc = UnhelpfulLoc FSLIT("<interactive session>")
+
+mkGeneralSrcLoc :: FastString -> SrcLoc
+mkGeneralSrcLoc = UnhelpfulLoc
+
+importedSrcLoc :: String -> SrcLoc
+importedSrcLoc mod_name = ImportedLoc mod_name
+
+isGoodSrcLoc (SrcLoc _ _ _) = True
+isGoodSrcLoc other = False
+
+srcLocFile :: SrcLoc -> FastString
+srcLocFile (SrcLoc fname _ _) = fname
+srcLocFile other = FSLIT("<unknown file")
+
+srcLocLine :: SrcLoc -> Int
+srcLocLine (SrcLoc _ l c) = l
+srcLocLine other = panic "srcLocLine: unknown line"
+
+srcLocCol :: SrcLoc -> Int
+srcLocCol (SrcLoc _ l c) = c
+srcLocCol other = panic "srcLocCol: unknown col"
+
+advanceSrcLoc :: SrcLoc -> Char -> SrcLoc
+advanceSrcLoc (SrcLoc f l c) '\n' = SrcLoc f (l + 1) 0
+advanceSrcLoc (SrcLoc f l c) _ = SrcLoc f l (c + 1)
+advanceSrcLoc loc _ = loc -- Better than nothing
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[SrcLoc-instances]{Instance declarations for various names}
+%* *
+%************************************************************************
+
+\begin{code}
+-- SrcLoc is an instance of Ord so that we can sort error messages easily
+instance Eq SrcLoc where
+ loc1 == loc2 = case loc1 `cmpSrcLoc` loc2 of
+ EQ -> True
+ other -> False
+
+instance Ord SrcLoc where
+ compare = cmpSrcLoc
+
+cmpSrcLoc (UnhelpfulLoc s1) (UnhelpfulLoc s2) = s1 `compare` s2
+cmpSrcLoc (UnhelpfulLoc _) other = LT
+
+cmpSrcLoc (ImportedLoc _) (UnhelpfulLoc _) = GT
+cmpSrcLoc (ImportedLoc m1) (ImportedLoc m2) = m1 `compare` m2
+cmpSrcLoc (ImportedLoc _) other = LT
+
+cmpSrcLoc (SrcLoc s1 l1 c1) (SrcLoc s2 l2 c2)
+ = (s1 `compare` s2) `thenCmp` (l1 `cmpline` l2) `thenCmp` (c1 `cmpline` c2)
+ where
+ l1 `cmpline` l2 | l1 < l2 = LT
+ | l1 == l2 = EQ
+ | otherwise = GT
+cmpSrcLoc (SrcLoc _ _ _) other = GT
+
+instance Outputable SrcLoc where
+ ppr (SrcLoc src_path src_line src_col)
+ = getPprStyle $ \ sty ->
+ if userStyle sty || debugStyle sty then
+ hcat [ ftext src_path, char ':',
+ int src_line,
+ char ':', int src_col
+ ]
+ else
+ hcat [text "{-# LINE ", int src_line, space,
+ char '\"', ftext src_path, text " #-}"]
+
+ ppr (ImportedLoc mod) = ptext SLIT("Imported from") <+> text mod
+ ppr (UnhelpfulLoc s) = ftext s
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[SrcSpan]{Source Spans}
+%* *
+%************************************************************************
+
+\begin{code}
+{- |
+A SrcSpan delimits a portion of a text file. It could be represented
+by a pair of (line,column) coordinates, but in fact we optimise
+slightly by using more compact representations for single-line and
+zero-length spans, both of which are quite common.
+
+The end position is defined to be the column *after* the end of the
+span. That is, a span of (1,1)-(1,2) is one character long, and a
+span of (1,1)-(1,1) is zero characters long.
+-}
+data SrcSpan
+ = SrcSpanOneLine -- a common case: a single line
+ { srcSpanFile :: FastString,
+ srcSpanLine :: !Int,
+ srcSpanSCol :: !Int,
+ srcSpanECol :: !Int
+ }
+
+ | SrcSpanMultiLine
+ { srcSpanFile :: FastString,
+ srcSpanSLine :: !Int,
+ srcSpanSCol :: !Int,
+ srcSpanELine :: !Int,
+ srcSpanECol :: !Int
+ }
+
+ | SrcSpanPoint
+ { srcSpanFile :: FastString,
+ srcSpanLine :: !Int,
+ srcSpanCol :: !Int
+ }
+
+ | ImportedSpan String -- Module name
+
+ | UnhelpfulSpan FastString -- Just a general indication
+ -- also used to indicate an empty span
+
+ deriving Eq
+
+-- We want to order SrcSpans first by the start point, then by the end point.
+instance Ord SrcSpan where
+ a `compare` b =
+ (srcSpanStart a `compare` srcSpanStart b) `thenCmp`
+ (srcSpanEnd a `compare` srcSpanEnd b)
+
+noSrcSpan = UnhelpfulSpan FSLIT("<no location info>")
+
+mkGeneralSrcSpan :: FastString -> SrcSpan
+mkGeneralSrcSpan = UnhelpfulSpan
+
+isGoodSrcSpan SrcSpanOneLine{} = True
+isGoodSrcSpan SrcSpanMultiLine{} = True
+isGoodSrcSpan SrcSpanPoint{} = True
+isGoodSrcSpan _ = False
+
+srcSpanStartLine SrcSpanOneLine{ srcSpanLine=l } = l
+srcSpanStartLine SrcSpanMultiLine{ srcSpanSLine=l } = l
+srcSpanStartLine SrcSpanPoint{ srcSpanLine=l } = l
+srcSpanStartLine _ = panic "SrcLoc.srcSpanStartLine"
+
+srcSpanEndLine SrcSpanOneLine{ srcSpanLine=l } = l
+srcSpanEndLine SrcSpanMultiLine{ srcSpanELine=l } = l
+srcSpanEndLine SrcSpanPoint{ srcSpanLine=l } = l
+srcSpanEndLine _ = panic "SrcLoc.srcSpanEndLine"
+
+srcSpanStartCol SrcSpanOneLine{ srcSpanSCol=l } = l
+srcSpanStartCol SrcSpanMultiLine{ srcSpanSCol=l } = l
+srcSpanStartCol SrcSpanPoint{ srcSpanCol=l } = l
+srcSpanStartCol _ = panic "SrcLoc.srcSpanStartCol"
+
+srcSpanEndCol SrcSpanOneLine{ srcSpanECol=c } = c
+srcSpanEndCol SrcSpanMultiLine{ srcSpanECol=c } = c
+srcSpanEndCol SrcSpanPoint{ srcSpanCol=c } = c
+srcSpanEndCol _ = panic "SrcLoc.srcSpanEndCol"
+
+srcSpanStart (ImportedSpan str) = ImportedLoc str
+srcSpanStart (UnhelpfulSpan str) = UnhelpfulLoc str
+srcSpanStart s =
+ mkSrcLoc (srcSpanFile s)
+ (srcSpanStartLine s)
+ (srcSpanStartCol s)
+
+srcSpanEnd (ImportedSpan str) = ImportedLoc str
+srcSpanEnd (UnhelpfulSpan str) = UnhelpfulLoc str
+srcSpanEnd s =
+ mkSrcLoc (srcSpanFile s)
+ (srcSpanEndLine s)
+ (srcSpanEndCol s)
+
+srcLocSpan :: SrcLoc -> SrcSpan
+srcLocSpan (ImportedLoc str) = ImportedSpan str
+srcLocSpan (UnhelpfulLoc str) = UnhelpfulSpan str
+srcLocSpan (SrcLoc file line col) = SrcSpanPoint file line col
+
+mkSrcSpan :: SrcLoc -> SrcLoc -> SrcSpan
+mkSrcSpan (ImportedLoc str) _ = ImportedSpan str
+mkSrcSpan (UnhelpfulLoc str) _ = UnhelpfulSpan str
+mkSrcSpan _ (ImportedLoc str) = ImportedSpan str
+mkSrcSpan _ (UnhelpfulLoc str) = UnhelpfulSpan str
+mkSrcSpan loc1 loc2
+ | line1 == line2 = if col1 == col2
+ then SrcSpanPoint file line1 col1
+ else SrcSpanOneLine file line1 col1 col2
+ | otherwise = SrcSpanMultiLine file line1 col1 line2 col2
+ where
+ line1 = srcLocLine loc1
+ line2 = srcLocLine loc2
+ col1 = srcLocCol loc1
+ col2 = srcLocCol loc2
+ file = srcLocFile loc1
+
+combineSrcSpans :: SrcSpan -> SrcSpan -> SrcSpan
+-- Assumes the 'file' part is the same in both
+combineSrcSpans (ImportedSpan str) _ = ImportedSpan str
+combineSrcSpans (UnhelpfulSpan str) r = r -- this seems more useful
+combineSrcSpans _ (ImportedSpan str) = ImportedSpan str
+combineSrcSpans l (UnhelpfulSpan str) = l
+combineSrcSpans start end
+ = case line1 `compare` line2 of
+ EQ -> case col1 `compare` col2 of
+ EQ -> SrcSpanPoint file line1 col1
+ LT -> SrcSpanOneLine file line1 col1 col2
+ GT -> SrcSpanOneLine file line1 col2 col1
+ LT -> SrcSpanMultiLine file line1 col1 line2 col2
+ GT -> SrcSpanMultiLine file line2 col2 line1 col1
+ where
+ line1 = srcSpanStartLine start
+ col1 = srcSpanStartCol start
+ line2 = srcSpanEndLine end
+ col2 = srcSpanEndCol end
+ file = srcSpanFile start
+
+pprDefnLoc :: SrcLoc -> SDoc
+-- "defined at ..." or "imported from ..."
+pprDefnLoc loc
+ | isGoodSrcLoc loc = ptext SLIT("Defined at") <+> ppr loc
+ | otherwise = ppr loc
+
+instance Outputable SrcSpan where
+ ppr span
+ = getPprStyle $ \ sty ->
+ if userStyle sty || debugStyle sty then
+ pprUserSpan span
+ else
+ hcat [text "{-# LINE ", int (srcSpanStartLine span), space,
+ char '\"', ftext (srcSpanFile span), text " #-}"]
+
+
+pprUserSpan (SrcSpanOneLine src_path line start_col end_col)
+ = hcat [ ftext src_path, char ':',
+ int line,
+ char ':', int start_col
+ ]
+ <> if end_col - start_col <= 1
+ then empty
+ -- for single-character or point spans, we just output the starting
+ -- column number
+ else char '-' <> int (end_col-1)
+
+pprUserSpan (SrcSpanMultiLine src_path sline scol eline ecol)
+ = hcat [ ftext src_path, char ':',
+ parens (int sline <> char ',' <> int scol),
+ char '-',
+ parens (int eline <> char ',' <>
+ if ecol == 0 then int ecol else int (ecol-1))
+ ]
+
+pprUserSpan (SrcSpanPoint src_path line col)
+ = hcat [ ftext src_path, char ':',
+ int line,
+ char ':', int col
+ ]
+
+pprUserSpan (ImportedSpan mod) = ptext SLIT("Imported from") <+> quotes (text mod)
+pprUserSpan (UnhelpfulSpan s) = ftext s
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[Located]{Attaching SrcSpans to things}
+%* *
+%************************************************************************
+
+\begin{code}
+-- | We attach SrcSpans to lots of things, so let's have a datatype for it.
+data Located e = L SrcSpan e
+
+unLoc :: Located e -> e
+unLoc (L _ e) = e
+
+getLoc :: Located e -> SrcSpan
+getLoc (L l _) = l
+
+noLoc :: e -> Located e
+noLoc e = L noSrcSpan e
+
+combineLocs :: Located a -> Located b -> SrcSpan
+combineLocs a b = combineSrcSpans (getLoc a) (getLoc b)
+
+addCLoc :: Located a -> Located b -> c -> Located c
+addCLoc a b c = L (combineSrcSpans (getLoc a) (getLoc b)) c
+
+-- not clear whether to add a general Eq instance, but this is useful sometimes:
+eqLocated :: Eq a => Located a -> Located a -> Bool
+eqLocated a b = unLoc a == unLoc b
+
+-- not clear whether to add a general Eq instance, but this is useful sometimes:
+cmpLocated :: Ord a => Located a -> Located a -> Ordering
+cmpLocated a b = unLoc a `compare` unLoc b
+
+instance Functor Located where
+ fmap f (L l e) = L l (f e)
+
+instance Outputable e => Outputable (Located e) where
+ ppr (L span e) = ppr e
+ -- do we want to dump the span in debugSty mode?
+\end{code}
diff --git a/compiler/basicTypes/UniqSupply.lhs b/compiler/basicTypes/UniqSupply.lhs
new file mode 100644
index 0000000000..41ad5c0f60
--- /dev/null
+++ b/compiler/basicTypes/UniqSupply.lhs
@@ -0,0 +1,203 @@
+%
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
+%
+\section[UniqSupply]{The @UniqueSupply@ data type and a (monadic) supply thereof}
+
+\begin{code}
+module UniqSupply (
+
+ UniqSupply, -- Abstractly
+
+ uniqFromSupply, uniqsFromSupply, -- basic ops
+
+ UniqSM, -- type: unique supply monad
+ initUs, initUs_, thenUs, thenUs_, returnUs, fixUs, getUs, withUs,
+ getUniqueUs, getUniquesUs,
+ mapUs, mapAndUnzipUs, mapAndUnzip3Us,
+ thenMaybeUs, mapAccumLUs,
+ lazyThenUs, lazyMapUs,
+
+ mkSplitUniqSupply,
+ splitUniqSupply
+ ) where
+
+#include "HsVersions.h"
+
+import Unique
+
+import GLAEXTS
+import UNSAFE_IO ( unsafeInterleaveIO )
+
+w2i x = word2Int# x
+i2w x = int2Word# x
+i2w_s x = (x :: Int#)
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Splittable Unique supply: @UniqSupply@}
+%* *
+%************************************************************************
+
+A value of type @UniqSupply@ is unique, and it can
+supply {\em one} distinct @Unique@. Also, from the supply, one can
+also manufacture an arbitrary number of further @UniqueSupplies@,
+which will be distinct from the first and from all others.
+
+\begin{code}
+data UniqSupply
+ = MkSplitUniqSupply Int -- make the Unique with this
+ UniqSupply UniqSupply
+ -- when split => these two supplies
+\end{code}
+
+\begin{code}
+mkSplitUniqSupply :: Char -> IO UniqSupply
+
+splitUniqSupply :: UniqSupply -> (UniqSupply, UniqSupply)
+uniqFromSupply :: UniqSupply -> Unique
+uniqsFromSupply :: UniqSupply -> [Unique] -- Infinite
+\end{code}
+
+\begin{code}
+mkSplitUniqSupply (C# c#)
+ = let
+#if __GLASGOW_HASKELL__ >= 503
+ mask# = (i2w (ord# c#)) `uncheckedShiftL#` (i2w_s 24#)
+#else
+ mask# = (i2w (ord# c#)) `shiftL#` (i2w_s 24#)
+#endif
+ -- here comes THE MAGIC:
+
+ -- This is one of the most hammered bits in the whole compiler
+ mk_supply#
+ = unsafeInterleaveIO (
+ mk_unique >>= \ uniq ->
+ mk_supply# >>= \ s1 ->
+ mk_supply# >>= \ s2 ->
+ return (MkSplitUniqSupply uniq s1 s2)
+ )
+
+ mk_unique = genSymZh >>= \ (W# u#) ->
+ return (I# (w2i (mask# `or#` u#)))
+ in
+ mk_supply#
+
+foreign import ccall unsafe "genSymZh" genSymZh :: IO Word
+
+splitUniqSupply (MkSplitUniqSupply _ s1 s2) = (s1, s2)
+\end{code}
+
+\begin{code}
+uniqFromSupply (MkSplitUniqSupply n _ _) = mkUniqueGrimily n
+uniqsFromSupply (MkSplitUniqSupply n _ s2) = mkUniqueGrimily n : uniqsFromSupply s2
+\end{code}
+
+%************************************************************************
+%* *
+\subsubsection[UniqSupply-monad]{@UniqSupply@ monad: @UniqSM@}
+%* *
+%************************************************************************
+
+\begin{code}
+type UniqSM result = UniqSupply -> (result, UniqSupply)
+
+-- the initUs function also returns the final UniqSupply; initUs_ drops it
+initUs :: UniqSupply -> UniqSM a -> (a,UniqSupply)
+initUs init_us m = case m init_us of { (r,us) -> (r,us) }
+
+initUs_ :: UniqSupply -> UniqSM a -> a
+initUs_ init_us m = case m init_us of { (r,us) -> r }
+
+{-# INLINE thenUs #-}
+{-# INLINE lazyThenUs #-}
+{-# INLINE returnUs #-}
+{-# INLINE splitUniqSupply #-}
+\end{code}
+
+@thenUs@ is where we split the @UniqSupply@.
+\begin{code}
+fixUs :: (a -> UniqSM a) -> UniqSM a
+fixUs m us
+ = (r,us') where (r,us') = m r us
+
+thenUs :: UniqSM a -> (a -> UniqSM b) -> UniqSM b
+thenUs expr cont us
+ = case (expr us) of { (result, us') -> cont result us' }
+
+lazyThenUs :: UniqSM a -> (a -> UniqSM b) -> UniqSM b
+lazyThenUs expr cont us
+ = let (result, us') = expr us in cont result us'
+
+thenUs_ :: UniqSM a -> UniqSM b -> UniqSM b
+thenUs_ expr cont us
+ = case (expr us) of { (_, us') -> cont us' }
+
+
+returnUs :: a -> UniqSM a
+returnUs result us = (result, us)
+
+withUs :: (UniqSupply -> (a, UniqSupply)) -> UniqSM a
+withUs f us = f us -- Ha ha!
+
+getUs :: UniqSM UniqSupply
+getUs us = splitUniqSupply us
+
+getUniqueUs :: UniqSM Unique
+getUniqueUs us = case splitUniqSupply us of
+ (us1,us2) -> (uniqFromSupply us1, us2)
+
+getUniquesUs :: UniqSM [Unique]
+getUniquesUs us = case splitUniqSupply us of
+ (us1,us2) -> (uniqsFromSupply us1, us2)
+\end{code}
+
+\begin{code}
+mapUs :: (a -> UniqSM b) -> [a] -> UniqSM [b]
+mapUs f [] = returnUs []
+mapUs f (x:xs)
+ = f x `thenUs` \ r ->
+ mapUs f xs `thenUs` \ rs ->
+ returnUs (r:rs)
+
+lazyMapUs :: (a -> UniqSM b) -> [a] -> UniqSM [b]
+lazyMapUs f [] = returnUs []
+lazyMapUs f (x:xs)
+ = f x `lazyThenUs` \ r ->
+ lazyMapUs f xs `lazyThenUs` \ rs ->
+ returnUs (r:rs)
+
+mapAndUnzipUs :: (a -> UniqSM (b,c)) -> [a] -> UniqSM ([b],[c])
+mapAndUnzip3Us :: (a -> UniqSM (b,c,d)) -> [a] -> UniqSM ([b],[c],[d])
+
+mapAndUnzipUs f [] = returnUs ([],[])
+mapAndUnzipUs f (x:xs)
+ = f x `thenUs` \ (r1, r2) ->
+ mapAndUnzipUs f xs `thenUs` \ (rs1, rs2) ->
+ returnUs (r1:rs1, r2:rs2)
+
+mapAndUnzip3Us f [] = returnUs ([],[],[])
+mapAndUnzip3Us f (x:xs)
+ = f x `thenUs` \ (r1, r2, r3) ->
+ mapAndUnzip3Us f xs `thenUs` \ (rs1, rs2, rs3) ->
+ returnUs (r1:rs1, r2:rs2, r3:rs3)
+
+thenMaybeUs :: UniqSM (Maybe a) -> (a -> UniqSM (Maybe b)) -> UniqSM (Maybe b)
+thenMaybeUs m k
+ = m `thenUs` \ result ->
+ case result of
+ Nothing -> returnUs Nothing
+ Just x -> k x
+
+mapAccumLUs :: (acc -> x -> UniqSM (acc, y))
+ -> acc
+ -> [x]
+ -> UniqSM (acc, [y])
+
+mapAccumLUs f b [] = returnUs (b, [])
+mapAccumLUs f b (x:xs)
+ = f b x `thenUs` \ (b__2, x__2) ->
+ mapAccumLUs f b__2 xs `thenUs` \ (b__3, xs__2) ->
+ returnUs (b__3, x__2:xs__2)
+\end{code}
diff --git a/compiler/basicTypes/Unique.lhs b/compiler/basicTypes/Unique.lhs
new file mode 100644
index 0000000000..874328863e
--- /dev/null
+++ b/compiler/basicTypes/Unique.lhs
@@ -0,0 +1,330 @@
+%
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
+%
+
+@Uniques@ are used to distinguish entities in the compiler (@Ids@,
+@Classes@, etc.) from each other. Thus, @Uniques@ are the basic
+comparison key in the compiler.
+
+If there is any single operation that needs to be fast, it is @Unique@
+comparison. Unsurprisingly, there is quite a bit of huff-and-puff
+directed to that end.
+
+Some of the other hair in this code is to be able to use a
+``splittable @UniqueSupply@'' if requested/possible (not standard
+Haskell).
+
+\begin{code}
+module Unique (
+ Unique, Uniquable(..), hasKey,
+
+ pprUnique,
+
+ mkUnique, -- Used in UniqSupply
+ mkUniqueGrimily, -- Used in UniqSupply only!
+ getKey, getKey#, -- Used in Var, UniqFM, Name only!
+
+ incrUnique, -- Used for renumbering
+ deriveUnique, -- Ditto
+ newTagUnique, -- Used in CgCase
+ initTyVarUnique,
+
+ isTupleKey,
+
+ -- now all the built-in Uniques (and functions to make them)
+ -- [the Oh-So-Wonderful Haskell module system wins again...]
+ mkAlphaTyVarUnique,
+ mkPrimOpIdUnique,
+ mkTupleTyConUnique, mkTupleDataConUnique,
+ mkPreludeMiscIdUnique, mkPreludeDataConUnique,
+ mkPreludeTyConUnique, mkPreludeClassUnique,
+ mkPArrDataConUnique,
+
+ mkBuiltinUnique,
+ mkPseudoUniqueC,
+ mkPseudoUniqueD,
+ mkPseudoUniqueE,
+ mkPseudoUniqueH
+ ) where
+
+#include "HsVersions.h"
+
+import BasicTypes ( Boxity(..) )
+import PackageConfig ( PackageId, packageIdFS )
+import FastString ( FastString, uniqueOfFS )
+import Outputable
+import FastTypes
+
+import GLAEXTS
+
+import Char ( chr, ord )
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[Unique-type]{@Unique@ type and operations}
+%* *
+%************************************************************************
+
+The @Chars@ are ``tag letters'' that identify the @UniqueSupply@.
+Fast comparison is everything on @Uniques@:
+
+\begin{code}
+data Unique = MkUnique Int#
+\end{code}
+
+Now come the functions which construct uniques from their pieces, and vice versa.
+The stuff about unique *supplies* is handled further down this module.
+
+\begin{code}
+mkUnique :: Char -> Int -> Unique -- Builds a unique from pieces
+unpkUnique :: Unique -> (Char, Int) -- The reverse
+
+mkUniqueGrimily :: Int -> Unique -- A trap-door for UniqSupply
+getKey :: Unique -> Int -- for Var
+getKey# :: Unique -> Int# -- for Var
+
+incrUnique :: Unique -> Unique
+deriveUnique :: Unique -> Int -> Unique
+newTagUnique :: Unique -> Char -> Unique
+
+isTupleKey :: Unique -> Bool
+\end{code}
+
+
+\begin{code}
+mkUniqueGrimily (I# x) = MkUnique x
+
+{-# INLINE getKey #-}
+getKey (MkUnique x) = I# x
+{-# INLINE getKey# #-}
+getKey# (MkUnique x) = x
+
+incrUnique (MkUnique i) = MkUnique (i +# 1#)
+
+-- deriveUnique uses an 'X' tag so that it won't clash with
+-- any of the uniques produced any other way
+deriveUnique (MkUnique i) delta = mkUnique 'X' (I# i + delta)
+
+-- newTagUnique changes the "domain" of a unique to a different char
+newTagUnique u c = mkUnique c i where (_,i) = unpkUnique u
+
+-- pop the Char in the top 8 bits of the Unique(Supply)
+
+-- No 64-bit bugs here, as long as we have at least 32 bits. --JSM
+
+w2i x = word2Int# x
+i2w x = int2Word# x
+i2w_s x = (x::Int#)
+
+mkUnique (C# c) (I# i)
+ = MkUnique (w2i (tag `or#` bits))
+ where
+#if __GLASGOW_HASKELL__ >= 503
+ tag = i2w (ord# c) `uncheckedShiftL#` i2w_s 24#
+#else
+ tag = i2w (ord# c) `shiftL#` i2w_s 24#
+#endif
+ bits = i2w i `and#` (i2w 16777215#){-``0x00ffffff''-}
+
+unpkUnique (MkUnique u)
+ = let
+ tag = C# (chr# (w2i ((i2w u) `shiftr` (i2w_s 24#))))
+ i = I# (w2i ((i2w u) `and#` (i2w 16777215#){-``0x00ffffff''-}))
+ in
+ (tag, i)
+ where
+#if __GLASGOW_HASKELL__ >= 503
+ shiftr x y = uncheckedShiftRL# x y
+#else
+ shiftr x y = shiftRL# x y
+#endif
+\end{code}
+
+
+
+%************************************************************************
+%* *
+\subsection[Uniquable-class]{The @Uniquable@ class}
+%* *
+%************************************************************************
+
+\begin{code}
+class Uniquable a where
+ getUnique :: a -> Unique
+
+hasKey :: Uniquable a => a -> Unique -> Bool
+x `hasKey` k = getUnique x == k
+
+instance Uniquable FastString where
+ getUnique fs = mkUniqueGrimily (I# (uniqueOfFS fs))
+
+instance Uniquable PackageId where
+ getUnique pid = getUnique (packageIdFS pid)
+
+instance Uniquable Int where
+ getUnique i = mkUniqueGrimily i
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection[Unique-instances]{Instance declarations for @Unique@}
+%* *
+%************************************************************************
+
+And the whole point (besides uniqueness) is fast equality. We don't
+use `deriving' because we want {\em precise} control of ordering
+(equality on @Uniques@ is v common).
+
+\begin{code}
+eqUnique (MkUnique u1) (MkUnique u2) = u1 ==# u2
+ltUnique (MkUnique u1) (MkUnique u2) = u1 <# u2
+leUnique (MkUnique u1) (MkUnique u2) = u1 <=# u2
+
+cmpUnique (MkUnique u1) (MkUnique u2)
+ = if u1 ==# u2 then EQ else if u1 <# u2 then LT else GT
+
+instance Eq Unique where
+ a == b = eqUnique a b
+ a /= b = not (eqUnique a b)
+
+instance Ord Unique where
+ a < b = ltUnique a b
+ a <= b = leUnique a b
+ a > b = not (leUnique a b)
+ a >= b = not (ltUnique a b)
+ compare a b = cmpUnique a b
+
+-----------------
+instance Uniquable Unique where
+ getUnique u = u
+\end{code}
+
+We do sometimes make strings with @Uniques@ in them:
+\begin{code}
+pprUnique :: Unique -> SDoc
+pprUnique uniq
+ = case unpkUnique uniq of
+ (tag, u) -> finish_ppr tag u (text (iToBase62 u))
+
+#ifdef UNUSED
+pprUnique10 :: Unique -> SDoc
+pprUnique10 uniq -- in base-10, dudes
+ = case unpkUnique uniq of
+ (tag, u) -> finish_ppr tag u (int u)
+#endif
+
+finish_ppr 't' u pp_u | u < 26
+ = -- Special case to make v common tyvars, t1, t2, ...
+ -- come out as a, b, ... (shorter, easier to read)
+ char (chr (ord 'a' + u))
+finish_ppr tag u pp_u = char tag <> pp_u
+
+instance Outputable Unique where
+ ppr u = pprUnique u
+
+instance Show Unique where
+ showsPrec p uniq = showsPrecSDoc p (pprUnique uniq)
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[Utils-base62]{Base-62 numbers}
+%* *
+%************************************************************************
+
+A character-stingy way to read/write numbers (notably Uniques).
+The ``62-its'' are \tr{[0-9a-zA-Z]}. We don't handle negative Ints.
+Code stolen from Lennart.
+
+\begin{code}
+iToBase62 :: Int -> String
+iToBase62 n@(I# n#)
+ = ASSERT(n >= 0) go n# ""
+ where
+ go n# cs | n# <# 62#
+ = case (indexCharOffAddr# chars62# n#) of { c# -> C# c# : cs }
+ | otherwise
+ = case (quotRem (I# n#) 62) of { (I# q#, I# r#) ->
+ case (indexCharOffAddr# chars62# r#) of { c# ->
+ go q# (C# c# : cs) }}
+
+ chars62# = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"#
+\end{code}
+
+%************************************************************************
+%* *
+\subsection[Uniques-prelude]{@Uniques@ for wired-in Prelude things}
+%* *
+%************************************************************************
+
+Allocation of unique supply characters:
+ v,t,u : for renumbering value-, type- and usage- vars.
+ B: builtin
+ C-E: pseudo uniques (used in native-code generator)
+ X: uniques derived by deriveUnique
+ _: unifiable tyvars (above)
+ 0-9: prelude things below
+
+ other a-z: lower case chars for unique supplies. Used so far:
+
+ d desugarer
+ f AbsC flattener
+ g SimplStg
+ l ndpFlatten
+ n Native codegen
+ r Hsc name cache
+ s simplifier
+
+\begin{code}
+mkAlphaTyVarUnique i = mkUnique '1' i
+
+mkPreludeClassUnique i = mkUnique '2' i
+
+-- Prelude type constructors occupy *three* slots.
+-- The first is for the tycon itself; the latter two
+-- are for the generic to/from Ids. See TysWiredIn.mk_tc_gen_info.
+
+mkPreludeTyConUnique i = mkUnique '3' (3*i)
+mkTupleTyConUnique Boxed a = mkUnique '4' (3*a)
+mkTupleTyConUnique Unboxed a = mkUnique '5' (3*a)
+
+-- Data constructor keys occupy *two* slots. The first is used for the
+-- data constructor itself and its wrapper function (the function that
+-- evaluates arguments as necessary and calls the worker). The second is
+-- used for the worker function (the function that builds the constructor
+-- representation).
+
+mkPreludeDataConUnique i = mkUnique '6' (2*i) -- Must be alphabetic
+mkTupleDataConUnique Boxed a = mkUnique '7' (2*a) -- ditto (*may* be used in C labels)
+mkTupleDataConUnique Unboxed a = mkUnique '8' (2*a)
+
+-- This one is used for a tiresome reason
+-- to improve a consistency-checking error check in the renamer
+isTupleKey u = case unpkUnique u of
+ (tag,_) -> tag == '4' || tag == '5' || tag == '7' || tag == '8'
+
+mkPrimOpIdUnique op = mkUnique '9' op
+mkPreludeMiscIdUnique i = mkUnique '0' i
+
+-- No numbers left anymore, so I pick something different for the character
+-- tag
+mkPArrDataConUnique a = mkUnique ':' (2*a)
+
+-- The "tyvar uniques" print specially nicely: a, b, c, etc.
+-- See pprUnique for details
+
+initTyVarUnique :: Unique
+initTyVarUnique = mkUnique 't' 0
+
+mkPseudoUniqueC, mkPseudoUniqueD, mkPseudoUniqueE, mkPseudoUniqueH,
+ mkBuiltinUnique :: Int -> Unique
+
+mkBuiltinUnique i = mkUnique 'B' i
+mkPseudoUniqueC i = mkUnique 'C' i -- used for getUnique on Regs
+mkPseudoUniqueD i = mkUnique 'D' i -- used in NCG for getUnique on RealRegs
+mkPseudoUniqueE i = mkUnique 'E' i -- used in NCG spiller to create spill VirtualRegs
+mkPseudoUniqueH i = mkUnique 'H' i -- used in NCG spiller to create spill VirtualRegs
+\end{code}
+
diff --git a/compiler/basicTypes/Var.lhs b/compiler/basicTypes/Var.lhs
new file mode 100644
index 0000000000..60fdf3831c
--- /dev/null
+++ b/compiler/basicTypes/Var.lhs
@@ -0,0 +1,337 @@
+%
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
+%
+\section{@Vars@: Variables}
+
+\begin{code}
+module Var (
+ Var,
+ varName, varUnique,
+ setVarName, setVarUnique,
+
+ -- TyVars
+ TyVar, mkTyVar, mkTcTyVar,
+ tyVarName, tyVarKind,
+ setTyVarName, setTyVarUnique,
+ tcTyVarDetails,
+
+ -- Ids
+ Id, DictId,
+ idName, idType, idUnique, idInfo, modifyIdInfo, maybeModifyIdInfo,
+ setIdName, setIdUnique, setIdType, setIdInfo, lazySetIdInfo,
+ setIdExported, setIdNotExported,
+
+ globalIdDetails, globaliseId,
+
+ mkLocalId, mkExportedLocalId, mkGlobalId,
+
+ isTyVar, isTcTyVar, isId, isLocalVar, isLocalId,
+ isGlobalId, isExportedId,
+ mustHaveLocalBinding
+ ) where
+
+#include "HsVersions.h"
+
+import {-# SOURCE #-} TypeRep( Type )
+import {-# SOURCE #-} TcType( TcTyVarDetails, pprTcTyVarDetails )
+import {-# SOURCE #-} IdInfo( GlobalIdDetails, notGlobalId, IdInfo, seqIdInfo )
+
+import Name ( Name, NamedThing(..),
+ setNameUnique, nameUnique
+ )
+import Kind ( Kind )
+import Unique ( Unique, Uniquable(..), mkUniqueGrimily, getKey# )
+import FastTypes
+import Outputable
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{The main data type declarations}
+%* *
+%************************************************************************
+
+
+Every @Var@ has a @Unique@, to uniquify it and for fast comparison, a
+@Type@, and an @IdInfo@ (non-essential info about it, e.g.,
+strictness). The essential info about different kinds of @Vars@ is
+in its @VarDetails@.
+
+\begin{code}
+data Var
+ = TyVar {
+ varName :: !Name,
+ realUnique :: FastInt, -- Key for fast comparison
+ -- Identical to the Unique in the name,
+ -- cached here for speed
+ tyVarKind :: Kind }
+
+ | TcTyVar { -- Used only during type inference
+ varName :: !Name,
+ realUnique :: FastInt,
+ tyVarKind :: Kind,
+ tcTyVarDetails :: TcTyVarDetails }
+
+ | GlobalId { -- Used for imported Ids, dict selectors etc
+ varName :: !Name,
+ realUnique :: FastInt,
+ idType :: Type,
+ idInfo :: IdInfo,
+ gblDetails :: GlobalIdDetails }
+
+ | LocalId { -- Used for locally-defined Ids (see NOTE below)
+ varName :: !Name,
+ realUnique :: FastInt,
+ idType :: Type,
+ idInfo :: IdInfo,
+ lclDetails :: LocalIdDetails }
+
+data LocalIdDetails
+ = NotExported -- Not exported
+ | Exported -- Exported
+ -- Exported Ids are kept alive;
+ -- NotExported things may be discarded as dead code.
+\end{code}
+
+LocalId and GlobalId
+~~~~~~~~~~~~~~~~~~~~
+A GlobalId is
+ * always a constant (top-level)
+ * imported, or data constructor, or primop, or record selector
+ * has a Unique that is globally unique across the whole
+ GHC invocation (a single invocation may compile multiple modules)
+
+A LocalId is
+ * bound within an expression (lambda, case, local let(rec))
+ * or defined at top level in the module being compiled
+
+After CoreTidy, top-level LocalIds are turned into GlobalIds
+
+
+\begin{code}
+instance Outputable Var where
+ ppr var = ppr (varName var) <+> ifPprDebug (brackets extra)
+ where
+ extra = case var of
+ GlobalId {} -> ptext SLIT("gid")
+ LocalId {} -> ptext SLIT("lid")
+ TyVar {} -> ptext SLIT("tv")
+ TcTyVar {tcTyVarDetails = details} -> pprTcTyVarDetails details
+
+instance Show Var where
+ showsPrec p var = showsPrecSDoc p (ppr var)
+
+instance NamedThing Var where
+ getName = varName
+
+instance Uniquable Var where
+ getUnique = varUnique
+
+instance Eq Var where
+ a == b = realUnique a ==# realUnique b
+
+instance Ord Var where
+ a <= b = realUnique a <=# realUnique b
+ a < b = realUnique a <# realUnique b
+ a >= b = realUnique a >=# realUnique b
+ a > b = realUnique a ># realUnique b
+ a `compare` b = varUnique a `compare` varUnique b
+\end{code}
+
+
+\begin{code}
+varUnique :: Var -> Unique
+varUnique var = mkUniqueGrimily (iBox (realUnique var))
+
+setVarUnique :: Var -> Unique -> Var
+setVarUnique var uniq
+ = var { realUnique = getKey# uniq,
+ varName = setNameUnique (varName var) uniq }
+
+setVarName :: Var -> Name -> Var
+setVarName var new_name
+ = var { realUnique = getKey# (getUnique new_name),
+ varName = new_name }
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Type variables}
+%* *
+%************************************************************************
+
+\begin{code}
+type TyVar = Var
+
+tyVarName = varName
+
+setTyVarUnique = setVarUnique
+setTyVarName = setVarName
+\end{code}
+
+\begin{code}
+mkTyVar :: Name -> Kind -> TyVar
+mkTyVar name kind = TyVar { varName = name
+ , realUnique = getKey# (nameUnique name)
+ , tyVarKind = kind
+ }
+
+mkTcTyVar :: Name -> Kind -> TcTyVarDetails -> TyVar
+mkTcTyVar name kind details
+ = TcTyVar { varName = name,
+ realUnique = getKey# (nameUnique name),
+ tyVarKind = kind,
+ tcTyVarDetails = details
+ }
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Id Construction}
+%* *
+%************************************************************************
+
+Most Id-related functions are in Id.lhs and MkId.lhs
+
+\begin{code}
+type Id = Var
+type DictId = Id
+\end{code}
+
+\begin{code}
+idName = varName
+idUnique = varUnique
+
+setIdUnique :: Id -> Unique -> Id
+setIdUnique = setVarUnique
+
+setIdName :: Id -> Name -> Id
+setIdName = setVarName
+
+setIdType :: Id -> Type -> Id
+setIdType id ty = id {idType = ty}
+
+setIdExported :: Id -> Id
+-- Can be called on GlobalIds, such as data cons and class ops,
+-- which are "born" as GlobalIds and automatically exported
+setIdExported id@(LocalId {}) = id { lclDetails = Exported }
+setIdExported other_id = ASSERT( isId other_id ) other_id
+
+setIdNotExported :: Id -> Id
+-- We can only do this to LocalIds
+setIdNotExported id = ASSERT( isLocalId id ) id { lclDetails = NotExported }
+
+globaliseId :: GlobalIdDetails -> Id -> Id
+-- If it's a local, make it global
+globaliseId details id = GlobalId { varName = varName id,
+ realUnique = realUnique id,
+ idType = idType id,
+ idInfo = idInfo id,
+ gblDetails = details }
+
+lazySetIdInfo :: Id -> IdInfo -> Id
+lazySetIdInfo id info = id {idInfo = info}
+
+setIdInfo :: Id -> IdInfo -> Id
+setIdInfo id info = seqIdInfo info `seq` id {idInfo = info}
+ -- Try to avoid spack leaks by seq'ing
+
+modifyIdInfo :: (IdInfo -> IdInfo) -> Id -> Id
+modifyIdInfo fn id
+ = seqIdInfo new_info `seq` id {idInfo = new_info}
+ where
+ new_info = fn (idInfo id)
+
+-- maybeModifyIdInfo tries to avoid unnecesary thrashing
+maybeModifyIdInfo :: (IdInfo -> Maybe IdInfo) -> Id -> Id
+maybeModifyIdInfo fn id
+ = case fn (idInfo id) of
+ Nothing -> id
+ Just new_info -> id {idInfo = new_info}
+\end{code}
+
+%************************************************************************
+%* *
+\subsection{Predicates over variables
+%* *
+%************************************************************************
+
+\begin{code}
+mkGlobalId :: GlobalIdDetails -> Name -> Type -> IdInfo -> Id
+mkGlobalId details name ty info
+ = GlobalId { varName = name,
+ realUnique = getKey# (nameUnique name), -- Cache the unique
+ idType = ty,
+ gblDetails = details,
+ idInfo = info }
+
+mk_local_id :: Name -> Type -> LocalIdDetails -> IdInfo -> Id
+mk_local_id name ty details info
+ = LocalId { varName = name,
+ realUnique = getKey# (nameUnique name), -- Cache the unique
+ idType = ty,
+ lclDetails = details,
+ idInfo = info }
+
+mkLocalId :: Name -> Type -> IdInfo -> Id
+mkLocalId name ty info = mk_local_id name ty NotExported info
+
+mkExportedLocalId :: Name -> Type -> IdInfo -> Id
+mkExportedLocalId name ty info = mk_local_id name ty Exported info
+\end{code}
+
+\begin{code}
+isTyVar, isTcTyVar :: Var -> Bool
+isId, isLocalVar, isLocalId :: Var -> Bool
+isGlobalId, isExportedId :: Var -> Bool
+mustHaveLocalBinding :: Var -> Bool
+
+isTyVar (TyVar {}) = True
+isTyVar (TcTyVar {}) = True
+isTyVar other = False
+
+isTcTyVar (TcTyVar {}) = True
+isTcTyVar other = False
+
+isId (LocalId {}) = True
+isId (GlobalId {}) = True
+isId other = False
+
+isLocalId (LocalId {}) = True
+isLocalId other = False
+
+-- isLocalVar returns True for type variables as well as local Ids
+-- These are the variables that we need to pay attention to when finding free
+-- variables, or doing dependency analysis.
+isLocalVar (GlobalId {}) = False
+isLocalVar other = True
+
+-- mustHaveLocalBinding returns True of Ids and TyVars
+-- that must have a binding in this module. The converse
+-- is not quite right: there are some GlobalIds that must have
+-- bindings, such as record selectors. But that doesn't matter,
+-- because it's only used for assertions
+mustHaveLocalBinding var = isLocalVar var
+
+isGlobalId (GlobalId {}) = True
+isGlobalId other = False
+
+-- isExportedId means "don't throw this away"
+isExportedId (GlobalId {}) = True
+isExportedId (LocalId {lclDetails = details})
+ = case details of
+ Exported -> True
+ other -> False
+isExportedId other = False
+\end{code}
+
+\begin{code}
+globalIdDetails :: Var -> GlobalIdDetails
+-- Works OK on local Ids too, returning notGlobalId
+globalIdDetails (GlobalId {gblDetails = details}) = details
+globalIdDetails other = notGlobalId
+\end{code}
+
diff --git a/compiler/basicTypes/VarEnv.lhs b/compiler/basicTypes/VarEnv.lhs
new file mode 100644
index 0000000000..bfeecdc923
--- /dev/null
+++ b/compiler/basicTypes/VarEnv.lhs
@@ -0,0 +1,344 @@
+
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
+%
+\section{@VarEnvs@: Variable environments}
+
+\begin{code}
+module VarEnv (
+ VarEnv, IdEnv, TyVarEnv,
+ emptyVarEnv, unitVarEnv, mkVarEnv,
+ elemVarEnv, varEnvElts, varEnvKeys,
+ extendVarEnv, extendVarEnv_C, extendVarEnvList,
+ plusVarEnv, plusVarEnv_C,
+ delVarEnvList, delVarEnv,
+ lookupVarEnv, lookupVarEnv_NF, lookupWithDefaultVarEnv,
+ mapVarEnv, zipVarEnv,
+ modifyVarEnv, modifyVarEnv_Directly,
+ isEmptyVarEnv, foldVarEnv,
+ elemVarEnvByKey, lookupVarEnv_Directly,
+ filterVarEnv_Directly,
+
+ -- InScopeSet
+ InScopeSet, emptyInScopeSet, mkInScopeSet, delInScopeSet,
+ extendInScopeSet, extendInScopeSetList, modifyInScopeSet,
+ getInScopeVars, lookupInScope, elemInScopeSet, uniqAway,
+ mapInScopeSet,
+
+ -- RnEnv2 and its operations
+ RnEnv2, mkRnEnv2, rnBndr2, rnBndrs2, rnOccL, rnOccR, inRnEnvL, inRnEnvR,
+ rnBndrL, rnBndrR, nukeRnEnvL, nukeRnEnvR,
+
+ -- TidyEnvs
+ TidyEnv, emptyTidyEnv
+ ) where
+
+#include "HsVersions.h"
+
+import OccName ( TidyOccEnv, emptyTidyOccEnv )
+import Var ( Var, setVarUnique )
+import VarSet
+import UniqFM
+import Unique ( Unique, deriveUnique, getUnique )
+import Util ( zipEqual, foldl2 )
+import Maybes ( orElse, isJust )
+import StaticFlags( opt_PprStyle_Debug )
+import Outputable
+import FastTypes
+\end{code}
+
+
+%************************************************************************
+%* *
+ In-scope sets
+%* *
+%************************************************************************
+
+\begin{code}
+data InScopeSet = InScope (VarEnv Var) FastInt
+ -- The Int# is a kind of hash-value used by uniqAway
+ -- For example, it might be the size of the set
+ -- INVARIANT: it's not zero; we use it as a multiplier in uniqAway
+
+instance Outputable InScopeSet where
+ ppr (InScope s i) = ptext SLIT("InScope") <+> ppr s
+
+emptyInScopeSet :: InScopeSet
+emptyInScopeSet = InScope emptyVarSet 1#
+
+getInScopeVars :: InScopeSet -> VarEnv Var
+getInScopeVars (InScope vs _) = vs
+
+mkInScopeSet :: VarEnv Var -> InScopeSet
+mkInScopeSet in_scope = InScope in_scope 1#
+
+extendInScopeSet :: InScopeSet -> Var -> InScopeSet
+extendInScopeSet (InScope in_scope n) v = InScope (extendVarEnv in_scope v v) (n +# 1#)
+
+extendInScopeSetList :: InScopeSet -> [Var] -> InScopeSet
+extendInScopeSetList (InScope in_scope n) vs
+ = InScope (foldl (\s v -> extendVarEnv s v v) in_scope vs)
+ (n +# iUnbox (length vs))
+
+modifyInScopeSet :: InScopeSet -> Var -> Var -> InScopeSet
+-- Exploit the fact that the in-scope "set" is really a map
+-- Make old_v map to new_v
+modifyInScopeSet (InScope in_scope n) old_v new_v = InScope (extendVarEnv in_scope old_v new_v) (n +# 1#)
+
+delInScopeSet :: InScopeSet -> Var -> InScopeSet
+delInScopeSet (InScope in_scope n) v = InScope (in_scope `delVarEnv` v) n
+
+mapInScopeSet :: (Var -> Var) -> InScopeSet -> InScopeSet
+mapInScopeSet f (InScope in_scope n) = InScope (mapVarEnv f in_scope) n
+
+elemInScopeSet :: Var -> InScopeSet -> Bool
+elemInScopeSet v (InScope in_scope n) = v `elemVarEnv` in_scope
+
+lookupInScope :: InScopeSet -> Var -> Maybe Var
+-- It's important to look for a fixed point
+-- When we see (case x of y { I# v -> ... })
+-- we add [x -> y] to the in-scope set (Simplify.simplCaseBinder).
+-- When we lookup up an occurrence of x, we map to y, but then
+-- we want to look up y in case it has acquired more evaluation information by now.
+lookupInScope (InScope in_scope n) v
+ = go v
+ where
+ go v = case lookupVarEnv in_scope v of
+ Just v' | v == v' -> Just v' -- Reached a fixed point
+ | otherwise -> go v'
+ Nothing -> Nothing
+\end{code}
+
+\begin{code}
+uniqAway :: InScopeSet -> Var -> Var
+-- (uniqAway in_scope v) finds a unique that is not used in the
+-- in-scope set, and gives that to v. It starts with v's current unique, of course,
+-- in the hope that it won't have to change it, and thereafter uses a combination
+-- of that and the hash-code found in the in-scope set
+uniqAway in_scope var
+ | var `elemInScopeSet` in_scope = uniqAway' in_scope var -- Make a new one
+ | otherwise = var -- Nothing to do
+
+uniqAway' :: InScopeSet -> Var -> Var
+-- This one *always* makes up a new variable
+uniqAway' (InScope set n) var
+ = try 1#
+ where
+ orig_unique = getUnique var
+ try k
+#ifdef DEBUG
+ | k ># 1000#
+ = pprPanic "uniqAway loop:" (ppr (iBox k) <+> text "tries" <+> ppr var <+> int (iBox n))
+#endif
+ | uniq `elemVarSetByKey` set = try (k +# 1#)
+#ifdef DEBUG
+ | opt_PprStyle_Debug && k ># 3#
+ = pprTrace "uniqAway:" (ppr (iBox k) <+> text "tries" <+> ppr var <+> int (iBox n))
+ setVarUnique var uniq
+#endif
+ | otherwise = setVarUnique var uniq
+ where
+ uniq = deriveUnique orig_unique (iBox (n *# k))
+\end{code}
+
+
+%************************************************************************
+%* *
+ Dual renaming
+%* *
+%************************************************************************
+
+When we are comparing (or matching) types or terms, we are faced with
+"going under" corresponding binders. E.g. when comparing
+ \x. e1 ~ \y. e2
+
+Basically we want to rename [x->y] or [y->x], but there are lots of
+things we must be careful of. In particular, x might be free in e2, or
+y in e1. So the idea is that we come up with a fresh binder that is free
+in neither, and rename x and y respectively. That means we must maintain
+ a) a renaming for the left-hand expression
+ b) a renaming for the right-hand expressions
+ c) an in-scope set
+
+Furthermore, when matching, we want to be able to have an 'occurs check',
+to prevent
+ \x. f ~ \y. y
+matching with f->y. So for each expression we want to know that set of
+locally-bound variables. That is precisely the domain of the mappings (a)
+and (b), but we must ensure that we always extend the mappings as we go in.
+
+
+\begin{code}
+data RnEnv2
+ = RV2 { envL :: VarEnv Var -- Renaming for Left term
+ , envR :: VarEnv Var -- Renaming for Right term
+ , in_scope :: InScopeSet } -- In scope in left or right terms
+
+-- The renamings envL and envR are *guaranteed* to contain a binding
+-- for every variable bound as we go into the term, even if it is not
+-- renamed. That way we can ask what variables are locally bound
+-- (inRnEnvL, inRnEnvR)
+
+mkRnEnv2 :: InScopeSet -> RnEnv2
+mkRnEnv2 vars = RV2 { envL = emptyVarEnv
+ , envR = emptyVarEnv
+ , in_scope = vars }
+
+rnBndrs2 :: RnEnv2 -> [Var] -> [Var] -> RnEnv2
+-- Arg lists must be of equal length
+rnBndrs2 env bsL bsR = foldl2 rnBndr2 env bsL bsR
+
+rnBndr2 :: RnEnv2 -> Var -> Var -> RnEnv2
+-- (rnBndr2 env bL bR) go under a binder bL in the Left term 1,
+-- and binder bR in the Right term
+-- It finds a new binder, new_b,
+-- and returns an environment mapping bL->new_b and bR->new_b resp.
+rnBndr2 (RV2 { envL = envL, envR = envR, in_scope = in_scope }) bL bR
+ = RV2 { envL = extendVarEnv envL bL new_b -- See Note
+ , envR = extendVarEnv envR bR new_b -- [Rebinding]
+ , in_scope = extendInScopeSet in_scope new_b }
+ where
+ -- Find a new binder not in scope in either term
+ new_b | not (bL `elemInScopeSet` in_scope) = bL
+ | not (bR `elemInScopeSet` in_scope) = bR
+ | otherwise = uniqAway' in_scope bL
+
+ -- Note [Rebinding]
+ -- If the new var is the same as the old one, note that
+ -- the extendVarEnv *deletes* any current renaming
+ -- E.g. (\x. \x. ...) ~ (\y. \z. ...)
+ --
+ -- Inside \x \y { [x->y], [y->y], {y} }
+ -- \x \z { [x->x], [y->y, z->x], {y,x} }
+
+rnBndrL, rnBndrR :: RnEnv2 -> Var -> (RnEnv2, Var)
+-- Used when there's a binder on one side or the other only
+-- Useful when eta-expanding
+rnBndrL (RV2 { envL = envL, envR = envR, in_scope = in_scope }) bL
+ = (RV2 { envL = extendVarEnv envL bL new_b
+ , envR = envR
+ , in_scope = extendInScopeSet in_scope new_b }, new_b)
+ where
+ new_b | not (bL `elemInScopeSet` in_scope) = bL
+ | otherwise = uniqAway' in_scope bL
+
+rnBndrR (RV2 { envL = envL, envR = envR, in_scope = in_scope }) bR
+ = (RV2 { envL = envL
+ , envR = extendVarEnv envR bR new_b
+ , in_scope = extendInScopeSet in_scope new_b }, new_b)
+ where
+ new_b | not (bR `elemInScopeSet` in_scope) = bR
+ | otherwise = uniqAway' in_scope bR
+
+rnOccL, rnOccR :: RnEnv2 -> Var -> Var
+-- Look up the renaming of an occurrence in the left or right term
+rnOccL (RV2 { envL = env }) v = lookupVarEnv env v `orElse` v
+rnOccR (RV2 { envR = env }) v = lookupVarEnv env v `orElse` v
+
+inRnEnvL, inRnEnvR :: RnEnv2 -> Var -> Bool
+-- Tells whether a variable is locally bound
+inRnEnvL (RV2 { envL = env }) v = isJust (lookupVarEnv env v)
+inRnEnvR (RV2 { envR = env }) v = isJust (lookupVarEnv env v)
+
+nukeRnEnvL, nukeRnEnvR :: RnEnv2 -> RnEnv2
+nukeRnEnvL env = env { envL = emptyVarEnv }
+nukeRnEnvR env = env { envR = emptyVarEnv }
+\end{code}
+
+
+%************************************************************************
+%* *
+ Tidying
+%* *
+%************************************************************************
+
+When tidying up print names, we keep a mapping of in-scope occ-names
+(the TidyOccEnv) and a Var-to-Var of the current renamings.
+
+\begin{code}
+type TidyEnv = (TidyOccEnv, VarEnv Var)
+
+emptyTidyEnv :: TidyEnv
+emptyTidyEnv = (emptyTidyOccEnv, emptyVarEnv)
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{@VarEnv@s}
+%* *
+%************************************************************************
+
+\begin{code}
+type VarEnv elt = UniqFM elt
+type IdEnv elt = VarEnv elt
+type TyVarEnv elt = VarEnv elt
+
+emptyVarEnv :: VarEnv a
+mkVarEnv :: [(Var, a)] -> VarEnv a
+zipVarEnv :: [Var] -> [a] -> VarEnv a
+unitVarEnv :: Var -> a -> VarEnv a
+extendVarEnv :: VarEnv a -> Var -> a -> VarEnv a
+extendVarEnv_C :: (a->a->a) -> VarEnv a -> Var -> a -> VarEnv a
+plusVarEnv :: VarEnv a -> VarEnv a -> VarEnv a
+extendVarEnvList :: VarEnv a -> [(Var, a)] -> VarEnv a
+
+lookupVarEnv_Directly :: VarEnv a -> Unique -> Maybe a
+filterVarEnv_Directly :: (Unique -> a -> Bool) -> VarEnv a -> VarEnv a
+delVarEnvList :: VarEnv a -> [Var] -> VarEnv a
+delVarEnv :: VarEnv a -> Var -> VarEnv a
+plusVarEnv_C :: (a -> a -> a) -> VarEnv a -> VarEnv a -> VarEnv a
+mapVarEnv :: (a -> b) -> VarEnv a -> VarEnv b
+modifyVarEnv :: (a -> a) -> VarEnv a -> Var -> VarEnv a
+varEnvElts :: VarEnv a -> [a]
+varEnvKeys :: VarEnv a -> [Unique]
+
+isEmptyVarEnv :: VarEnv a -> Bool
+lookupVarEnv :: VarEnv a -> Var -> Maybe a
+lookupVarEnv_NF :: VarEnv a -> Var -> a
+lookupWithDefaultVarEnv :: VarEnv a -> a -> Var -> a
+elemVarEnv :: Var -> VarEnv a -> Bool
+elemVarEnvByKey :: Unique -> VarEnv a -> Bool
+foldVarEnv :: (a -> b -> b) -> b -> VarEnv a -> b
+\end{code}
+
+\begin{code}
+elemVarEnv = elemUFM
+elemVarEnvByKey = elemUFM_Directly
+extendVarEnv = addToUFM
+extendVarEnv_C = addToUFM_C
+extendVarEnvList = addListToUFM
+plusVarEnv_C = plusUFM_C
+delVarEnvList = delListFromUFM
+delVarEnv = delFromUFM
+plusVarEnv = plusUFM
+lookupVarEnv = lookupUFM
+lookupWithDefaultVarEnv = lookupWithDefaultUFM
+mapVarEnv = mapUFM
+mkVarEnv = listToUFM
+emptyVarEnv = emptyUFM
+varEnvElts = eltsUFM
+varEnvKeys = keysUFM
+unitVarEnv = unitUFM
+isEmptyVarEnv = isNullUFM
+foldVarEnv = foldUFM
+lookupVarEnv_Directly = lookupUFM_Directly
+filterVarEnv_Directly = filterUFM_Directly
+
+zipVarEnv tyvars tys = mkVarEnv (zipEqual "zipVarEnv" tyvars tys)
+lookupVarEnv_NF env id = case (lookupVarEnv env id) of { Just xx -> xx }
+\end{code}
+
+@modifyVarEnv@: Look up a thing in the VarEnv,
+then mash it with the modify function, and put it back.
+
+\begin{code}
+modifyVarEnv mangle_fn env key
+ = case (lookupVarEnv env key) of
+ Nothing -> env
+ Just xx -> extendVarEnv env key (mangle_fn xx)
+
+modifyVarEnv_Directly mangle_fn env key
+ = case (lookupUFM_Directly env key) of
+ Nothing -> env
+ Just xx -> addToUFM_Directly env key (mangle_fn xx)
+\end{code}
diff --git a/compiler/basicTypes/VarSet.lhs b/compiler/basicTypes/VarSet.lhs
new file mode 100644
index 0000000000..55e82a8515
--- /dev/null
+++ b/compiler/basicTypes/VarSet.lhs
@@ -0,0 +1,105 @@
+%
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
+%
+\section{@VarSet@: Variable sets}
+
+\begin{code}
+module VarSet (
+ VarSet, IdSet, TyVarSet,
+ emptyVarSet, unitVarSet, mkVarSet,
+ extendVarSet, extendVarSetList, extendVarSet_C,
+ elemVarSet, varSetElems, subVarSet,
+ unionVarSet, unionVarSets,
+ intersectVarSet, intersectsVarSet,
+ isEmptyVarSet, delVarSet, delVarSetList, delVarSetByKey,
+ minusVarSet, foldVarSet, filterVarSet,
+ lookupVarSet, mapVarSet, sizeVarSet, seqVarSet,
+ elemVarSetByKey
+ ) where
+
+#include "HsVersions.h"
+
+import Var ( Var, Id, TyVar )
+import Unique ( Unique )
+import UniqSet
+import UniqFM ( delFromUFM_Directly, addToUFM_C )
+\end{code}
+
+%************************************************************************
+%* *
+\subsection{@VarSet@s}
+%* *
+%************************************************************************
+
+\begin{code}
+type VarSet = UniqSet Var
+type IdSet = UniqSet Id
+type TyVarSet = UniqSet TyVar
+
+emptyVarSet :: VarSet
+intersectVarSet :: VarSet -> VarSet -> VarSet
+unionVarSet :: VarSet -> VarSet -> VarSet
+unionVarSets :: [VarSet] -> VarSet
+varSetElems :: VarSet -> [Var]
+unitVarSet :: Var -> VarSet
+extendVarSet :: VarSet -> Var -> VarSet
+extendVarSetList:: VarSet -> [Var] -> VarSet
+elemVarSet :: Var -> VarSet -> Bool
+delVarSet :: VarSet -> Var -> VarSet
+delVarSetList :: VarSet -> [Var] -> VarSet
+minusVarSet :: VarSet -> VarSet -> VarSet
+isEmptyVarSet :: VarSet -> Bool
+mkVarSet :: [Var] -> VarSet
+foldVarSet :: (Var -> a -> a) -> a -> VarSet -> a
+lookupVarSet :: VarSet -> Var -> Maybe Var
+ -- Returns the set element, which may be
+ -- (==) to the argument, but not the same as
+mapVarSet :: (Var -> Var) -> VarSet -> VarSet
+sizeVarSet :: VarSet -> Int
+filterVarSet :: (Var -> Bool) -> VarSet -> VarSet
+extendVarSet_C :: (Var->Var->Var) -> VarSet -> Var -> VarSet
+
+delVarSetByKey :: VarSet -> Unique -> VarSet
+elemVarSetByKey :: Unique -> VarSet -> Bool
+
+emptyVarSet = emptyUniqSet
+unitVarSet = unitUniqSet
+extendVarSet = addOneToUniqSet
+extendVarSetList= addListToUniqSet
+intersectVarSet = intersectUniqSets
+
+intersectsVarSet:: VarSet -> VarSet -> Bool -- True if non-empty intersection
+ -- (s1 `intersectsVarSet` s2) doesn't compute s2 if s1 is empty
+subVarSet :: VarSet -> VarSet -> Bool -- True if first arg is subset of second
+ -- (s1 `subVarSet` s2) doesn't compute s2 if s1 is empty
+
+unionVarSet = unionUniqSets
+unionVarSets = unionManyUniqSets
+varSetElems = uniqSetToList
+elemVarSet = elementOfUniqSet
+minusVarSet = minusUniqSet
+delVarSet = delOneFromUniqSet
+delVarSetList = delListFromUniqSet
+isEmptyVarSet = isEmptyUniqSet
+mkVarSet = mkUniqSet
+foldVarSet = foldUniqSet
+lookupVarSet = lookupUniqSet
+mapVarSet = mapUniqSet
+sizeVarSet = sizeUniqSet
+filterVarSet = filterUniqSet
+extendVarSet_C combine s x = addToUFM_C combine s x x
+delVarSetByKey = delFromUFM_Directly -- Can't be bothered to add this to UniqSet
+elemVarSetByKey = elemUniqSet_Directly
+\end{code}
+
+\begin{code}
+-- See comments with type signatures
+intersectsVarSet s1 s2 = not (isEmptyVarSet (s1 `intersectVarSet` s2))
+a `subVarSet` b = isEmptyVarSet (a `minusVarSet` b)
+\end{code}
+
+\begin{code}
+seqVarSet :: VarSet -> ()
+seqVarSet s = sizeVarSet s `seq` ()
+\end{code}
+