-- | This module contains a compiler pass that qualifies the names of all -- top-level declarations of the converted module with the name of that -- module. -- -- = Example -- -- Consider the following module. -- -- > module Data.Tree where -- > -- > data Tree a = Leaf a | Branch (Tree a) (Tree a) -- > -- > mapTree :: (a -> b) -> Tree a -> Tree b -- > mapTree f t = case t of -- > Leaf x -> Leaf (f x) -- > Branch l r -> Branch (mapTree f l) (mapTree f r) -- -- After this pass the declarations of @Tree@ and @mapTree@ as well -- as the type signature for @mapTree@ and the constructors @Leaf@ -- and @Branch@ are qualified. -- -- > module Data.Tree where -- > -- > data Data.Tree.Tree a -- > = Data.Tree.Leaf a -- > | Data.Tree.Branch (Tree a) (Tree a) -- > -- > Data.Tree.mapTree :: (a -> b) -> Tree a -> Tree b -- > Data.Tree.mapTree f t = case t of -- > Leaf x -> Leaf (f x) -- > Branch l r -> Branch (mapTree f l) (mapTree f r) -- -- However, references to @Tree@, @Leaf@, @Branch@ and @mapTree@ -- in the fields of the constructor declarations and on the right-hand -- side of the function's type signature and declaration remain unqualified. -- Also (type) arguments and local variable are not affected. -- -- = Specification -- -- == Precondition -- -- There are no special requirements. -- -- == Translation -- -- In a module @M@ all declarations, type signatures and pragmas of the forms -- -- * @type T α₁ … αₘ = τ@ -- * @data D α₁ … αₘ = C₁ τ₍₁,₁₎ … τ₍₁,ₖ₁₎ | … | Cₙ τ₍ₙ,₁₎ … τ₍ₙ,ₖₙ₎@ -- * @f₁, …, fₙ :: τ@ -- * @f x₁ … xₙ = e@ -- * @{-\# FreeC f DECREASES ON x \#-}@ -- -- are translated to -- -- * @type M.T α₁ … αₘ = τ@ -- * @data M.D α₁ … αₘ = M.C₁ τ₍₁,₁₎ … τ₍₁,ₖ₁₎ | … | M.Cₙ τ₍ₙ,₁₎ … τ₍ₙ,ₖₙ₎@ -- * @M.f₁, …, M.fₙ :: τ@ -- * @M.f x₁ … xₙ = e@ -- * @{-\# FreeC M.f DECREASES ON x \#-}@ -- -- If an identifier is qualified already, it keeps its original qualifier. -- -- == Postcondition -- -- All 'IR.DeclIdent's in the module contain qualified identifiers -- (i.e., 'IR.Qual's). module FreeC.Pass.QualifierPass ( qualifierPass ) where import qualified FreeC.IR.Syntax as IR import FreeC.Pass -- | Compiler pass that qualifies the names of all declarations in the module -- with the name of the module. qualifierPass :: Pass IR.Module IR.Module qualifierPass = return . qualifyDecls -- | Qualifies the names of declarations in the given module with the name -- of the module. qualifyDecls :: IR.Module -> IR.Module qualifyDecls ast = ast { IR.modPragmas = map qualifyPragma (IR.modPragmas ast) , IR.modContents = map qualifyTopLevelDecl (IR.modContents ast) } where -- | The name of the module to qualify the names of all declarations with. modName :: IR.ModName modName = IR.modName ast -- | Qualifies unqualified names with 'modName'. -- -- If the name is qualified already, it remains unchanged. qualify :: IR.QName -> IR.QName qualify (IR.UnQual name) = IR.Qual modName name qualify name@(IR.Qual _ _) = name -- | Qualifies the name of a declaration with 'modName'. qualifyDeclIdent :: IR.DeclIdent -> IR.DeclIdent qualifyDeclIdent declIdent = declIdent { IR.declIdentName = qualify (IR.declIdentName declIdent) } -- | Qualifies the given top level declaration. qualifyTopLevelDecl :: IR.TopLevelDecl -> IR.TopLevelDecl qualifyTopLevelDecl (IR.TopLevelTypeDecl typeDecl) = IR.TopLevelTypeDecl (qualifyTypeDecl typeDecl) qualifyTopLevelDecl (IR.TopLevelTypeSig typeSig) = IR.TopLevelTypeSig (qualifyTypeSig typeSig) qualifyTopLevelDecl (IR.TopLevelFuncDecl funcDecl) = IR.TopLevelFuncDecl (qualifyFuncDecl funcDecl) -- | Qualifies the name of the given type declaration with 'modName'. -- -- If the declaration is a data type declaration, the names of its -- constructors are also qualified. qualifyTypeDecl :: IR.TypeDecl -> IR.TypeDecl qualifyTypeDecl decl@IR.TypeSynDecl {} = decl { IR.typeDeclIdent = qualifyDeclIdent (IR.typeDeclIdent decl) } qualifyTypeDecl decl@IR.DataDecl {} = decl { IR.typeDeclIdent = qualifyDeclIdent (IR.typeDeclIdent decl) , IR.dataDeclCons = map qualifyConDecl (IR.dataDeclCons decl) } -- | Qualifies the name of the given constructor declaration with 'modName'. qualifyConDecl :: IR.ConDecl -> IR.ConDecl qualifyConDecl decl = decl { IR.conDeclIdent = qualifyDeclIdent (IR.conDeclIdent decl) } -- | Qualifies the function names annotated by the given type signature -- with 'modName'. qualifyTypeSig :: IR.TypeSig -> IR.TypeSig qualifyTypeSig typeSig = typeSig { IR.typeSigDeclIdents = map qualifyDeclIdent (IR.typeSigDeclIdents typeSig) } -- | Qualifies function names annotated by the given pragmas with 'modName'. qualifyPragma :: IR.Pragma -> IR.Pragma qualifyPragma (IR.DecArgPragma srcSpan funcName decArg) = IR.DecArgPragma srcSpan (qualify funcName) decArg -- | Qualifies the name of the given function declaration with 'modName'. qualifyFuncDecl :: IR.FuncDecl -> IR.FuncDecl qualifyFuncDecl decl = decl { IR.funcDeclIdent = qualifyDeclIdent (IR.funcDeclIdent decl) }