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:
+43
-42
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user