release: v21.0.0 – Full Self‑Hosting (S1/S2/S3 complete)

- DoD met: S1/S2 determinism (const/compare/threeblock-collect), PRIMARY hv1 inline no-fallback, S3 (llvmlite+kernel) reps green
- Harness: v1→llvmlite direct, EXE links to libnyash_kernel.a
- Python LLVM builder fixes: cmp normalization, ret PHI synthesis, mir_call flat shape
- Using/alias polish (prod): modules-first; missing aliases added; duplicate using cleaned
- Docs: phase-21.0 COMPLETE; CurrentTask closed; release notes added
This commit is contained in:
nyash-codex
2025-11-06 16:59:34 +09:00
parent c40fdd95bc
commit e326e787a4
21 changed files with 311 additions and 100 deletions

View File

@ -167,12 +167,51 @@ pub fn collect_using_and_strip(
}
// Resolve namespaces/packages
if prod {
// prod: only allow names present in aliases/packages (toml)
let mut pkg_name: String = target_unquoted.clone();
// prod: allow only names present in aliases/modules/packages (nyash.toml)
let mut name: String = target_unquoted.clone();
if let Some(v) = using_ctx.aliases.get(&target_unquoted) {
pkg_name = v.clone();
name = v.clone();
}
if let Some(pkg) = using_ctx.packages.get(&pkg_name) {
// 1) modules mapping (name -> path)
if let Some((_, mod_path)) = using_ctx
.pending_modules
.iter()
.find(|(n, _)| n == &name)
{
let out_path = mod_path.clone();
// Duplicate detection (same semantics as packages below)
let canon = std::fs::canonicalize(&out_path)
.ok()
.map(|pb| pb.to_string_lossy().to_string())
.unwrap_or_else(|| out_path.clone());
if let Some((prev_alias, prev_line)) = seen_paths.get(&canon) {
return Err(format!(
"using: duplicate import of '{}' at {}:{} (previous alias: '{}' first seen at line {})",
canon, filename, line_no, prev_alias, prev_line
));
} else {
seen_paths.insert(
canon.clone(),
(alias_name.clone().unwrap_or_else(|| "<none>".into()), line_no),
);
}
if let Some(alias) = alias_name.clone() {
if let Some((prev_path, prev_line)) = seen_aliases.get(&alias) {
if prev_path != &canon {
return Err(format!(
"using: alias '{}' rebound at {}:{} (was '{}' first seen at line {})",
alias, filename, line_no, prev_path, prev_line
));
}
} else {
seen_aliases.insert(alias, (canon, line_no));
}
}
prelude_paths.push(out_path);
}
// 2) named packages
else if let Some(pkg) = using_ctx.packages.get(&name) {
use crate::using::spec::PackageKind;
match pkg.kind {
PackageKind::Dylib => {
@ -189,13 +228,13 @@ pub fn collect_using_and_strip(
} else if matches!(base.extension().and_then(|s| s.to_str()), Some("nyash") | Some("hako")) {
pkg.path.clone()
} else {
let leaf = base
.file_name()
.and_then(|s| s.to_str())
.unwrap_or(&pkg_name);
base.join(format!("{}.hako", leaf))
.to_string_lossy()
.to_string()
let leaf = base
.file_name()
.and_then(|s| s.to_str())
.unwrap_or(&name);
base.join(format!("{}.hako", leaf))
.to_string_lossy()
.to_string()
};
// Duplicate detection for prod package alias resolution
let canon = std::fs::canonicalize(&out)