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:
@ -54,7 +54,9 @@ impl NyashRunner {
|
||||
let using_ast = crate::config::env::using_ast_enabled();
|
||||
if using_ast {
|
||||
// Text-based merge: faster for inline/selfhost execution
|
||||
match crate::runner::modes::common_util::resolve::merge_prelude_text(self, &code, filename) {
|
||||
match crate::runner::modes::common_util::resolve::merge_prelude_text(
|
||||
self, &code, filename,
|
||||
) {
|
||||
Ok(merged) => {
|
||||
code_ref = std::borrow::Cow::Owned(merged);
|
||||
}
|
||||
@ -65,7 +67,9 @@ impl NyashRunner {
|
||||
}
|
||||
} else {
|
||||
// Legacy: strip only (no prelude merge)
|
||||
match crate::runner::modes::common_util::resolve::resolve_prelude_paths_profiled(self, &code, filename) {
|
||||
match crate::runner::modes::common_util::resolve::resolve_prelude_paths_profiled(
|
||||
self, &code, filename,
|
||||
) {
|
||||
Ok((clean, paths)) => {
|
||||
if !paths.is_empty() {
|
||||
eprintln!("[ny-compiler] using: AST prelude merge is disabled in this profile. Enable NYASH_USING_AST=1 or remove 'using' lines.");
|
||||
@ -73,14 +77,18 @@ impl NyashRunner {
|
||||
}
|
||||
code_ref = std::borrow::Cow::Owned(clean);
|
||||
}
|
||||
Err(e) => { eprintln!("[ny-compiler] {}", e); return false; }
|
||||
Err(e) => {
|
||||
eprintln!("[ny-compiler] {}", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Promote dev sugar to standard: pre-expand line-head '@name[:T] = expr' to 'local name[:T] = expr'
|
||||
{
|
||||
let expanded = crate::runner::modes::common_util::resolve::preexpand_at_local(code_ref.as_ref());
|
||||
let expanded =
|
||||
crate::runner::modes::common_util::resolve::preexpand_at_local(code_ref.as_ref());
|
||||
code_ref = std::borrow::Cow::Owned(expanded);
|
||||
}
|
||||
|
||||
@ -98,47 +106,56 @@ impl NyashRunner {
|
||||
{
|
||||
let preenv = std::env::var("NYASH_MACRO_SELFHOST_PRE_EXPAND")
|
||||
.ok()
|
||||
.or_else(|| if crate::r#macro::enabled() { Some("auto".to_string()) } else { None });
|
||||
.or_else(|| {
|
||||
if crate::r#macro::enabled() {
|
||||
Some("auto".to_string())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
let do_pre = match preenv.as_deref() {
|
||||
Some("1") => true,
|
||||
Some("auto") => crate::r#macro::enabled() && crate::config::env::vm_use_py(),
|
||||
_ => false,
|
||||
};
|
||||
if do_pre && crate::r#macro::enabled() {
|
||||
crate::cli_v!("[ny-compiler] selfhost macro pre-expand: engaging (mode={:?})", preenv);
|
||||
match NyashParser::parse_from_string(code_ref.as_ref()) {
|
||||
Ok(ast0) => {
|
||||
let ast = crate::r#macro::maybe_expand_and_dump(&ast0, false);
|
||||
// Compile to MIR and execute (respect VM/PyVM policy similar to vm mode)
|
||||
let mut mir_compiler = MirCompiler::with_options(true);
|
||||
match mir_compiler.compile(ast) {
|
||||
Ok(result) => {
|
||||
let prefer_pyvm = crate::config::env::vm_use_py();
|
||||
if prefer_pyvm {
|
||||
if let Ok(code) = crate::runner::modes::common_util::pyvm::run_pyvm_harness_lib(&result.module, "selfhost-preexpand") {
|
||||
crate::cli_v!(
|
||||
"[ny-compiler] selfhost macro pre-expand: engaging (mode={:?})",
|
||||
preenv
|
||||
);
|
||||
match NyashParser::parse_from_string(code_ref.as_ref()) {
|
||||
Ok(ast0) => {
|
||||
let ast = crate::r#macro::maybe_expand_and_dump(&ast0, false);
|
||||
// Compile to MIR and execute (respect VM/PyVM policy similar to vm mode)
|
||||
let mut mir_compiler = MirCompiler::with_options(true);
|
||||
match mir_compiler.compile(ast) {
|
||||
Ok(result) => {
|
||||
let prefer_pyvm = crate::config::env::vm_use_py();
|
||||
if prefer_pyvm {
|
||||
if let Ok(code) = crate::runner::modes::common_util::pyvm::run_pyvm_harness_lib(&result.module, "selfhost-preexpand") {
|
||||
println!("Result: {}", code);
|
||||
std::process::exit(code);
|
||||
} else {
|
||||
eprintln!("❌ PyVM error (selfhost-preexpand)");
|
||||
std::process::exit(1);
|
||||
}
|
||||
} else {
|
||||
// For now, only PyVM path is supported in pre-expand mode; fall back otherwise.
|
||||
crate::cli_v!("[ny-compiler] pre-expand path requires NYASH_VM_USE_PY=1; falling back to default selfhost");
|
||||
} else {
|
||||
// For now, only PyVM path is supported in pre-expand mode; fall back otherwise.
|
||||
crate::cli_v!("[ny-compiler] pre-expand path requires NYASH_VM_USE_PY=1; falling back to default selfhost");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("[ny-compiler] pre-expand compile error: {}", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("[ny-compiler] pre-expand compile error: {}", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("[ny-compiler] pre-expand parse error: {}", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("[ny-compiler] pre-expand parse error: {}", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let tmp_path = tmp_dir.join("ny_parser_input.ny");
|
||||
@ -194,7 +211,9 @@ impl NyashRunner {
|
||||
.collect();
|
||||
if !items.is_empty() {
|
||||
extra_owned.push("--".to_string());
|
||||
for it in items { extra_owned.push(it); }
|
||||
for it in items {
|
||||
extra_owned.push(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
let extra: Vec<&str> = extra_owned.iter().map(|s| s.as_str()).collect();
|
||||
@ -204,10 +223,7 @@ impl NyashRunner {
|
||||
parser_prog,
|
||||
timeout_ms,
|
||||
&extra,
|
||||
&[
|
||||
"NYASH_USE_NY_COMPILER",
|
||||
"NYASH_CLI_VERBOSE",
|
||||
],
|
||||
&["NYASH_USE_NY_COMPILER", "NYASH_CLI_VERBOSE"],
|
||||
&[
|
||||
("NYASH_JSON_ONLY", "1"),
|
||||
("NYASH_DISABLE_PLUGINS", "1"),
|
||||
@ -220,9 +236,9 @@ impl NyashRunner {
|
||||
match json::parse_json_v0_line(&line) {
|
||||
Ok(module) => {
|
||||
if crate::config::env::cli_verbose() {
|
||||
if crate::config::env::cli_verbose() {
|
||||
super::json_v0_bridge::maybe_dump_mir(&module);
|
||||
}
|
||||
if crate::config::env::cli_verbose() {
|
||||
super::json_v0_bridge::maybe_dump_mir(&module);
|
||||
}
|
||||
}
|
||||
let emit_only = crate::config::env::ny_compiler_emit_only();
|
||||
if emit_only {
|
||||
@ -230,14 +246,14 @@ impl NyashRunner {
|
||||
}
|
||||
// Prefer PyVM path when requested
|
||||
if crate::config::env::vm_use_py() {
|
||||
if let Some(code) = crate::runner::modes::common_util::selfhost::json::run_pyvm_module(&module, "selfhost") {
|
||||
if let Some(code) = crate::runner::modes::common_util::selfhost::json::run_pyvm_module(&module, "selfhost") {
|
||||
println!("Result: {}", code);
|
||||
std::process::exit(code);
|
||||
}
|
||||
}
|
||||
self.execute_mir_module(&module);
|
||||
return true;
|
||||
}
|
||||
self.execute_mir_module(&module);
|
||||
return true;
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("[ny-compiler] json parse error (child): {}", e);
|
||||
}
|
||||
@ -260,10 +276,14 @@ impl NyashRunner {
|
||||
.ok()
|
||||
.and_then(|s| s.parse().ok())
|
||||
.unwrap_or(60000); // Phase 25.1b: Increased to 60000ms (60s) for consistency
|
||||
let out = match super::modes::common_util::io::spawn_with_timeout(cmd, timeout_ms) {
|
||||
Ok(o) => o,
|
||||
Err(e) => { eprintln!("[ny-compiler] python harness failed: {}", e); return false; }
|
||||
};
|
||||
let out =
|
||||
match super::modes::common_util::io::spawn_with_timeout(cmd, timeout_ms) {
|
||||
Ok(o) => o,
|
||||
Err(e) => {
|
||||
eprintln!("[ny-compiler] python harness failed: {}", e);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
if !out.timed_out {
|
||||
if let Ok(s) = String::from_utf8(out.stdout) {
|
||||
if let Some(line) = crate::runner::modes::common_util::selfhost::json::first_json_v0_line(&s) {
|
||||
@ -340,14 +360,18 @@ impl NyashRunner {
|
||||
.ok()
|
||||
.and_then(|s| s.parse().ok())
|
||||
.unwrap_or(2000);
|
||||
if let Some(module) = super::modes::common_util::selfhost_exe::exe_try_parse_json_v0(filename, timeout_ms) {
|
||||
if let Some(module) = super::modes::common_util::selfhost_exe::exe_try_parse_json_v0(
|
||||
filename, timeout_ms,
|
||||
) {
|
||||
if crate::config::env::cli_verbose() {
|
||||
super::json_v0_bridge::maybe_dump_mir(&module);
|
||||
}
|
||||
let emit_only = std::env::var("NYASH_NY_COMPILER_EMIT_ONLY")
|
||||
.unwrap_or_else(|_| "1".to_string())
|
||||
== "1";
|
||||
if emit_only { return false; }
|
||||
if emit_only {
|
||||
return false;
|
||||
}
|
||||
// Prefer PyVM when requested (reference semantics)
|
||||
if std::env::var("NYASH_VM_USE_PY").ok().as_deref() == Some("1") {
|
||||
if let Ok(py3) = which::which("python3") {
|
||||
@ -356,20 +380,40 @@ impl NyashRunner {
|
||||
let tmp_dir = std::path::Path::new("tmp");
|
||||
let _ = std::fs::create_dir_all(tmp_dir);
|
||||
let mir_json_path = tmp_dir.join("nyash_pyvm_mir.json");
|
||||
if let Err(e) = crate::runner::mir_json_emit::emit_mir_json_for_harness_bin(&module, &mir_json_path) {
|
||||
if let Err(e) =
|
||||
crate::runner::mir_json_emit::emit_mir_json_for_harness_bin(
|
||||
&module,
|
||||
&mir_json_path,
|
||||
)
|
||||
{
|
||||
eprintln!("❌ PyVM MIR JSON emit error: {}", e);
|
||||
process::exit(1);
|
||||
}
|
||||
crate::cli_v!("[Bridge] using PyVM (selfhost) → {}", mir_json_path.display());
|
||||
crate::cli_v!(
|
||||
"[Bridge] using PyVM (selfhost) → {}",
|
||||
mir_json_path.display()
|
||||
);
|
||||
let allow_top = crate::config::env::entry_allow_toplevel_main();
|
||||
let entry = if module.functions.contains_key("Main.main") { "Main.main" }
|
||||
else if allow_top && module.functions.contains_key("main") { "main" }
|
||||
else if module.functions.contains_key("main") { eprintln!("[entry] Warning: using top-level 'main' without explicit allow; set NYASH_ENTRY_ALLOW_TOPLEVEL_MAIN=1 to silence."); "main" }
|
||||
else { "Main.main" };
|
||||
let entry = if module.functions.contains_key("Main.main") {
|
||||
"Main.main"
|
||||
} else if allow_top && module.functions.contains_key("main") {
|
||||
"main"
|
||||
} else if module.functions.contains_key("main") {
|
||||
eprintln!("[entry] Warning: using top-level 'main' without explicit allow; set NYASH_ENTRY_ALLOW_TOPLEVEL_MAIN=1 to silence.");
|
||||
"main"
|
||||
} else {
|
||||
"Main.main"
|
||||
};
|
||||
let mut cmd = std::process::Command::new(py3);
|
||||
crate::runner::child_env::apply_core_wrapper_env(&mut cmd);
|
||||
let status = cmd
|
||||
.args(["tools/pyvm_runner.py", "--in", &mir_json_path.display().to_string(), "--entry", entry])
|
||||
.args([
|
||||
"tools/pyvm_runner.py",
|
||||
"--in",
|
||||
&mir_json_path.display().to_string(),
|
||||
"--entry",
|
||||
entry,
|
||||
])
|
||||
.status()
|
||||
.map_err(|e| format!("spawn pyvm: {}", e))
|
||||
.unwrap();
|
||||
@ -382,11 +426,13 @@ impl NyashRunner {
|
||||
crate::runner::child_env::pre_run_reset_oob_if_strict();
|
||||
crate::runner::child_env::pre_run_reset_oob_if_strict();
|
||||
self.execute_mir_module(&module);
|
||||
if crate::config::env::oob_strict_fail() && crate::runtime::observe::oob_seen() {
|
||||
if crate::config::env::oob_strict_fail() && crate::runtime::observe::oob_seen()
|
||||
{
|
||||
eprintln!("[selfhost][oob-strict] Out-of-bounds observed → exit(1)");
|
||||
std::process::exit(1);
|
||||
}
|
||||
if crate::config::env::oob_strict_fail() && crate::runtime::observe::oob_seen() {
|
||||
if crate::config::env::oob_strict_fail() && crate::runtime::observe::oob_seen()
|
||||
{
|
||||
eprintln!("[selfhost][oob-strict] Out-of-bounds observed → exit(1)");
|
||||
std::process::exit(1);
|
||||
}
|
||||
@ -419,28 +465,37 @@ impl NyashRunner {
|
||||
if emit_only {
|
||||
return false;
|
||||
}
|
||||
// Phase-15 policy: when NYASH_VM_USE_PY=1, prefer PyVM as reference executor
|
||||
// regardless of BoxCall presence to ensure semantics parity (e.g., PHI merges).
|
||||
let prefer_pyvm = std::env::var("NYASH_VM_USE_PY").ok().as_deref() == Some("1");
|
||||
// Backward compatibility: if not preferring PyVM explicitly, still auto-enable when BoxCalls exist.
|
||||
let needs_pyvm = !prefer_pyvm
|
||||
&& module.functions.values().any(|f| {
|
||||
f.blocks.values().any(|bb| {
|
||||
bb.instructions.iter().any(|inst| {
|
||||
matches!(inst, crate::mir::MirInstruction::BoxCall { .. })
|
||||
// Phase-15 policy: when NYASH_VM_USE_PY=1, prefer PyVM as reference executor
|
||||
// regardless of BoxCall presence to ensure semantics parity (e.g., PHI merges).
|
||||
let prefer_pyvm = std::env::var("NYASH_VM_USE_PY").ok().as_deref() == Some("1");
|
||||
// Backward compatibility: if not preferring PyVM explicitly, still auto-enable when BoxCalls exist.
|
||||
let needs_pyvm = !prefer_pyvm
|
||||
&& module.functions.values().any(|f| {
|
||||
f.blocks.values().any(|bb| {
|
||||
bb.instructions.iter().any(|inst| {
|
||||
matches!(inst, crate::mir::MirInstruction::BoxCall { .. })
|
||||
})
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
if prefer_pyvm || needs_pyvm {
|
||||
let label = if prefer_pyvm { "selfhost" } else { "selfhost-fallback" };
|
||||
if let Some(code) = crate::runner::modes::common_util::selfhost::json::run_pyvm_module(&module, label) {
|
||||
let label = if prefer_pyvm {
|
||||
"selfhost"
|
||||
} else {
|
||||
"selfhost-fallback"
|
||||
};
|
||||
if let Some(code) =
|
||||
crate::runner::modes::common_util::selfhost::json::run_pyvm_module(
|
||||
&module, label,
|
||||
)
|
||||
{
|
||||
println!("Result: {}", code);
|
||||
std::process::exit(code);
|
||||
}
|
||||
}
|
||||
crate::runner::child_env::pre_run_reset_oob_if_strict();
|
||||
self.execute_mir_module(&module);
|
||||
if crate::config::env::oob_strict_fail() && crate::runtime::observe::oob_seen() {
|
||||
if crate::config::env::oob_strict_fail() && crate::runtime::observe::oob_seen()
|
||||
{
|
||||
eprintln!("[selfhost][oob-strict] Out-of-bounds observed → exit(1)");
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user