module GHC.Unit.Env
    ( UnitEnv (..)
    , preloadUnitsInfo
    , preloadUnitsInfo'
    )
where

import GHC.Prelude

import GHC.Unit.State
import GHC.Unit.Home
import GHC.Unit.Types

import GHC.Platform
import GHC.Settings
import GHC.Data.Maybe

data UnitEnv = UnitEnv
    { UnitEnv -> UnitState
ue_units     :: !UnitState      -- ^ Units
    , UnitEnv -> HomeUnit
ue_home_unit :: !HomeUnit       -- ^ Home unit
    , UnitEnv -> Platform
ue_platform  :: !Platform       -- ^ Platform
    , UnitEnv -> GhcNameVersion
ue_namever   :: !GhcNameVersion -- ^ GHC name/version (used for dynamic library suffix)
    }

-- -----------------------------------------------------------------------------
-- Extracting information from the packages in scope

-- Many of these functions take a list of packages: in those cases,
-- the list is expected to contain the "dependent packages",
-- i.e. those packages that were found to be depended on by the
-- current module/program.  These can be auto or non-auto packages, it
-- doesn't really matter.  The list is always combined with the list
-- of preload (command-line) packages to determine which packages to
-- use.

-- | Lookup 'UnitInfo' for every preload unit from the UnitState, for every unit
-- used to instantiate the home unit, and for every unit explicitly passed in
-- the given list of UnitId.
preloadUnitsInfo' :: UnitEnv -> [UnitId] -> MaybeErr UnitErr [UnitInfo]
preloadUnitsInfo' :: UnitEnv -> [UnitId] -> MaybeErr UnitErr [UnitInfo]
preloadUnitsInfo' UnitEnv
unit_env [UnitId]
ids0 = MaybeErr UnitErr [UnitInfo]
all_infos
  where
    home_unit :: HomeUnit
home_unit  = UnitEnv -> HomeUnit
ue_home_unit UnitEnv
unit_env
    unit_state :: UnitState
unit_state = UnitEnv -> UnitState
ue_units     UnitEnv
unit_env
    ids :: [UnitId]
ids      = [UnitId]
ids0 [UnitId] -> [UnitId] -> [UnitId]
forall a. [a] -> [a] -> [a]
++ [UnitId]
inst_ids
    inst_ids :: [UnitId]
inst_ids
       -- An indefinite package will have insts to HOLE,
       -- which is not a real package. Don't look it up.
       -- Fixes #14525
       | HomeUnit -> Bool
forall u. GenHomeUnit u -> Bool
isHomeUnitIndefinite HomeUnit
home_unit = []
       | Bool
otherwise = ((ModuleName, GenModule Unit) -> UnitId)
-> [(ModuleName, GenModule Unit)] -> [UnitId]
forall a b. (a -> b) -> [a] -> [b]
map (Unit -> UnitId
toUnitId (Unit -> UnitId)
-> ((ModuleName, GenModule Unit) -> Unit)
-> (ModuleName, GenModule Unit)
-> UnitId
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GenModule Unit -> Unit
forall unit. GenModule unit -> unit
moduleUnit (GenModule Unit -> Unit)
-> ((ModuleName, GenModule Unit) -> GenModule Unit)
-> (ModuleName, GenModule Unit)
-> Unit
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ModuleName, GenModule Unit) -> GenModule Unit
forall a b. (a, b) -> b
snd) (HomeUnit -> [(ModuleName, GenModule Unit)]
forall u. GenHomeUnit u -> GenInstantiations u
homeUnitInstantiations HomeUnit
home_unit)
    pkg_map :: UnitInfoMap
pkg_map = UnitState -> UnitInfoMap
unitInfoMap UnitState
unit_state
    preload :: [UnitId]
preload = UnitState -> [UnitId]
preloadUnits UnitState
unit_state

    all_pkgs :: MaybeErr UnitErr [UnitId]
all_pkgs  = UnitInfoMap
-> [UnitId]
-> [(UnitId, Maybe UnitId)]
-> MaybeErr UnitErr [UnitId]
closeUnitDeps' UnitInfoMap
pkg_map [UnitId]
preload ([UnitId]
ids [UnitId] -> [Maybe UnitId] -> [(UnitId, Maybe UnitId)]
forall a b. [a] -> [b] -> [(a, b)]
`zip` Maybe UnitId -> [Maybe UnitId]
forall a. a -> [a]
repeat Maybe UnitId
forall a. Maybe a
Nothing)
    all_infos :: MaybeErr UnitErr [UnitInfo]
all_infos = (UnitId -> UnitInfo) -> [UnitId] -> [UnitInfo]
forall a b. (a -> b) -> [a] -> [b]
map (HasDebugCallStack => UnitState -> UnitId -> UnitInfo
UnitState -> UnitId -> UnitInfo
unsafeLookupUnitId UnitState
unit_state) ([UnitId] -> [UnitInfo])
-> MaybeErr UnitErr [UnitId] -> MaybeErr UnitErr [UnitInfo]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MaybeErr UnitErr [UnitId]
all_pkgs


-- | Lookup 'UnitInfo' for every preload unit from the UnitState and for every
-- unit used to instantiate the home unit.
preloadUnitsInfo :: UnitEnv -> MaybeErr UnitErr [UnitInfo]
preloadUnitsInfo :: UnitEnv -> MaybeErr UnitErr [UnitInfo]
preloadUnitsInfo UnitEnv
unit_env = UnitEnv -> [UnitId] -> MaybeErr UnitErr [UnitInfo]
preloadUnitsInfo' UnitEnv
unit_env []