> module ModSysSem(mProgram) where > > import Modules > import CheckModules > import ModSysAST > import NamesEntities > import Relations(Rel,emptyRel) The semantics of a Haskell program ================================== \label{SemProg} Having defined the meaning of imports and exports, and how to detect errors, we can now glue everything together and define the meaning of a Haskell program. The semantics of a Haskell program (with respect to the module system) is a mapping from a collection of modules to their corresponding in-scope and export relations. It can be given by a function of type: > mProgram :: > [Module] -> Either [[ModSysErr]] > [(Rel QName Entity,Rel Name Entity)] Given a list of modules, the function either reports a list of errors found in each module, or returns the in-scope and export relations of the modules. There is a one-to-one correspondence between positions in the module list and positions in the resulting lists. Using the functions defined Sections~\ref{Sem} and \ref{Err}, we define the function #mProgram# as follows: > mProgram modules > | not (all null errs) = Left errs > | otherwise = Right rels > where > rels = computeInsOuts (const emptyRel) modules > errs = zipWith (chkModule expsOf) inscps modules > > (inscps,exps) = unzip rels > expsOf m = lookup m mod_exps > mod_exps = map modName modules `zip` exps It is assumed that implicit imports of the Prelude \cite[Section 5.6.1]{Haskell98} have been made explicit before #mProgram# is called. It is also assumed that all modules in the argument list have unique names. While the function #mProgram# is sufficient to explain the meaning of a Haskell program, it would probably not be very practical in a Haskell implementation, since it does not support separate compilation. Instead of #mProgram#, we have implemented a more sophisticated function based on the same key ingredients: the functions #computeInsOuts# (which supports separate compilation) and #chkModule#, described in sections \ref{rec-mods} and \ref{Err} respectively. Our Haskell front-end processes modules one strongly connected component at a time, caches module interfaces between runs, and has better error handling. We omit the implementation of these practical details from this presentation. % Section~\ref{rec-mods}