The GHC Commentary - The Glorious Renamer
(This section is, like most of the Commentary, rather incomplete.)
The renamer sits between the parser and the typechecker.
Roughly speaking, It has the type:
HsModule RdrName -> HsModule Name
That is, it converts all the RdrNames to Names.
OccNames, RdrNames, and Names
A RdrNames is pretty much just a string (for an unqualified name
like "f") or a pair of strings (for a qualified name like "M.f").
Well, not quite just strings, because in Haskell a name like "C" could mean a type
constructor or data constructor, depending on context. So GHC defines a type
OccName (defined in basicTypes/OccName.lhs) that is a pair of
a FastString and a NameSpace indicating which name space the
name is drawn from:
data OccName = OccName NameSpace EncodedFS
The EncodedFS is a synonym for FastString indicating that the
string is Z-encoded. (Details in OccName.lhs.)
The name spaces are:
- VarName: ordinary variables
- TvName: type variables
- DataName: data constructors
- TcClsName: type constructors and classes (in Haskell they share a name space)
So a RdrName is defined thus:
data RdrName = RdrName Qual OccName
data Qual = Unqual
| Qual ModuleName -- 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 ModuleName -- This is an *original* name; the module is the place
-- where the thing was defined
The OrigName variant is used internally; it allows GHC to speak of RdrNames
that refer to the original name of the thing.
On the other hand, a Name:
- Contains the original name for the thing.
- Contains a Unique that makes it easy to compare names for equality quickly.
- Contains a SrcLoc saying where the name was bound.
The original name of an entity (type constructor, class, function etc) is
the (module,name) pair describing where the thing was originally defined. So for example,
if we have
module M where
f = e1
g = e2
module A where
import qualified M as Q
import M
a = Q.f + g
then the RdrNames for "a", "Q.f" and "g" get replaced by the Names
"A.a", "M.f", and "M.g" respectively.
Names come in two flavours: Local and Global. The Global kind contain
both a Module and an OccName
Not all Names are qualifed. Local (e.g. lambda-bound) names are given Local Names
Rebindable syntax
In Haskell when one writes "3" one gets "fromInteger 3", where
"fromInteger" comes from the Prelude (regardless of whether the
Prelude is in scope). If you want to completely redefine numbers,
that becomes inconvenient. So GHC lets you say
"-fno-implicit-prelude"; in that case, the "fromInteger" comes from
whatever is in scope. (This is documented in the User Guide.)
This feature is implemented as follows (I always forget).
- Four HsSyn constructs (NegApp, NPlusKPat, HsIntegral, HsFractional)
contain a Name (i.e. it is not parameterised).
- When the parser builds these constructs, it puts in the built-in Prelude
Name (e.g. PrelNum.fromInteger).
- When the renamer encounters these constructs, it calls RnEnv.lookupSyntaxName.
This checks for -fno-implicit-prelude; if not, it just returns the same Name;
otherwise it takes the occurrence name of the Name, turns it into an unqualified RdrName, and looks
it up in the environment. The returned name is plugged back into the construct.
- The typechecker uses the Name to generate the appropriate typing constraints.
Last modified: Tue Nov 13 14:11:35 EST 2001