<commit_before>%
% (c) The University of Glasgow, 2000
%
\section[CompManager]{The Compilation Manager}

\begin{code}
module CompManager ( cmInit, cmLoadModule, cmUnload,
#ifdef GHCI
                     cmGetExpr, cmRunExpr,
#endif
                     CmState, emptyCmState  -- abstract
                   )
where

#include "HsVersions.h"

import CmLink
import CmTypes
import HscTypes
import Module		( Module, ModuleName, moduleName, isHomeModule,
			  mkModuleName, moduleNameUserString )
import CmStaticInfo	( GhciMode(..) )
import DriverPipeline
import GetImports
import HscTypes		( HomeSymbolTable, HomeIfaceTable, 
			  PersistentCompilerState, ModDetails(..) )
import HscMain		( initPersistentCompilerState )
import Finder
import UniqFM		( emptyUFM, lookupUFM, addToUFM, delListFromUFM,
			  UniqFM, listToUFM )
import Unique		( Uniquable )
import Digraph		( SCC(..), stronglyConnComp, flattenSCC )
import DriverFlags	( getDynFlags )
import DriverPhases
import DriverUtil	( splitFilename3 )
import ErrUtils		( showPass )
import Util
import DriverUtil
import Outputable
import Panic
import CmdLineOpts	( DynFlags(..) )
import IOExts

