Files
AILang/crates
Brummel 140a0c0ef7 iter raw-buf.1-intercept-registry (DONE 5/5): try_emit_primitive_instance_body → registry table (refs #7)
Pure refactor — first iter of the raw-buf milestone. The
hardcoded 18-arm match in try_emit_primitive_instance_body
(crates/ailang-codegen/src/lib.rs L2841-3147 pre-iter, ~305
lines) becomes a 6-line shim that consults a single registry
table in the new sibling module crates/ailang-codegen/src/intercepts.rs.

Zero behavioural change. The wrapper name survives, all 14
in-source comment-refs to try_emit_primitive_instance_body stay
valid pointers to the canonical dispatch entry.

What landed (5 tasks):

  Task 1 — module skeleton: Intercept struct, INTERCEPTS static
  table (empty), lookup(name), check_sig(intercept, params, ret).
  mod intercepts; wired into lib.rs at L43.

  Task 2 — populate: 18 free emit fns lifted from the legacy
  match arms; INTERCEPTS populated with one entry per name. Three
  Emitter fields (body, locals, block_terminated) and three helper
  methods (emit_compare_ladder, emit_ordering_arm,
  emit_direct_int_icmp_intercept) bumped to pub(crate) so the
  sibling module can reach them. lower_ctor stayed at its existing
  visibility — not consumed by sibling-module fns.

  Task 3 — rewire dispatch: try_emit_primitive_instance_body body
  becomes `match intercepts::lookup(fn_name) { Some(i) => {
  check_sig(i, params, ret)?; (i.emit)(self)?; Ok(true) } None =>
  Ok(false) }`. The 305-line match collapses to 9 lines.

  Task 4 — fold wants_alwaysinline into the registry: every entry
  in INTERCEPTS carries wants_alwaysinline: bool. The predicate
  intercept_emit_wants_alwaysinline now consults the registry for
  branch 1 (the literal 13-name list the predicate hardcoded). One
  source of truth instead of two — closes the silent-drift class
  recon flagged.

  Task 5 — registry_contains_all_legacy_arms pin test: enumerates
  all 18 legacy names + asserts each resolves to a registered
  entry. A half-finished migration that drops any name becomes a
  hard test fail.

Two judgement calls the implementer made (both behaviour-
preserving, both worth knowing):

  (1) eq__Unit param shape: the plan named expected_params: &[]
  per the recon's "params ignored" reading. Reality: the call
  site delivers ["i8","i8"] (Unit lowers to i8 per codegen //!
  header). The registry entry uses ["i8","i8"]; the emit fn
  discards the operand SSAs and returns `ret i1 1` — semantically
  equivalent to the legacy arm that checked only ret_ty and
  ignored params. An inline rustdoc on the entry names the
  rationale.

  (2) intercept_emit_wants_alwaysinline has TWO branches, not one
  as the plan inferred. Branch 1 = the literal 13-name list (which
  the iter's drift-closure intent covers). Branch 2 = a stem-prefix
  carve-out matching {ne|lt|le|gt|ge}__* that covers polymorphic-
  body monomorphizations (lt__Bool, ne__Str, ne__MyADT, …) which
  are NOT registry entries and never were. A literal "replace with
  one-line registry lookup" would silently drop alwaysinline on
  those names, breaking the bench-perf parity established in iter
  operator-routing-eq-ord.1. Branch 2 stays as it was, with a
  fresh comment naming what the registry covers vs. what branch 2
  covers.

  Follow-up consideration (not in this iter): extend the Intercept
  variant to a predicate-only entry shape so branch 2 can fold
  into the registry as well, OR accept the carve-out as the final
  shape. Either is reasonable. Filed as a backlog idea (see Gitea
  issue created post-commit if labelled).

Verification:

  cargo test --workspace      → 667 passed, 0 failed, 2 ignored
                                (baseline was 666 + 2 ignored;
                                +1 from registry_contains_all_legacy_arms)

  Four E2E ratifiers GREEN (named in spec § Testing strategy
  raw-buf.1):
    - eq_primitives_smoke_compiles_and_runs (crates/ail/tests/e2e.rs)
    - compare_primitives_smoke_prints_1_2_3_thrice (crates/ail/tests/e2e.rs)
    - float_compare_smoke_prints_true_true_false
    - eq_ord_polymorphic_runs_end_to_end

  Alwaysinline pins GREEN (regression net for branch-2 carve-out):
    - crates/ailang-codegen/tests/eq_primitives_pin.rs
    - crates/ail/tests/prelude_eq_alwaysinline_ir_pin.rs

  New pin GREEN:
    - intercepts::tests::registry_contains_all_legacy_arms

Diff size: lib.rs −318 / +26 (net −292); intercepts.rs +488 (new
file). Net repository LOC delta: +196. The size reduction in
lib.rs is the wrong proxy — the value is the consolidation: one
table, one drift-closed predicate, one pin test enumerating the
migration surface.

The raw-buf.2 iter will rename crates/ailang-kernel-stub/ to
crates/ailang-kernel/ and reshape it as the family-crate that
hosts raw_buf alongside kernel_stub. The registry shipped here
is the substrate raw-buf.3 will plug RawBuf's 12 codegen
intercepts into.
2026-05-29 11:06:55 +02:00
..