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:
2026-05-20 09:58:04 +02:00
parent bcd41810f4
commit ac4d545570
43 changed files with 1004 additions and 1000 deletions
+43 -42
View File
@@ -137,10 +137,10 @@ enum Cmd {
/// `runtime/rc.c`'s `@ailang_rc_alloc` (libc-malloc backing +
/// 8-byte refcount header) with `ailang_rc_inc`/`_dec`
/// instrumentation emitted by codegen; this is the runtime
/// AILang's memory model (RC + uniqueness, Decision 10) is
/// AILang's memory model (RC + uniqueness) is
/// designed for. `gc` retains the Boehm conservative GC path
/// (`@GC_malloc`, libgc); it is kept as a differential parity
/// oracle for codegen diagnosis (Decision 9). `bump` is a
/// oracle for codegen diagnosis (the transitional dual-allocator). `bump` is a
/// bench-only no-free stub from `runtime/bump.c` — it leaks
/// every allocation by design.
#[arg(long, default_value = "rc", value_parser = ["gc", "bump", "rc"])]
@@ -199,7 +199,7 @@ enum Cmd {
/// Loads a workspace (entry module + transitive imports) and lists
/// all reachable modules with hash and def count.
///
/// Iter 5a: listing only. Cross-module typecheck/codegen follow in
/// listing only. Cross-module typecheck/codegen follow in
/// 5b/5c; existing subcommands continue to work per single module.
Workspace {
entry: PathBuf,
@@ -217,14 +217,14 @@ enum Cmd {
#[arg(short, long)]
output: Option<PathBuf>,
},
/// Iter 20a: prints the module as human-readable prose (form B).
/// prints the module as human-readable prose (form B).
///
/// One-way projection: the renderer is deterministic, but no
/// parser exists for the prose surface. The canonical authoring
/// surface remains form (A) (`render` / `parse`) and the canonical
/// hashable artefact remains the JSON-AST.
Prose { path: PathBuf },
/// Iter 20d: composes a prompt for the prose-edit round-trip.
/// composes a prompt for the prose-edit round-trip.
///
/// Given the original `.ail.json` and the edited `.prose.txt`,
/// prints a prompt that asks an external LLM to emit an updated
@@ -241,7 +241,7 @@ enum Cmd {
/// Edited `.prose.txt` (carries the human's intent).
edited: PathBuf,
},
/// ct.1 (dev-only): rewrite every `*.ail.json` under `<dir>` so
/// Dev-only: rewrite every `*.ail.json` under `<dir>` so
/// that bare cross-module `Type::Con` and `Term::Ctor.type_name`
/// references gain their owning module's qualifier. Idempotent.
///
@@ -268,10 +268,10 @@ enum Cmd {
/// string is the role-statement, contract, and output spec that frame
/// the LLM's task.
///
/// Iter 20f rewrote this function: the prompt now embeds
/// the prompt now embeds
/// [`ailang_core::FORM_A_SPEC`] (the language reference an LLM needs
/// to generate AILang from scratch) and the original module as Form-A
/// (the canonical authoring surface, Decision 6) instead of JSON-AST.
/// (the canonical authoring surface) instead of JSON-AST.
/// JSON-AST stays the canonical hashable artefact, but no human or
/// LLM should write it directly — `ail parse` converts the LLM's
/// Form-A output to JSON.
@@ -444,15 +444,15 @@ fn main() -> Result<()> {
print!("{}", ailang_surface::print(&m));
}
Cmd::Prose { path } => {
// Iter 20a: load via `load_module` (single-module mode,
// load via `load_module` (single-module mode,
// matching how `render` / `parse` work). Workspace-wide
// prose is not in scope for 20a.
let m = ailang_surface::load_module(&path)?;
print!("{}", ailang_prose::module_to_prose(&m));
}
Cmd::MergeProse { original, edited } => {
// Iter 20f: load the original .ail.json, render it as
// Form-A (the canonical authoring surface, Decision 6),
// load the original .ail.json, render it as
// Form-A (the canonical authoring surface),
// and embed *that* in the prompt — not the raw JSON-AST.
// Form-A is the form an LLM should produce; JSON is the
// hashable artefact, not the writing surface. The prose
@@ -582,7 +582,7 @@ fn main() -> Result<()> {
}
}
Cmd::Check { path, json } => {
// Iter 5b: `ail check` now **always** loads via
// `ail check` now **always** loads via
// `load_workspace` and checks cross-module. For modules
// without imports, the workspace loader behaves equivalently
// to `load_module` plus a hash consistency check of the
@@ -626,7 +626,7 @@ fn main() -> Result<()> {
d.message,
);
}
// Iter 19a: only Error-severity diagnostics fail the
// only Error-severity diagnostics fail the
// command. Warning-severity diagnostics (e.g. the
// `over-strict-mode` lint) print to stderr but the
// module is still considered to have typechecked.
@@ -646,7 +646,7 @@ fn main() -> Result<()> {
}
}
Cmd::EmitIr { path, out, emit } => {
// Iter 5c: workspace lowering. For single-module programs the
// workspace lowering. For single-module programs the
// workspace is effectively a trivial workspace with one module.
let ws = load_workspace_human(&path)?;
let diags = ailang_check::check_workspace(&ws);
@@ -666,7 +666,7 @@ fn main() -> Result<()> {
d.message,
);
}
// Iter 19a: only Error-severity blocks codegen.
// only Error-severity blocks codegen.
if diags
.iter()
.any(|d| matches!(d.severity, ailang_check::Severity::Error))
@@ -674,7 +674,7 @@ fn main() -> Result<()> {
std::process::exit(1);
}
}
// Iter 23.4: emit-ir must run the same pre-codegen pipeline
// emit-ir must run the same pre-codegen pipeline
// as `build` — `lift_letrecs` per module, then
// `monomorphise_workspace`. Pre-iter-23.4 this was implicit:
// codegen's poly-call path handled specialisation internally.
@@ -726,7 +726,7 @@ fn main() -> Result<()> {
}
}
Cmd::Run { path, opt, alloc, args } => {
// Iter 9b: build into a fresh tempdir per run, exec, propagate
// build into a fresh tempdir per run, exec, propagate
// exit code. The artefact dir is left around (no cleanup) so
// it can be inspected in case of a crash; OS temp policy
// collects them.
@@ -1098,9 +1098,10 @@ fn workspace_error_to_diagnostic(
"module": name,
})),
),
// Iter 22b.1: typeclass-coherence diagnostics emitted from
// typeclass-coherence diagnostics emitted from
// `workspace::build_registry`. The codes follow the JOURNAL
// queue's wording and Decision 11 §"Diagnostic categories".
// queue's wording and the diagnostic-categories section of
// `design/contracts/typeclasses.md`.
W::OrphanInstance {
class,
type_repr,
@@ -1231,7 +1232,7 @@ fn workspace_error_to_diagnostic(
"type": type_repr,
})),
),
// Iter 23.1: the user named a module `prelude`, which the
// the user named a module `prelude`, which the
// loader reserves for the auto-injected prelude module.
W::ReservedModuleName { name } => Some(
ailang_check::Diagnostic::error(
@@ -1244,7 +1245,7 @@ fn workspace_error_to_diagnostic(
"module": name,
})),
),
// ct.1 (canonical-type-names): bare `Type::Con` that does not
// the canonical-form rule for type references: bare `Type::Con` that does not
// resolve to a primitive or a local TypeDef of the owning
// module. `candidates` lists qualified suggestions scanned
// from imports.
@@ -1263,7 +1264,7 @@ fn workspace_error_to_diagnostic(
"candidates": candidates,
})),
),
// ct.1: qualified `<owner>.<type>` where `<owner>` is not a
// qualified `<owner>.<type>` where `<owner>` is not a
// known module or `<owner>` has no `TypeDef <type>`.
W::BadCrossModuleTypeRef { module, name } => Some(
ailang_check::Diagnostic::error(
@@ -1278,7 +1279,7 @@ fn workspace_error_to_diagnostic(
"name": name,
})),
),
// mq.1 (canonical-class-names): bare class-ref that does not
// the canonical-form rule for class references: bare class-ref that does not
// resolve to a local class of the owning module. Sibling of
// `BareCrossModuleTypeRef` for class-reference fields.
W::BareCrossModuleClassRef { module, name, candidates } => Some(
@@ -1295,7 +1296,7 @@ fn workspace_error_to_diagnostic(
"candidates": candidates,
})),
),
// mq.1: qualified `<owner>.<class>` where `<owner>` is not a
// qualified `<owner>.<class>` where `<owner>` is not a
// known module or `<owner>` has no class `<class>`.
W::BadCrossModuleClassRef { module, name } => Some(
ailang_check::Diagnostic::error(
@@ -1310,7 +1311,7 @@ fn workspace_error_to_diagnostic(
"name": name,
})),
),
// ct.1: a class-reference field contains a `.` — class names
// a class-reference field contains a `.` — class names
// are not module-qualified in this milestone.
W::QualifiedClassName { module, name, field } => Some(
ailang_check::Diagnostic::error(
@@ -1343,7 +1344,7 @@ fn workspace_error_to_diagnostic(
}
}
/// Iter cli-diag-human (2026-05-14): loads a workspace and, on
/// loads a workspace and, on
/// `WorkspaceLoadError`, routes through `workspace_error_to_diagnostic`
/// to print a stderr line matching the JSON path's `[code]`-bracketed
/// format before exiting non-zero. Pure I/O errors have no diagnostic
@@ -1416,7 +1417,7 @@ fn collect_refs(def: &ailang_core::Def) -> std::collections::BTreeSet<String> {
}
}
}
// Iter 22b.1: `ail deps` does not yet trace references inside
// `ail deps` does not yet trace references inside
// class/instance defs. Walking method signatures and bodies
// (default bodies, instance method bodies) lands in 22b.2 along
// with the typecheck arms — until then a class/instance def
@@ -1514,7 +1515,7 @@ fn walk_term(
walk_term(rhs, out, builtins, scope);
}
Term::LetRec { name, params, body, in_term, .. } => {
// Iter 16b.1: `deps` walks the on-disk module before the
// `deps` walks the on-disk module before the
// desugar pass, so a `Term::LetRec` is reachable here.
// Treat it like a fn def for dependency purposes:
// `name` shadows for both body and in_term; params shadow
@@ -1536,12 +1537,12 @@ fn walk_term(
}
}
Term::Clone { value } => {
// Iter 18c.1: clone is identity for dependency-walk
// clone is identity for dependency-walk
// purposes. The wrapper introduces no new symbols.
walk_term(value, out, builtins, scope);
}
Term::ReuseAs { source, body } => {
// Iter 18d.1: walk both children; the wrapper introduces no
// walk both children; the wrapper introduces no
// new bindings of its own.
walk_term(source, out, builtins, scope);
walk_term(body, out, builtins, scope);
@@ -1851,7 +1852,7 @@ fn def_summary(d: &ailang_core::Def) -> (&'static str, String, Vec<String>) {
.join(" | ");
("type", s, vec![])
}
// Iter 22b.1: a one-line `class C a` / `instance C T` summary
// a one-line `class C a` / `instance C T` summary
// for `ail manifest`. The `effects` slot is empty for both —
// class methods carry their own effect annotations on each
// method signature, but the class itself does not (it is a
@@ -2243,13 +2244,13 @@ fn locate_str_runtime() -> Result<PathBuf> {
)
}
/// Iter 9b: shared build helper for `Cmd::Build` and `Cmd::Run`.
/// shared build helper for `Cmd::Build` and `Cmd::Run`.
/// Loads the workspace, runs the typechecker, emits IR, and links via
/// clang. On typecheck failure, prints diagnostics to stderr and exits
/// the process with code 1. On clang failure, returns a Result error
/// (the .ll path is preserved for post-mortem inspection).
///
/// Iter 16b.3: between `check_workspace` and `lower_workspace` we run
/// between `check_workspace` and `lower_workspace` we run
/// `ailang_check::lift_letrecs` per module. The lift eliminates any
/// `Term::LetRec` that the desugar pass left in place (specifically:
/// LetRecs that capture `Term::Let`-bound names, whose types are
@@ -2287,7 +2288,7 @@ fn build_to(
d.message,
);
}
// Iter 19a: only Error-severity blocks the build. Warning-
// only Error-severity blocks the build. Warning-
// severity diagnostics (e.g. `over-strict-mode`) print but
// do not abort.
if diags
@@ -2297,7 +2298,7 @@ fn build_to(
std::process::exit(1);
}
}
// Iter 16b.3: run `lift_letrecs` per module on the post-desugar
// run `lift_letrecs` per module on the post-desugar
// form. Codegen's internal desugar pass is idempotent on a
// module that contains no `Term::LetRec`, so the lifted output
// can be handed directly to `lower_workspace`.
@@ -2312,13 +2313,13 @@ fn build_to(
entry: ws.entry.clone(),
modules: lifted_modules,
root_dir: ws.root_dir.clone(),
// Iter 22b.1: pass the registry through the lift pass. Lift
// pass the registry through the lift pass. Lift
// only rewrites `Term::LetRec` into top-level fns; it does
// not touch class/instance defs, so the registry built at
// load-time remains valid.
registry: ws.registry.clone(),
};
// Iter 22b.3: monomorphisation pass. After `lift_letrecs` and
// monomorphisation pass. After `lift_letrecs` and
// before codegen, every (class-method, concrete-type) call-site
// pair becomes a synthesised top-level fn; user call sites are
// rewritten to target those names. Class-free workspaces flow
@@ -2333,7 +2334,7 @@ fn build_to(
let out_bin = out.unwrap_or_else(|| Path::new(".").join(&ws.entry).with_extension(""));
let mut clang = std::process::Command::new("clang");
clang.arg(opt).arg("-o").arg(&out_bin).arg(&ll_path);
// Iter 23.2: compile and link `runtime/str.c` unconditionally —
// compile and link `runtime/str.c` unconditionally —
// `@ail_str_eq` is emitted in the IR header without an alloc-strategy
// guard (it backs the prelude `eq__Str` mono symbol). The .o is
// cached at <tmpdir>/str.o per build invocation; if a program never
@@ -2356,7 +2357,7 @@ fn build_to(
);
}
clang.arg(&str_obj);
// Iter hs.4: compile and link `runtime/rc.c` unconditionally,
// compile and link `runtime/rc.c` unconditionally,
// hoisted out of the AllocStrategy::Rc arm. `runtime/str.c`'s
// `ailang_int_to_str` / `ailang_float_to_str` call
// `ailang_rc_alloc` defined in rc.c; the weak extern declaration
@@ -2386,7 +2387,7 @@ fn build_to(
clang.arg(&rc_obj);
match alloc {
ailang_codegen::AllocStrategy::Gc => {
// Boehm conservative GC (Decision 9 / Iter 14f). The lowered
// Boehm conservative GC (the transitional dual-allocator). The lowered
// IR calls @GC_malloc; libgc supplies it. Pthread/dl are
// pulled in transitively via libgc.so on Linux, so a single
// -lgc suffices.
@@ -2418,7 +2419,7 @@ fn build_to(
clang.arg(&bump_obj);
}
ailang_codegen::AllocStrategy::Rc => {
// Iter hs.4: rc.c compile-and-link hoisted to the
// rc.c compile-and-link hoisted to the
// unconditional path above. `--alloc=rc` is still a
// valid CLI flag — it drives codegen's
// `@ailang_rc_alloc`-vs-`@GC_malloc` selection in the IR
@@ -2547,7 +2548,7 @@ fn run_cmd(bin: &str, args: &[&str], ctx: &str) -> Result<()> {
Ok(())
}
/// ct.1 migration helper: rewrite bare cross-module Type::Con names
/// Canonical-form migration helper: rewrite bare cross-module Type::Con names
/// and Term::Ctor.type_name to their qualified form. Sets
/// `*changed` to `true` if any rewrite happened. Uses the
/// first-match-in-imports-order disambiguation rule with prelude as