Skip to content

experiment: A non-line breaking pretty printer implementation based on Wadler-Lindig#12465

Draft
gwydd12 wants to merge 144 commits into
flix:masterfrom
gwydd12:add-pretty-printer
Draft

experiment: A non-line breaking pretty printer implementation based on Wadler-Lindig#12465
gwydd12 wants to merge 144 commits into
flix:masterfrom
gwydd12:add-pretty-printer

Conversation

@gwydd12

@gwydd12 gwydd12 commented Mar 13, 2026

Copy link
Copy Markdown
Contributor

This implementation is not a full implementation of the Wadler-Lindig pretty-printing algorithm. Nevertheless, it is a baseline to further proceed working with a more structured approach than currently done with the lsp/Formatter.

In this approach there are a few missing pieces:

  • All the actual formatting rules
  • Possibility to only return TextEdit
  • Line breaking and grouping

On the other hand, we need to discuss the current location of the pretty printer, I've added it into tools/, which might not be suitable. However, it makes sense to have the base of the pretty printer in tools/ as it should be treated as an additional tool to the compiler.

Please note as well, this will be rewritten many times to play around with the algorithm. Maybe I'll even try different algorithms. In addition, it also has an experimental ordering of imports.

Cheers :)

gwydd12 added 5 commits March 12, 2026 15:12
- add wadler based `Doc` structure for the pretty printer implementation
- pretty printer just takes a syntax tree and transforms it into a Doc
  and prints it without any formatting applied
- implement logic to filter the spaces and line breaks from the original
  source code to preserve it in the Doc structure
- make pretty function non-recursive due to possible stackoverflow
- refactor gapDoc function to make it more readable and maintainable
@gwydd12 gwydd12 changed the title experiment: A pretty printer non-line breaking pretty printer implementation based on Wadler-Lindig experiment: A non-line breaking pretty printer implementation based on Wadler-Lindig Mar 13, 2026
gwydd12 added 5 commits March 13, 2026 13:30
- implement alphabetical import ordering as a formatting rule
- this operator allows for syntactic sugar to avoid writing `doc <>
  space <> doc` in the styling rules
- based on partialfunction now have ad-hoc rules adding of different
  formatting rules
- reimplement all currently existing rules in the formatter as formatter
  modules aka formatting rules
@magnus-madsen

Copy link
Copy Markdown
Member

On the other hand, we need to discuss the current location of the pretty printer, I've added it into tools/, which might not be suitable. However, it makes sense to have the base of the pretty printer in tools/ as it should be treated as an additional tool to the compiler.

I agree. This is fine.

@magnus-madsen

Copy link
Copy Markdown
Member

Hi Din,

Just getting up to speed, but already a couple of questions:

  • Do you think that Text and SoftLine should perhaps contain Tokens instead of Strings?
  • Speaking of tokens, doc comments can be span multiple lines. Is that a problem?
  • Do you see a way to support alignment of => e.g. in pattern match cases? It does not look straightforward to me...

Comment thread main/src/ca/uwaterloo/flix/tools/Doc.scala Outdated
@gwydd12

gwydd12 commented Mar 23, 2026

Copy link
Copy Markdown
Contributor Author

Hey Magnus,

Of course we can further discuss these in the meeting, but here some thoughts to your questions.

  • Do you think that Text and SoftLine should perhaps contain Tokens instead of Strings?

I would like to keep the abstraction or at least have the Doc as near to the original paper implementation as possible. Just out of curiosity, what benefits would implementing it with Token bring?

  • Speaking of tokens, doc comments can be span multiple lines. Is that a problem?

Currently not no. I've rebuilt some structures in some local commits which I will show you in the meeting. However, currently multi-line comments do not cause any problem.

  • Do you see a way to support alignment of => e.g. in pattern match cases? It does not look straightforward to me...

Out of the box with only Wadler itself it would not work. However, if I remember correctly Alignment could be achieved with extending Wadler with Leijen to include align.

@magnus-madsen

Copy link
Copy Markdown
Member

I would like to keep the abstraction or at least have the Doc as near to the original paper implementation as possible. Just out of curiosity, what benefits would implementing it with Token bring?

