iter 23.1.2: load_workspace auto-injects prelude module
This commit is contained in:
@@ -282,6 +282,13 @@ pub enum WorkspaceLoadError {
|
||||
superclass: String,
|
||||
type_repr: String,
|
||||
},
|
||||
|
||||
/// Iter 23.1: a user module attempted to use the reserved
|
||||
/// module name `prelude`. The prelude is auto-injected by
|
||||
/// the loader, so a user module of the same name would
|
||||
/// collide silently. Reject explicitly.
|
||||
#[error("module name {name:?} is reserved (auto-injected by the loader)")]
|
||||
ReservedModuleName { name: String },
|
||||
}
|
||||
|
||||
/// Hash over the canonical bytes of a complete module.
|
||||
@@ -295,6 +302,23 @@ pub fn module_hash(m: &Module) -> String {
|
||||
h.to_hex().as_str()[..16].to_string()
|
||||
}
|
||||
|
||||
/// Iter 23.1: the prelude module is embedded into the binary at
|
||||
/// compile time so the loader needs no on-disk resolution. The
|
||||
/// canonical source-of-truth file remains
|
||||
/// `examples/prelude.ail.json` (the file the LLM-author edits).
|
||||
const PRELUDE_JSON: &str = include_str!(
|
||||
"../../../examples/prelude.ail.json"
|
||||
);
|
||||
|
||||
/// Iter 23.1: parse the embedded prelude source into a `Module`.
|
||||
/// Panics on parse failure — the prelude is build-time-validated;
|
||||
/// a failure here means the embedded file is malformed and is a
|
||||
/// build-correctness bug, not a runtime concern.
|
||||
fn load_prelude() -> Module {
|
||||
serde_json::from_str(PRELUDE_JSON)
|
||||
.expect("examples/prelude.ail.json must parse as a Module")
|
||||
}
|
||||
|
||||
/// Load entry module plus all transitively reachable modules.
|
||||
///
|
||||
/// Algorithm: DFS over `imports`, with two sets:
|
||||
@@ -333,6 +357,19 @@ pub fn load_workspace(entry_path: &Path) -> Result<Workspace, WorkspaceLoadError
|
||||
&mut visiting_set,
|
||||
)?;
|
||||
|
||||
// Iter 23.1: inject the prelude module. It is implicitly
|
||||
// part of every workspace, so the user's import graph
|
||||
// does not name it. A user module that happens to be named
|
||||
// "prelude" would collide here; reject explicitly so the
|
||||
// failure is informative rather than silent.
|
||||
if modules.contains_key("prelude") {
|
||||
return Err(WorkspaceLoadError::ReservedModuleName {
|
||||
name: "prelude".to_string(),
|
||||
});
|
||||
}
|
||||
let prelude = load_prelude();
|
||||
modules.insert("prelude".to_string(), prelude);
|
||||
|
||||
// Iter 22b.2: class-schema validation runs before registry
|
||||
// construction so that ill-kinded class definitions are rejected
|
||||
// before any instance against them is registered.
|
||||
@@ -851,7 +888,37 @@ mod tests {
|
||||
assert_eq!(ws.entry, "ws_main");
|
||||
assert!(ws.modules.contains_key("ws_main"));
|
||||
assert!(ws.modules.contains_key("ws_lib"));
|
||||
assert_eq!(ws.modules.len(), 2);
|
||||
// Iter 23.1: the loader auto-injects the `prelude` module,
|
||||
// so the count is the user's two modules plus prelude.
|
||||
assert_eq!(ws.modules.len(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn loads_workspace_auto_injects_prelude() {
|
||||
// Iter 23.1: the prelude module is implicitly part of every
|
||||
// workspace, regardless of whether the user's modules import
|
||||
// it. Loading any well-formed workspace must result in
|
||||
// `ws.modules["prelude"]` being present with the Ordering
|
||||
// type def.
|
||||
let workspace_root =
|
||||
std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../..");
|
||||
let entry = workspace_root.join("examples").join("ws_main.ail.json");
|
||||
|
||||
let ws = load_workspace(&entry).expect("load workspace");
|
||||
assert!(
|
||||
ws.modules.contains_key("prelude"),
|
||||
"prelude module must be auto-injected; modules present: {:?}",
|
||||
ws.modules.keys().collect::<Vec<_>>()
|
||||
);
|
||||
let prelude = &ws.modules["prelude"];
|
||||
assert_eq!(prelude.name, "prelude");
|
||||
assert!(
|
||||
prelude.defs.iter().any(|d| matches!(
|
||||
d,
|
||||
crate::ast::Def::Type(t) if t.name == "Ordering"
|
||||
)),
|
||||
"prelude must contain Ordering type def"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user