diff --git a/app/Main.hs b/app/Main.hs index 3624342be64cf28e0d4605ce1c3884590321e2e8..3127c0ee36055decbb8c457d767c834e832e0b9d 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -1,6 +1,6 @@ module Main where -import qualified HpcMain as HPC +import qualified Trace.Hpc.Main as HPC main :: IO () -main = HPC.main \ No newline at end of file +main = HPC.main diff --git a/hpc-bin.cabal b/hpc-bin.cabal index 58bad0470a7fa46d2630e1a3c6d6a0a16f6ebf79..a52430ec769aaf13c26a18fe050abcf280c6d1cd 100644 --- a/hpc-bin.cabal +++ b/hpc-bin.cabal @@ -29,17 +29,20 @@ executable hpc app, src main-is: Main.hs - other-modules: HpcParser - HpcCombine - HpcDraft - HpcFlags - HpcLexer - HpcMarkup - HpcOverlay - HpcReport - HpcShowTix - HpcUtils - HpcMain + other-modules: Trace.Hpc.Parser + Trace.Hpc.Combine + Trace.Hpc.Draft + Trace.Hpc.Flags + Trace.Hpc.Lexer + Trace.Hpc.Plugin + Trace.Hpc.Markup + Trace.Hpc.Map + Trace.Hpc.Sum + Trace.Hpc.Overlay + Trace.Hpc.Report + Trace.Hpc.ShowTix + Trace.Hpc.Utils + Trace.Hpc.Main Paths_hpc_bin autogen-modules: Paths_hpc_bin diff --git a/src/HpcCombine.hs b/src/HpcCombine.hs deleted file mode 100644 index 7dc568ddcb84308e70b167fd60956d14f81827e2..0000000000000000000000000000000000000000 --- a/src/HpcCombine.hs +++ /dev/null @@ -1,150 +0,0 @@ ---------------------------------------------------------- --- The main program for the hpc-add tool, part of HPC. --- Andy Gill, Oct 2006 ---------------------------------------------------------- - -module HpcCombine (sumPlugin, combinePlugin, mapPlugin) where - -import Control.DeepSeq -import Control.Monad -import qualified Data.Map as Map -import qualified Data.Set as Set -import HpcFlags -import Trace.Hpc.Tix - ------------------------------------------------------------------------------- - -sumOptions :: FlagOptSeq -sumOptions = - excludeOpt - . includeOpt - . outputOpt - . unionModuleOpt - . verbosityOpt - -sumPlugin :: Plugin -sumPlugin = - Plugin - { name = "sum", - usage = "[OPTION] .. <TIX_FILE> [<TIX_FILE> [<TIX_FILE> ..]]", - options = sumOptions, - summary = "Sum multiple .tix files in a single .tix file", - implementation = sumMain - } - -combineOptions :: FlagOptSeq -combineOptions = - excludeOpt - . includeOpt - . outputOpt - . combineFunOpt - . combineFunOptInfo - . unionModuleOpt - . verbosityOpt - -combinePlugin :: Plugin -combinePlugin = - Plugin - { name = "combine", - usage = "[OPTION] .. <TIX_FILE> <TIX_FILE>", - options = combineOptions, - summary = "Combine two .tix files in a single .tix file", - implementation = combineMain - } - -mapOptions :: FlagOptSeq -mapOptions = - excludeOpt - . includeOpt - . outputOpt - . mapFunOpt - . mapFunOptInfo - . unionModuleOpt - . verbosityOpt - -mapPlugin :: Plugin -mapPlugin = - Plugin - { name = "map", - usage = "[OPTION] .. <TIX_FILE> ", - options = mapOptions, - summary = "Map a function over a single .tix file", - implementation = mapMain - } - ------------------------------------------------------------------------------- - -sumMain :: Flags -> [String] -> IO () -sumMain _ [] = hpcError sumPlugin "no .tix file specified" -sumMain flags (first_file : more_files) = do - Just tix <- readTix first_file - - tix' <- foldM (mergeTixFile flags (+)) (filterTix flags tix) more_files - - case outputFile flags of - "-" -> print tix' - out -> writeTix out tix' - -combineMain :: Flags -> [String] -> IO () -combineMain flags [first_file, second_file] = do - let f = theCombineFun (combineFun flags) - - Just tix1 <- readTix first_file - Just tix2 <- readTix second_file - - let tix = mergeTix (mergeModule flags) f (filterTix flags tix1) (filterTix flags tix2) - - case outputFile flags of - "-" -> print tix - out -> writeTix out tix -combineMain _ _ = hpcError combinePlugin "need exactly two .tix files to combine" - -mapMain :: Flags -> [String] -> IO () -mapMain flags [first_file] = do - let f = thePostFun (postFun flags) - - Just tix <- readTix first_file - - let (Tix inside_tix) = filterTix flags tix - let tix' = Tix [TixModule m p i (map f t) | TixModule m p i t <- inside_tix] - - case outputFile flags of - "-" -> print tix' - out -> writeTix out tix' -mapMain _ [] = hpcError mapPlugin "no .tix file specified" -mapMain _ _ = hpcError mapPlugin "to many .tix files specified" - -mergeTixFile :: Flags -> (Integer -> Integer -> Integer) -> Tix -> String -> IO Tix -mergeTixFile flags fn tix file_name = do - Just new_tix <- readTix file_name - return $! force $ mergeTix (mergeModule flags) fn tix (filterTix flags new_tix) - --- could allow different numbering on the module info, --- as long as the total is the same; will require normalization. - -mergeTix :: MergeFun -> (Integer -> Integer -> Integer) -> Tix -> Tix -> Tix -mergeTix modComb f (Tix t1) (Tix t2) = - Tix - [ case (Map.lookup m fm1, Map.lookup m fm2) of - -- todo, revisit the semantics of this combination - (Just (TixModule _ hash1 len1 tix1), Just (TixModule _ hash2 len2 tix2)) - | hash1 /= hash2 - || length tix1 /= length tix2 - || len1 /= length tix1 - || len2 /= length tix2 -> - error $ "mismatched in module " ++ m - | otherwise -> - TixModule m hash1 len1 (zipWith f tix1 tix2) - (Just m1, Nothing) -> - m1 - (Nothing, Just m2) -> - m2 - _ -> error "impossible" - | m <- Set.toList (theMergeFun modComb m1s m2s) - ] - where - m1s = Set.fromList $ map tixModuleName t1 - m2s = Set.fromList $ map tixModuleName t2 - - fm1 = Map.fromList [(tixModuleName tix, tix) | tix <- t1] - fm2 = Map.fromList [(tixModuleName tix, tix) | tix <- t2] diff --git a/src/Trace/Hpc/Combine.hs b/src/Trace/Hpc/Combine.hs new file mode 100644 index 0000000000000000000000000000000000000000..95da809fb6a0ae7d4989e918a94f97b912ddbfe5 --- /dev/null +++ b/src/Trace/Hpc/Combine.hs @@ -0,0 +1,49 @@ +-- | +-- Module : Trace.Hpc.Combine +-- Description : The subcommand @hpc combine@ +-- Copyright : Andy Gill, 2006 +-- License : BSD-3-Clause +module Trace.Hpc.Combine (combinePlugin) where + +import Control.DeepSeq +import Control.Monad +import qualified Data.Map as Map +import qualified Data.Set as Set +import Trace.Hpc.Flags +import Trace.Hpc.Plugin +import Trace.Hpc.Tix +import Trace.Hpc.Utils + +combineOptions :: FlagOptSeq +combineOptions = + excludeOpt + . includeOpt + . outputOpt + . combineFunOpt + . combineFunOptInfo + . unionModuleOpt + . verbosityOpt + +combinePlugin :: Plugin +combinePlugin = + Plugin + { name = "combine", + usage = "[OPTION] .. <TIX_FILE> <TIX_FILE>", + options = combineOptions, + summary = "Combine two .tix files in a single .tix file", + implementation = combineMain + } + +combineMain :: Flags -> [String] -> IO () +combineMain flags [first_file, second_file] = do + let f = theCombineFun (combineFun flags) + + Just tix1 <- readTix first_file + Just tix2 <- readTix second_file + + let tix = mergeTix (mergeModule flags) f (filterTix flags tix1) (filterTix flags tix2) + + case outputFile flags of + "-" -> print tix + out -> writeTix out tix +combineMain _ _ = hpcError combinePlugin "need exactly two .tix files to combine" diff --git a/src/HpcDraft.hs b/src/Trace/Hpc/Draft.hs similarity index 94% rename from src/HpcDraft.hs rename to src/Trace/Hpc/Draft.hs index ea4acc1f980f83d60ae8af5af813de960098c5d9..9d47b8acae66e4544afdeca3a125d9b5cfd069ac 100644 --- a/src/HpcDraft.hs +++ b/src/Trace/Hpc/Draft.hs @@ -1,13 +1,18 @@ -module HpcDraft (draftPlugin) where +-- | +-- Module : Trace.Hpc.Draft +-- Description : The subcommand @hpc draft@ +-- License : BSD-3-Clause +module Trace.Hpc.Draft (draftPlugin) where import qualified Data.Map as Map import qualified Data.Set as Set import Data.Tree -import HpcFlags -import HpcUtils +import Trace.Hpc.Flags import Trace.Hpc.Mix +import Trace.Hpc.Plugin import Trace.Hpc.Tix import Trace.Hpc.Util +import Trace.Hpc.Utils ------------------------------------------------------------------------------ diff --git a/src/HpcFlags.hs b/src/Trace/Hpc/Flags.hs similarity index 90% rename from src/HpcFlags.hs rename to src/Trace/Hpc/Flags.hs index c7952677423cb814ec17207e878b1b3c1c933c88..361f91f2579a07cd30190891bb3a49022bea9a99 100644 --- a/src/HpcFlags.hs +++ b/src/Trace/Hpc/Flags.hs @@ -1,6 +1,9 @@ --- (c) 2007 Andy Gill - -module HpcFlags where +-- | +-- Module : Trace.Hpc.Flags +-- Description : Commandline flags for hpc +-- Copyright : Andy Gill, 2007 +-- License : BSD-3-Clause +module Trace.Hpc.Flags where import Data.Char import qualified Data.Set as Set @@ -233,38 +236,6 @@ readMixWithFlags flags = hpcDir <- hpcDirs flags ] -------------------------------------------------------------------------------- - -commandUsage :: Plugin -> IO () -commandUsage plugin = - putStrLn $ - "Usage: hpc " - ++ name plugin - ++ " " - ++ usage plugin - ++ "\n" - ++ summary plugin - ++ "\n" - ++ if null (options plugin []) - then "" - else usageInfo "\n\nOptions:\n" (options plugin []) - -hpcError :: Plugin -> String -> IO a -hpcError plugin msg = do - putStrLn $ "Error: " ++ msg - commandUsage plugin - exitFailure - -------------------------------------------------------------------------------- - -data Plugin = Plugin - { name :: String, - usage :: String, - options :: FlagOptSeq, - summary :: String, - implementation :: Flags -> [String] -> IO () - } - ------------------------------------------------------------------------------ -- filterModules takes a list of candidate modules, diff --git a/src/HpcLexer.hs b/src/Trace/Hpc/Lexer.hs similarity index 91% rename from src/HpcLexer.hs rename to src/Trace/Hpc/Lexer.hs index 2cee0fde934650e4b34ff954f8300c1a8b723d6f..fe41c46cc899bc362b1820e059ff3368db4291c1 100644 --- a/src/HpcLexer.hs +++ b/src/Trace/Hpc/Lexer.hs @@ -1,4 +1,8 @@ -module HpcLexer where +-- | +-- Module : Trace.Hpc.Lexer +-- Description : A lexer for overlay files use by @hpc overlay@ +-- License : BSD-3-Clause +module Trace.Hpc.Lexer where import Data.Char diff --git a/src/HpcMain.hs b/src/Trace/Hpc/Main.hs similarity index 92% rename from src/HpcMain.hs rename to src/Trace/Hpc/Main.hs index 74c98ceadc31027eadf25d61b362d4fa00be1c90..11b005b5da55651e0039f693342dc15024634ee6 100644 --- a/src/HpcMain.hs +++ b/src/Trace/Hpc/Main.hs @@ -1,29 +1,34 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TupleSections #-} -module HpcMain (main) where - --- (c) 2007 Andy Gill --- Main driver for Hpc +-- | +-- Module : Trace.Hpc.Main +-- Description : The main driver for Hpc +-- Copyright : Andy Gill, 2007 +-- License : BSD-3-Clause +module Trace.Hpc.Main (main) where import Control.Monad import Data.Bifunctor -import Data.List ( intercalate, partition, uncons ) +import Data.List (intercalate, partition, uncons) import Data.List.NonEmpty (NonEmpty (..)) import Data.Maybe import Data.Version -import HpcCombine -import HpcDraft -import HpcFlags -import HpcMarkup -import HpcOverlay -import HpcReport -import HpcShowTix import Paths_hpc_bin import System.Console.GetOpt import System.Directory import System.Environment import System.Exit +import Trace.Hpc.Combine +import Trace.Hpc.Draft +import Trace.Hpc.Flags +import Trace.Hpc.Map +import Trace.Hpc.Markup +import Trace.Hpc.Overlay +import Trace.Hpc.Plugin +import Trace.Hpc.Report +import Trace.Hpc.ShowTix +import Trace.Hpc.Sum ------------------------------------------------------------------------------ diff --git a/src/Trace/Hpc/Map.hs b/src/Trace/Hpc/Map.hs new file mode 100644 index 0000000000000000000000000000000000000000..66f30b50362488d670dd4d3b44c46fbf5340b2a7 --- /dev/null +++ b/src/Trace/Hpc/Map.hs @@ -0,0 +1,45 @@ +-- | +-- Module : Trace.Hpc.Map +-- Description : The subcommand @hpc map@ +-- Copyright : Andy Gill, 2006 +-- License : BSD-3-Clause +module Trace.Hpc.Map (mapPlugin) where + +import Trace.Hpc.Flags +import Trace.Hpc.Plugin +import Trace.Hpc.Tix + +mapOptions :: FlagOptSeq +mapOptions = + excludeOpt + . includeOpt + . outputOpt + . mapFunOpt + . mapFunOptInfo + . unionModuleOpt + . verbosityOpt + +mapPlugin :: Plugin +mapPlugin = + Plugin + { name = "map", + usage = "[OPTION] .. <TIX_FILE> ", + options = mapOptions, + summary = "Map a function over a single .tix file", + implementation = mapMain + } + +mapMain :: Flags -> [String] -> IO () +mapMain flags [first_file] = do + let f = thePostFun (postFun flags) + + Just tix <- readTix first_file + + let (Tix inside_tix) = filterTix flags tix + let tix' = Tix [TixModule m p i (map f t) | TixModule m p i t <- inside_tix] + + case outputFile flags of + "-" -> print tix' + out -> writeTix out tix' +mapMain _ [] = hpcError mapPlugin "no .tix file specified" +mapMain _ _ = hpcError mapPlugin "to many .tix files specified" diff --git a/src/HpcMarkup.hs b/src/Trace/Hpc/Markup.hs similarity index 98% rename from src/HpcMarkup.hs rename to src/Trace/Hpc/Markup.hs index 1c787db9be8c8adace23c8dd93ad4068879953c3..884d02065dd3c609ba305a79ae37e79fdd8ebe48 100644 --- a/src/HpcMarkup.hs +++ b/src/Trace/Hpc/Markup.hs @@ -1,22 +1,23 @@ ---------------------------------------------------------- --- The main program for the hpc-markup tool, part of HPC. --- Andy Gill and Colin Runciman, June 2006 ---------------------------------------------------------- - -module HpcMarkup (markupPlugin) where +-- | +-- Module : Trace.Hpc.Markup +-- Description : The subcommand @hpc markup@ +-- Copyright : Andy Gill and Colin Runciman, 2006 +-- License : BSD-3-Clause +module Trace.Hpc.Markup (markupPlugin) where import Control.Monad import Data.Array -import Data.List ( find, sortBy ) +import Data.List (find, sortBy) import Data.Maybe import Data.Semigroup as Semi import qualified Data.Set as Set -import HpcFlags -import HpcUtils import System.FilePath +import Trace.Hpc.Flags import Trace.Hpc.Mix +import Trace.Hpc.Plugin import Trace.Hpc.Tix import Trace.Hpc.Util +import Trace.Hpc.Utils ------------------------------------------------------------------------------ diff --git a/src/HpcOverlay.hs b/src/Trace/Hpc/Overlay.hs similarity index 94% rename from src/HpcOverlay.hs rename to src/Trace/Hpc/Overlay.hs index 831edb8b246e0fcda3512b9a0894de7e4c2f6b77..77b882310e0d29ff2c090a3d842b1c9c25822001 100644 --- a/src/HpcOverlay.hs +++ b/src/Trace/Hpc/Overlay.hs @@ -1,13 +1,18 @@ -module HpcOverlay where +-- | +-- Module : Trace.Hpc.Overlay +-- Description : The subcommand @hpc overlay@ +-- License : BSD-3-Clause +module Trace.Hpc.Overlay where import qualified Data.Map as Map import Data.Tree -import HpcFlags -import HpcParser -import HpcUtils +import Trace.Hpc.Flags import Trace.Hpc.Mix +import Trace.Hpc.Parser +import Trace.Hpc.Plugin import Trace.Hpc.Tix import Trace.Hpc.Util +import Trace.Hpc.Utils ------------------------------------------------------------------------------ diff --git a/src/HpcParser.y b/src/Trace/Hpc/Parser.y similarity index 97% rename from src/HpcParser.y rename to src/Trace/Hpc/Parser.y index ea660893ad2afbfe8ef9eb89e83881ba86b05cc4..92a24867c66fee9dafbaa194d9683832ca5657a9 100644 --- a/src/HpcParser.y +++ b/src/Trace/Hpc/Parser.y @@ -1,7 +1,7 @@ { -module HpcParser where +module Trace.Hpc.Parser where -import HpcLexer +import Trace.Hpc.Lexer } %name parser diff --git a/src/Trace/Hpc/Plugin.hs b/src/Trace/Hpc/Plugin.hs new file mode 100644 index 0000000000000000000000000000000000000000..c3f22bdaa26b1135a143e80779f08c237b118576 --- /dev/null +++ b/src/Trace/Hpc/Plugin.hs @@ -0,0 +1,37 @@ +-- | +-- Module : Trace.Hpc.Plugin +-- Description : The plugin type used by subcommands +-- License : BSD-3-Clause +module Trace.Hpc.Plugin where + +import System.Console.GetOpt +import System.Exit +import Trace.Hpc.Flags + +data Plugin = Plugin + { name :: String, + usage :: String, + options :: FlagOptSeq, + summary :: String, + implementation :: Flags -> [String] -> IO () + } + +commandUsage :: Plugin -> IO () +commandUsage plugin = + putStrLn $ + "Usage: hpc " + ++ name plugin + ++ " " + ++ usage plugin + ++ "\n" + ++ summary plugin + ++ "\n" + ++ if null (options plugin []) + then "" + else usageInfo "\n\nOptions:\n" (options plugin []) + +hpcError :: Plugin -> String -> IO a +hpcError plugin msg = do + putStrLn $ "Error: " ++ msg + commandUsage plugin + exitFailure diff --git a/src/HpcReport.hs b/src/Trace/Hpc/Report.hs similarity index 97% rename from src/HpcReport.hs rename to src/Trace/Hpc/Report.hs index ca01da43b8870fb0050e301b764b0f7157a4b8e8..d7fa1be114d35b06ecf3c4b4939c779ae570b4fd 100644 --- a/src/HpcReport.hs +++ b/src/Trace/Hpc/Report.hs @@ -1,16 +1,17 @@ ---------------------------------------------------------- --- The main program for the hpc-report tool, part of HPC. --- Colin Runciman and Andy Gill, June 2006 ---------------------------------------------------------- - -module HpcReport (reportPlugin) where +-- | +-- Module : Trace.Hpc.Report +-- Description : The subcommand @hpc report@ +-- Copyright : Andy Gill and Colin Runciman, 2006 +-- License : BSD-3-Clause +module Trace.Hpc.Report (reportPlugin) where import Control.Monad hiding (guard) import Data.Function import Data.List (intercalate, sort, sortBy) import qualified Data.Set as Set -import HpcFlags +import Trace.Hpc.Flags import Trace.Hpc.Mix +import Trace.Hpc.Plugin import Trace.Hpc.Tix import Prelude hiding (exp) diff --git a/src/HpcShowTix.hs b/src/Trace/Hpc/ShowTix.hs similarity index 89% rename from src/HpcShowTix.hs rename to src/Trace/Hpc/ShowTix.hs index bb346219f65f589de20a356dc18d384c175c1637..4eeb9564748f7a80b4878a088020d0dc0ec88367 100644 --- a/src/HpcShowTix.hs +++ b/src/Trace/Hpc/ShowTix.hs @@ -1,8 +1,13 @@ -module HpcShowTix (showtixPlugin) where +-- | +-- Module : Trace.Hpc.ShowTix +-- Description : The subcommand @hpc show@ +-- License : BSD-3-Clause +module Trace.Hpc.ShowTix (showtixPlugin) where import qualified Data.Set as Set -import HpcFlags +import Trace.Hpc.Flags import Trace.Hpc.Mix +import Trace.Hpc.Plugin import Trace.Hpc.Tix ------------------------------------------------------------------------------ diff --git a/src/Trace/Hpc/Sum.hs b/src/Trace/Hpc/Sum.hs new file mode 100644 index 0000000000000000000000000000000000000000..3416e644c092b0207942b2a056d7e5b6a2697732 --- /dev/null +++ b/src/Trace/Hpc/Sum.hs @@ -0,0 +1,47 @@ +-- | +-- Module : Trace.Hpc.Sum +-- Description : The subcommand @hpc sum@ +-- Copyright : Andy Gill, 2006 +-- License : BSD-3-Clause +module Trace.Hpc.Sum (sumPlugin) where + +import Control.DeepSeq +import Control.Monad +import Trace.Hpc.Flags +import Trace.Hpc.Plugin +import Trace.Hpc.Tix +import Trace.Hpc.Utils + +sumOptions :: FlagOptSeq +sumOptions = + excludeOpt + . includeOpt + . outputOpt + . unionModuleOpt + . verbosityOpt + +sumPlugin :: Plugin +sumPlugin = + Plugin + { name = "sum", + usage = "[OPTION] .. <TIX_FILE> [<TIX_FILE> [<TIX_FILE> ..]]", + options = sumOptions, + summary = "Sum multiple .tix files in a single .tix file", + implementation = sumMain + } + +sumMain :: Flags -> [String] -> IO () +sumMain _ [] = hpcError sumPlugin "no .tix file specified" +sumMain flags (first_file : more_files) = do + Just tix <- readTix first_file + + tix' <- foldM (mergeTixFile flags (+)) (filterTix flags tix) more_files + + case outputFile flags of + "-" -> print tix' + out -> writeTix out tix' + +mergeTixFile :: Flags -> (Integer -> Integer -> Integer) -> Tix -> String -> IO Tix +mergeTixFile flags fn tix file_name = do + Just new_tix <- readTix file_name + return $! force $ mergeTix (mergeModule flags) fn tix (filterTix flags new_tix) diff --git a/src/HpcUtils.hs b/src/Trace/Hpc/Utils.hs similarity index 53% rename from src/HpcUtils.hs rename to src/Trace/Hpc/Utils.hs index a3ee5a66bc273171db5399086d3a3db2011720ea..bf0b608452d9aa30882b085a6460072ee46b200c 100644 --- a/src/HpcUtils.hs +++ b/src/Trace/Hpc/Utils.hs @@ -1,7 +1,15 @@ -module HpcUtils where +-- | +-- Module : Trace.Hpc.Utils +-- Description : Utility functions for hpc-bin +-- License : BSD-3-Clause +module Trace.Hpc.Utils where +import Control.DeepSeq import qualified Data.Map as Map +import qualified Data.Set as Set import System.FilePath +import Trace.Hpc.Flags +import Trace.Hpc.Tix import Trace.Hpc.Util ------------------------------------------------------------------------------ @@ -46,3 +54,30 @@ readFileFromPath err filename path0 = readTheFile path0 catchIO (readFileUtf8 (dir </> filename)) (\_ -> readTheFile dirs) + +mergeTix :: MergeFun -> (Integer -> Integer -> Integer) -> Tix -> Tix -> Tix +mergeTix modComb f (Tix t1) (Tix t2) = + Tix + [ case (Map.lookup m fm1, Map.lookup m fm2) of + -- todo, revisit the semantics of this combination + (Just (TixModule _ hash1 len1 tix1), Just (TixModule _ hash2 len2 tix2)) + | hash1 /= hash2 + || length tix1 /= length tix2 + || len1 /= length tix1 + || len2 /= length tix2 -> + error $ "mismatched in module " ++ m + | otherwise -> + TixModule m hash1 len1 (zipWith f tix1 tix2) + (Just m1, Nothing) -> + m1 + (Nothing, Just m2) -> + m2 + _ -> error "impossible" + | m <- Set.toList (theMergeFun modComb m1s m2s) + ] + where + m1s = Set.fromList $ map tixModuleName t1 + m2s = Set.fromList $ map tixModuleName t2 + + fm1 = Map.fromList [(tixModuleName tix, tix) | tix <- t1] + fm2 = Map.fromList [(tixModuleName tix, tix) | tix <- t2]