GHC Contributors’ Workshop
Sam Derbyshire, Well-Typed
June 7th, 2023
COMPLETE sets of pattern synonyms and
do notation).⭲
⭲
There are many ways that GHC can refer to an identifier depending on how much it knows about it.
OccNameNameRdrNameGlobalRdrEltVar, TyVar, Id
⭲
OccName: occurrences with a NameSpaceName: unique identifiersRdrName: umbrella datatypeVar and Id: variablesdata Var -- slightly abridged
= TyVar { varName :: Name
, varType :: Kind }
| TcTyVar { varName :: Name
, varType :: Kind
, tc_tv_details :: TcTyVarDetails }
| Id { varName :: Name
, varType :: Type
, varMult :: Mult
, idScope :: IdScope
, id_details :: IdDetails
, id_info :: IdInfo
}
data IdScope = GlobalId | LocalId ExportFlag
data ExportFlag = NotExported | Exported
data IdDetails = VanillaId | RecSelId {} | PrimOpId {} | CoVarId {} | ...
type TyVar = Var
type Id = VarNames: TyThing and
GREInfoGlobalRdrElt and the GlobalRdrEnvThe renamer primarily deals with GlobalRdrElt, which
consists of a Name, information about how it’s in scope in
the renamer, and additional information that the renamer might need to
know.
TcRn monadRenaming and typechecking happens in a shared monad, TcM
(also called TcRn or RnM).
This is ReaderT over IO, with access
to:
HscEnv –
per-module options (e.g. flags passed to GHC) and environmentUnitEnv,
currently loaded modules;TcGblEnv –
generated during typechecking and passed onTypeEnv,
InstEnv, GlobalRdrEnv;TcLclEnv –
changes as we move inside expressionsSrcSpan,
TcLevel, LocalRdrEnv.
⭲
Start by looking at rnExpr (RecordUpd {..}):
After handling duplicates, rnHsRecUpdFields starts by
calling lookupRecUpdFields to look up each field
individually.
We retrieve GlobalRdrElts for each record field.
These have GREInfos which specify which constructors have
that field.
We can use that to disambiguate.
⭲
Lookup:
[(x, [MkS1, MkS2, MkT1]), (y, [MkS1, MkS2, MkT2])].
Intersect all the possible data constructors:
[MkS1, MkS2].
Take parents (removing duplicates): [S].
There is a single parent: the record update is unambiguous!
⭲
We start off by lexing. See GHC.Parser.Lexer.x:
@varid = $small $idchar* -- variable identifiers
@conid = $large $idchar* -- constructor identifiers
@varsym = ($symbol # \:) $symbol* -- variable (operator) symbol
@consym = \: $symbol* -- constructor (operator) symbol
$small = [a-z \_]
$large = [A-Z]
$symbol = [\!\#\$\%\&\*\+\.\/\<\=\>\?\@\\\^\|\-\~\:]
$idchar = [$small $large $digit \']⭲
Then parsing, in GHC.Parser.y.
RdrName.
mkQual/mkUnqual depending on
qualification.
NameSpace using context (e.g. whether we are
parsing a term or a type).
Parse this as a type first. Then, after properly associating using
the fixities, we find that :+: should be namespaced as a
data constructor, and the others remain type constructors.
GHC.Parser.PostProcess.
⭲
The main entry point is
GHC.Tc.Module.tcRnModuleTcRnM.
tcRnImports.
tcRnSrcDecls.
rnTopSrcDecls.
tcTopSrcDecls.
rnExportList. This allows us to
assemble a final TcGblEnv which contains everything
provided by the module.
Assemble the final typechecked module, to be passed onto the next
stage of the compiler pipeline. Everything is extracted from the
TcGblEnv.
⭲
Entry point: GHC.Rename.Names.rnImportDecl.
filterImports.
import M( A(x, ..), B(..) )
import M hiding ( .. )
Works the same, except now we filter out instead.
Add all the imported identifiers to the GlobalRdrEnv. We
will look up in this environment when renaming the body of the
module.
⭲
The main entry point to renaming local declarations is
GHC.Rename.Module.rnSrcDecls. Control flow:
Names for all binders.
getLocalNonValBinders.
extendPatSynEnv.
Names and rename the LHS of top-level value
bindings (rnTopBindsLHS).
⤞
rnTyClDecls.
rnValBindsRHS.
RULES, foreign import/exports, default
declarations…
⭲
rnTyClDecls - renames all types/classes defined in the
module - uses this information to compute dependency groups
(strongly-connected components).
rnTyClDecls :: [TyClGroup GhcPs] -> RnM ([TyClGroup GhcRn], FreeVars)
rnTyClDecls tycl_ds =
do { tycls_w_fvs <- mapM rnTyClDecl (tyClGroupTyClDecls tycl_ds)
; kisigs_w_fvs <- rnStandaloneKindSigs (tyClGroupKindSigs tycl_ds)
; instds_w_fvs <- mapM rnSrcInstDecl (tyClGroupInstDecls tycl_ds)
; let tycl_sccs = depAnalTyClDecls kisig_fv_env tycls_w_fvs
; .. }See Note [Dependency analysis of type, class, and instance decls] in
GHC.Rename.Module.
⭲
rnValBindsRHS - renames all value bindings - performs
dependency analysis
Slides available online: sheaf.github.io/ghc-renamer.