Phase 11 just introduced compound assign lowering on submain, pulling +=, -=, *=, /=, and %%= into the IR backend. All in all, 126 new lines in src/ir/lower.rs and three fresh tests. These operators mark their maiden voyage through the IR backend, and while main keeps its 78/78 green tests, submain stays ahead by 22 commits with a 33-day bridge to cross.
Compound Assign Lowering
Commit 9015aff on submain is the sentinel. Gone is the CompoundAssign stub that only returned an UnresolvedSemanticArtifact. Now, it has real weight with true lowering logic. For Binding LValues, it mirrors the plain assignment's SSA journey:
- Fetch the SSA value of the binding.
- Lower the right-hand argument.
- Emit a
Binaryinstruction mapping to the op (Addfor+=,Subfor-=, etc.). - Re-bind via
SsaBindand adjust the binding map.
For DotAccess LValues, things are different. Instead of silently bypassing, compound assigns for struct fields raise an intentional typed error. This mirrors the handling of other unsupported constructs and lays down a marker – struct field work needs pointer arithmetic, which isn't in the mix yet.
There are three tests now in play:
-
lowers_compound_assign_addensures+=lands asBinary::Add. -
lowers_compound_assign_subdrives-=end-to-end throughlower_and_validate. -
rejects_compound_assign_dot_accessmakes sure DotAccess gets shown the door with the expected error.
Two older error-message checks refined their format, adopting "compound assign binding BindingId(N)" over the bland "CompoundAssign".
In summary, a plus of 126 lines with just 5 lines trimmed, all within src/ir/lower.rs.
The Pattern
This move exemplifies the piecemeal approach standing firm throughout Phase 11. Each parcel grabs one syntax category, works the lowering logic, wraps it in tailored tests, and writes stubs with explicit error signals for what can’t be reached yet. Think of unary expressions landing on April 26. Compound assigns line up now. What remains – ArrayLit, Index, MethodCall, and others, along with compound assign on DotAccess – are nailed down with typed errors, not panic.
The four-day pause from April 26 until now – noteworthy mainly because it broke a steady rhythm – doesn't reflect an existential challenge, but a continued expression lowering march.
Submain Divergence
The rift between main and submain hasn’t changed. Right now, it looms large. Submain's 22 commits are sitting pretty with a 33-day lead covering Phases 10 and 11, the error model (Result), integer overflows, optional semicolons, thorough audits, diagnostic sheen, and the roadmap to v5.0 with its 9 hard blockers checked off. Main is back at v4.8 still staring at those very same 9 blockers.
Merge day has been the linchpin priority forever, but here we are. Every spin in the submain-alone orbit means the merge becomes a bit more of a puzzle. The test gap right now? 39 tests wide (main’s 78 vs submain’s 117).
What's Next
The backend's immediate path is buffered through the remaining expression lowerings. Compound assign on DotAccess, particularly, hinges on struct field access revamps (pointer arithmetic and Load/Store), yet to make its landing.
Merging remains king. The daily-log PR bloat – nearly 30 stagnant branches stretching from March 29 through April 29 – stacks as maintenance debt going forward.
Follow the Cx language project:
- Website: cx-lang.com
- GitHub: github.com/COMMENTERTHE9/Cx_lang
- Dev.to: dev.to/commenterthe9
- Bluesky: thecomment.bsky.social
- Twitter/X: @commenterthe9
Originally published at https://cx-lang.com/blog/2026-04-30
Top comments (0)