DEV Community

COMMENTERTHE9
COMMENTERTHE9

Posted on • Originally published at cx-lang.com

Cx Dev Log — 2026-03-26

Multi-file imports actually work now. Yesterday, the parser could read the #![imports] syntax, but nothing happened at runtime. Today, 10 commits on submain have built a complete pipeline: file resolution, dependency graphing, semantic merging across file boundaries, and runtime dispatch. The first multi-file Cx program runs end to end.

The import pipeline

Three critical commits form the core of this work. We have module alias resolution now wired into analyze_method_call in semantic.rs, making method calls on imported module aliases resolve correctly through the module's export table. A new function, analyze_resolved_program, now exists in semantic.rs. This function takes a ResolvedProgram from the resolver and performs unified semantic analysis across all files in topological order. Importantly, main.rs has been updated to use analyze_resolved_program. The pipeline now looks like this: parse, resolve imports, topo-sort, semantic merge, runtime dispatch.

In the resolver module (src/frontend/resolver.rs, 301 lines), the graph infrastructure covers ModuleId, ResolvedFile, ResolvedProgram, ImportEdge, circular import detection, and topological sorting. Although this infrastructure came from earlier submain commits, it ties cohesively into today's semantic and runtime developments.

Testing with t74_import_basic.cx proves the concept by importing t74_import_basic_lib.cx and successfully calling math.add(10, 20) and math.multiply(3, 4) across the file boundary. This is the first multi-file program compiling and running in Cx. We're also testing pub enforcement. The test t64_import_pub_only specifically checks that only pub-marked functions have visibility across import boundaries — the resolver is enforcing visibility rules effectively.

Audit pass and cleanup

Post-pipeline deployment, an audit caught five semantic and runtime bugs in parser.rs, semantic.rs, and runtime.rs. Corrections involved small fixes (+22/-11 lines) addressing correctness-related issues.

We also removed dead code from the old interpreter path across 8 files. Functions like Print and PrintInline, along with a few others like Range, Placeholder, and wait_for_step, were stripped from ast.rs, diagnostics.rs, parser.rs, semantic.rs, semantic_types.rs, lower.rs, main.rs, and runtime.rs. These were leftovers from an earlier phase.

Test infrastructure improvements

Improvements to our test infrastructure include enhancements to the matrix runner (run_matrix.sh) for output verification. Now, tests with a .expected_output sidecar file compare actual results with expected outputs, reporting PASS (output verified) or FAIL (output mismatch) instead of just exit codes. Two sidecar files shipped with this change (t75 and t76).

Six new tests have been added to submain:

  • t64_import_pub_only — Testing pub visibility enforcement.
  • t74_import_basic — An end-to-end test for two-file imports.
  • t75_string_interpolation — validates {varname} expansion in print statements.
  • t76_block_comments — testing block comment syntax.

Today, our submain matrix sees perfect results — 78/78 tests passing, compared to 72/72 on the main branch.

Documentation sync

Our documentation has caught up with the current state of the language, with six files updated: ROADMAP_v3.1.md, cx_backend_roadmap_v3_1.md, backlog_notes.md, cx_flags.md, cx_syntax.md, and docs/frontend/ROADMAP.md. The syntax reference saw the most changes (+158 lines) as it reflects everything we've built since its last update.

The submain roadmap (v4.5) is now marking significant progress milestones like struct field type checking and method call return type resolution as complete. There's a version misalignment between main (v4.6) and submain (v4.5) that we'll address when reconciling these branches.

The submain gap

While all of these changes are branch-contained, submain is currently 13 commits ahead of main. We haven't merged them in the past 24 hours. The multi-file import pipeline is blocking 0.1 right now, and it's ready on the branch. We've added 6 tests, fixed bugs, cut dead code, and synced docs, but all this waits in limbo.

What's next

Merging to main is overdue. Holding 13 commits of working, tested code introduces greater risk with each passing day. Moving forward, we need to improve the test framework and assertions (#[test], assert(cond), assert_eq(a, b), cx test). The error model (Result) still blocks 0.1 and needs progress. Backend IR work, specifically loops and structures in the lowering pipeline, has been deferred multiple times for front-end fixes.


Follow the Cx language project:

Originally published at https://cx-lang.com/blog/2026-03-26

Top comments (0)