News #24:
Another major milestone achieved: the total execution time on the core stress tests just dropped from ~40.5 ms to ~28 ms!
This massive 30% gain comes from a single, targeted compiler pass I just implemented, which I’d call “Thunk Fusion” (added a dedicated test for it in the official passing/ folder).
By deeply analyzing the TAST, gopurs can now detect when a Lazy thunk encapsulates pure, total integer arithmetic and is immediately forced by its consumer. When this precise pattern is matched, the compiler safely bypasses the dynamic closure allocation entirely and generates a strict, unboxed, tight loop in Go. It essentially synthesizes the “cheatcode” performance automatically.
Crucially, this does not break the Lazy contract or semantics:
- It only applies to total operations (no side-effects, no risk of evaluating diverging effects prematurely).
- It strictly requires an immediate consumer. If the
Lazyvalue is passed around or stored, it gracefully falls back to a standard deferred closure. - Recursive
LetRecblocks are explicitly excluded to maintain safe initialization semantics. - etc.
This perfectly embodies the AOT philosophy I was aiming for with this backend: letting the compiler cancel out the overhead of high-level functional abstractions (like abusing Lazy in a hot path) without forcing the developer to manually drop down to FFI or rewrite their code imperatively.
In doing so, the compiler becomes more and more forgiving of upfront design mistakes. A PureScript developer can write naive, unoptimized code (abusing closures or deferring execution unnecessarily) and the compiler will silently catch and clean up those architectural flaws behind the scenes, ensuring top-tier performance anyway.
I’m remaining cautious, of course. With optimizations this aggressive, there is always a risk of hitting unexpected edge cases in the wild. But the strict semantic guards I’ve put in place, along with the test suite passing flawlessly, give me more confidence.
We are now incredibly close to imperative and native Go (~27 ms).
Today is a good day. ![]()