#ifdef GHCI
import Interpreter	( HValue )
import HscMain		( hscExpr )
import Type		( Type )
import PrelGHC		( unsafeCoerce# )
#endif

-- lang
import Exception	( throwDyn )

-- std
import Time             ( ClockTime )
import Directory        ( getModificationTime, doesFileExist )
import IO
import Monad
import List		( nub )
import Maybe		( catMaybes, fromMaybe, maybeToList, isJust )
\end{code}


\begin{code}
cmInit :: GhciMode -> IO CmState
cmInit gmode
   = emptyCmState gmode

#ifdef GHCI
cmGetExpr :: CmState
	  -> DynFlags
	  -> Bool	-- True <=> wrap in 'print' to get an IO-typed result
          -> Module
          -> String
          -> IO (CmState, Maybe (HValue, PrintUnqualified, Type))
cmGetExpr cmstate dflags wrap_io mod expr
   = do (new_pcs, maybe_stuff) <- 
	   hscExpr dflags wrap_io hst hit pcs mod expr
        case maybe_stuff of
	   Nothing     -> return (cmstate{ pcs=new_pcs }, Nothing)
	   Just (bcos, print_unqual, ty) -> do
		hValue <- linkExpr pls bcos
	        return (cmstate{ pcs=new_pcs }, 
			Just (hValue, print_unqual, ty))

   -- ToDo: check that the module we passed in is sane/exists?
   where
       CmState{ hst=hst, hit=hit, pcs=pcs, pls=pls } = cmstate

-- The HValue should represent a value of type IO () (Perhaps IO a?)
cmRunExpr :: HValue -> IO ()
cmRunExpr hval
   = do unsafeCoerce# hval :: IO ()
	-- putStrLn "done."
#endif

emptyHIT :: HomeIfaceTable
emptyHIT = emptyUFM
emptyHST :: HomeSymbolTable
emptyHST = emptyUFM

-- Persistent state for the entire system
data CmState
   = CmState {
        hst   :: HomeSymbolTable,    -- home symbol table
        hit   :: HomeIfaceTable,     -- home interface table
        ui    :: UnlinkedImage,      -- the unlinked images
        mg    :: ModuleGraph,        -- the module graph
        gmode :: GhciMode,           -- NEVER CHANGES

        pcs    :: PersistentCompilerState, -- compile's persistent state
        pls    :: PersistentLinkerState    -- link's persistent state
     }

emptyCmState :: GhciMode -> IO CmState
emptyCmState gmode
    = do pcs     <- initPersistentCompilerState
         pls     <- emptyPLS
         return (CmState { hst = emptyHST,
                           hit = emptyHIT,
                           ui  = emptyUI,
                           mg  = emptyMG, 
                           gmode = gmode,
                           pcs    = pcs,
                           pls    = pls })

-- CM internal types
type UnlinkedImage = [Linkable]	-- the unlinked images (should be a set, really)
emptyUI :: UnlinkedImage
emptyUI = []

type ModuleGraph = [ModSummary]  -- the module graph, topologically sorted
emptyMG :: ModuleGraph
emptyMG = []

\end{code}

Unload the compilation manager's state: everything it knows about the
current collection of modules in the Home package.

\begin{code}
cmUnload :: CmState -> IO CmState
cmUnload state 
 = do -- Throw away the old home dir cache
      emptyHomeDirCache
      -- Throw away the HIT and the HST
      return state{ hst=new_hst, hit=new_hit }
   where
     CmState{ hst=hst, hit=hit } = state
     (new_hst, new_hit) = retainInTopLevelEnvs [] (hst,hit)
\end{code}

The real business of the compilation manager: given a system state and
a module name, try and bring the module up to date, probably changing
the system state at the same time.

\begin{code}
cmLoadModule :: CmState 
             -> FilePath
             -> IO (CmState,		-- new state<commit_msg>[project @ 2001-01-31 12:40:51 by simonmar] Throw away linkables in cmUnload, as well as interfaces.<commit_after>%
% (c) The University of Glasgow, 2000
%
\section[CompManager]{The Compilation Manager}

\begin{code}
module CompManager ( cmInit, cmLoadModule, cmUnload,
#ifdef GHCI
                     cmGetExpr, cmRunExpr,
#endif
                     CmState, emptyCmState  -- abstract
                   )
where

#include "HsVersions.h"

import CmLink
import CmTypes
import HscTypes
import Module		( Module, ModuleName, moduleName, isHomeModule,
			  mkModuleName, moduleNameUserString )
import CmStaticInfo	( GhciMode(..) )
import DriverPipeline
import GetImports
import HscTypes		( HomeSymbolTable, HomeIfaceTable, 
			  PersistentCompilerState, ModDetails(..) )
import HscMain		( initPersistentCompilerState )
import Finder
import UniqFM		( emptyUFM, lookupUFM, addToUFM, delListFromUFM,
			  UniqFM, listToUFM )
import Unique		( Uniquable )
import Digraph		( SCC(..), stronglyConnComp, flattenSCC )
import DriverFlags	( getDynFlags )
import DriverPhases
import DriverUtil	( splitFilename3 )
import ErrUtils		( showPass )
import Util
import DriverUtil
import Outputable
import Panic
import CmdLineOpts	( DynFlags(..) )
import IOExts

#ifdef GHCI
import Interpreter	( HValue )
import HscMain		( hscExpr )
import Type		( Type )
import PrelGHC		( unsafeCoerce# )
#endif

-- lang
import Exception	( throwDyn )

-- std
import Time             ( ClockTime )
import Directory        ( getModificationTime, doesFileExist )
import IO
import Monad
import List		( nub )
import Maybe		( catMaybes, fromMaybe, maybeToList, isJust )
\end{code}


\begin{code}
cmInit :: GhciMode -> IO CmState
cmInit gmode
   = emptyCmState gmode

#ifdef GHCI
cmGetExpr :: CmState
	  -> DynFlags
	  -> Bool	-- True <=> wrap in 'print' to get an IO-typed result
          -> Module
          -> String
          -> IO (CmState, Maybe (HValue, PrintUnqualified, Type))
cmGetExpr cmstate dflags wrap_io mod expr
   = do (new_pcs, maybe_stuff) <- 
	   hscExpr dflags wrap_io hst hit pcs mod expr
        case maybe_stuff of
	   Nothing     -> return (cmstate{ pcs=new_pcs }, Nothing)
	   Just (bcos, print_unqual, ty) -> do
		hValue <- linkExpr pls bcos
	        return (cmstate{ pcs=new_pcs }, 
			Just (hValue, print_unqual, ty))

   -- ToDo: check that the module we passed in is sane/exists?
   where
       CmState{ hst=hst, hit=hit, pcs=pcs, pls=pls } = cmstate

-- The HValue should represent a value of type IO () (Perhaps IO a?)
cmRunExpr :: HValue -> IO ()
cmRunExpr hval
   = do unsafeCoerce# hval :: IO ()
	-- putStrLn "done."
#endif

emptyHIT :: HomeIfaceTable
emptyHIT = emptyUFM
emptyHST :: HomeSymbolTable
emptyHST = emptyUFM

-- Persistent state for the entire system
data CmState
   = CmState {
        hst   :: HomeSymbolTable,    -- home symbol table
        hit   :: HomeIfaceTable,     -- home interface table
        ui    :: UnlinkedImage,      -- the unlinked images
        mg    :: ModuleGraph,        -- the module graph
        gmode :: GhciMode,           -- NEVER CHANGES

        pcs    :: PersistentCompilerState, -- compile's persistent state
        pls    :: PersistentLinkerState    -- link's persistent state
     }

emptyCmState :: GhciMode -> IO CmState
emptyCmState gmode
    = do pcs     <- initPersistentCompilerState
         pls     <- emptyPLS
         return (CmState { hst = emptyHST,
                           hit = emptyHIT,
                           ui  = emptyUI,
                           mg  = emptyMG, 
                           gmode = gmode,
                           pcs    = pcs,
                           pls    = pls })

-- CM internal types
type UnlinkedImage = [Linkable]	-- the unlinked images (should be a set, really)
emptyUI :: UnlinkedImage
emptyUI = []

type ModuleGraph = [ModSummary]  -- the module graph, topologically sorted
emptyMG :: ModuleGraph
emptyMG = []

\end{code}

Unload the compilation manager's state: everything it knows about the
current collection of modules in the Home package.

\begin{code}
cmUnload :: CmState -> IO CmState
cmUnload state 
 = do -- Throw away the old home dir cache
      emptyHomeDirCache
      -- Throw away the HIT and the HST
      return state{ hst=new_hst, hit=new_hit, ui=emptyUI }
   where
     CmState{ hst=hst, hit=hit } = state
     (new_hst, new_hit) = retainInTopLevelEnvs [] (hst,hit)
\end{code}

The real business of the compilation manager: given a system state and
a module name, try and bring the module up to date, probably changing
the system state at the same time.

\begin{code}
cmLoadModule :: CmState 
             -> FilePath
             -> IO (CmState,		-- new state
{'fraction_non_alphanumeric': 0.0839364805012423, 'fraction_numerical': 0.0025926326023549746, 'mean_word_length': 2.5925494761350407, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '111961', 'n_tokens_mistral': 3005, 'n_tokens_neox': 2882, 'n_words': 925}