008d18bb18
Moved PRELUDE_AIL const + parse_prelude fn to ailang-surface; re-exported from surface's lib.rs. surface::load_workspace rewritten 3-line shim-call → 7-line composition: load_modules_with → reserved-name check → inject parse_prelude → build_workspace(&["prelude"]). Five deletions in core: PRELUDE_JSON, load_prelude, load_workspace_with (the pd.1 shim), the top-level cfg(test) load_one fn, and the cfg(test) crate::load_module import. Production literal-"prelude" count in crates/ailang-core/src/ is now zero. Cross-form-identity preflight PASSED at module_hash 3abe0d3fa3c11c99 — parse(prelude.ail) ≡ deserialize(prelude.ail.json), so pd.3's deletion of the JSON is safe. Three new pin tests in ailang-surface/tests/: prelude_parse_pin (succeeds + min defs); prelude_module_hash_pin (cross-form-identity + literal-hex anchor); prelude_injection_pin (inject + reservation). Plan deviations (recorded in journal): switched the regression-pin fixture from non-existent examples/hello.ail.json to hello.ail; relocated 10 in-mod core tests to crates/ailang-core/tests/workspace_pin.rs because the dev-dep cycle (core ↔ surface) prevents in-mod aliasing in the lib-test target (form-a.1 T5 precedent); preserved load_one production-symbol-deletion by adding a test-mod-private load_one helper in core's mod tests for the 2 pd.1-introduced tests still consuming it. cargo test --workspace 573 green (+9 net from pd.1 baseline). bench/cross_lang.py + bench/compile_check.py exit 0; bench/check.py exit 1 with established noise envelope (bench_list_sum.bump_s, 13th consecutive observation; pd.2 is workspace-loader-only, no codegen touch — baseline pristine).
44 lines
1.6 KiB
Rust
44 lines
1.6 KiB
Rust
//! pd.2 (`prelude-decouple` milestone): pin that
|
|
//! `surface::load_workspace` injects the prelude into every workspace
|
|
//! and rejects user modules trying to take the reserved name.
|
|
|
|
use ailang_core::workspace::WorkspaceLoadError;
|
|
use ailang_surface::load_workspace;
|
|
use std::path::Path;
|
|
|
|
#[test]
|
|
fn surface_load_workspace_injects_prelude_into_every_workspace() {
|
|
// Use any existing single-module example from `examples/`. The hello
|
|
// example is a stable choice (used by other surface tests). Post-
|
|
// form-a.1 the canonical sidecar is `.ail` (Form A); the `.ail.json`
|
|
// for `hello` was deleted by form-a.1 T8.
|
|
let entry = Path::new("../../examples/hello.ail");
|
|
let ws = load_workspace(entry).expect("load");
|
|
assert!(
|
|
ws.modules.contains_key("prelude"),
|
|
"prelude must appear in every workspace post-pd.2"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn surface_load_workspace_rejects_user_module_named_prelude() {
|
|
let dir = tempfile::tempdir().unwrap();
|
|
// Create a JSON-form fixture for the user-side "prelude" module.
|
|
// Surface's loader should fail with ReservedModuleName.
|
|
let prelude_path = dir.path().join("prelude.ail.json");
|
|
std::fs::write(
|
|
&prelude_path,
|
|
r#"{"schema":"ailang/v0","name":"prelude","imports":[],"defs":[]}"#,
|
|
)
|
|
.unwrap();
|
|
// Single-file workspace where the entry IS named "prelude" trips
|
|
// the reservation.
|
|
let err = load_workspace(&prelude_path).expect_err("must reject");
|
|
match err {
|
|
WorkspaceLoadError::ReservedModuleName { name } => {
|
|
assert_eq!(name, "prelude");
|
|
}
|
|
other => panic!("expected ReservedModuleName, got: {other:?}"),
|
|
}
|
|
}
|