source: scrub iter-code / Decision-N residue from inline comments
Follow-up to bcd4181: the remaining ~530 inline `//` and `///`
comments still carrying opaque shorthand are now reformulated to
their content phrases. The only surviving `iter-<code>` reference
in source is the literal filename
`docs/journals/2026-05-13-iter-mq.3.md` (a real journal file).
Sweep covered:
- `// Iter X.Y: <text>` prefixes (Iter 13a / 14a / 14e / 15g-aux /
16b.x / 16d / 16e / 18b / 18c.x / 18d.x / 18e / 18g.x / 19a /
19a.1 / 19b / 20a / 20f / 22-floats.x / 22b.x / 22c / 23.x /
24.1 / cli-diag-human / hs.x / str-concat / etc.) — fully
removed; the descriptive text that followed each prefix stays.
- `// (Decision N)` and `per Decision N` and `Decision N axis 3` —
replaced with the content phrase plus the relevant contract
file (`design/contracts/tail-calls.md` for Decision 8,
`design/contracts/memory-model.md` for Decision 10,
`design/contracts/typeclasses.md` and `design/models/typeclasses.md`
for Decision 11, `design/contracts/authoring-surface.md` for
Decision 6, "the transitional dual-allocator" for Decision 9,
"Effect prose" for Decision 3).
- `// mq.X / mq.X (Task N) / mq.X journal / mq.X invariant` ->
"the canonical-class-form rule / Class-class repurpose /
method-dispatch-refactor journal / canonical-class-form
invariant".
- `// ct.X / ct.X (canonical-type-names) / ct.1.5a + ctt.2 /
ct.2 Task N` -> "the canonical-form rule for type references /
the canonical-form normalisation step / canonical-type-lookup
refactor".
- `// eob.X` -> "heap-Str-ABI" / "the Str carve-out".
- `// rpe.X` -> "the per-type-print-op retirement".
- `// post-mq.X / Pre-ct.X / pre-mq.X` -> "post-canonical-class-form" /
"Pre-canonical-type-form" etc.
- `/// Iter X regression: / /// Iter X.Y: / /// Iter A arm-close /
/// Iter ct.4 (...): / /// Iter rpe.1 ...` -> descriptive
phrases.
The journal filename in `crates/ailang-core/src/workspace.rs:573`
stays verbatim because it points at an actual file under
`docs/journals/`.
Tests: full `cargo test --workspace` green (80/80 test-result blocks
clean, no FAILED line). design_index_pin 5/5 + docs_honesty_pin 5/5
gating tests pass.
This commit is contained in:
@@ -33,7 +33,7 @@ impl<'a> Emitter<'a> {
|
||||
/// i1 and i8 fields also occupy a full 8-byte slot — the typed
|
||||
/// load/store instructions write/read only the required size.
|
||||
///
|
||||
/// Iter 17a: `term_ptr` is the pointer-as-usize of the lowered
|
||||
/// `term_ptr` is the pointer-as-usize of the lowered
|
||||
/// `Term::Ctor` node. If escape analysis flagged this site as
|
||||
/// non-escaping (i.e., the value cannot live past the current fn
|
||||
/// frame), allocation lowers to LLVM `alloca` instead of
|
||||
@@ -52,13 +52,13 @@ impl<'a> Emitter<'a> {
|
||||
"ctor `{type_name}/{ctor_name}` arity"
|
||||
)));
|
||||
}
|
||||
// Iter 13b: for parameterised ADTs the precomputed `cref.fields`
|
||||
// for parameterised ADTs the precomputed `cref.fields`
|
||||
// is meaningless because field types reference rigid type vars.
|
||||
// Derive a per-use-site substitution from the arg types and
|
||||
// re-lower each field type. Monomorphic ADTs hit the fast path
|
||||
// (no var-set, substitution is empty, ail_fields lower exactly
|
||||
// like cref.fields).
|
||||
// Iter 15b: for cross-module ctors, qualify any local type-cons
|
||||
// for cross-module ctors, qualify any local type-cons
|
||||
// in `cref.ail_fields` (symmetric to the term-ctor synth fix).
|
||||
let qualified_ail_fields: Vec<Type> = if type_name.matches('.').count() == 1 {
|
||||
let (prefix, _) = type_name.split_once('.').expect("checked");
|
||||
@@ -108,7 +108,7 @@ impl<'a> Emitter<'a> {
|
||||
// design/contracts/frozen-value-layout.md. size = 8 + n*8, tag@0, fields@8+i*8.
|
||||
let size_bytes = 8 + (compiled.len() * 8) as i64;
|
||||
let p = self.fresh_ssa();
|
||||
// Iter 17a: pick allocator based on escape analysis. `alloca`
|
||||
// pick allocator based on escape analysis. `alloca`
|
||||
// for non-escaping (stack-allocated, freed on fn return);
|
||||
// `@GC_malloc` for everything else.
|
||||
if self.non_escape.contains(&term_ptr) {
|
||||
@@ -139,7 +139,7 @@ impl<'a> Emitter<'a> {
|
||||
Ok((p, "ptr".into()))
|
||||
}
|
||||
|
||||
/// Iter 18d.2: lower `Term::ReuseAs { source, body = Term::Ctor }`
|
||||
/// lower `Term::ReuseAs { source, body = Term::Ctor }`
|
||||
/// under `--alloc=rc` as a runtime refcount-1 dispatch.
|
||||
///
|
||||
/// IR shape (Lean 4 / Roc lineage):
|
||||
@@ -192,7 +192,7 @@ impl<'a> Emitter<'a> {
|
||||
"reuse-as source type must be ptr, got {src_ty}"
|
||||
)));
|
||||
}
|
||||
// Iter 18d.3: the source binder name keys into `moved_slots`
|
||||
// the source binder name keys into `moved_slots`
|
||||
// so the reuse arm can skip dec'ing fields that earlier
|
||||
// pattern-extracted out of the source. Linearity already
|
||||
// ensures `source` is `Term::Var` here; the var-resolution
|
||||
@@ -323,7 +323,7 @@ impl<'a> Emitter<'a> {
|
||||
|
||||
// 5. Reuse arm: overwrite tag and field slots in place.
|
||||
//
|
||||
// Iter 18d.3: per-field dec is now safe — moved-out slots
|
||||
// per-field dec is now safe — moved-out slots
|
||||
// are skipped via the codegen `moved_slots` side table;
|
||||
// non-moved slots are dec'd via `field_drop_call`'s null-
|
||||
// guarded drop fns BEFORE the new field values overwrite
|
||||
@@ -344,7 +344,7 @@ impl<'a> Emitter<'a> {
|
||||
// pointer-typed fields are dec'd via `field_drop_call`,
|
||||
// closing the 18d.2 leak.
|
||||
self.start_block(&reuse_lbl);
|
||||
// Iter 18d.3: dec non-moved pointer-typed slots before the
|
||||
// dec non-moved pointer-typed slots before the
|
||||
// overwrite. The dec fns are null-guarded, so an empty slot
|
||||
// is a no-op. Clone the move set out of the side table so
|
||||
// the loop below can mutably borrow `self` for SSA allocation.
|
||||
@@ -449,7 +449,7 @@ impl<'a> Emitter<'a> {
|
||||
"match on non-ADT scrutinee (got {s_ty}); MVP supports only ADTs"
|
||||
)));
|
||||
}
|
||||
// Iter 18d.3: move tracking key — the bare-Var binder name of
|
||||
// move tracking key — the bare-Var binder name of
|
||||
// the scrutinee, if it has one. A complex expression scrutinee
|
||||
// (e.g. the result of `(map_inc xs)` matched directly) has no
|
||||
// binder we can key off; moves through such matches are
|
||||
@@ -486,7 +486,7 @@ impl<'a> Emitter<'a> {
|
||||
open_var = Some(name.clone());
|
||||
}
|
||||
Pattern::Ctor { ctor, fields } => {
|
||||
// Iter 15a: lookup falls back to imported modules when
|
||||
// lookup falls back to imported modules when
|
||||
// a bare ctor name doesn't resolve locally.
|
||||
let cref = self.lookup_ctor_in_pattern(ctor)?;
|
||||
let bindings: Vec<Option<String>> = fields
|
||||
@@ -530,7 +530,7 @@ impl<'a> Emitter<'a> {
|
||||
|
||||
for (i, (cref, arm, bindings)) in ctor_arms.iter().enumerate() {
|
||||
self.start_block(&arm_labels[i]);
|
||||
// Iter 13b: derive substitution for parameterised ADTs from
|
||||
// derive substitution for parameterised ADTs from
|
||||
// the scrutinee's concrete type-args. Map `cref.type_vars[i]`
|
||||
// → `s_ail.args[i]`. For monomorphic ADTs the mapping is
|
||||
// empty and substitution is a no-op. The substituted AILang
|
||||
@@ -559,7 +559,7 @@ impl<'a> Emitter<'a> {
|
||||
}
|
||||
};
|
||||
// Load fields and bind as locals.
|
||||
// Iter 15b: when the scrutinee's ADT lives in another module,
|
||||
// when the scrutinee's ADT lives in another module,
|
||||
// `cref.ail_fields[idx]` carries the field type written in
|
||||
// the owner's local namespace. Qualify it before substituting
|
||||
// — symmetric to the term-ctor and pat-ctor fixes in
|
||||
@@ -571,13 +571,13 @@ impl<'a> Emitter<'a> {
|
||||
_ => None,
|
||||
};
|
||||
let mut pushed = 0usize;
|
||||
// Iter 18d.3: collect the binder names this arm pushes so
|
||||
// collect the binder names this arm pushes so
|
||||
// we can drop their `moved_slots` entries when the arm
|
||||
// body closes (these binders are themselves freshly named
|
||||
// here — their move tracking starts empty and ends at arm
|
||||
// body close).
|
||||
//
|
||||
// Iter 18d.4: the metadata is widened to (name, SSA,
|
||||
// the metadata is widened to (name, SSA,
|
||||
// llvm-type, AILang-type) so that the arm-close drop
|
||||
// emission can route the call through the binder's
|
||||
// per-type drop symbol without re-walking `self.locals`.
|
||||
@@ -608,7 +608,7 @@ impl<'a> Emitter<'a> {
|
||||
self.body.push_str(&format!(
|
||||
" {v} = load {fty}, ptr {addr}, align 8\n"
|
||||
));
|
||||
// Iter 18d.3: a non-wildcard, pointer-typed slot
|
||||
// a non-wildcard, pointer-typed slot
|
||||
// bound here is treated as moved out of the
|
||||
// scrutinee binder. The source slot is NOT
|
||||
// mutated; codegen records the move statically so
|
||||
@@ -632,9 +632,9 @@ impl<'a> Emitter<'a> {
|
||||
pushed += 1;
|
||||
}
|
||||
}
|
||||
// Iter 18d.4 fix + 18g.1: scrutinee ownership signal,
|
||||
// hoisted here so both the pre-tail-call shallow-dec
|
||||
// (Iter 18g.1, below) and the arm-close pattern-binder
|
||||
// Scrutinee ownership signal, hoisted here so both the
|
||||
// pre-tail-call shallow-dec (below) and the arm-close
|
||||
// pattern-binder
|
||||
// dec (Iter A, further below) consult the same gate.
|
||||
//
|
||||
// If the scrutinee resolves to a fn-param whose mode is
|
||||
@@ -657,7 +657,7 @@ impl<'a> Emitter<'a> {
|
||||
},
|
||||
None => true,
|
||||
};
|
||||
// Iter 18g.1: pre-tail-call shallow-dec for moved-from
|
||||
// pre-tail-call shallow-dec for moved-from
|
||||
// scrutinee outer cell. Iter A (arm-close pattern-binder
|
||||
// dec, below) cannot fire when `arm.body` is a tail call:
|
||||
// `lower_term` emits `musttail call ... ret` and sets
|
||||
@@ -739,7 +739,7 @@ impl<'a> Emitter<'a> {
|
||||
}
|
||||
}
|
||||
let (val, vty) = self.lower_term(&arm.body)?;
|
||||
// Iter 18d.4: arm-close pattern-binder dec. Symmetric to
|
||||
// arm-close pattern-binder dec. Symmetric to
|
||||
// 18c.3/18c.4's `Term::Let`-scope-close drop emission, but
|
||||
// fired at the lexical close of a match arm. For each
|
||||
// pattern-bound binder this arm pushed, emit a drop call
|
||||
@@ -763,11 +763,11 @@ impl<'a> Emitter<'a> {
|
||||
// through the tail slot. Now the arm itself dec's `t`,
|
||||
// freeing the 4-cell tail.
|
||||
//
|
||||
// Iter 18d.4 fix (regression
|
||||
// `alloc_rc_pattern_bind_in_implicit_fn_does_not_dec_borrowed_children`):
|
||||
// Iter A is symmetric to Iter B (Own-param dec at fn
|
||||
// return) and must share Iter B's mode gate. If the
|
||||
// scrutinee resolves to a fn-param whose mode is
|
||||
// Regression
|
||||
// `alloc_rc_pattern_bind_in_implicit_fn_does_not_dec_borrowed_children`:
|
||||
// arm-close pattern-binder dec is symmetric to Own-param
|
||||
// dec at fn return and must share the same mode gate. If
|
||||
// the scrutinee resolves to a fn-param whose mode is
|
||||
// `Borrow` or `Implicit`, the caller still holds a
|
||||
// reference to the heap value the pattern-binders were
|
||||
// loaded from. Dec'ing those binders fragments the
|
||||
@@ -823,7 +823,7 @@ impl<'a> Emitter<'a> {
|
||||
" call void @{drop_call}(ptr {b_ssa})\n"
|
||||
));
|
||||
} else {
|
||||
// Iter 18g.tidy.fu2: pattern-binder with
|
||||
// pattern-binder with
|
||||
// statically-recorded moved slots routes
|
||||
// through the tag-conditional helper
|
||||
// `partial_drop_<owner>_<T>(b, mask)`. The
|
||||
@@ -852,13 +852,13 @@ impl<'a> Emitter<'a> {
|
||||
for _ in 0..pushed {
|
||||
self.locals.pop();
|
||||
}
|
||||
// Iter 18d.3: arm-bound binders go out of scope at arm
|
||||
// arm-bound binders go out of scope at arm
|
||||
// body close. Drop their move-tracking entries (any moves
|
||||
// recorded against `h`/`t` belonged to this arm only).
|
||||
for (bname, _, _, _) in &arm_pushed_binders {
|
||||
self.moved_slots.remove(bname);
|
||||
}
|
||||
// Iter 14e: if the arm body lowered to a `musttail call` +
|
||||
// if the arm body lowered to a `musttail call` +
|
||||
// `ret`, the block is already terminated. Skip the
|
||||
// fall-through `br` and exclude this arm from the join phi.
|
||||
if !self.block_terminated {
|
||||
@@ -912,7 +912,7 @@ impl<'a> Emitter<'a> {
|
||||
}
|
||||
|
||||
// join
|
||||
// Iter 14e: if every arm tail-called and terminated its own
|
||||
// if every arm tail-called and terminated its own
|
||||
// block, no predecessor branches into the join. Mark the whole
|
||||
// match as block-terminated and emit no join body — the
|
||||
// surrounding context (top-level fn body, seq rhs, etc.) checks
|
||||
|
||||
Reference in New Issue
Block a user