Not sure yet, but perhaps:

  • A lot more information than a string would have.
  • Source positions which may be useful for computing specific text edits.

Out of the box with only Wadler itself it would not work. However, if I remember correctly Alignment could be achieved with extending Wadler with Leijen to include align.

Roger 👍

gwydd12 added 6 commits March 23, 2026 15:08
- rule engine has some major flaws implemented nevertheless it would
  work to some degree
- implement the most basic traversal of the tree
- implement the most basic wadler lindig doc
- add space after comma and colon
- each examples is compileable after formatting
- be aware this formatter still has many hiccups and can break
  functional code
@gwydd12

gwydd12 commented Apr 4, 2026

Copy link
Copy Markdown
Contributor Author

As discussed with Magnus, we simply try to pattern match instead of already planning a big ruling engine (we incrementally try to refactor and improve). Please note that this progress currently has many hiccups and might break functional code. Example of such breaking:

import java.lang.Runnable
import java.lang.Thread

def newRunnable(): Runnable \ IO = new Runnable {
    // Note: In Flix `run` is a keyword so we must escape it with $.
    def run(_this: Runnable): Unit \ IO = {
        println("Running...")
    }
}

def main(): Unit \ IO =
    new Thread(newRunnable()).start()

As stated in the comment // Note: In Flix run is a keyword so we must escape it with $. it must add a $ in front of run, which causes the PrettyPrinter to break the existing code.

@magnus-madsen

Copy link
Copy Markdown
Member

!!!jar

@github-actions

Copy link
Copy Markdown

Building JAR...

@github-actions

Copy link
Copy Markdown

The JAR is available HERE.

@gwydd12

gwydd12 commented May 18, 2026

Copy link
Copy Markdown
Contributor Author

@magnus-madsen You might want to invoke the jar build again. I did not push everything, sorry, so the jar up there might be outdated.

@magnus-madsen

Copy link
Copy Markdown
Member

!!!jar

@github-actions

Copy link
Copy Markdown

Building JAR...

@github-actions

Copy link
Copy Markdown

The JAR is available HERE.

gwydd12 added 3 commits May 20, 2026 12:16
- rename Formatter to FormatterLsp as it is not the formatting
  implementation
- add correctness and aesthetic property tests to test flixfmt (not
  included in this PR)
@magnus-madsen

Copy link
Copy Markdown
Member

!!!jar

@github-actions

github-actions Bot commented Jun 5, 2026

Copy link
Copy Markdown

Building JAR...

@github-actions

github-actions Bot commented Jun 5, 2026

Copy link
Copy Markdown

The JAR is available HERE.

@gwydd12

gwydd12 commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

Hello @mweyland and @dandolo

First of all, thanks again. After all you might want to test the actual formatter and see, how it looks and feels. Therefore, I requested Magnus to invoke the jar build action to provide a executable for you.

I'll provide two short instructions on how you can use this jar file.

  • First, download the jar and unzip it. Then execute it with java -jar out.jar of course, you might want to run it in a project and append the format
$ cd <flix-project>

# Formatting the whole project.
$ java -jar <path-to-jar>/out.jar format

# Formatting a specific file (e.g. Main.flix)
$ java -jar <path-to-jar>/out.jar format src/Main.flix 
  • After all, you might want to use it in Visual Studio Code (Because this feels more real and is cooler in my opinion). This can be done by moving the jar file into the flix project, into the project root, and open the project in Visual Studio Code.
$ cd <flix-project>

# Option 1: copy out.jar
$ cp <path-to-jar>/out.jar .

# Option 2: move out.jar
$ mv <path-to-jar>/out.jar .

# Open Visual Studio code
$ code .

It is to note all this can be done graphically as well of course. Aside from that the code command might be named differently for Visual Studio Code.

And for Visual Studio Code you might need this extension, https://marketplace.visualstudio.com/items?itemName=flix.flix . It can happen that there might some conflicts with which compiler it takes.

In case you have some issues and are not able to play around with it, feel free to contact me any time and I'll try to help with finding a solution. And of course if you find any issues with formatting, feel free to open an issue or just note them down if possible, hopefully you don't find to many^^

PS: The jar file can be found in the comment before this one.

Cheers gwydd :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants