chore: Phase 25.1 完了 - LoopForm v2/Stage1 CLI/環境変数削減 + Phase 26-D からの変更
Phase 25.1 完了成果: - ✅ LoopForm v2 テスト・ドキュメント・コメント完備 - 4ケース(A/B/C/D)完全テストカバレッジ - 最小再現ケース作成(SSAバグ調査用) - SSOT文書作成(loopform_ssot.md) - 全ソースに [LoopForm] コメントタグ追加 - ✅ Stage-1 CLI デバッグ環境構築 - stage1_cli.hako 実装 - stage1_bridge.rs ブリッジ実装 - デバッグツール作成(stage1_debug.sh/stage1_minimal.sh) - アーキテクチャ改善提案文書 - ✅ 環境変数削減計画策定 - 25変数の完全調査・分類 - 6段階削減ロードマップ(25→5、80%削減) - 即時削除可能変数特定(NYASH_CONFIG/NYASH_DEBUG) Phase 26-D からの累積変更: - PHI実装改善(ExitPhiBuilder/HeaderPhiBuilder等) - MIRビルダーリファクタリング - 型伝播・最適化パス改善 - その他約300ファイルの累積変更 🎯 技術的成果: - SSAバグ根本原因特定(条件分岐内loop変数変更) - Region+next_iパターン適用完了(UsingCollectorBox等) - LoopFormパターン文書化・テスト化完了 - セルフホスティング基盤強化 Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: ChatGPT <noreply@openai.com> Co-Authored-By: Task Assistant <task@anthropic.com>
This commit is contained in:
@ -25,8 +25,8 @@ pub fn populate_from_toml(
|
||||
for name in candidates.iter() {
|
||||
let p = std::path::Path::new(name);
|
||||
if p.exists() {
|
||||
let txt = std::fs::read_to_string(p)
|
||||
.map_err(|e| UsingError::ReadToml(e.to_string()))?;
|
||||
let txt =
|
||||
std::fs::read_to_string(p).map_err(|e| UsingError::ReadToml(e.to_string()))?;
|
||||
found = Some((txt, p.to_path_buf()));
|
||||
break;
|
||||
}
|
||||
@ -48,8 +48,8 @@ pub fn populate_from_toml(
|
||||
// 3) Fallback: empty content and path
|
||||
Ok(found.unwrap_or((String::new(), std::path::PathBuf::from(""))))
|
||||
}?;
|
||||
let doc = toml::from_str::<toml::Value>(&text)
|
||||
.map_err(|e| UsingError::ParseToml(e.to_string()))?;
|
||||
let doc =
|
||||
toml::from_str::<toml::Value>(&text).map_err(|e| UsingError::ParseToml(e.to_string()))?;
|
||||
let toml_dir = toml_path
|
||||
.parent()
|
||||
.map(|p| p.to_path_buf())
|
||||
@ -59,7 +59,11 @@ pub fn populate_from_toml(
|
||||
if let Some(mods) = doc.get("modules").and_then(|v| v.as_table()) {
|
||||
fn visit(prefix: &str, tbl: &toml::value::Table, out: &mut Vec<(String, String)>) {
|
||||
for (k, v) in tbl.iter() {
|
||||
let name = if prefix.is_empty() { k.to_string() } else { format!("{}.{}", prefix, k) };
|
||||
let name = if prefix.is_empty() {
|
||||
k.to_string()
|
||||
} else {
|
||||
format!("{}.{}", prefix, k)
|
||||
};
|
||||
if let Some(s) = v.as_str() {
|
||||
out.push((name, s.to_string()));
|
||||
} else if let Some(t) = v.as_table() {
|
||||
@ -97,15 +101,35 @@ pub fn populate_from_toml(
|
||||
}
|
||||
// named packages: any subtable not paths/aliases is a package
|
||||
for (k, v) in using_tbl.iter() {
|
||||
if k == "paths" || k == "aliases" { continue; }
|
||||
if k == "paths" || k == "aliases" {
|
||||
continue;
|
||||
}
|
||||
if let Some(tbl) = v.as_table() {
|
||||
let kind = tbl.get("kind").and_then(|x| x.as_str()).map(PackageKind::from_str).unwrap_or(PackageKind::Package);
|
||||
let kind = tbl
|
||||
.get("kind")
|
||||
.and_then(|x| x.as_str())
|
||||
.map(PackageKind::from_str)
|
||||
.unwrap_or(PackageKind::Package);
|
||||
// path is required
|
||||
if let Some(path_s) = tbl.get("path").and_then(|x| x.as_str()) {
|
||||
let path = path_s.to_string();
|
||||
let main = tbl.get("main").and_then(|x| x.as_str()).map(|s| s.to_string());
|
||||
let bid = tbl.get("bid").and_then(|x| x.as_str()).map(|s| s.to_string());
|
||||
packages.insert(k.to_string(), UsingPackage { kind, path, main, bid });
|
||||
let main = tbl
|
||||
.get("main")
|
||||
.and_then(|x| x.as_str())
|
||||
.map(|s| s.to_string());
|
||||
let bid = tbl
|
||||
.get("bid")
|
||||
.and_then(|x| x.as_str())
|
||||
.map(|s| s.to_string());
|
||||
packages.insert(
|
||||
k.to_string(),
|
||||
UsingPackage {
|
||||
kind,
|
||||
path,
|
||||
main,
|
||||
bid,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -139,7 +163,9 @@ pub fn resolve_using_target_common(
|
||||
) -> Result<String, String> {
|
||||
// 1) modules mapping
|
||||
if let Some((_, p)) = modules.iter().find(|(n, _)| n == tgt) {
|
||||
if verbose { eprintln!("[using/resolve] modules '{}' -> '{}'", tgt, p); }
|
||||
if verbose {
|
||||
eprintln!("[using/resolve] modules '{}' -> '{}'", tgt, p);
|
||||
}
|
||||
return Ok(p.clone());
|
||||
}
|
||||
// 2) named packages
|
||||
@ -147,28 +173,43 @@ pub fn resolve_using_target_common(
|
||||
match pkg.kind {
|
||||
PackageKind::Dylib => {
|
||||
let out = format!("dylib:{}", pkg.path);
|
||||
if verbose { eprintln!("[using/resolve] dylib '{}' -> '{}'", tgt, out); }
|
||||
if verbose {
|
||||
eprintln!("[using/resolve] dylib '{}' -> '{}'", tgt, out);
|
||||
}
|
||||
return Ok(out);
|
||||
}
|
||||
PackageKind::Package => {
|
||||
let base = std::path::Path::new(&pkg.path);
|
||||
let out = if let Some(m) = &pkg.main {
|
||||
if matches!(base.extension().and_then(|s| s.to_str()), Some("nyash") | Some("hako")) {
|
||||
if matches!(
|
||||
base.extension().and_then(|s| s.to_str()),
|
||||
Some("nyash") | Some("hako")
|
||||
) {
|
||||
pkg.path.clone()
|
||||
} else {
|
||||
base.join(m).to_string_lossy().to_string()
|
||||
}
|
||||
} else {
|
||||
if matches!(base.extension().and_then(|s| s.to_str()), Some("nyash") | Some("hako")) {
|
||||
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(tgt);
|
||||
let hako = base.join(format!("{}.hako", leaf));
|
||||
if hako.exists() { hako.to_string_lossy().to_string() }
|
||||
else { base.join(format!("{}.hako", leaf)).to_string_lossy().to_string() }
|
||||
if hako.exists() {
|
||||
hako.to_string_lossy().to_string()
|
||||
} else {
|
||||
base.join(format!("{}.hako", leaf))
|
||||
.to_string_lossy()
|
||||
.to_string()
|
||||
}
|
||||
}
|
||||
};
|
||||
if verbose { eprintln!("[using/resolve] package '{}' -> '{}'", tgt, out); }
|
||||
if verbose {
|
||||
eprintln!("[using/resolve] package '{}' -> '{}'", tgt, out);
|
||||
}
|
||||
return Ok(out);
|
||||
}
|
||||
}
|
||||
@ -179,26 +220,41 @@ pub fn resolve_using_target_common(
|
||||
let mut cand: Vec<String> = Vec::new();
|
||||
if let Some(dir) = context_dir {
|
||||
let c1 = dir.join(&rel_hako);
|
||||
if c1.exists() { cand.push(c1.to_string_lossy().to_string()); }
|
||||
if c1.exists() {
|
||||
cand.push(c1.to_string_lossy().to_string());
|
||||
}
|
||||
let c2 = dir.join(&rel_ny);
|
||||
if c2.exists() { cand.push(c2.to_string_lossy().to_string()); }
|
||||
if c2.exists() {
|
||||
cand.push(c2.to_string_lossy().to_string());
|
||||
}
|
||||
}
|
||||
for base in using_paths {
|
||||
let p = std::path::Path::new(base);
|
||||
let c1 = p.join(&rel_hako);
|
||||
if c1.exists() { cand.push(c1.to_string_lossy().to_string()); }
|
||||
if c1.exists() {
|
||||
cand.push(c1.to_string_lossy().to_string());
|
||||
}
|
||||
let c2 = p.join(&rel_ny);
|
||||
if c2.exists() { cand.push(c2.to_string_lossy().to_string()); }
|
||||
if c2.exists() {
|
||||
cand.push(c2.to_string_lossy().to_string());
|
||||
}
|
||||
}
|
||||
if cand.is_empty() {
|
||||
if verbose { eprintln!("[using] unresolved '{}' (searched: rel+paths)", tgt); }
|
||||
return Err(format!("using: unresolved '{}': searched relative and using.paths", tgt));
|
||||
if verbose {
|
||||
eprintln!("[using] unresolved '{}' (searched: rel+paths)", tgt);
|
||||
}
|
||||
return Err(format!(
|
||||
"using: unresolved '{}': searched relative and using.paths",
|
||||
tgt
|
||||
));
|
||||
}
|
||||
if cand.len() > 1 && strict {
|
||||
return Err(format!("ambiguous using '{}': {}", tgt, cand.join(", ")));
|
||||
}
|
||||
let out = cand.remove(0);
|
||||
if verbose { eprintln!("[using/resolve] '{}' -> '{}'", tgt, out); }
|
||||
if verbose {
|
||||
eprintln!("[using/resolve] '{}' -> '{}'", tgt, out);
|
||||
}
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
@ -211,12 +267,20 @@ fn load_workspace_modules(
|
||||
let members = workspace_tbl
|
||||
.get("members")
|
||||
.and_then(|v| v.as_array())
|
||||
.ok_or_else(|| UsingError::ParseWorkspaceModule("modules.workspace".into(), "expected members array".into()))?;
|
||||
.ok_or_else(|| {
|
||||
UsingError::ParseWorkspaceModule(
|
||||
"modules.workspace".into(),
|
||||
"expected members array".into(),
|
||||
)
|
||||
})?;
|
||||
|
||||
for entry in members {
|
||||
let raw_path = entry
|
||||
.as_str()
|
||||
.ok_or_else(|| UsingError::ParseWorkspaceModule("modules.workspace".into(), "members must be string paths".into()))?;
|
||||
let raw_path = entry.as_str().ok_or_else(|| {
|
||||
UsingError::ParseWorkspaceModule(
|
||||
"modules.workspace".into(),
|
||||
"members must be string paths".into(),
|
||||
)
|
||||
})?;
|
||||
let module_path = if std::path::Path::new(raw_path).is_absolute() {
|
||||
std::path::PathBuf::from(raw_path)
|
||||
} else {
|
||||
@ -227,10 +291,16 @@ fn load_workspace_modules(
|
||||
.map(|p| p.to_path_buf())
|
||||
.unwrap_or_else(|| nyash_dir.to_path_buf());
|
||||
let module_text = std::fs::read_to_string(&module_path).map_err(|e| {
|
||||
UsingError::ReadWorkspaceModule(module_path.to_string_lossy().to_string(), e.to_string())
|
||||
UsingError::ReadWorkspaceModule(
|
||||
module_path.to_string_lossy().to_string(),
|
||||
e.to_string(),
|
||||
)
|
||||
})?;
|
||||
let module_doc = toml::from_str::<toml::Value>(&module_text).map_err(|e| {
|
||||
UsingError::ParseWorkspaceModule(module_path.to_string_lossy().to_string(), e.to_string())
|
||||
UsingError::ParseWorkspaceModule(
|
||||
module_path.to_string_lossy().to_string(),
|
||||
e.to_string(),
|
||||
)
|
||||
})?;
|
||||
let module_name = module_doc
|
||||
.get("module")
|
||||
|
||||
Reference in New Issue
Block a user