This announcement is a bit delayed, since much of this was included in elm-format 0.8.6, but the Windows npm installer had problems that were discovered after release, so I was waiting to announce until those were fixed. So this it the combined update for 0.8.6 and 0.8.7.
As always, you can install with elm-tooling, nixpkgs, npm, or download from the release page.
Thanks to many contributors, elm-format is now much faster. Testers have consistently reported an 11x speedup (wall time) on MacOS ARM, and a 4x speedup on other platforms. This is thanks to the following:
- Native binaries are now provided for MacOS ARM64 (previous versions required Rosetta) and for Linux ARM64 (aarch64)
- File are now processed in parallel
- The low-level parser API (previously parsec) has been replaced by Evan’s new parsing primitives that he introduced in Elm 0.19’s compiler. The work to integrate this into elm-format was done in Emma’s 2021 Google Summer of Code project (work submission, implementation notes), and it’s now finally available in a released version! If you’re interested in Haskell, here are a few details about why it’s fast (or at least my own understanding of it):
- It avoids a lot of memory allocation (and garbage collection) by loading the input file into a memory buffer and having parsed tokens refer to ranges in that buffer instead of making copies of all retained strings.
- It speeds up backtracking by modeling parser state as pointers into the memory buffer, instead of managing a queue of input tokens.
- It avoids UTF-8 decoding and encoding by working with ByteStrings and ByteArrays directly.
- It avoid unnecessary memory allocation and copying when writing output derived from the input file by using ByteString.Builder when possible.
- There are a lot of other optimizations like the use of continuation-passing style, strictness flags, and unboxed types, which Evan did a lot of benchmarking on to find the most performant design decisions.
- Improvements to ghc (the Haskell compiler) and the text-2.0 library
Other changes (0.8.6 and 0.8.7 combined)
New features:
-
case ... then
is now auto-corrected tocase ... of
-
=>
is now auto-corrected to->
when unambiguous
Bug fixes:
-
module exposing
listings containing comments no longer add extra leading spaces - Redundant import aliases (when the alias is the same as the module name) are now removed
- Top-level declarations named “infix” no longer make files unprocessable
Other changes:
- The npm installer now has zero dependencies
Thanks to …
- Lamdera for providing CI runners to build the MacOS ARM64 release binaries
- @emmabastas for refactoring the parser internals to integrate Elm 0.19’s compiler’s parser, and the initial draft of test coverage scripts
- @lydell for processing files in parallel, and the new dependency-free npm installer script
-
@mdevlamynck for the
exposing
listings bug fix - @tfausak for linux-aarch64 build script updates
- @supermario for mac-arm64 build script updates
- @kutyel for lenient parsing additions
- @jfmengels for continued thoughtful issue discussion across the Elm devtools community (only partially related to elm-format, but thank you!)
- @8n8 for code cleanup help
- Elm community members for testing the new binaries and npm packages
Also thanks to anyone who’s contributed to cross-compilation support in ghc or nix in the past two years — that made the ARM64 binaries possible.
What’s next
My open-source work has mostly been on pause for the past three years (since COVID started), but I’m now finding time for it again. I’m hoping to take what I’ve learned from elm-format in the past 7½ years and help make it easier for folks to write tools for Elm or for other new languages. If you have any such projects and are interested in the following, please get in touch!
Here’s specifically what’s next:
- extract some publishable Haskell libraries from elm-format:
- a slightly-opinionated, language-agnostic library for writing the “formatting” part of a code formatter
- a library for parsing, formatting, and transforming Elm code
- a convenience library for writing command line tools that transform and/or validate files
- do a new “experimental” version of Elm format (roadmap) — the first one since 2017. “Experimental” means it will contain some formatting behavior changes that may or may not get promoted to the next stable release after we see how they work in real-world use.
- explore using ghc-9.6’s javascript backend to compile elm-format as a javascript library (interested contributors, please get in touch)