Iter 5a: Workspace-Loader mit Imports
ailang_core::Workspace + load_workspace folgt imports-Feld rekursiv vom Eintrittsmodul. DFS mit Zyklus-Erkennung; Konvention: Modulname == Dateiname (.ail.json). WorkspaceLoadError sammelt strukturiert: Cycle, ModuleNotFound, ModuleNameMismatch, Schema, Io. Neues ail workspace <entry> [--json] listet erreichbare Module mit module_hash und Def-Count. Bestehende Subkommandos arbeiten weiter pro Einzelmodul (Iter 5d).
This commit is contained in:
@@ -83,6 +83,16 @@ enum Cmd {
|
||||
#[arg(long)]
|
||||
json: bool,
|
||||
},
|
||||
/// Lädt einen Workspace (Eintrittsmodul + transitive Imports) und
|
||||
/// listet alle erreichbaren Module mit Hash und Def-Anzahl.
|
||||
///
|
||||
/// Iter 5a: nur das Listing. Cross-Module-Typcheck/Codegen folgt in
|
||||
/// 5b/5c; bestehende Subkommandos arbeiten weiter pro Einzelmodul.
|
||||
Workspace {
|
||||
entry: PathBuf,
|
||||
#[arg(long)]
|
||||
json: bool,
|
||||
},
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
@@ -286,6 +296,61 @@ fn main() -> Result<()> {
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
Cmd::Workspace { entry, json } => {
|
||||
let ws = ailang_core::load_workspace(&entry)?;
|
||||
// Alphabetisch über Modul-Namen iterieren (BTreeMap-Order ist
|
||||
// bereits sortiert; explizit absichern).
|
||||
let mut entries: Vec<(String, String, usize)> = ws
|
||||
.modules
|
||||
.iter()
|
||||
.map(|(name, m)| {
|
||||
(
|
||||
name.clone(),
|
||||
ailang_core::module_hash(m),
|
||||
m.defs.len(),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
entries.sort_by(|a, b| a.0.cmp(&b.0));
|
||||
|
||||
if json {
|
||||
let arr: Vec<_> = entries
|
||||
.iter()
|
||||
.map(|(name, hash, defs)| {
|
||||
serde_json::json!({
|
||||
"name": name,
|
||||
"hash": hash,
|
||||
"defs": defs,
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
let out = serde_json::json!({
|
||||
"entry": ws.entry,
|
||||
"modules": arr,
|
||||
});
|
||||
println!("{}", serde_json::to_string_pretty(&out)?);
|
||||
} else {
|
||||
// Spaltenbreite an längstem Modulnamen ausrichten. Erste Zeile
|
||||
// markiert das Eintrittsmodul mit `*`.
|
||||
let name_width = entries
|
||||
.iter()
|
||||
.map(|(n, _, _)| n.len())
|
||||
.max()
|
||||
.unwrap_or(0)
|
||||
.max(6);
|
||||
println!("entry: {}", ws.entry);
|
||||
for (name, hash, defs) in &entries {
|
||||
let marker = if *name == ws.entry { "*" } else { " " };
|
||||
println!(
|
||||
"{marker} {:<width$} {} {:>3} defs",
|
||||
name,
|
||||
hash,
|
||||
defs,
|
||||
width = name_width,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Cmd::Deps { path, of, json } => {
|
||||
let m = ailang_core::load_module(&path)?;
|
||||
let mut entries = Vec::new();
|
||||
|
||||
Reference in New Issue
Block a user