Opened 12 years ago

Closed 8 years ago

#1799 closed bug (fixed)

Retain export-list order in ModIface, use it in :browse

Reported by: guest Owned by:
Priority: normal Milestone: 7.2.1
Component: GHCi Version: 6.6.1
Keywords: Cc: claus.reinke@…
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

Description

while trying to write a test for an extension of :browse, i encountered an issue with the existing functionality: the order of names is not stable, making it difficult to write meaningful tests for :browse.

a reduced test case & output are appended below, showing that output order is affected by prior usage, in both 6.6.1 and HEAD.

i would prefer for the items to appear in source order, but at the point :browse gets a hand on them, source location information might not be available; sorting by Name would be random due to uniqueIds, and lexicographic sorting would be confusing to users (spreading related items all over the alphabet, instead of keeping the order in which they appear in source and documentation).

is there a way to keep the items in source order, within each module (modules themselves could be sorted lexicographically)? note that alphabetically sorting names would very much be a last resort!

--------------------------------------- testing :browse
$ cat y.hs
import Prelude()
import Data.Maybe(catMaybes,mapMaybe)

$ cat .ghci
:t Data.Maybe.mapMaybe

$ ghcii.sh --version
The Glorious Glasgow Haskell Compilation System, version 6.6.1

$ /cygdrive/c/fptools/ghc/compiler/stage2/ghc-inplace --interactive --version
The Glorious Glasgow Haskell Compilation System, version 6.9.20071019

$ (echo :l y.hs;echo :browse '*Main') | ghcii.sh -v0
Data.Maybe.mapMaybe :: (a -> Maybe b) -> [a] -> [b]
mapMaybe :: (a -> Data.Maybe.Maybe b) -> [a] -> [b]
catMaybes :: [Data.Maybe.Maybe a] -> [a]

$ (echo :l y.hs;echo :browse '*Main') | ghcii.sh -v0 -ignore-dot-ghci
catMaybes :: [Data.Maybe.Maybe a] -> [a]
mapMaybe :: (a -> Data.Maybe.Maybe b) -> [a] -> [b]

$ (echo :l y.hs;echo :browse '*Main') | /cygdrive/c/fptools/ghc/compiler/stage2/ghc-inplace --inter
active  -v0
Data.Maybe.mapMaybe :: (a -> Maybe b) -> [a] -> [b]
mapMaybe :: (a -> Data.Maybe.Maybe b) -> [a] -> [b]
catMaybes :: [Data.Maybe.Maybe a] -> [a]

$ (echo :l y.hs;echo :browse '*Main') | /cygdrive/c/fptools/ghc/compiler/stage2/ghc-inplace --inter
active  -v0 -ignore-dot-ghci
catMaybes :: [Data.Maybe.Maybe a] -> [a]
mapMaybe :: (a -> Data.Maybe.Maybe b) -> [a] -> [b]

Change History (12)

comment:1 Changed 12 years ago by guest

i notice that :browse <module> does not seem to suffer from this issue, so the information in GHC.modInfoExports seems more stable than that in GHC.modInfoTopLevelScope. is that an accident or something we could rely on as a basis for ordering names?

would it be possible to take the position of a name in its defining module's minf_exports NameSet, and add that to the name's srcLoc (in parens, to distinguish from proper srcSpans)? then we could list names in source order where we have the source, and in export order otherwise, both represented by comparing source location info.

btw, i can think of several reasons why a name's srcLoc should be part of the defining module's interface. are the reason's against really stronger?

for:

  • :browse could simply list names in source order, which is usually the right thing to do (are there any reasons for making the export order differ from the source order?)
  • ghc users could download library sources for libraries installed only as object code, and use ghci to navigate them (Hugs has supported this many many years with :find, and it is terrific both for beginners studying standard library code and for advanced users looking for issues with performance, etc.)
  • :ctags/:etags could be made to work with non-interpreted modules, so we could finally put hasktags to rest
  • ghc-based ide developers would have more information to work with
  • ghc developers could use any of the above to navigate ghc's sources

