2 % (c) The University of Glasgow, 2000
4 \section[CmSummarise]{Module summariser for GHCI}
7 module CmSummarise ( ModImport(..), mi_name,
8 ModSummary(..), summarise, ms_get_imports,
9 name_of_summary, deps_of_summary,
13 #include "HsVersions.h"
16 import Char ( ord, isAlphaNum )
20 import Module ( Module, ModuleName, mkModuleName)
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_ppsource :: (Maybe (FilePath, Fingerprint)), -- preprocessed and sig if .hs
39 ms_imports :: (Maybe [ModImport]) -- imports if .hs or .hi
42 instance Outputable ModSummary where
44 = sep [text "ModSummary {",
45 nest 3 (sep [text "ms_mod =" <+> ppr (ms_mod ms),
46 text "ms_ppsource =" <+> fooble (ms_ppsource ms),
47 text "ms_imports=" <+> ppr (ms_imports ms)]),
51 fooble Nothing = text "Nothing"
52 fooble (Just (cppd_source_name,fp))
53 = text "(fp =" <+> int fp <> text ","
54 <+> text (show cppd_source_name) <> text ")"
57 = MINormal ModuleName | MISource ModuleName
60 instance Outputable ModImport where
61 ppr (MINormal nm) = ppr nm
62 ppr (MISource nm) = text "{-# SOURCE #-}" <+> ppr nm
65 mi_name (MINormal nm) = nm
66 mi_name (MISource nm) = nm
68 name_of_summary :: ModSummary -> ModuleName
69 name_of_summary = moduleName . ms_mod
71 deps_of_summary :: ModSummary -> [ModuleName]
72 deps_of_summary = map mi_name . ms_get_imports
74 ms_get_imports :: ModSummary -> [ModImport]
76 = case ms_imports summ of { Just is -> is; Nothing -> [] }
78 type Fingerprint = Int
80 summarise :: Module -> IO ModSummary
82 = case mod_kind mod of
83 InPackage path -- if in a package, investigate no further
84 -> return (ModSummary mod Nothing Nothing)
85 SourceOnly path -- source; read, cache and get imports
86 -> readFile path >>= \ modsrc ->
87 let imps = getImports modsrc
88 fp = fingerprint modsrc
89 in return (ModSummary mod (Just (path,fp)) (Just imps))
90 ObjectCode oPath hiPath -- can we get away with the src summariser
91 -- for interface files?
92 -> readFile hiPath >>= \ hisrc ->
93 let imps = getImports hisrc
94 in return (ModSummary mod Nothing (Just imps))
96 fingerprint :: String -> Int
98 = dofp s (_ILIT 3) (_ILIT 3)
100 -- Copied from hash() in Hugs' storage.c.
101 dofp :: String -> FastInt -> FastInt -> Int
102 dofp [] m fp = iBox fp
103 dofp (c:cs) m fp = dofp cs (m +# _ILIT 1)
104 (iabs (fp +# m *# iUnbox (ord c)))
106 iabs :: FastInt -> FastInt
107 iabs n = if n <# _ILIT 0 then (_ILIT 0) -# n else n
110 Collect up the imports from a Haskell source module. This is
111 approximate: we don't parse the module, but we do eliminate comments
112 and strings. Doesn't currently know how to unlit or cppify the module
117 getImports :: String -> [ModImport]
118 getImports = nub . gmiBase . clean
120 -- really get the imports from a de-litted, cpp'd, de-literal'd string
121 gmiBase :: String -> [ModImport]
125 f ("foreign" : "import" : ws) = f ws
126 f ("import" : "{-#" : "SOURCE" : "#-}" : "qualified" : m : ws)
127 = MISource (mkMN m) : f ws
128 f ("import" : "{-#" : "SOURCE" : "#-}" : m : ws)
129 = MISource (mkMN m) : f ws
130 f ("import" : "qualified" : m : ws)
131 = MINormal (mkMN m) : f ws
132 f ("import" : m : ws)
133 = MINormal (mkMN m) : f ws
137 mkMN str = mkModuleName (takeWhile isModId str)
138 isModId c = isAlphaNum c || c `elem` "'_"
140 -- remove literals and comments from a string
141 clean :: String -> String
145 -- running through text we want to keep
147 keep ('"':cs) = dquote cs
148 -- try to eliminate single quotes when they're part of
150 keep (c:'\'':cs) | isAlphaNum c || c == '_' = keep (dropWhile (=='\'') cs)
151 keep ('\'':cs) = squote cs
152 keep ('-':'-':cs) = linecomment cs
153 keep ('{':'-':'#':' ':cs) = "{-# " ++ keep cs
154 keep ('{':'-':cs) = runcomment cs
155 keep (c:cs) = c : keep cs
157 -- in a double-quoted string
159 dquote ('\\':'\"':cs) = dquote cs
160 dquote ('\\':'\\':cs) = dquote cs
161 dquote ('\"':cs) = keep cs
162 dquote (c:cs) = dquote cs
164 -- in a single-quoted string
166 squote ('\\':'\'':cs) = squote cs
167 squote ('\\':'\\':cs) = squote cs
168 squote ('\'':cs) = keep cs
169 squote (c:cs) = squote cs
173 linecomment ('\n':cs) = '\n':keep cs
174 linecomment (c:cs) = linecomment cs
176 -- in a running comment
178 runcomment ('-':'}':cs) = keep cs
179 runcomment (c:cs) = runcomment cs