-- | This module contains a compiler pass that adds all entries from imported -- modules to the environment. -- -- = Example -- -- When a module @A@ that exports a data type @Foo@ -- -- > module A where -- > -- > data Foo = Foo -- -- is imported by a module @B@ -- -- > module B where -- > -- > import A -- > -- > type Bar a = Foo -> a -- -- then an entry for @Foo@ is added to the environment under its original -- name @A.Foo@. The resolver pass will make sure that the reference to @Foo@ -- in the declaration of @Bar@ is resolved to @A.Foo@. Thus, the entry for -- @Foo@ can be looked up in the translation of @B@. -- -- When a module @C@ imports @B@ -- -- > module C where -- > -- > import B -- > -- > baz :: Bar () -- > baz x = () -- -- both @A.Foo@ and @B.Bar@ are added to the environment of @C@ since all -- entries imported by @B@ are part of the @B@'s module interface. -- In the example above this is needed among others during type inference. -- To infer the type of @x@ the type synonym @Bar@ needs to be expanded. -- The type of @x@ is @A.Foo@. Thus, the corresponding entry must be visible. -- The resolver pass will make sure that @C@ does not directly refer to the -- hidden entries of @B@'s module interface. -- -- = Specification -- -- == Preconditions -- -- Module interfaces for all imported modules must be available. -- -- == Translation -- -- No modifications are made to the AST. All entries from module interfaces -- of imported modules are added to the environment. This includes entries -- that are not exported by the imported module. -- -- == Postconditions -- -- All external entries that could be referenced (directly or indirectly) -- by the module are in the environment. -- -- == Error cases -- -- * A fatal error is reported if there is an import for a module @M@ but -- there is no such module interface available. module FreeC.Pass.ImportPass ( importPass ) where import qualified Data.Set as Set import FreeC.Environment import FreeC.Environment.Entry import FreeC.Environment.LookupOrFail import FreeC.Environment.ModuleInterface import qualified FreeC.IR.Syntax as IR import FreeC.Monad.Converter import FreeC.Pass -- | Compiler pass that adds entries imported by the given module to the -- environment. importPass :: Pass IR.Module IR.Module importPass ast = do mapM_ importModule (IR.modImports ast) return ast -- | Inserts multiple entries into the given environment and associates them -- with their original names. importEntries :: [EnvEntry] -> Environment -> Environment importEntries = flip (foldr addEntry) -- | Imports all entries from the given module interface into the given -- interface. -- -- This function imports entries that are not exported by the given -- interface as well. importInterface :: ModuleInterface -> Environment -> Environment importInterface = importEntries . Set.toList . interfaceEntries -- | Adds the entries of the module interface imported by the given import -- declaration to the environment. -- -- Reports a fatal error when there is no such module. importModule :: IR.ImportDecl -> Converter () importModule (IR.ImportDecl srcSpan modName) = do iface <- lookupAvailableModuleOrFail srcSpan modName modifyEnv $ importInterface iface