DEV Community

COMMENTERTHE9
COMMENTERTHE9

Posted on • Originally published at cx-lang.com

Cx Dev Log - 2026-05-04

37 days. That's how long the main and submain branches diverged before the big merge today. It wasn't just about closing this gap; it was about making the biggest forward leap we've seen in weeks. The test matrix exploded from 78 to 117 tests, and we dropped an 11-commit sprint into IR lowering that hammered out essential struct and array support. That alone makes you want to take a closer look at what's changed.

The submain merge (PR #57)

The main branch just caught up with a glut of overdue updates. Submain had all the action, while main was stuck at v4.9 with 78 tests since late March. Finally, PR #57 has us breathing easy: 117/117 test matrix fully up, all nine blockade issues unlocked, and every example is passing smoothly. Improvements included tweaking the error model, enforcing integer overflow rules, refining semicolon behaviors, fixing parser body handling, ensuring struct field overflow handling, streamlining recursive types, and sealing memory soundness. Every daily log marked this as the crucial hurdle. It’s cleared.

IR lowering sprint: CX-7 through CX-17

Eleven commits in one day have reshaped composite type support in the lowering pass. Let's dive into some of the headliners:

CX-7 brought in direct function call lowering, adding tests around function bodies, binary expressions, and multi-argument calls, driving home 193 new lines to lower.rs.

CX-9 handled struct literal lowering. The StructInstance transitions to an Alloca coupled with per-field PtrOffset/Store. This introduced IrInst::PtrOffset for compile-time pointer arithmetic, backed by four new tests.

CX-10 empowered struct field reads using DotAccess, built on layout table lookups, binding resolutions, and PtrOffset for non-zero positions. We made struct_name part of the DotAccess variant in the semantic layer to accommodate these changes, wrapping up with six fresh tests and over 411 lines modified across six different files.

CX-13 streamlined void function call lowering. These now emit IrInst::Call { dst: None, return_ty: None }, intercepting void calls at the statement level in lower_stmt—way before they get to lower_expr, which anticipates a return.

CX-14 focused on struct field writes, extending capabilities for both Assign and CompoundAssign on DotAccess LValues, consolidating pointer resolution logic by reusing the existing resolve_field_ptr from the read path. This added three to our test suite, with 266 lines tacked on.

CX-16 and CX-17 handled arrays. From array type and literal lowering to array element access—arrays now follow the similar patterns laid down for struct literals using SemanticType::Array(_, _) to IrType::Ptr. Six fresh tests anchored these changes, alongside a 475-line increase in codebase heft.

Design decisions that matter

We went hard on one memory model for both structs and arrays, aligning on IrType::Ptr to stack-allocated storage. Field accesses use compile-time PtrOffset; array elements turn to runtime PtrAdd. It's a conscious choice—single addressing pattern, solitary memory model, with backends handling only pointer arithmetic.

Our decision for void calls is to fix them firmly at statement-level rather than expression-level. Since lower_expr mandates a return value, we cleanly intercepted voids in lower_stmt—keeping paths from tangling in Options types through expression lowering.

Branch-local work (not yet merged)

We’re lining up CX-18, aimed at solidifying array-of-structs lowering with a quartet of new tests ensuring accurate instruction sequences. CX-19 is poised to replace the hasty unsupported!("Range") panics with a directly named error: LoweringError::UnsupportedSemanticConstruct, showing exactly why range expressions fail as values. Both are ready, staged on local branches.

What's next

Immediate moves involve merging CX-18 and CX-19—both safe steps already locked and loaded. After clearing those, we’re hitting method call lowering, targeting those still dodging unsupported! in the passes. Methods in impl blocks have a hefty test presence, making this a priority.

Then, bridging submain back to main before we lose another 20 commits' worth of separation, as seen post-sprint. Keeping branches from drifting 37 days apart like past experience is a must.

In the distance lies when block lowering—the most winding control-flow structure left, with an open question dangling around TBool's tricky three-way branching.

Matrix status shows triumph right now: 117 PASS / 0 FAIL.


Follow the Cx language project:

Originally published at https://cx-lang.com/blog/2026-05-04

Top comments (0)