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, is_source_import,
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) <> comma,
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 is_source_import (MINormal _) = False
62 is_source_import (MISource _) = True
64 name_of_summary :: ModSummary -> ModuleName
65 name_of_summary = moduleName . ms_mod
67 deps_of_summary :: ModSummary -> [ModuleName]
68 deps_of_summary = map mimp_name . ms_get_imports
70 ms_get_imports :: ModSummary -> [ModImport]
72 = case ms_imports summ of { Just is -> is; Nothing -> [] }
74 type Fingerprint = Int
76 -- The first arg is supposed to be DriverPipeline.preprocess.
77 -- Passed in here to avoid a hard-to-avoid circular dependency
78 -- between CmSummarise and DriverPipeline. Same deal as with
80 summarise :: (FilePath -> IO FilePath)
81 -> Module -> ModuleLocation -> IO ModSummary
82 summarise preprocess mod location
83 | isModuleInThisPackage mod
84 = do let hs_fn = unJust (ml_hs_file location) "summarise"
85 hspp_fn <- preprocess hs_fn
86 modsrc <- readFile hspp_fn
87 let imps = getImports modsrc
88 return (ModSummary mod location{ml_hspp_file=Just hspp_fn} (Just imps))
90 = return (ModSummary mod location Nothing)
93 Collect up the imports from a Haskell source module. This is
94 approximate: we don't parse the module, but we do eliminate comments
95 and strings. Doesn't currently know how to unlit or cppify the module
98 NB !!!!! Ignores source imports, pro tem.
102 getImports :: String -> [ModImport]
103 getImports = filter (not . is_source_import) .
104 nub . gmiBase . clean
106 -- really get the imports from a de-litted, cpp'd, de-literal'd string
107 gmiBase :: String -> [ModImport]
111 f ("foreign" : "import" : ws) = f ws
112 f ("import" : "{-#" : "SOURCE" : "#-}" : "qualified" : m : ws)
113 = MISource (mkMN m) : f ws
114 f ("import" : "{-#" : "SOURCE" : "#-}" : m : ws)
115 = MISource (mkMN m) : f ws
116 f ("import" : "qualified" : m : ws)
117 = MINormal (mkMN m) : f ws
118 f ("import" : m : ws)
119 = MINormal (mkMN m) : f ws
123 mkMN str = mkModuleName (takeWhile isModId str)
124 isModId c = isAlphaNum c || c `elem` "'_"
126 -- remove literals and comments from a string
127 clean :: String -> String
131 -- running through text we want to keep
133 keep ('"':cs) = dquote cs -- "
134 -- try to eliminate single quotes when they're part of
136 keep (c:'\'':cs) | isAlphaNum c || c == '_' = keep (dropWhile (=='\'') cs)
137 keep ('\'':cs) = squote cs
138 keep ('-':'-':cs) = linecomment cs
139 keep ('{':'-':'#':' ':cs) = "{-# " ++ keep cs
140 keep ('{':'-':cs) = runcomment cs -- -}
141 keep (c:cs) = c : keep cs
143 -- in a double-quoted string
145 dquote ('\\':'\"':cs) = dquote cs -- "
146 dquote ('\\':'\\':cs) = dquote cs
147 dquote ('\"':cs) = keep cs -- "
148 dquote (c:cs) = dquote cs
150 -- in a single-quoted string
152 squote ('\\':'\'':cs) = squote cs
153 squote ('\\':'\\':cs) = squote cs
154 squote ('\'':cs) = keep cs
155 squote (c:cs) = squote cs
159 linecomment ('\n':cs) = '\n':keep cs
160 linecomment (c:cs) = linecomment cs
162 -- in a running comment
164 runcomment ('-':'}':cs) = keep cs
165 runcomment (c:cs) = runcomment cs