Changes between Version 2 and Version 3 of Commentary/Compiler/Renamer

Sep 8, 2006 3:08:43 PM (11 years ago)



  • Commentary/Compiler/Renamer

    v2 v3  
    33= The renamer =
    6 The renamer's Number One taks is to replace [wiki:Commentary/Compiler/RdrNameType RdrNames] with [wiki:Commentary/Compiler/NameType Names].  For example, consider
     5The renamer's Number One task is to replace [wiki:Commentary/Compiler/RdrNameType RdrNames] with [wiki:Commentary/Compiler/NameType Names].  For example, consider
    87module K where
    3433 * Lots of lexical error checking: variables out of scope, unused bindings, unused imports, patterns that use the same binder many times, etc.
     35The renamer sits between the parser and the typechecker. However, its operation is quite tightly interwoven with the typechecker. This is mainly due to support for Template Haskell, where spliced code has to be renamed and type checked. In particular, top-level splices lead to multiple rounds of renaming and type checking.  It uses the [wike:Commentary/Compiler/TcRnMonad same monad as the typechecker].
     37== The global renamer environment, {{{GlobalRdrEnv}}} ==
     39A big part of the renamer's task is to build the '''global rdr-env''' for the module, of type {{{GlobalRdrEnv}}}.  This environment allows us to take a qualified or un-qualified {{{RdrName}}} and figure out which {{{Name}}} it means.  The global rdr-env is built by looking at all the imports, and the top-level declarations of the module.
     41You might think that the global rdr-env would be a mapping from {{{RdrName}}} to {{{Name}}}, but it isn't.  Here is what it looks like, after at least three iterations (all in [[GhcFile(compiler/basicTypes/RdrName.lhs)]]):
     43type GlobalRdrEnv = OccEnv [GlobalRdrElt]
     44  -- An (OccEnv a) is a mapping from OccName to a
     46data GlobalRdrElt = GRE { gre_name :: Name, gre_prov :: Provenance }
     48data Provenance = LocalDef | Imported [ImportSpec]
     50The environment maps an {{{OccName}}} to a list of all entities with that occurence name that are in scope (in any way).  Each of these is represented by a {{{GlobalRdrElt}}}, which gives the entity's {{{Name}}} plus a specification of how it is in scope, its {{{Provenance}}}.  Either it is in scope because it is defined in this module ({{{LocalDef}}}), or because it is imported.  In the latter case, the {{{[ImportSpec]}}} describes all the import statements that bring it into scope. You can look in {{{RdrName.lhs}}} to see what an {{{ImportSpec}}} is, but among other things it says whether the import is qualified-only, and whether there is an "{{{as}}}" clause on the import statement. 
     52With all that information, we can give good error messages, especially in the case where an occurrence "f" is ambiguous (i.e. different entities, both called "f", were imported by diffferent import statements).
     54The global rdr-env is created by [[GhcFile(compiler/rename/RnNames.lhs)]].
     56It is important to note that the global rdr-env is created  ''before'' the renamer actually descends into the top=level bindings of a module. In other words, before {{{TcRnDriver.rnTopSrcDecls}}} performs the renaming of a module by way of {{{RnSource.rnSrcDecls}}}, it uses {{{RnNames.importsFromLocalDecls}}} to set up the global rdr-env environment, which contains {{{Names}}} for all imported and all locally defined toplevel binders.  Hence, when the helpers of {{{rnSrcDecls}}} come across the defining occurences of a toplevel {{{RdrName}}}, they don't rename it by generating a new name, but they simply look up its name in the global rdr-env.
     58== Name Space Management ==
     60(too much detail?)
     62As anticipated by the variants {{{Orig}}} and {{{Exact}}} of {{{RdrName}}}, some names should not change during renaming, whereas others need to be turned into unique names. In this context, the two functions {{{RnEnv.newTopSrcBinder}}} and {{{RnEnv.newLocals}}} are important:
     64newTopSrcBinder :: Module -> Maybe Name -> Located RdrName -> RnM Name
     65newLocalsRn     :: [Located RdrName] -> RnM [Name]
     67The two functions introduces new toplevel and new local names, respectively, where the first two arguments to newTopSrcBinder determine the currently compiled module and the parent construct of the newly defined name. Both functions create new names only for RdrNames that are neither exact nor original.
     69== Rebindable syntax ==
     71(!ToDo: Not fully proof-read.)
     73In 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.)
     75This feature is implemented as follows (I always forget).
     77 * Names that are implicitly bound by the Prelude, are marked by the type {{{HsExpr.SyntaxExpr}}}. Moreover, the association list {{{HsExpr.SyntaxTable}}} is set up by the renamer to map rebindable names to the value they are bound to.
     78 * Currently, five constructs related to numerals ({{{HsExpr.NegApp}}}, {{{HsPat.NPat}}}, {{{HsPat.NPlusKPat}}}, {{{HsLit.HsIntegral}}}, and {{{HsLit.HsFractional}}}) and two constructs related to do-expressions ({{{HsExpr.BindStmt}}} and {{{HsExpr.ExprStmt}}}) have rebindable syntax.
     79 * When the parser builds these constructs, it puts in the built-in Prelude Name (e.g. {{{PrelNum.fromInteger}}}).
     80 * 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.
     81 * The typechecker uses the {{{Name}}} to generate the appropriate typing constraints.