docs: update CURRENT_TASK.md with logging helpers and next steps (runner trace + selfhost helpers)
This commit is contained in:
@ -29,6 +29,8 @@ What Changed (today)
|
||||
- LLVM(select/terminators): `function.rs` から `instructions::term_emit_*` を利用しつつ、`normalize_branch_condition()` をブランチ直前で適用する流れを固定化(truthy 正規化の前段フック)。
|
||||
- Runner/env 集約: `src/config/env.rs` に CLI/自ホスト/VM まわりの getter を追加(`cli_verbose()/enable_using()/vm_use_py()/ny_compiler_*()` など)。`runner/selfhost.rs`/`runner/pipe_io.rs`/`runner/modes/common.rs` のホットパスを getter 参照に更新(段階導入)。
|
||||
- VM dispatch: 実装は既に dispatch 中央化済み(`backend::dispatch` 経由)。`NYASH_VM_USE_DISPATCH` フラグの getter を追加(将来の選択切替用)。
|
||||
- Runner/log: `runner/trace.rs` を追加。`cli_verbose()` と `cli_v!` マクロを導入し、`modes/common.rs` の一部情報ログを置換(verbose ガードの明確化)。
|
||||
- Selfhost helpers: PyVM ハーネス実行を `NyashRunner::run_pyvm_harness(..)` として共通化。EXE パーサ経路の JSON 抽出をまとめる `exe_try_parse_json_v0(..)` を追加(段階適用の足場)。
|
||||
|
||||
Refactor Progress (2025‑09‑16, end of day)
|
||||
- Runner: ヘッダ指令スキャンとトレース出力を分離(`runner/cli_directives.rs`, `runner/trace.rs`)。using 解決ログを集約。
|
||||
@ -55,6 +57,10 @@ Remaining Refactors (Phase‑15 mainline)
|
||||
- `normalize` の terminator 側の補完(未移行箇所があれば寄せる)。
|
||||
- Runner/env 集約
|
||||
- ホットパスの環境参照を `config::env` getter へ置換(残件: VM trace/diagnostics の一部)。
|
||||
- Runner/log 整理(第2〜第3弾)
|
||||
- 情報ログ(verbose 連動)を `cli_v!` に一本化。エラー系は従来通り eprintln のまま。
|
||||
- Selfhost EXE 経路の関数抽出(仕上げ)
|
||||
- 既存の EXE‑first ブロックを `exe_try_parse_json_v0(..)` を用いた薄い分岐に縮退(挙動不変)。
|
||||
- LLVM select/terminators(実装化)
|
||||
- `select` に truthy 規約の軽い正規化を追加(等価変換のみ)。
|
||||
- `terminators` へ実体移動(`flow` からの段階的差し替え)。
|
||||
@ -159,6 +165,7 @@ Current Status
|
||||
- Stage‑3: 構文受理のみ完了(break/continue/throw/try/catch/finally)。現時点では JSON 降格(no‑op/Expr)で安全受理。
|
||||
- Runner: Using/Resolver を前処理に統合(BoxIndex/キャッシュ/strict)。`--ny-parser-pipe` は PyVM 委譲(exit code 判定)。
|
||||
- llvmlite/AOT: Array/Map の基本操作(push/get/set/has/size, length)が NyRT ハンドルAPIで動作。`ny_main` は i64 戻り・`Main.main/1` 優先で起動。
|
||||
- ログ: verbose 出力の一部を `cli_v!` で共通化(引き続き適用範囲を拡大中)。
|
||||
|
||||
Open
|
||||
- Bridge/PHI の正規化: 短絡(入れ子)における merge/PHI incoming を固定化(rhs_end/fall_bb の順序)。
|
||||
@ -192,6 +199,11 @@ Smokes
|
||||
- 無限ループ防止: `./tools/selfhost_progress_guard_smoke.sh`
|
||||
- 自己ホスト → Interpreter(BoxCallなし集合): `./tools/selfhost_stage2_smoke.sh`
|
||||
- 自己ホスト → JSON → PyVM(Array/String/Console 含む): `./tools/selfhost_stage2_bridge_smoke.sh`
|
||||
- 動作確認(ローカル)
|
||||
- VM: `./target/debug/nyash --backend vm apps/tmp_hello.nyash`(Result: 0)
|
||||
- LLVM モック: `./target/debug/nyash --backend llvm apps/tmp_hello.nyash`
|
||||
- PyVM/Stage‑2: `tools/pyvm_stage2_smoke.sh`(All PASS)
|
||||
- Bridge/Stage‑2: `tools/ny_stage2_bridge_smoke.sh`(All PASS)
|
||||
|
||||
Notes / Policies
|
||||
- PyVM は意味論の参照実行器として運用(exit code 判定を基本)。
|
||||
|
||||
@ -11,6 +11,8 @@ use std::thread::sleep;
|
||||
use crate::runner::pipeline::{suggest_in_base, resolve_using_target};
|
||||
use crate::runner::trace::cli_verbose;
|
||||
use crate::cli_v;
|
||||
use crate::runner::trace::cli_verbose;
|
||||
use crate::cli_v;
|
||||
|
||||
// (moved) suggest_in_base is now in runner/pipeline.rs
|
||||
|
||||
@ -127,6 +129,101 @@ impl NyashRunner {
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper: run PyVM harness over a MIR module, returning the exit code
|
||||
fn run_pyvm_harness(&self, module: &nyash_rust::mir::MirModule, tag: &str) -> Result<i32, String> {
|
||||
let py3 = which::which("python3").map_err(|e| format!("python3 not found: {}", e))?;
|
||||
let runner = std::path::Path::new("tools/pyvm_runner.py");
|
||||
if !runner.exists() { return Err(format!("PyVM runner not found: {}", runner.display())); }
|
||||
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");
|
||||
crate::runner::mir_json_emit::emit_mir_json_for_harness_bin(module, &mir_json_path)
|
||||
.map_err(|e| format!("PyVM MIR JSON emit error: {}", e))?;
|
||||
cli_v!("[ny-compiler] using PyVM ({} ) → {}", tag, mir_json_path.display());
|
||||
// Determine entry function hint (prefer Main.main if present)
|
||||
let entry = if module.functions.contains_key("Main.main") { "Main.main" }
|
||||
else if module.functions.contains_key("main") { "main" } else { "Main.main" };
|
||||
let status = std::process::Command::new(py3)
|
||||
.args([
|
||||
runner.to_string_lossy().as_ref(),
|
||||
"--in",
|
||||
&mir_json_path.display().to_string(),
|
||||
"--entry",
|
||||
entry,
|
||||
])
|
||||
.status()
|
||||
.map_err(|e| format!("spawn pyvm: {}", e))?;
|
||||
let code = status.code().unwrap_or(1);
|
||||
if !status.success() { cli_v!("❌ PyVM ({}) failed (status={})", tag, code); }
|
||||
Ok(code)
|
||||
}
|
||||
|
||||
/// Helper: try external selfhost compiler EXE to parse Ny -> JSON v0 and return MIR module
|
||||
/// Returns Some(module) on success, None on failure (timeout/invalid output/missing exe)
|
||||
fn exe_try_parse_json_v0(&self, filename: &str, timeout_ms: u64) -> Option<nyash_rust::mir::MirModule> {
|
||||
// Resolve parser EXE path
|
||||
let exe_path = if let Ok(p) = std::env::var("NYASH_NY_COMPILER_EXE_PATH") {
|
||||
std::path::PathBuf::from(p)
|
||||
} else {
|
||||
let mut p = std::path::PathBuf::from("dist/nyash_compiler");
|
||||
#[cfg(windows)]
|
||||
{ p.push("nyash_compiler.exe"); }
|
||||
#[cfg(not(windows))]
|
||||
{ p.push("nyash_compiler"); }
|
||||
if !p.exists() {
|
||||
if let Ok(w) = which::which("nyash_compiler") { w } else { p }
|
||||
} else { p }
|
||||
};
|
||||
if !exe_path.exists() { cli_v!("[ny-compiler] exe not found at {}", exe_path.display()); return None; }
|
||||
|
||||
// Build command
|
||||
let mut cmd = std::process::Command::new(&exe_path);
|
||||
cmd.arg(filename);
|
||||
if crate::config::env::ny_compiler_min_json() { cmd.arg("--min-json"); }
|
||||
if crate::config::env::selfhost_read_tmp() { cmd.arg("--read-tmp"); }
|
||||
if let Some(raw) = crate::config::env::ny_compiler_child_args() { for tok in raw.split_whitespace() { cmd.arg(tok); } }
|
||||
let mut cmd = cmd.stdout(Stdio::piped()).stderr(Stdio::piped());
|
||||
let mut child = match cmd.spawn() { Ok(c) => c, Err(e) => { eprintln!("[ny-compiler] exe spawn failed: {}", e); return None; } };
|
||||
let mut ch_stdout = child.stdout.take();
|
||||
let mut ch_stderr = child.stderr.take();
|
||||
let start = Instant::now();
|
||||
let mut timed_out = false;
|
||||
loop {
|
||||
match child.try_wait() {
|
||||
Ok(Some(_)) => break,
|
||||
Ok(None) => {
|
||||
if start.elapsed() >= Duration::from_millis(timeout_ms) { let _ = child.kill(); let _ = child.wait(); timed_out = true; break; }
|
||||
sleep(Duration::from_millis(10));
|
||||
}
|
||||
Err(e) => { eprintln!("[ny-compiler] exe wait error: {}", e); return None; }
|
||||
}
|
||||
}
|
||||
let mut out_buf = Vec::new();
|
||||
let mut err_buf = Vec::new();
|
||||
if let Some(mut s) = ch_stdout { let _ = s.read_to_end(&mut out_buf); }
|
||||
if let Some(mut s) = ch_stderr { let _ = s.read_to_end(&mut err_buf); }
|
||||
if timed_out {
|
||||
let head = String::from_utf8_lossy(&out_buf).chars().take(200).collect::<String>();
|
||||
eprintln!("[ny-compiler] exe timeout after {} ms; stdout(head)='{}'", timeout_ms, head.replace('\n', "\\n"));
|
||||
return None;
|
||||
}
|
||||
let stdout = match String::from_utf8(out_buf) { Ok(s) => s, Err(_) => String::new() };
|
||||
let mut json_line = String::new();
|
||||
for line in stdout.lines() { let t = line.trim(); if t.starts_with('{') && t.contains("\"version\"") && t.contains("\"kind\"") { json_line = t.to_string(); break; } }
|
||||
if json_line.is_empty() {
|
||||
if cli_verbose() {
|
||||
let head: String = stdout.chars().take(200).collect();
|
||||
let errh: String = String::from_utf8_lossy(&err_buf).chars().take(200).collect();
|
||||
cli_v!("[ny-compiler] exe produced no JSON; stdout(head)='{}' stderr(head)='{}'", head.replace('\n', "\\n"), errh.replace('\n', "\\n"));
|
||||
}
|
||||
return None;
|
||||
}
|
||||
match json_v0_bridge::parse_json_v0_to_module(&json_line) {
|
||||
Ok(module) => Some(module),
|
||||
Err(e) => { eprintln!("[ny-compiler] JSON parse failed (exe): {}", e); None }
|
||||
}
|
||||
}
|
||||
|
||||
/// Phase-15.3: Attempt Ny compiler pipeline (Ny -> JSON v0 via Ny program), then execute MIR
|
||||
pub(crate) fn try_run_ny_compiler_pipeline(&self, filename: &str) -> bool {
|
||||
// Delegate to centralized selfhost pipeline to avoid drift
|
||||
@ -285,26 +382,7 @@ impl NyashRunner {
|
||||
eprintln!("❌ PyVM MIR JSON emit error: {}", e);
|
||||
return true; // prevent double-run fallback
|
||||
}
|
||||
if crate::config::env::cli_verbose() {
|
||||
eprintln!("[ny-compiler] using PyVM (exe) → {}", mir_json_path.display());
|
||||
}
|
||||
// Determine entry function hint (prefer Main.main if present)
|
||||
let entry = if module.functions.contains_key("Main.main") { "Main.main" }
|
||||
else if module.functions.contains_key("main") { "main" } else { "Main.main" };
|
||||
let status = std::process::Command::new(py3)
|
||||
.args([
|
||||
runner.to_string_lossy().as_ref(),
|
||||
"--in",
|
||||
&mir_json_path.display().to_string(),
|
||||
"--entry",
|
||||
entry,
|
||||
])
|
||||
.status()
|
||||
.map_err(|e| format!("spawn pyvm: {}", e))
|
||||
.unwrap();
|
||||
let code = status.code().unwrap_or(1);
|
||||
if !status.success() { if crate::config::env::cli_verbose() { eprintln!("❌ PyVM (exe) failed (status={})", code); } }
|
||||
// Harmonize CLI output with interpreter path for smokes
|
||||
let code = self.run_pyvm_harness(&module, "exe").unwrap_or(1);
|
||||
println!("Result: {}", code);
|
||||
std::process::exit(code);
|
||||
} else {
|
||||
@ -488,20 +566,7 @@ impl NyashRunner {
|
||||
// Determine entry function hint (prefer Main.main if present)
|
||||
let entry = if module.functions.contains_key("Main.main") { "Main.main" }
|
||||
else if module.functions.contains_key("main") { "main" } else { "Main.main" };
|
||||
let status = std::process::Command::new(py3)
|
||||
.args([
|
||||
runner.to_string_lossy().as_ref(),
|
||||
"--in",
|
||||
&mir_json_path.display().to_string(),
|
||||
"--entry",
|
||||
entry,
|
||||
])
|
||||
.status()
|
||||
.map_err(|e| format!("spawn pyvm: {}", e))
|
||||
.unwrap();
|
||||
let code = status.code().unwrap_or(1);
|
||||
if !status.success() { if crate::config::env::cli_verbose() { eprintln!("❌ PyVM (mvp) failed (status={})", code); } }
|
||||
// Harmonize CLI output with interpreter path for smokes
|
||||
let code = self.run_pyvm_harness(&module, "mvp").unwrap_or(1);
|
||||
println!("Result: {}", code);
|
||||
std::process::exit(code);
|
||||
} else {
|
||||
|
||||
@ -10,3 +10,5 @@ macro_rules! cli_v {
|
||||
}};
|
||||
}
|
||||
|
||||
/// Unstructured trace output function used by pipeline helpers
|
||||
pub fn log<S: AsRef<str>>(msg: S) { eprintln!("{}", msg.as_ref()); }
|
||||
|
||||
Reference in New Issue
Block a user