against:

  • interface sizes would increase, though only by a line-number per exported item
  • interface comparison would need to ignore line-numbers, both for compatibility and for re-compilation (but doesn't already? the srcLocs are there as dummies)

[claus] (where has the field for the commenter's name disappeared to?)

comment:2 Changed 12 years ago by guest

as a workaround, i've got a minor patch that adds a -s option to :browse, so

Prelude> :browse Data.Maybe
data Maybe a = Nothing | Just a
maybe :: b -> (a -> b) -> Maybe a -> b
isJust :: Maybe a -> Bool
isNothing :: Maybe a -> Bool
fromJust :: Maybe a -> a
fromMaybe :: a -> Maybe a -> a
maybeToList :: Maybe a -> [a]
listToMaybe :: [a] -> Maybe a
catMaybes :: [Maybe a] -> [a]
mapMaybe :: (a -> Maybe b) -> [a] -> [b]
Prelude>
Prelude> :browse -s Data.Maybe
data Maybe a = Nothing | Just a
catMaybes :: [Maybe a] -> [a]
fromJust :: Maybe a -> a
fromMaybe :: a -> Maybe a -> a
isJust :: Maybe a -> Bool
isNothing :: Maybe a -> Bool
listToMaybe :: [a] -> Maybe a
mapMaybe :: (a -> Maybe b) -> [a] -> [b]
maybe :: b -> (a -> b) -> Maybe a -> b
maybeToList :: Maybe a -> [a]

i wouldn't want that as the default, but it should enable reproducable tests, and it might occasionally be useful in itself. in the longer term, the default order should be source order, rather than some odd mixture of use/source.

claus

comment:3 Changed 12 years ago by simonmar

Milestone: 6.10 branch
Priority: normallow
Summary: ghci ':browse *<module>' does not list items in source orderRetain export-list order in ModIface, use it in :browse

In the patch for #1617, I implemented the following:

  • if a module is interpreted, then browse output is in source order
  • otherwise, browse output is alphabetically sorted by name

Ideally I'd like to retain the order of the export list in the ModIface, so that all :browse M output (as opposed to :browse *M) would appear in export-list order. The compiled/interpreted distinction would then disappear. At the moment it appears that md_exports in ModDetails is always sorted by OccName.

comment:4 in reply to:  3 Changed 12 years ago by simonpj

Replying to simonmar:

Ideally I'd like to retain the order of the export list in the ModIface, so that all :browse M output (as opposed to :browse *M) would appear in export-list order. The compiled/interpreted distinction would then disappear. At the moment it appears that md_exports in ModDetails is always sorted by OccName.

There seem to be two places where the order might get scrambled:

  • The call to nubAvails in RnNames.rnExports. This combines T(C) with T(D) to give T(C,D). I'm not sure whether you want to retain exactly the former.
  • The groupFM stuff in MkIface.mkIfaceExports, which further groups exports by modules. This part could readily be omitted (although the interface file format would then change).

The other potential cost is that module M( a,b ) would be recorded as a change from module M( b, a ) and hence force recompilation. That probably barely matters, though.

Simon

comment:5 Changed 11 years ago by simonmar

Architecture: UnknownUnknown/Multiple

comment:6 Changed 11 years ago by simonmar

Operating System: UnknownUnknown/Multiple

comment:7 Changed 11 years ago by igloo

Milestone: 6.10 branch6.12 branch

comment:8 Changed 10 years ago by igloo

Milestone: 6.12 branch6.12.3

comment:9 Changed 10 years ago by igloo

Milestone: 6.12.36.14.1
Priority: lownormal
Type of failure: None/Unknown

comment:10 Changed 9 years ago by igloo

Milestone: 7.0.17.0.2

comment:11 Changed 9 years ago by igloo

Milestone: 7.0.27.2.1

comment:12 Changed 8 years ago by igloo

Resolution: fixed
Status: newclosed

The order is now stable, so closing.

We may in the future use info from the haddock interface to determine the order, instead of what we currently do.

Note: See TracTickets for help on using tickets.