Iter 15e: render is the exact inverse of parse — CLI hygiene
The CLI help text claimed `render` was symmetric to `parse`, but `render` was wired to ailang_core::pretty::module (an older human-pretty form) while `parse` consumed form (A). Two different "text projections" coexisted under one name. Fix: Cmd::Render and Cmd::Describe (both branches) now call ailang_surface::print, the actual inverse of `parse`. Round-trip gate via `ail render | ail parse` is now an e2e test in crates/ail/tests/e2e.rs in addition to the existing unit-level round-trip across all 25 fixtures in ailang-surface/tests. Cleanup: `ailang_core::pretty::module` and its three private helpers (`def_block`, `term_block`, `term_inline`) deleted — ~260 LOC of duplicate-purpose code removed. pretty.rs goes from 457 to 196 LOC. Surviving surface is intentionally narrow: manifest, type_to_string, pattern_to_string — the diagnostic stringification used in error messages, where one-line ML notation reads better than form (A)'s nested S-expressions. Module-level doc rewritten to nail down the single-purpose framing. Tests: 89/89 (e2e +1, ailang-core unit -1 since the deleted test exercised the deleted fn). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+11
-7
@@ -13,8 +13,9 @@
|
||||
//!
|
||||
//! - `manifest` — compact symbol table of a module (or workspace);
|
||||
//! one line per def with type, effects, hash.
|
||||
//! - `render` — pretty-print a `.ail.json` module as the textual
|
||||
//! `.ail` projection.
|
||||
//! - `render` — print a `.ail.json` module as form-(A) text. Exact
|
||||
//! inverse of `parse`; piping `render | parse` round-trips to the
|
||||
//! same canonical bytes.
|
||||
//! - `describe` — full detail of a single definition, JSON or text.
|
||||
//! - `deps` — static call edges per def (or for one named def);
|
||||
//! workspace mode emits cross-module edges.
|
||||
@@ -70,7 +71,10 @@ enum Cmd {
|
||||
#[arg(long)]
|
||||
workspace: bool,
|
||||
},
|
||||
/// Prints the module in text form (pretty-printer).
|
||||
/// Prints the module as form (A) text — the canonical authoring
|
||||
/// surface and the exact inverse of `parse`. Round-tripping
|
||||
/// `render | parse` reproduces the input's canonical bytes
|
||||
/// (gated by `crates/ailang-surface/tests/round_trip.rs`).
|
||||
Render { path: PathBuf },
|
||||
/// Prints a single definition as JSON or pretty text.
|
||||
Describe {
|
||||
@@ -278,7 +282,7 @@ fn main() -> Result<()> {
|
||||
}
|
||||
Cmd::Render { path } => {
|
||||
let m = ailang_core::load_module(&path)?;
|
||||
print!("{}", ailang_core::pretty::module(&m));
|
||||
print!("{}", ailang_surface::print(&m));
|
||||
}
|
||||
Cmd::Describe { path, name, json, workspace } => {
|
||||
if workspace {
|
||||
@@ -310,7 +314,7 @@ fn main() -> Result<()> {
|
||||
let h = ailang_core::def_hash(def);
|
||||
println!("module: {}", mod_name);
|
||||
println!("hash: {h}");
|
||||
print!("{}", ailang_core::pretty::module(&one));
|
||||
print!("{}", ailang_surface::print(&one));
|
||||
}
|
||||
} else {
|
||||
let m = ailang_core::load_module(&path)?;
|
||||
@@ -323,7 +327,7 @@ fn main() -> Result<()> {
|
||||
let s = serde_json::to_string_pretty(def)?;
|
||||
println!("{s}");
|
||||
} else {
|
||||
// Pretty form: render module with only this def.
|
||||
// Form-(A) projection of a one-def module.
|
||||
let one = ailang_core::Module {
|
||||
schema: m.schema.clone(),
|
||||
name: m.name.clone(),
|
||||
@@ -332,7 +336,7 @@ fn main() -> Result<()> {
|
||||
};
|
||||
let h = ailang_core::def_hash(def);
|
||||
println!("hash: {h}");
|
||||
print!("{}", ailang_core::pretty::module(&one));
|
||||
print!("{}", ailang_surface::print(&one));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user