The family of functions that extracted a meaningful "identifier" for a
declaration contained a large amount of duplication, owing to
type-specific pattern-matching. Encapsulating this pattern-matching in
a Rule means we can go from six functions to one.
The major bumps we get here are `algebraic-graphs` v0.2, which
contains a number of speed improvements, and the removal of the
`foundation` as a dependency.
We use the `pretty-show` for pretty-printing Haskell values. This is a
convenient package in that it provides acceptably-good output without
having to define any extra instances of some `Pretty` class, and
we get nice colored output with `hscolour`.
It's not all skateboards and firecrackers, though. `pretty-show` uses
a predefined parser targeting the `Show` idioms in Haskell, and it
doesn't always do the thing we mean. For example, in #2192 we changed
the `Show` instance of `Range` to be a little more concise: a value of
shape `Range n m` is now printed as `[ n - m ]`. However, the
`pretty-show` parser sees that dash as Haskell's negate operator,
which is wrong, and leads to confused output from `ppShow` versus
`show`: the former prints out `[ n (-m) ]`, which is wrong.
There are three solutions we could pursue here, in increasing order of
practicality:
1. Dispense with `Show` entirely. There's an argument that we should
never write our own `Show` instances, as this ensures that
`read . show` is equivalent to `id`. If we want to examine values in
the REPL, we should be using a `Pretty` typeclass from some
library, and our `-interactive-print` function should operate on
`Pretty` values rather than `Show`. This would mean we could elide
a lot of generated `Show` instances, which is nice.
2. Keep our `Show` instances around, but move any custom
instances to a `Pretty` class, and use a function that engages that
class for our `-interactive-print` function.
3. Change the output of this `Show` instance to use something other
than `-` for its separator.
Option 1 is the most principled, but also would require a lot of
legwork (though it might save us some compile time). Option 2 would be
more tolerable if we had `-XDerivingVia` or some easy way to use
`Show` as a `Pretty` instance. But both are unsatisfactory in light of
option 3, so I've changed the `-` to a `..`, which avoids all
lexer-related confusion.
Right now, when opening a shell with `script/ghci`, you can encounter
a tremendous slowdown by turning on pretty-printing (with `pretty`)
then printing any value (`[0..3]` should work).
This stems from the fact that our `.ghci` specifies the `prettyShow`
function, defined in Semantic.Util, as its `-interactive-print`
function. While this is a good choice of a pretty-printer, the fact
that it is in Util, a file which imports many modules and uses fancy
types, is not good: pretty-printing cannot begin until Util is
recompiled and linked in. This explains why benchmarking this slowdown
revealed nothing but `dlsym` calls: we thought it was due to linking
in the tree-sitter libraries, but it was actually waiting for Util to
compile and link in.
The fix is simple: define `prettyShow` in another module. This should
provide significant speedups to our developer workflow.