on master help sign in
Improve analysis of existing solutions (#10)
commitcfc8dbf3280f92f37afaba54a4548be767836e97 authorMark Karpov <markkarpov92@gmail.com> dateThu 3 Jan 2019, 23:00 (8 years ago) parent690d7e8
1 file changed+34−31
DESIGN.md+34−31
DESIGN.md+34−31
@@ -47,12 +47,23 @@ reconstruction, thus Brittany still lacks support for handling source code
4747with CPP in it. That said, we'll show later supporting CPP correctly is
4848virtually impossible anyway.
4949
50+The [theory][brittany-theory] behind Brittany is quite complex and the code
51+itself is fairly undocumented.
52+
5053After parsing, Haskell AST and a collection of annotations are available.
5154The annotations are there because Haskell AST doesn't provide enough
5255information to reconstruct source code (for example it doesn't include
53−comments). Brittany's approach then amounts to manipulation of these
54−entities using a stateful monad in which very low-level transformations are
55−described.
56+comments). Brittany's approach then amounts to converting AST to the special
57+`BriDoc` data type which describes syntactical entities with just enough
58+details to pretty-print them. Stateful transformations are then performed on
59+that `BriDoc` type.
60+
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
66+overcome.
5667
5768After the manipulations a few functions from `ghc-exactprint` are used for
5869rendering 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.
6172The code is hard to read and is buggy too, as one would expect with such
6273approach. There are enough bugs in Brittany at the moment so that it's
6374hardly 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
65−which seems to be very fragile.
75+clear that almost all of them are because of the implementation and design
76+complexity.
6677
6778### Hindent
6879
@@ -335,32 +346,23 @@ anymore. For every issue that we find this way, a test case should be added.
335346
336347### Why not contribute to/fork HIndent or Brittany?
337348
338−* Forking or contributing to Brittany is not a good idea because this would
339− require re-doing of all transformation logic, which is harder than writing
340− pretty-printing code from scratch. Good documentation would help
341− readability of the code somewhat, but then we would need to spend time
342− either collaborating with the original author or investigating how
343− everything works ourselves.
344−
345− Of course with sufficient persistence we could succeed in fixing
346− Brittany's bugs, but the point is that pretty-printing à la Hindent is
347− more maintainable (IMO) and switching to that is equal to re-doing the
348− project.
349−
350− In the end, design of Ormolu is going to be simpler and will:
351−
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)
358−
359−* 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
361− work 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
363− is also possible that we'll find a nicer way to write pretty-printer.
349+We want to simultaneously optimize three goals:
350+
351+1. simplicity of implementation,
352+2. efficiency,
353+3. predictable and readable output that doesn't overuse vertical spacing.
354+
355+Hindent optimizes for (1) and gives up on (2) and (3). Brittany gives up on
356+(1) but goes a long way towards (3) and presumably does OK on (2). Ormolu
357+goes for (1)-(3), by outsourcing the hard part of (3) to the user. Ormolu is
358+less normative than Brittany, and less normative than Hindent, but arguably
359+stills achieves consistent style.
360+
361+Forking or contributing to Hindent is not an option because if we replace
362+`haskell-src-exts` with `ghc` (or `ghc-exact-print`) then we'll have to work
363+with a different AST type and all the code in Hindent will become
364+incompatible and there won't be much code to be re-used in that case. It is
365+also possible that we'll find a nicer way to write pretty-printer.
364366
365367## Examples
366368
@@ -403,4 +405,5 @@ Proposed roadmap (for a single person, about 39 full-time work days):
403405[outputable]: https://hackage.haskell.org/package/ghc-8.4.3/docs/Outputable.html
404406[haskell-src-exts]: https://hackage.haskell.org/package/haskell-src-exts
405407[ghc-exactprint]: https://hackage.haskell.org/package/ghc-exactprint
408+[brittany-theory]: https://github.com/lspitzner/brittany/blob/master/doc/implementation/index.md
406409[hindent-printer]: https://github.com/commercialhaskell/hindent/blob/master/src/HIndent/Pretty.hs