diff options
author | simonmar <unknown> | 2002-05-27 09:03:52 +0000 |
---|---|---|
committer | simonmar <unknown> | 2002-05-27 09:03:52 +0000 |
commit | a4e4c5f822416dbe2b8abe34301e8d3e39051bc1 (patch) | |
tree | 48743b04e3ebced1288b7ee51700f01fb4d02fa3 | |
parent | 01c2ddd27ae8776b03464d091d6dce989b7ee13f (diff) |
[haddock @ 2002-05-27 09:03:51 by simonmar]
Lots of changes:
- instances of a class are listed with the class, and
instances involving a datatype are listed with that type.
Derived instances aren't included at the moment: the calculation
to find the instance head for a derived instance is non-trivial.
- some formatting changes; use rows with specified height rather than
cellspacing in some places.
- various fixes (source file links were wrong, amongst others)
-rw-r--r-- | src/HaddockHtml.hs | 257 | ||||
-rw-r--r-- | src/HaddockRename.hs | 8 | ||||
-rw-r--r-- | src/HaddockTypes.hs | 10 | ||||
-rw-r--r-- | src/HaddockUtil.hs | 12 | ||||
-rw-r--r-- | src/HsParseUtils.lhs | 11 | ||||
-rw-r--r-- | src/HsParser.ly | 5 | ||||
-rw-r--r-- | src/HsSyn.lhs | 4 | ||||
-rw-r--r-- | src/Main.hs | 105 |
8 files changed, 257 insertions, 155 deletions
diff --git a/src/HaddockHtml.hs b/src/HaddockHtml.hs index 87d76d51..61113154 100644 --- a/src/HaddockHtml.hs +++ b/src/HaddockHtml.hs @@ -32,14 +32,19 @@ iconFile = "haskell_icon.gif" -- ----------------------------------------------------------------------------- -- Generating HTML documentation +type InstMaps = + (FiniteMap HsQName [InstHead], -- maps class names to instances + FiniteMap HsQName [InstHead]) -- maps type names to instances + ppHtml :: String -> Maybe String -> [(Module, Interface)] -> FilePath -- destination directory -> Maybe String -- CSS file -> String -- $libdir + -> InstMaps -> IO () -ppHtml title source_url ifaces odir maybe_css libdir = do +ppHtml title source_url ifaces odir maybe_css libdir inst_maps = do let css_file = case maybe_css of Nothing -> libdir ++ pathSeparator:cssFile @@ -59,7 +64,7 @@ ppHtml title source_url ifaces odir maybe_css libdir = do ppHtmlContents odir title source_url (map fst visible_ifaces) ppHtmlIndex odir title visible_ifaces - mapM_ (ppHtmlModule odir title source_url) visible_ifaces + mapM_ (ppHtmlModule odir title source_url inst_maps) visible_ifaces moduleHtmlFile :: String -> FilePath moduleHtmlFile mod = mod ++ ".html" -- ToDo: Z-encode filename? @@ -131,15 +136,14 @@ pageHeader mod iface title source_url = moduleInfo iface | Nothing <- iface_info iface = Html.emptyTable | Just info <- iface_info iface = - tda [align "right"] << - (table ! [border 0, cellspacing 0, cellpadding 0] << ( + tda [align "right"] << narrowTable << ( (tda [theclass "infohead"] << toHtml "Portability") <-> (tda [theclass "infoval"] << toHtml (portability info)) </> (tda [theclass "infohead"] << toHtml "Stability") <-> (tda [theclass "infoval"] << toHtml (stability info)) </> (tda [theclass "infohead"] << toHtml "Maintainer") <-> (tda [theclass "infoval"] << toHtml (maintainer info)) - )) + ) -- --------------------------------------------------------------------------- -- Generate the module contents @@ -292,30 +296,29 @@ idBeginsWith (HsSpecial s) c = head s `elem` [toLower c, toUpper c] -- --------------------------------------------------------------------------- -- Generate the HTML page for a module -ppHtmlModule :: FilePath -> String -> Maybe String +ppHtmlModule :: FilePath -> String -> Maybe String -> InstMaps -> (Module,Interface) -> IO () -ppHtmlModule odir title source_url (Module mod,iface) = do +ppHtmlModule odir title source_url inst_maps (Module mod,iface) = do let html = header (thetitle (toHtml mod) +++ thelink ! [href cssFile, rel "stylesheet", thetype "text/css"]) +++ body << vanillaTable << ( - pageHeader mod iface title source_url </> - ifaceToHtml mod iface </> + pageHeader mod iface title source_url </> s15 </> + ifaceToHtml mod iface inst_maps </> s15 </> footer ) writeFile (odir ++ pathSeparator:moduleHtmlFile mod) (renderHtml html) -ifaceToHtml :: String -> Interface -> HtmlTable -ifaceToHtml mod iface +ifaceToHtml :: String -> Interface -> InstMaps -> HtmlTable +ifaceToHtml mod iface inst_maps | null exports = Html.emptyTable - | otherwise = - td << table ! [width "100%", cellpadding 0, cellspacing 15] << - (contents </> description </> synopsis </> maybe_hr </> body) + | otherwise = + abovesSep s15 (contents: description: synopsis: maybe_doc_hdr: body) where exports = numberSectionHeadings (iface_exports iface) - has_doc (ExportDecl d) = isJust (declDoc d) + has_doc (ExportDecl _ d) = isJust (declDoc d) has_doc (ExportModule _) = False has_doc _ = True @@ -335,16 +338,22 @@ ifaceToHtml mod iface | no_doc_at_all = Html.emptyTable | otherwise = (tda [theclass "section1"] << toHtml "Synopsis") </> - (tda [width "100%", theclass "synopsis"] << - table ! [width "100%", cellpadding 0, cellspacing 8, border 0] << - aboves (map (processExport True) exports)) - - maybe_hr - | not (no_doc_at_all), ExportGroup 1 _ _ <- head exports - = td << hr + s15 </> + (tda [theclass "body"] << vanillaTable << + abovesSep s8 (map (processExport True inst_maps) + (filter forSummary exports)) + ) + + -- if the documentation doesn't begin with a section header, then + -- add one ("Documentation"). + maybe_doc_hdr + | not (no_doc_at_all) = + case exports of + ExportGroup _ _ _ : _ -> Html.emptyTable + _ -> tda [ theclass "section1" ] << toHtml "Documentation" | otherwise = Html.emptyTable - body = aboves (map (processExport False) exports) + body = map (processExport False inst_maps) exports ppModuleContents :: [ExportItem] -> HtmlTable ppModuleContents exports @@ -379,18 +388,20 @@ numberSectionHeadings exports = go 1 exports go n (other:es) = other : go n es -processExport :: Bool -> ExportItem -> HtmlTable -processExport summary (ExportGroup lev id doc) - | summary = Html.emptyTable - | otherwise = ppDocGroup lev (anchor ! [name id] << docToHtml doc) -processExport summary (ExportDecl decl) - = doDecl summary decl -processExport summary (ExportDoc doc) - | summary = Html.emptyTable - | otherwise = docBox (docToHtml doc) -processExport summary (ExportModule (Module mod)) +processExport :: Bool -> InstMaps -> ExportItem -> HtmlTable +processExport summary inst_maps (ExportGroup lev id doc) + = ppDocGroup lev (anchor ! [name id] << docToHtml doc) +processExport summary inst_maps (ExportDecl x decl) + = doDecl summary inst_maps x decl +processExport summary inst_maps (ExportDoc doc) + = docBox (docToHtml doc) +processExport summary inst_maps (ExportModule (Module mod)) = declBox (toHtml "module" <+> ppHsModule mod) +forSummary (ExportGroup _ _ _) = False +forSummary (ExportDoc _) = False +forSummary _ = True + ppDocGroup lev doc | lev == 1 = tda [ theclass "section1" ] << doc | lev == 2 = tda [ theclass "section2" ] << doc @@ -404,18 +415,16 @@ declWithDoc :: Bool -> Maybe Doc -> Html -> HtmlTable declWithDoc True doc html_decl = declBox html_decl declWithDoc False Nothing html_decl = declBox html_decl declWithDoc False (Just doc) html_decl = - tda [width "100%"] << - vanillaTable << - (declBox html_decl </> docBox (docToHtml doc)) + declBox html_decl </> docBox (docToHtml doc) -doDecl :: Bool -> HsDecl -> HtmlTable -doDecl summary decl = do_decl decl +doDecl :: Bool -> InstMaps -> HsQName -> HsDecl -> HtmlTable +doDecl summary inst_maps x decl = do_decl decl where do_decl (HsTypeSig _ [nm] ty doc) = ppFunSig summary nm ty doc do_decl (HsForeignImport _ _ _ _ n ty doc) - = declWithDoc summary doc (ppTypeSig summary n ty) + = ppFunSig summary n ty doc do_decl (HsTypeDecl _ nm args ty doc) = declWithDoc summary doc ( @@ -423,15 +432,15 @@ doDecl summary decl = do_decl decl ++ map ppHsName args) <+> equals <+> ppHsType ty) do_decl (HsNewTypeDecl loc ctx nm args con drv doc) - = ppHsDataDecl summary True{-is newtype-} + = ppHsDataDecl summary inst_maps True{-is newtype-} x (HsDataDecl loc ctx nm args [con] drv doc) -- print it as a single-constructor datatype do_decl decl@(HsDataDecl loc ctx nm args cons drv doc) - = ppHsDataDecl summary False{-not newtype-} decl + = ppHsDataDecl summary inst_maps False{-not newtype-} x decl do_decl decl@(HsClassDecl _ _ _ _ _) - = ppHsClassDecl summary decl + = ppHsClassDecl summary inst_maps x decl do_decl (HsDocGroup loc lev str) = if summary then Html.emptyTable @@ -470,49 +479,56 @@ ppShortDataDecl summary is_newty -- First, the abstract case: -ppHsDataDecl summary is_newty (HsDataDecl loc ctx nm args [] drv doc) = +ppHsDataDecl summary inst_maps is_newty x + (HsDataDecl loc ctx nm args [] drv doc) = declWithDoc summary doc (ppHsDataHeader summary is_newty nm args) -- The rest of the cases: -ppHsDataDecl summary is_newty decl@(HsDataDecl loc ctx nm args cons drv doc) - | summary || (isNothing doc && no_constr_docs) - = declWithDoc summary doc (ppShortDataDecl summary is_newty decl) +ppHsDataDecl summary (_, ty_inst_map) is_newty + x decl@(HsDataDecl loc ctx nm args cons drv doc) + | summary = declWithDoc summary doc (ppShortDataDecl summary is_newty decl) | otherwise - = td << vanillaTable << ( - header </> + = header </> tda [theclass "body"] << vanillaTable << ( datadoc </> constr_hdr </> - (tda [theclass "body"] << table << constrs)) - ) + (tda [theclass "body"] << constr_table << constrs) </> + instances_bit + ) where header = declBox (ppHsDataHeader False is_newty nm args) - table - | any isRecDecl cons = spacedTable5 - | otherwise = spacedTable1 + constr_table + | any isRecDecl cons = spacedTable5 + | otherwise = spacedTable1 - datadoc - | isJust doc = ndocBox (docToHtml (fromJust doc)) - | otherwise = Html.emptyTable - - constr_hdr = tda [ theclass "section4" ] << toHtml "Constructors" + datadoc | isJust doc = ndocBox (docToHtml (fromJust doc)) + | otherwise = Html.emptyTable - constrs - | null cons = Html.emptyTable - | otherwise = aboves (map ppSideBySideConstr cons) + constrs | null cons = Html.emptyTable + | otherwise = aboves (map ppSideBySideConstr cons) no_constr_docs = all constr_has_no_doc cons - constr_has_no_doc (HsConDecl _ nm _ _ _ doc) - = isNothing doc - constr_has_no_doc (HsRecDecl _ nm _ _ fields doc) - = isNothing doc && all field_has_no_doc fields + instances = lookupFM ty_inst_map x + + instances_bit + = case instances of + Nothing -> Html.emptyTable + Just [] -> Html.emptyTable + Just is -> + inst_hdr </> + tda [theclass "body"] << spacedTable1 << ( + aboves (map (declBox.ppInstHead) is) + ) + +constr_has_no_doc (HsConDecl _ _ _ _ _ doc) = isNothing doc +constr_has_no_doc (HsRecDecl _ _ _ _ fields doc) + = isNothing doc && all field_has_no_doc fields - field_has_no_doc (HsFieldDecl nms _ doc) - = isNothing doc +field_has_no_doc (HsFieldDecl nms _ doc) = isNothing doc isRecDecl (HsRecDecl pos nm tvs ctxt fields maybe_doc) = True isRecDecl _ = False @@ -523,7 +539,7 @@ ppShortConstr summary (HsConDecl pos nm tvs ctxt typeList _maybe_doc) = hsep (ppHsBinder summary nm : map ppHsBangType typeList) ppShortConstr summary (HsRecDecl pos nm tvs ctxt fields maybe_doc) = ppHsConstrHdr tvs ctxt +++ - ppHsBinder summary nm +++ + ppHsBinder summary nm <+> braces (vanillaTable << aboves (map (ppShortField summary) fields)) ppHsConstrHdr tvs ctxt @@ -534,11 +550,11 @@ ppHsConstrHdr tvs ctxt (if null ctxt then noHtml else ppHsContext ctxt <+> toHtml "=> ") ppSideBySideConstr (HsConDecl pos nm tvs ctxt typeList doc) = - narrowDeclBox (hsep ((ppHsConstrHdr tvs ctxt +++ + declBox (hsep ((ppHsConstrHdr tvs ctxt +++ ppHsBinder False nm) : map ppHsBangType typeList)) <-> maybeRDocBox doc ppSideBySideConstr (HsRecDecl pos nm tvs ctxt fields doc) = - narrowDeclBox (ppHsConstrHdr tvs ctxt +++ ppHsBinder False nm) <-> + declBox (ppHsConstrHdr tvs ctxt +++ ppHsBinder False nm) <-> maybeRDocBox doc </> (tda [theclass "body"] << spacedTable1 << aboves (map ppSideBySideField fields)) @@ -606,29 +622,32 @@ ppClassHdr ty fds = fundep (vars1,vars2) = hsep (map ppHsName vars1) <+> toHtml "->" <+> hsep (map ppHsName vars2) -ppShortClassDecl summary decl@(HsClassDecl loc ty fds decls doc) = +ppShortClassDecl summary inst_maps decl@(HsClassDecl loc ty fds decls doc) = if null decls then declBox hdr - else td << ( - vanillaTable << ( - declBox (hdr <+> keyword "where") + else declBox (hdr <+> keyword "where") </> - tda [theclass "body"] << ( - vanillaTable << ( - aboves (map (doDecl summary) (filter keepDecl decls)) - )) - )) + (tda [theclass "body"] << + vanillaTable << + aboves [ ppFunSig summary n ty doc + | HsTypeSig _ [n] ty doc <- decls + ] + ) + where Just c = declMainBinder decl hdr | not summary = linkTarget c +++ ppClassHdr ty fds | otherwise = ppClassHdr ty fds -ppHsClassDecl summary decl@(HsClassDecl loc ty fds decls doc) - | summary || (isNothing doc && all decl_has_no_doc kept_decls) - = ppShortClassDecl summary decl +ppHsClassDecl summary inst_maps@(cls_inst_map, _) orig_c + decl@(HsClassDecl loc ty fds decls doc) + | summary = ppShortClassDecl summary inst_maps decl | otherwise - = td << vanillaTable << (header </> classdoc </> body) + = header </> + tda [theclass "body"] << vanillaTable << ( + classdoc </> methods_bit </> instances_bit + ) where Just c = declMainBinder decl @@ -639,24 +658,39 @@ ppHsClassDecl summary decl@(HsClassDecl loc ty fds decls doc) keyword "where") classdoc - | Just d <- doc = docBox (docToHtml d) + | Just d <- doc = ndocBox (docToHtml d) | otherwise = Html.emptyTable - meth_hdr = tda [ theclass "section4" ] << toHtml "Methods" - - body + methods_bit | null decls = Html.emptyTable | otherwise = - td << table ! [width "100%", cellpadding 0, cellspacing 8] << ( - meth_hdr </> - aboves (map (doDecl False) kept_decls) - ) + meth_hdr </> + tda [theclass "body"] << spacedTable1 << ( + aboves [ ppFunSig summary n ty doc + | HsTypeSig _ [n] ty doc <- decls + ] + ) + + instances_bit + = case instances of + Nothing -> Html.emptyTable + Just [] -> Html.emptyTable + Just is -> + inst_hdr </> + tda [theclass "body"] << spacedTable1 << ( + aboves (map (declBox.ppInstHead) is) + ) + + instances = lookupFM cls_inst_map orig_c kept_decls = filter keepDecl decls - decl_has_no_doc decl = isNothing (declDoc decl) --- ----------------------------------------------------------------------------- +ppInstHead :: InstHead -> Html +ppInstHead ([],asst) = ppHsAsst asst +ppInstHead (ctxt,asst) = ppHsContext ctxt <+> toHtml "=>" <+> ppHsAsst asst + +-- ---------------------------------------------------------------------------- -- Type signatures ppFunSig summary nm ty doc @@ -664,7 +698,6 @@ ppFunSig summary nm ty doc declWithDoc summary doc (ppTypeSig summary nm ty) | otherwise = - td << vanillaTable << ( declBox (ppHsBinder False nm) </> (tda [theclass "body"] << vanillaTable << ( (if (isJust doc) @@ -672,7 +705,6 @@ ppFunSig summary nm ty doc else Html.emptyTable) </> do_args True ty )) - ) where no_arg_docs (HsForAllType _ _ ty) = no_arg_docs ty no_arg_docs (HsTyFun (HsTyDoc _ _) _) = False @@ -682,18 +714,19 @@ ppFunSig summary nm ty doc do_args :: Bool -> HsType -> HtmlTable do_args first (HsForAllType maybe_tvs ctxt ty) - = narrowDeclBox (leader first <+> ppHsForAll maybe_tvs ctxt) </> + = (declBox (leader first <+> ppHsForAll maybe_tvs ctxt) + <-> rdocBox noHtml) </> do_args False ty do_args first (HsTyFun (HsTyDoc ty doc) r) - = (narrowDeclBox (leader first <+> ppHsBType ty) <-> + = (declBox (leader first <+> ppHsBType ty) <-> rdocBox (docToHtml doc)) </> do_args False r do_args first (HsTyFun ty r) - = (narrowDeclBox (leader first <+> ppHsBType ty) <-> + = (declBox (leader first <+> ppHsBType ty) <-> rdocBox noHtml) </> do_args False r do_args first (HsTyDoc ty doc) - = (narrowDeclBox (leader first <+> ppHsBType ty) <-> + = (declBox (leader first <+> ppHsBType ty) <-> rdocBox (docToHtml doc)) do_args first ty = declBox (leader first <+> ppHsBType ty) <-> rdocBox (noHtml) @@ -704,10 +737,12 @@ ppFunSig summary nm ty doc -- ----------------------------------------------------------------------------- -- Types and contexts -ppHsContext :: HsContext -> Html -ppHsContext [] = empty -ppHsContext context = parenList (map (\ (a,b) -> ppHsQName a <+> - hsep (map ppHsAType b)) context) +ppHsAsst :: (HsQName,[HsType]) -> Html +ppHsAsst (c,args) = ppHsQName c <+> hsep (map ppHsAType args) + +ppHsContext :: HsContext -> Html +ppHsContext [] = empty +ppHsContext context = parenList (map ppHsAsst context) ppHsForAll Nothing context = hsep [ ppHsContext context, toHtml "=>" ] @@ -721,9 +756,9 @@ ppHsType :: HsType -> Html ppHsType (HsForAllType maybe_tvs context htype) = ppHsForAll maybe_tvs context <+> ppHsType htype ppHsType (HsTyFun a b) = hsep [ppHsBType a, toHtml "->", ppHsType b] -ppHsType (HsTyDoc ty doc) = ppHsBType ty ppHsType t = ppHsBType t +ppHsBType (HsTyDoc ty doc) = ppHsBType ty ppHsBType (HsTyApp (HsTyCon (Qual (Module "Prelude") (HsTyClsName (HsSpecial "[]")))) b ) = brackets $ ppHsType b ppHsBType (HsTyApp a b) = ppHsBType a <+> ppHsAType b @@ -837,6 +872,13 @@ punctuate p (d:ds) = go d ds go d [] = [d] go d (e:es) = (d +++ p) : go e es +abovesSep :: HtmlTable -> [HtmlTable] -> HtmlTable +abovesSep p [] = Html.emptyTable +abovesSep p (d:ds) = go d ds + where + go d [] = d + go d (e:es) = d </> p </> go e es + parenList :: [Html] -> Html parenList = parens . hsep . punctuate comma @@ -883,3 +925,10 @@ narrowTable = table ! [theclass "narrow", cellspacing 0, cellpadding 0] spacedTable1 = table ! [theclass "vanilla", cellspacing 1, cellpadding 0] spacedTable5 = table ! [theclass "vanilla", cellspacing 5, cellpadding 0] +constr_hdr = tda [ theclass "section4" ] << toHtml "Constructors" +meth_hdr = tda [ theclass "section4" ] << toHtml "Methods" +inst_hdr = tda [ theclass "section4" ] << toHtml "Instances" + +s8, s15 :: HtmlTable +s8 = tda [ theclass "s8" ] << noHtml +s15 = tda [ theclass "s15" ] << noHtml diff --git a/src/HaddockRename.hs b/src/HaddockRename.hs index 02085e2e..d1bc5efa 100644 --- a/src/HaddockRename.hs +++ b/src/HaddockRename.hs @@ -105,6 +105,10 @@ renameDecl decl ty <- renameType ty doc <- renameMaybeDoc doc return (HsForeignImport loc cc safe ent n ty doc) + HsInstDecl loc ctxt asst decls -> do + ctxt <- mapM renamePred ctxt + asst <- renamePred asst + return (HsInstDecl loc ctxt asst decls) _ -> return decl @@ -217,9 +221,9 @@ renameExportItems items = mapM rn items rn (ExportGroup lev id doc) = do doc <- renameDoc doc return (ExportGroup lev id doc) - rn (ExportDecl decl) + rn (ExportDecl x decl) -- x is an original name, don't rename it = do decl <- renameDecl decl - return (ExportDecl decl) + return (ExportDecl x decl) rn (ExportDoc doc) = do doc <- renameDoc doc return (ExportDoc doc) diff --git a/src/HaddockTypes.hs b/src/HaddockTypes.hs index 9c957dd5..5554bddc 100644 --- a/src/HaddockTypes.hs +++ b/src/HaddockTypes.hs @@ -7,8 +7,9 @@ module HaddockTypes ( -- * Module interfaces NameEnv, Interface(..), ExportItem(..), ModuleMap, - DocOption(..), + -- * Misc types + DocOption(..), InstHead, ) where import FiniteMap @@ -39,6 +40,9 @@ data Interface -- restricted to only those bits exported. -- the map key is the "main name" of the decl. + iface_insts :: [HsDecl], + -- ^ instances from this module + iface_info :: Maybe ModuleInfo, -- ^ information from the module header @@ -52,10 +56,9 @@ data Interface data DocOption = OptHide | OptPrune | OptIgnoreExports deriving (Eq) -type DocString = String - data ExportItem = ExportDecl + HsQName -- the original name HsDecl -- a declaration (with doc annotations) | ExportGroup -- a section heading @@ -71,3 +74,4 @@ data ExportItem type ModuleMap = FiniteMap Module Interface +type InstHead = (HsContext,HsAsst) diff --git a/src/HaddockUtil.hs b/src/HaddockUtil.hs index 58033edc..27595f33 100644 --- a/src/HaddockUtil.hs +++ b/src/HaddockUtil.hs @@ -9,7 +9,7 @@ module HaddockUtil ( -- * Misc utilities nameOfQName, collectNames, declBinders, declMainBinder, splitTyConApp, - restrictTo, declDoc, parseModuleHeader, + restrictTo, declDoc, parseModuleHeader, freeTyCons, -- * Filename utilities basename, dirname, splitFilename3, @@ -76,6 +76,16 @@ splitTyConApp t = split t [] split (HsTyCon t) ts = (t,ts) split _ _ = error "splitTyConApp" +freeTyCons :: HsType -> [HsQName] +freeTyCons ty = go ty [] + where go (HsForAllType _ _ t) r = go t r + go (HsTyApp t u) r = go t (go u r) + go (HsTyCon c) r = c : r + go (HsTyFun f a) r = go f (go a r) + go (HsTyTuple b ts) r = foldr go r ts + go (HsTyVar v) r = r + go (HsTyDoc t _) r = go t r + -- --------------------------------------------------------------------------- -- Making abstract declarations diff --git a/src/HsParseUtils.lhs b/src/HsParseUtils.lhs index 3d795837..148fff07 100644 --- a/src/HsParseUtils.lhs +++ b/src/HsParseUtils.lhs @@ -1,5 +1,5 @@ ----------------------------------------------------------------------------- --- $Id: HsParseUtils.lhs,v 1.2 2002/04/10 16:10:26 simonmar Exp $ +-- $Id: HsParseUtils.lhs,v 1.3 2002/05/27 09:03:52 simonmar Exp $ -- -- (c) The GHC Team 1997-2000 -- @@ -17,6 +17,7 @@ module HsParseUtils ( , checkPrec -- String -> P String , checkContext -- HsType -> P HsContext , checkAssertion -- HsType -> P HsAsst + , checkInstHeader -- HsType -> P (HsContext, HsAsst) , checkDataHeader -- HsType -> P (HsContext,HsName,[HsName]) , checkSimple -- HsType -> [HsName] -> P ((HsName,[HsName])) , checkPattern -- HsExp -> P HsPat @@ -73,6 +74,14 @@ checkAssertion = checkAssertion' [] checkAssertion' _ _ = parseError "Illegal class assertion" +checkInstHeader :: HsType -> P (HsContext, HsAsst) +checkInstHeader (HsForAllType Nothing ctxt ty) = + checkAssertion ty `thenP` \asst -> + returnP (ctxt, asst) +checkInstHeader ty = + checkAssertion ty `thenP` \asst -> + returnP ([], asst) + checkDataHeader :: HsType -> P (HsContext,HsName,[HsName]) checkDataHeader (HsForAllType Nothing cs t) = checkSimple t [] `thenP` \(c,ts) -> diff --git a/src/HsParser.ly b/src/HsParser.ly index 9b47f117..4c12adc7 100644 --- a/src/HsParser.ly +++ b/src/HsParser.ly @@ -1,5 +1,5 @@ ----------------------------------------------------------------------------- -$Id: HsParser.ly,v 1.11 2002/05/15 13:03:02 simonmar Exp $ +$Id: HsParser.ly,v 1.12 2002/05/27 09:03:52 simonmar Exp $ (c) Simon Marlow, Sven Panne 1997-2002 @@ -306,7 +306,8 @@ shift/reduce-conflict, so we don't handle this case here, but in bodyaux. > | 'class' srcloc ctype fds optcbody > { HsClassDecl $2 $3 $4 $5 Nothing} > | 'instance' srcloc ctype optvaldefs -> { HsInstDecl $2 $3 $4 } +> {% checkInstHeader $3 `thenP` \(ctxt,asst) -> +> returnP (HsInstDecl $2 ctxt asst $4) } > | 'default' srcloc '(' typelist ')' > { HsDefaultDecl $2 $4 } > | 'foreign' fdecl { $2 } diff --git a/src/HsSyn.lhs b/src/HsSyn.lhs index ecd2b0ce..8f3ef31d 100644 --- a/src/HsSyn.lhs +++ b/src/HsSyn.lhs @@ -1,5 +1,5 @@ % ----------------------------------------------------------------------------- -% $Id: HsSyn.lhs,v 1.9 2002/05/15 13:03:02 simonmar Exp $ +% $Id: HsSyn.lhs,v 1.10 2002/05/27 09:03:52 simonmar Exp $ % % (c) The GHC Team, 1997-2002 % @@ -144,7 +144,7 @@ data HsDecl | HsClassDecl SrcLoc HsType [HsFunDep] [HsDecl] (Maybe Doc) - | HsInstDecl SrcLoc HsType [HsDecl] + | HsInstDecl SrcLoc HsContext HsAsst [HsDecl] | HsDefaultDecl SrcLoc [HsType] diff --git a/src/Main.hs b/src/Main.hs index 96425a46..288d1632 100644 --- a/src/Main.hs +++ b/src/Main.hs @@ -107,28 +107,29 @@ run flags files = do writeIORef saved_flags flags parsed_mods <- sequence (map parse_file files) - sorted_mods <- sortModules parsed_mods + sorted_mod_files <- sortModules (zip parsed_mods files) -- emits an error message if there are recursive modules -- process the modules in sorted order, building up a mapping from -- modules to interfaces. let - loop ifaces [] _ = return ifaces - loop ifaces (hsmod:hsmods) (file:files) = do + loop ifaces [] = return ifaces + loop ifaces ((hsmod,file):mods) = do let ((mod,iface),msgs) = runWriter (mkInterface ifaces file hsmod) new_ifaces = addToFM ifaces mod iface mapM (hPutStrLn stderr) msgs - loop new_ifaces hsmods files + loop new_ifaces mods - module_map <- loop emptyFM sorted_mods files + module_map <- loop emptyFM sorted_mod_files let mod_ifaces = fmToList module_map -- when (Flag_DocBook `elem` flags) $ -- putStr (ppDocBook odir mod_ifaces) - when (Flag_Html `elem` flags) $ - ppHtml title source_url mod_ifaces odir css_file libdir + let inst_maps = collectInstances mod_ifaces + when (Flag_Html `elem` flags) $ + ppHtml title source_url mod_ifaces odir css_file libdir inst_maps parse_file file = do bracket @@ -201,9 +202,11 @@ mkInterface mod_map filename decl_map :: FiniteMap HsName HsDecl decl_map = listToFM [ (n,d) | d <- final_decls, n <- declBinders d ] + instances = [ d | d@HsInstDecl{} <- final_decls ] + -- make the "export items", which will be converted into docs later - orig_export_list <- mkExportItems mod_map mod orig_env - decl_map final_decls options orig_exports + orig_export_list <- mkExportItems mod_map mod decl_map + final_decls options orig_exports let -- prune the export list to just those declarations that have @@ -236,6 +239,7 @@ mkInterface mod_map filename iface_env = name_env, iface_exports = renamed_export_list, iface_orig_exports = pruned_export_list, + iface_insts = instances, iface_decls = decl_map, iface_info = maybe_info, iface_doc = maybe_doc, @@ -245,17 +249,19 @@ mkInterface mod_map filename -- ----------------------------------------------------------------------------- -- Build the list of items that will become the documentation, from the --- export list. At the same time we rename *original* names in the declarations --- to *imported* names. +-- export list. At this point, the list of ExportItems is in terms of +-- original names. -mkExportItems :: ModuleMap -> Module - -> FiniteMap HsQName HsQName -- maps orig to imported names +mkExportItems + :: ModuleMap + -> Module -- this module -> FiniteMap HsName HsDecl -- maps local names to declarations -> [HsDecl] -- decls in the current module -> [DocOption] -> Maybe [HsExportSpec] -> ErrMsgM [ExportItem] -mkExportItems mod_map mod env decl_map decls options maybe_exps + +mkExportItems mod_map mod decl_map decls options maybe_exps | Nothing <- maybe_exps = everything_local_exported | OptIgnoreExports `elem` options = everything_local_exported | Just specs <- maybe_exps = do @@ -264,26 +270,21 @@ mkExportItems mod_map mod env decl_map decls options maybe_exps where everything_local_exported = - fullContentsOfThisModule mod decls env -- everything exported + return (fullContentsOfThisModule mod decl_map) -- everything exported lookupExport (HsEVar x) | Just decl <- findDecl x - = let decl' | HsTypeSig loc ns ty doc <- decl - = HsTypeSig loc [nameOfQName x] ty doc - | otherwise - = decl - in - return [ ExportDecl decl' ] + = return [ ExportDecl x decl ] -- ToDo: cope with record selectors here lookupExport (HsEAbs t) | Just decl <- findDecl t - = return [ ExportDecl (restrictTo [] decl) ] + = return [ ExportDecl t (restrictTo [] decl) ] lookupExport (HsEThingAll t) | Just decl <- findDecl t - = return [ ExportDecl decl ] + = return [ ExportDecl t decl ] lookupExport (HsEThingWith t cs) | Just decl <- findDecl t - = return [ ExportDecl (restrictTo (map nameOfQName cs) decl) ] + = return [ ExportDecl t (restrictTo (map nameOfQName cs) decl) ] lookupExport (HsEModuleContents m) = fullContentsOf m lookupExport (HsEGroup lev doc) = return [ ExportGroup lev "" doc ] @@ -298,7 +299,7 @@ mkExportItems mod_map mod env decl_map decls options maybe_exps lookupExport _ = return [] -- didn't find it? fullContentsOf m - | m == mod = fullContentsOfThisModule mod decls env + | m == mod = return (fullContentsOfThisModule mod decl_map) | otherwise = case lookupFM mod_map m of Just iface @@ -318,12 +319,10 @@ mkExportItems mod_map mod env decl_map decls options maybe_exps Just iface -> lookupFM (iface_decls iface) n Nothing -> Nothing -fullContentsOfThisModule mod decls env = - mapM mkExportItem (filter keepDecl decls) - where mkExportItem (HsDocGroup loc lev doc) = - return (ExportGroup lev "" doc) - mkExportItem decl = - return (ExportDecl decl) +fullContentsOfThisModule mod decl_map = + map mkExportItem (filter (keepDecl.snd) (fmToList decl_map)) + where mkExportItem (x,HsDocGroup loc lev doc) = ExportGroup lev "" doc + mkExportItem (x,decl) = ExportDecl (Qual mod x) decl keepDecl HsTypeSig{} = True keepDecl HsTypeDecl{} = True @@ -338,7 +337,7 @@ keepDecl _ = False pruneExportItems :: [ExportItem] -> [ExportItem] pruneExportItems items = filter has_doc items - where has_doc (ExportDecl d) = isJust (declDoc d) + where has_doc (ExportDecl x d) = isJust (declDoc d) has_doc _ = True -- ----------------------------------------------------------------------------- @@ -510,22 +509,48 @@ parseOption other = do tell ["Unrecognised option: " ++ other]; return Nothing -- ----------------------------------------------------------------------------- -- Topologically sort the modules -sortModules :: [HsModule] -> IO [HsModule] -sortModules hsmodules = mapM for_each_scc sccs +sortModules :: [(HsModule,FilePath)] -> IO [(HsModule,FilePath)] +sortModules mods = mapM for_each_scc sccs where sccs = stronglyConnComp edges - edges :: [(HsModule, Module, [Module])] - edges = [ (hsmod, mod, [ imp | HsImportDecl _ imp _ _ _ <- impdecls ]) - | hsmod@(HsModule mod _ impdecls _ _ _ _) <- hsmodules + edges :: [((HsModule,FilePath), Module, [Module])] + edges = [ ((hsmod,file), mod, get_imps impdecls) + | (hsmod@(HsModule mod _ impdecls _ _ _ _), file) <- mods ] + get_imps impdecls = [ imp | HsImportDecl _ imp _ _ _ <- impdecls ] + + get_mods hsmodules = [ mod | HsModule mod _ _ _ _ _ _ <- hsmodules ] + for_each_scc (AcyclicSCC hsmodule) = return hsmodule for_each_scc (CyclicSCC hsmodules) = - dieMsg ("modules are recursive: " ++ - unwords (map show [ mod | HsModule mod _ _ _ _ _ _ - <- hsmodules ])) + dieMsg ("modules are recursive: " ++ + unwords (map show (get_mods (map fst hsmodules)))) + +-- ----------------------------------------------------------------------------- +-- Collect instances +collectInstances + :: [(Module,Interface)] + -> (FiniteMap HsQName [InstHead], -- maps class names to instances + FiniteMap HsQName [InstHead]) -- maps type names to instances + +collectInstances mod_ifaces + = (addListToFM_C (++) emptyFM class_inst_pairs, + addListToFM_C (++) emptyFM ty_inst_pairs) + where + all_instances = concat (map (iface_insts.snd) mod_ifaces) + + class_inst_pairs = [ (cls, [(ctxt,(cls,args))]) + | HsInstDecl _ ctxt (cls,args) _ <- all_instances ] + + ty_inst_pairs = [ (nm, [(ctxt,(cls,args))]) + | HsInstDecl _ ctxt (cls,args) _ <- all_instances, + arg <- args, + nm <- freeTyCons arg + ] + -- ----------------------------------------------------------------------------- -- A monad which collects error messages |