test(cli): RED pin for type-scoped describe resolution
`ail describe <Type>.<op>` is the canonical form (model 0007 §1) but currently errors `no module \`Series\` in workspace` because resolve_describe_name (crates/ail/src/main.rs) only looks up the left segment as a MODULE, never as a known TYPE. The module-scoped `series.push` and bare `push` forms already resolve fine. RED pin: describe_resolves_type_scoped_op asserts `ail describe --workspace examples/series_sma.ail Series.push` exits 0 and prints the `series.push` def. Fails today on the exit-0 assertion (feature absent), not on scaffolding. GREEN side follows. refs #64
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
//! Pins the canonical type-scoped resolution path of `ail describe`.
|
||||
//!
|
||||
//! Property protected: `ail describe` resolves the CANONICAL
|
||||
//! `<Type>.<op>` form for a type-associated operation (model 0007 §1
|
||||
//! declares `<Type>.<op>` the canonical form; the op lives in the
|
||||
//! type's home module). For `series_sma`, `Series` is a known TYPE
|
||||
//! (its `TypeDef` is defined in module `series`), not a module — so
|
||||
//! `Series.push` must resolve to the SAME `push` fn that the
|
||||
//! module-scoped `series.push` and the bare `push` already resolve to.
|
||||
//!
|
||||
//! Scope: this pins ONLY `Type.op` resolution (issue #64 part 1). It
|
||||
//! does NOT pin "describe Type lists the type's ops" (part 2).
|
||||
//!
|
||||
//! Pure reader: spawns the committed `ail` binary against the
|
||||
//! committed `examples/series_sma.ail` fixture; mutates nothing.
|
||||
|
||||
use ailang_test_support::examples_dir;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
||||
fn ail_bin() -> PathBuf {
|
||||
// CARGO_BIN_EXE_<name> is set by cargo when building integration tests.
|
||||
PathBuf::from(env!("CARGO_BIN_EXE_ail"))
|
||||
}
|
||||
|
||||
/// `ail describe --workspace examples/series_sma.ail Series.push`
|
||||
/// exits 0 and prints the `series.push` function definition — the
|
||||
/// same def the module-scoped `series.push` resolves to. `Series` is
|
||||
/// a type defined in module `series`, so the canonical `<Type>.<op>`
|
||||
/// form must resolve through the type's home module.
|
||||
#[test]
|
||||
fn describe_resolves_type_scoped_op() {
|
||||
let fixture = examples_dir().join("series_sma.ail");
|
||||
let output = Command::new(ail_bin())
|
||||
.args([
|
||||
"describe",
|
||||
"--workspace",
|
||||
fixture.to_str().unwrap(),
|
||||
"Series.push",
|
||||
])
|
||||
.output()
|
||||
.expect("ail binary must launch");
|
||||
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
|
||||
assert!(
|
||||
output.status.success(),
|
||||
"describe Series.push must exit 0 (resolve the canonical \
|
||||
type-scoped form); exit={:?}\nstdout: {stdout}\nstderr: {stderr}",
|
||||
output.status.code(),
|
||||
);
|
||||
// Same def the module-scoped `series.push` prints: the home
|
||||
// module line and the `push` fn header (Form-A projection).
|
||||
assert!(
|
||||
stdout.contains("module: series"),
|
||||
"expected the home-module line `module: series`; got:\n{stdout}"
|
||||
);
|
||||
assert!(
|
||||
stdout.contains("(fn push"),
|
||||
"expected the `push` fn definition in the output; got:\n{stdout}"
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user