@@ -47,12 +47,23 @@ reconstruction, thus Brittany still lacks support for handling source code
47with CPP in it. That said, we'll show later supporting CPP correctly is
47with CPP in it. That said, we'll show later supporting CPP correctly is
48virtually impossible anyway.
48virtually impossible anyway.
50+The [theory][brittany-theory] behind Brittany is quite complex and the code
51+itself is fairly undocumented.
50After parsing, Haskell AST and a collection of annotations are available.
53After parsing, Haskell AST and a collection of annotations are available.
51The annotations are there because Haskell AST doesn't provide enough
54The annotations are there because Haskell AST doesn't provide enough
52information to reconstruct source code (for example it doesn't include
55information to reconstruct source code (for example it doesn't include
53−comments). Brittany's approach then amounts to manipulation of these
56+comments). Brittany's approach then amounts to converting AST to the special
54−entities using a stateful monad in which very low-level transformations are
57+`BriDoc` data type which describes syntactical entities with just enough
55−described.
58+details to pretty-print them. Stateful transformations are then performed on
61+Using `BriDoc` data type alone would lead to exponential time complexity
62+though and so `BriDocF` type is also added. There are multiple ways to build
63+a `BriDocF`, and only some of them meet the linear space property. Which
64+means there is no safety net to ensure that the resulting structures fit in
65+linear space. And this is a problem that certainly would require redesign to
57After the manipulations a few functions from `ghc-exactprint` are used for
68After the manipulations a few functions from `ghc-exactprint` are used for
58rendering of code together with some custom logic. I do not fully understand
69rendering of code together with some custom logic. I do not fully understand
@@ -61,8 +72,8 @@ why the function `exactPrint` from `ghc-exactprint` is not used directly.
61The code is hard to read and is buggy too, as one would expect with such
72The code is hard to read and is buggy too, as one would expect with such
62approach. There are enough bugs in Brittany at the moment so that it's
73approach. There are enough bugs in Brittany at the moment so that it's
63hardly usable although it's now 2 years old. Looking at the opened bugs it's
74hardly usable although it's now 2 years old. Looking at the opened bugs it's
64−clear that almost all of them are because of the too-low-level approach
75+clear that almost all of them are because of the implementation and design
65−which seems to be very fragile.
76+complexity.
67### Hindent
78### Hindent
@@ -335,32 +346,23 @@ anymore. For every issue that we find this way, a test case should be added.
336### Why not contribute to/fork HIndent or Brittany?
347### Why not contribute to/fork HIndent or Brittany?
338−* Forking or contributing to Brittany is not a good idea because this would
349+We want to simultaneously optimize three goals:
339− require re-doing of all transformation logic, which is harder than writing
350+
340− pretty-printing code from scratch. Good documentation would help
351+1. simplicity of implementation,
341− readability of the code somewhat, but then we would need to spend time
352+2. efficiency,
342− either collaborating with the original author or investigating how
353+3. predictable and readable output that doesn't overuse vertical spacing.
343− everything works ourselves.
354+
344−
355+Hindent optimizes for (1) and gives up on (2) and (3). Brittany gives up on
345− Of course with sufficient persistence we could succeed in fixing
356+(1) but goes a long way towards (3) and presumably does OK on (2). Ormolu
346− Brittany's bugs, but the point is that pretty-printing à la Hindent is
357+goes for (1)-(3), by outsourcing the hard part of (3) to the user. Ormolu is
347− more maintainable (IMO) and switching to that is equal to re-doing the
358+less normative than Brittany, and less normative than Hindent, but arguably
348− project.
359+stills achieves consistent style.
350− In the end, design of Ormolu is going to be simpler and will:
352− * make the project more maintainable
353− * bugs easier to fix
354− * more people will be able to contribute to our project (I couldn't figure
355− out what is going on in Brittany, so I'd not be able to contribute, but
356− I could contribute to Hindent because I understand how it works even
357− though I spent equal amount of time looking at both)
359−* Forking or contributing to Hindent is not an option because if we replace
361+Forking or contributing to Hindent is not an option because if we replace
360− `haskell-src-exts` with `ghc` (or `ghc-exact-print`) then we'll have to
362+`haskell-src-exts` with `ghc` (or `ghc-exact-print`) then we'll have to work
361− work with a different AST type and all the code in Hindent will become
363+with a different AST type and all the code in Hindent will become
362− incompatible and there won't be much code to be re-used in that case. It
364+incompatible and there won't be much code to be re-used in that case. It is
363− is also possible that we'll find a nicer way to write pretty-printer.
365+also possible that we'll find a nicer way to write pretty-printer.
365## Examples
367## Examples
@@ -403,4 +405,5 @@ Proposed roadmap (for a single person, about 39 full-time work days):
403[outputable]: https://hackage.haskell.org/package/ghc-8.4.3/docs/Outputable.html
405[outputable]: https://hackage.haskell.org/package/ghc-8.4.3/docs/Outputable.html
404[haskell-src-exts]: https://hackage.haskell.org/package/haskell-src-exts
406[haskell-src-exts]: https://hackage.haskell.org/package/haskell-src-exts
405[ghc-exactprint]: https://hackage.haskell.org/package/ghc-exactprint
407[ghc-exactprint]: https://hackage.haskell.org/package/ghc-exactprint
408+[brittany-theory]: https://github.com/lspitzner/brittany/blob/master/doc/implementation/index.md
406[hindent-printer]: https://github.com/commercialhaskell/hindent/blob/master/src/HIndent/Pretty.hs
409[hindent-printer]: https://github.com/commercialhaskell/hindent/blob/master/src/HIndent/Pretty.hs