2 % (c) The University of Glasgow, 2000
4 \section[CmSummarise]{Module summariser for GHCI}
7 module CmSummarise ( ModImport(..), mimp_name,
8 ModSummary(..), summarise, ms_get_imports,
9 name_of_summary, deps_of_summary,
13 #include "HsVersions.h"
16 import Char ( isAlphaNum )
17 import Util ( unJust )
18 import HscTypes ( ModuleLocation(..) )
27 -- The Module contains the original source filename of the module.
28 -- The ms_ppsource field contains another filename, which is intended to
29 -- be the cleaned-up source file after all preprocessing has happened to
30 -- it. The point is that the summariser will have to cpp/unlit/whatever
31 -- all files anyway, and there's no point in doing this twice -- just
32 -- park the result in a temp file, put the name of it in ms_ppsource,
33 -- and let @compile@ read from that file on the way back up.
36 ms_mod :: Module, -- name, package
37 ms_location :: ModuleLocation, -- location
38 ms_imports :: (Maybe [ModImport]) -- imports if .hs or .hi
41 instance Outputable ModSummary where
43 = sep [text "ModSummary {",
44 nest 3 (sep [text "ms_mod =" <+> ppr (ms_mod ms),
45 text "ms_imports=" <+> ppr (ms_imports ms)]),
50 = MINormal ModuleName | MISource ModuleName
53 instance Outputable ModImport where
54 ppr (MINormal nm) = ppr nm
55 ppr (MISource nm) = text "{-# SOURCE #-}" <+> ppr nm
58 mimp_name (MINormal nm) = nm
59 mimp_name (MISource nm) = nm
61 name_of_summary :: ModSummary -> ModuleName
62 name_of_summary = moduleName . ms_mod
64 deps_of_summary :: ModSummary -> [ModuleName]
65 deps_of_summary = map mimp_name . ms_get_imports
67 ms_get_imports :: ModSummary -> [ModImport]
69 = case ms_imports summ of { Just is -> is; Nothing -> [] }
71 type Fingerprint = Int
73 summarise :: Module -> ModuleLocation -> IO ModSummary
74 summarise mod location
75 | isModuleInThisPackage mod
76 = do let hspp_fn = unJust (ml_hspp_file location) "summarise"
77 modsrc <- readFile hspp_fn
78 let imps = getImports modsrc
79 return (ModSummary mod location (Just imps))
81 = return (ModSummary mod location Nothing)
84 Collect up the imports from a Haskell source module. This is
85 approximate: we don't parse the module, but we do eliminate comments
86 and strings. Doesn't currently know how to unlit or cppify the module
91 getImports :: String -> [ModImport]
92 getImports = nub . gmiBase . clean
94 -- really get the imports from a de-litted, cpp'd, de-literal'd string
95 gmiBase :: String -> [ModImport]
99 f ("foreign" : "import" : ws) = f ws
100 f ("import" : "{-#" : "SOURCE" : "#-}" : "qualified" : m : ws)
101 = MISource (mkMN m) : f ws
102 f ("import" : "{-#" : "SOURCE" : "#-}" : m : ws)
103 = MISource (mkMN m) : f ws
104 f ("import" : "qualified" : m : ws)
105 = MINormal (mkMN m) : f ws
106 f ("import" : m : ws)
107 = MINormal (mkMN m) : f ws
111 mkMN str = mkModuleName (takeWhile isModId str)
112 isModId c = isAlphaNum c || c `elem` "'_"
114 -- remove literals and comments from a string
115 clean :: String -> String
119 -- running through text we want to keep
121 keep ('"':cs) = dquote cs -- "
122 -- try to eliminate single quotes when they're part of
124 keep (c:'\'':cs) | isAlphaNum c || c == '_' = keep (dropWhile (=='\'') cs)
125 keep ('\'':cs) = squote cs
126 keep ('-':'-':cs) = linecomment cs
127 keep ('{':'-':'#':' ':cs) = "{-# " ++ keep cs
128 keep ('{':'-':cs) = runcomment cs -- -}
129 keep (c:cs) = c : keep cs
131 -- in a double-quoted string
133 dquote ('\\':'\"':cs) = dquote cs -- "
134 dquote ('\\':'\\':cs) = dquote cs
135 dquote ('\"':cs) = keep cs -- "
136 dquote (c:cs) = dquote cs
138 -- in a single-quoted string
140 squote ('\\':'\'':cs) = squote cs
141 squote ('\\':'\\':cs) = squote cs
142 squote ('\'':cs) = keep cs
143 squote (c:cs) = squote cs
147 linecomment ('\n':cs) = '\n':keep cs
148 linecomment (c:cs) = linecomment cs
150 -- in a running comment
152 runcomment ('-':'}':cs) = keep cs
153 runcomment (c:cs) = runcomment cs