-- | See module Distribution.Backpack.ModuleScope ( -- * Module scopes ModuleScope(..), ModuleProvides, ModuleSource(..), emptyModuleScope, ) where import Prelude () import Distribution.ModuleName import Distribution.Package import Distribution.Types.IncludeRenaming import Distribution.Backpack import Distribution.Backpack.ModSubst import Data.Map (Map) import qualified Data.Map as Map import Data.Set (Set) import qualified Data.Set as Set ----------------------------------------------------------------------- -- Module scopes -- Why is ModuleProvides so complicated? The basic problem is that -- we want to support this: -- -- package p where -- include q (A) -- include r (A) -- module B where -- import "q" A -- import "r" A -- -- Specifically, in Cabal today it is NOT an error have two modules in -- scope with the same identifier. So we need to preserve this for -- Backpack. The modification is that an ambiguous module name is -- OK... as long as it is NOT used to fill a requirement! -- -- So as a first try, we might try deferring unifying provisions that -- are being glommed together, and check for equality after the fact. -- But this doesn't work, because what if a multi-module provision -- is used to fill a requirement?! So you do the equality test -- IMMEDIATELY before a requirement fill happens... or never at all. -- -- Alternate strategy: go ahead and unify, and then if it is revealed -- that some requirements got filled "out-of-thin-air", error. -- | A 'ModuleScope' describes the modules and requirements that -- are in-scope as we are processing a Cabal package. Unlike -- a 'ModuleShape', there may be multiple modules in scope at -- the same 'ModuleName'; this is only an error if we attempt -- to use those modules to fill a requirement. A 'ModuleScope' -- can influence the 'ModuleShape' via a reexport. data ModuleScope = ModuleScope { modScopeProvides :: ModuleProvides, modScopeRequires :: Set ModuleName } -- | Every 'Module' in scope at a 'ModuleName' is annotated with -- the 'PackageName' it comes from. type ModuleProvides = Map ModuleName [ModuleSource] data ModuleSource = ModuleSource { -- We don't have line numbers, but if we did the -- package name and renaming could be associated -- with that as well msrc_pkgname :: PackageName, msrc_renaming :: IncludeRenaming, msrc_module :: OpenModule } instance ModSubst ModuleScope where modSubst subst (ModuleScope provs reqs) = ModuleScope (modSubst subst provs) (modSubst subst reqs) -- | An empty 'ModuleScope'. emptyModuleScope :: ModuleScope emptyModuleScope = ModuleScope Map.empty Set.empty instance ModSubst ModuleSource where modSubst subst src = src { msrc_module = modSubst subst (msrc_module src) }