Span trace utilities and runner source hint

This commit is contained in:
nyash-codex
2025-11-24 14:17:02 +09:00
parent 3154903121
commit 466e636af6
106 changed files with 4597 additions and 958 deletions

View File

@ -12,11 +12,7 @@ use crate::mir::MirCompiler;
use crate::parser::NyashParser;
fn require_experiment_toggle() -> bool {
if std::env::var("NYASH_JOINIR_EXPERIMENT")
.ok()
.as_deref()
!= Some("1")
{
if std::env::var("NYASH_JOINIR_EXPERIMENT").ok().as_deref() != Some("1") {
eprintln!(
"[joinir/runner] NYASH_JOINIR_EXPERIMENT=1 not set, skipping experimental runner test"
);
@ -50,8 +46,7 @@ static box Runner {
"#;
let full_src = format!("{src}\n{runner}");
let ast: ASTNode =
NyashParser::parse_from_string(&full_src).expect("skip_ws: parse failed");
let ast: ASTNode = NyashParser::parse_from_string(&full_src).expect("skip_ws: parse failed");
let mut mc = MirCompiler::with_options(false);
let compiled = mc.compile(ast).expect("skip_ws: MIR compile failed");
@ -113,8 +108,7 @@ static box Runner {
"#;
let full_src = format!("{func_scanner_src}\n{test_src}\n{runner}");
let ast: ASTNode =
NyashParser::parse_from_string(&full_src).expect("trim_min: parse failed");
let ast: ASTNode = NyashParser::parse_from_string(&full_src).expect("trim_min: parse failed");
let mut mc = MirCompiler::with_options(false);
let compiled = mc.compile(ast).expect("trim_min: MIR compile failed");

View File

@ -14,11 +14,7 @@ use crate::mir::join_ir::*;
use crate::mir::join_ir_runner::{run_joinir_function, JoinValue};
fn require_experiment_toggle() -> bool {
if std::env::var("NYASH_JOINIR_EXPERIMENT")
.ok()
.as_deref()
!= Some("1")
{
if std::env::var("NYASH_JOINIR_EXPERIMENT").ok().as_deref() != Some("1") {
eprintln!(
"[joinir/runner/standalone] NYASH_JOINIR_EXPERIMENT=1 not set, skipping standalone test"
);
@ -161,7 +157,10 @@ fn joinir_runner_standalone_trim() {
)
.expect("trim runner failed");
match result {
JoinValue::Str(s) => assert_eq!(s, "abc ", "simplified trim should remove only leading spaces"),
JoinValue::Str(s) => assert_eq!(
s, "abc ",
"simplified trim should remove only leading spaces"
),
other => panic!("trim returned non-string: {:?}", other),
}
@ -209,12 +208,14 @@ fn build_skip_ws_joinir() -> JoinModule {
let mut entry_func = JoinFunction::new(entry_id, "skip_ws_entry".to_string(), vec![s_param]);
// n = s.length()
entry_func.body.push(JoinInst::Compute(MirLikeInst::BoxCall {
dst: Some(n_var),
box_name: "StringBox".to_string(),
method: "length".to_string(),
args: vec![s_param],
}));
entry_func
.body
.push(JoinInst::Compute(MirLikeInst::BoxCall {
dst: Some(n_var),
box_name: "StringBox".to_string(),
method: "length".to_string(),
args: vec![s_param],
}));
// i_init = 0
entry_func.body.push(JoinInst::Compute(MirLikeInst::Const {
@ -360,12 +361,14 @@ fn build_trim_joinir() -> JoinModule {
let mut entry_func = JoinFunction::new(entry_id, "trim_entry".to_string(), vec![s_param]);
// n = s.length()
entry_func.body.push(JoinInst::Compute(MirLikeInst::BoxCall {
dst: Some(n_var),
box_name: "StringBox".to_string(),
method: "length".to_string(),
args: vec![s_param],
}));
entry_func
.body
.push(JoinInst::Compute(MirLikeInst::BoxCall {
dst: Some(n_var),
box_name: "StringBox".to_string(),
method: "length".to_string(),
args: vec![s_param],
}));
// const_0 = 0
entry_func.body.push(JoinInst::Compute(MirLikeInst::Const {
@ -383,12 +386,14 @@ fn build_trim_joinir() -> JoinModule {
});
// result = s.substring(start, n)
entry_func.body.push(JoinInst::Compute(MirLikeInst::BoxCall {
dst: Some(result_var),
box_name: "StringBox".to_string(),
method: "substring".to_string(),
args: vec![s_param, start_var, n_var],
}));
entry_func
.body
.push(JoinInst::Compute(MirLikeInst::BoxCall {
dst: Some(result_var),
box_name: "StringBox".to_string(),
method: "substring".to_string(),
args: vec![s_param, start_var, n_var],
}));
// return result
entry_func.body.push(JoinInst::Ret {

View File

@ -21,14 +21,8 @@ use crate::mir::MirCompiler;
use crate::parser::NyashParser;
fn require_experiment_toggle() -> bool {
if std::env::var("NYASH_JOINIR_VM_BRIDGE")
.ok()
.as_deref()
!= Some("1")
{
eprintln!(
"[joinir/vm_bridge] NYASH_JOINIR_VM_BRIDGE=1 not set, skipping VM bridge test"
);
if std::env::var("NYASH_JOINIR_VM_BRIDGE").ok().as_deref() != Some("1") {
eprintln!("[joinir/vm_bridge] NYASH_JOINIR_VM_BRIDGE=1 not set, skipping VM bridge test");
return false;
}
true
@ -57,8 +51,7 @@ static box Runner {
"#;
let full_src = format!("{src}\n{runner}");
let ast: ASTNode =
NyashParser::parse_from_string(&full_src).expect("skip_ws: parse failed");
let ast: ASTNode = NyashParser::parse_from_string(&full_src).expect("skip_ws: parse failed");
let mut mc = MirCompiler::with_options(false);
let compiled = mc.compile(ast).expect("skip_ws: MIR compile failed");
@ -86,10 +79,16 @@ static box Runner {
)
.expect("JoinIR VM bridge failed for skip_ws");
eprintln!("[joinir_vm_bridge_test] Route C result: {:?}", bridge_result);
eprintln!(
"[joinir_vm_bridge_test] Route C result: {:?}",
bridge_result
);
// Assertions: Both routes should produce the same result
assert_eq!(vm_result, "3", "Route A (VM) expected to skip 3 leading spaces");
assert_eq!(
vm_result, "3",
"Route A (VM) expected to skip 3 leading spaces"
);
match bridge_result {
JoinValue::Int(v) => {
assert_eq!(v, 3, "Route C (JoinIR→VM bridge) skip_ws result mismatch");

View File

@ -106,4 +106,3 @@ static box Main {
std::env::remove_var("NYASH_DISABLE_PLUGINS");
std::env::remove_var("HAKO_MIR_BUILDER_METHODIZE");
}

View File

@ -30,10 +30,8 @@ fn mir_funcscanner_parse_params_trim_min_verify_and_vm() {
// std::env::set_var("NYASH_IF_HOLE_TRACE", "1");
// Bundle FuncScanner 本体と最小テスト。
let func_scanner_src =
include_str!("../../lang/src/compiler/entry/func_scanner.hako");
let test_src =
std::fs::read_to_string(test_file).expect("Failed to read minimal test .hako");
let func_scanner_src = include_str!("../../lang/src/compiler/entry/func_scanner.hako");
let test_src = std::fs::read_to_string(test_file).expect("Failed to read minimal test .hako");
let src = format!("{func_scanner_src}\n\n{test_src}");
let ast: ASTNode =
@ -86,4 +84,3 @@ fn mir_funcscanner_parse_params_trim_min_verify_and_vm() {
std::env::remove_var("NYASH_VM_VERIFY_MIR");
std::env::remove_var("NYASH_IF_HOLE_TRACE");
}

View File

@ -29,14 +29,11 @@ fn mir_funcscanner_trim_min_verify_and_vm() {
// std::env::set_var("NYASH_IF_HOLE_TRACE", "1");
// FuncScanner 本体と最小 _trim テストを 1 ソースにまとめる。
let func_scanner_src =
include_str!("../../lang/src/compiler/entry/func_scanner.hako");
let test_src =
std::fs::read_to_string(test_file).expect("Failed to read trim_min .hako");
let func_scanner_src = include_str!("../../lang/src/compiler/entry/func_scanner.hako");
let test_src = std::fs::read_to_string(test_file).expect("Failed to read trim_min .hako");
let src = format!("{func_scanner_src}\n\n{test_src}");
let ast: ASTNode =
NyashParser::parse_from_string(&src).expect("trim_min: parse failed");
let ast: ASTNode = NyashParser::parse_from_string(&src).expect("trim_min: parse failed");
let mut mc = MirCompiler::with_options(false);
let compiled = mc.compile(ast).expect("trim_min: MIR compile failed");

View File

@ -25,6 +25,7 @@ use crate::mir::join_ir::lowering::funcscanner_append_defs::lower_funcscanner_ap
use crate::mir::join_ir::*;
use crate::mir::{MirCompiler, ValueId};
use crate::parser::NyashParser;
use std::collections::BTreeMap;
#[test]
#[ignore] // 手動実行用Phase 27.14 実験段階)
@ -47,11 +48,13 @@ fn mir_joinir_funcscanner_append_defs_auto_lowering() {
let src = std::fs::read_to_string(test_file)
.unwrap_or_else(|_| panic!("Failed to read {}", test_file));
let ast: ASTNode = NyashParser::parse_from_string(&src)
.expect("funcscanner_append_defs: parse failed");
let ast: ASTNode =
NyashParser::parse_from_string(&src).expect("funcscanner_append_defs: parse failed");
let mut mc = MirCompiler::with_options(false);
let compiled = mc.compile(ast).expect("funcscanner_append_defs: MIR compile failed");
let compiled = mc
.compile(ast)
.expect("funcscanner_append_defs: MIR compile failed");
eprintln!(
"[joinir/funcscanner_append_defs] MIR module compiled, {} functions",
@ -66,32 +69,69 @@ fn mir_joinir_funcscanner_append_defs_auto_lowering() {
eprintln!("{:#?}", join_module);
// Step 3: 妥当性検証Phase 27.14
assert_eq!(join_module.functions.len(), 2, "Expected 2 functions (append_defs_entry + loop_step)");
assert_eq!(
join_module.functions.len(),
2,
"Expected 2 functions (append_defs_entry + loop_step)"
);
let entry_id = JoinFuncId::new(0);
let loop_step_id = JoinFuncId::new(1);
// append_defs_entry 関数の検証
let entry_func = join_module.functions.get(&entry_id)
let entry_func = join_module
.functions
.get(&entry_id)
.expect("append_defs_entry function not found");
assert_eq!(entry_func.name, "append_defs_entry");
assert_eq!(entry_func.params.len(), 3, "append_defs_entry has 3 parameters (dst, defs_box, n)");
assert_eq!(
entry_func.params.len(),
3,
"append_defs_entry has 3 parameters (dst, defs_box, n)"
);
// loop_step 関数の検証
let loop_step_func = join_module.functions.get(&loop_step_id)
let loop_step_func = join_module
.functions
.get(&loop_step_id)
.expect("loop_step function not found");
assert_eq!(loop_step_func.name, "loop_step");
assert_eq!(loop_step_func.params.len(), 4, "loop_step has 4 parameters (dst, defs_box, n, i)");
assert_eq!(
loop_step_func.params.len(),
4,
"loop_step has 4 parameters (dst, defs_box, n, i)"
);
// ValueId range 検証 (9000-10999)
assert_eq!(entry_func.params[0].0, 9000, "dst parameter should be ValueId(9000)");
assert_eq!(entry_func.params[1].0, 9001, "defs_box parameter should be ValueId(9001)");
assert_eq!(entry_func.params[2].0, 9002, "n parameter should be ValueId(9002)");
assert_eq!(
entry_func.params[0].0, 9000,
"dst parameter should be ValueId(9000)"
);
assert_eq!(
entry_func.params[1].0, 9001,
"defs_box parameter should be ValueId(9001)"
);
assert_eq!(
entry_func.params[2].0, 9002,
"n parameter should be ValueId(9002)"
);
assert_eq!(loop_step_func.params[0].0, 10000, "dst_loop parameter should be ValueId(10000)");
assert_eq!(loop_step_func.params[1].0, 10001, "defs_box_loop parameter should be ValueId(10001)");
assert_eq!(loop_step_func.params[2].0, 10002, "n_loop parameter should be ValueId(10002)");
assert_eq!(loop_step_func.params[3].0, 10003, "i_loop parameter should be ValueId(10003)");
assert_eq!(
loop_step_func.params[0].0, 10000,
"dst_loop parameter should be ValueId(10000)"
);
assert_eq!(
loop_step_func.params[1].0, 10001,
"defs_box_loop parameter should be ValueId(10001)"
);
assert_eq!(
loop_step_func.params[2].0, 10002,
"n_loop parameter should be ValueId(10002)"
);
assert_eq!(
loop_step_func.params[3].0, 10003,
"i_loop parameter should be ValueId(10003)"
);
eprintln!("[joinir/funcscanner_append_defs] ✅ 自動変換成功Phase 27.14");
}
@ -127,5 +167,78 @@ fn mir_joinir_funcscanner_append_defs_empty_module_returns_none() {
let result = lower_funcscanner_append_defs_to_joinir(&test_module);
eprintln!("[joinir/funcscanner_append_defs] empty_module test: result is None (expected)");
assert!(result.is_none(), "Empty MirModule should return None (target function not found)");
assert!(
result.is_none(),
"Empty MirModule should return None (target function not found)"
);
}
#[test]
#[ignore] // 手動実行: generic_case_a トグル検証append_defs minimal
fn mir_joinir_funcscanner_append_defs_generic_matches_handwritten() {
if std::env::var("NYASH_JOINIR_EXPERIMENT").ok().as_deref() != Some("1") {
eprintln!("[joinir/funcscanner_append_defs] NYASH_JOINIR_EXPERIMENT=1 not set, skipping generic test");
return;
}
std::env::set_var("NYASH_PARSER_STAGE3", "1");
std::env::set_var("HAKO_PARSER_STAGE3", "1");
let test_file = "apps/tests/funcscanner_append_defs_minimal.hako";
let src = std::fs::read_to_string(test_file)
.unwrap_or_else(|_| panic!("Failed to read {}", test_file));
let ast: ASTNode =
NyashParser::parse_from_string(&src).expect("append_defs generic: parse failed");
let mut mc = MirCompiler::with_options(false);
let compiled = mc
.compile(ast)
.expect("append_defs generic: MIR compile failed");
fn params_by_name(jm: &JoinModule) -> BTreeMap<String, usize> {
jm.functions
.values()
.map(|f| (f.name.clone(), f.params.len()))
.collect()
}
// Baseline (generic OFF)
std::env::set_var("NYASH_JOINIR_LOWER_GENERIC", "0");
let baseline = lower_funcscanner_append_defs_to_joinir(&compiled.module)
.expect("baseline append_defs lowering failed");
// Generic ON
std::env::set_var("NYASH_JOINIR_LOWER_GENERIC", "1");
let generic = lower_funcscanner_append_defs_to_joinir(&compiled.module)
.expect("generic append_defs lowering failed");
let baseline_params = params_by_name(&baseline);
let generic_params = params_by_name(&generic);
assert_eq!(baseline_params.len(), 2, "baseline should have 2 functions");
assert_eq!(generic_params.len(), 2, "generic should have 2 functions");
assert_eq!(
baseline_params.len(),
generic_params.len(),
"function count mismatch"
);
let expected_funcs = ["append_defs_entry", "loop_step"];
for name in expected_funcs {
let b_params = baseline_params
.get(name)
.copied()
.unwrap_or_else(|| panic!("baseline missing function {}", name));
let g_params = generic_params
.get(name)
.copied()
.unwrap_or_else(|| panic!("generic missing function {}", name));
assert_eq!(
b_params, g_params,
"param count differs for function {}",
name
);
}
eprintln!("[joinir/funcscanner_append_defs] ✅ generic_case_a JoinIR matches baseline");
}

View File

@ -25,6 +25,7 @@ use crate::ast::ASTNode;
use crate::mir::join_ir::*;
use crate::mir::{MirCompiler, ValueId};
use crate::parser::NyashParser;
use std::collections::BTreeMap;
#[test]
#[ignore] // 手動実行用Phase 27.1 実験段階)
@ -51,8 +52,7 @@ fn mir_joinir_funcscanner_trim_auto_lowering() {
.unwrap_or_else(|_| panic!("Failed to read {}", test_file));
let src = format!("{func_scanner_src}\n\n{test_src}");
let ast: ASTNode = NyashParser::parse_from_string(&src)
.expect("trim: parse failed");
let ast: ASTNode = NyashParser::parse_from_string(&src).expect("trim: parse failed");
let mut mc = MirCompiler::with_options(false);
let compiled = mc.compile(ast).expect("trim: MIR compile failed");
@ -70,24 +70,46 @@ fn mir_joinir_funcscanner_trim_auto_lowering() {
eprintln!("{:#?}", join_module);
// Step 3: 妥当性検証
assert_eq!(join_module.functions.len(), 3, "Expected 3 functions (trim_main + loop_step + skip_leading)");
assert_eq!(
join_module.functions.len(),
3,
"Expected 3 functions (trim_main + loop_step + skip_leading)"
);
let trim_main_id = JoinFuncId::new(0);
let loop_step_id = JoinFuncId::new(1);
// trim_main 関数の検証
let trim_main_func = join_module.functions.get(&trim_main_id)
let trim_main_func = join_module
.functions
.get(&trim_main_id)
.expect("trim_main function not found");
assert_eq!(trim_main_func.name, "trim_main");
assert_eq!(trim_main_func.params.len(), 1, "trim_main has 1 parameter (s)");
assert!(trim_main_func.body.len() >= 5, "trim_main should have at least 5 instructions");
assert_eq!(
trim_main_func.params.len(),
1,
"trim_main has 1 parameter (s)"
);
assert!(
trim_main_func.body.len() >= 5,
"trim_main should have at least 5 instructions"
);
// loop_step 関数の検証
let loop_step_func = join_module.functions.get(&loop_step_id)
let loop_step_func = join_module
.functions
.get(&loop_step_id)
.expect("loop_step function not found");
assert_eq!(loop_step_func.name, "loop_step");
assert_eq!(loop_step_func.params.len(), 3, "loop_step has 3 parameters (str, b, e)");
assert!(loop_step_func.body.len() >= 10, "loop_step should have multiple instructions");
assert_eq!(
loop_step_func.params.len(),
3,
"loop_step has 3 parameters (str, b, e)"
);
assert!(
loop_step_func.body.len() >= 10,
"loop_step should have multiple instructions"
);
eprintln!("[joinir/trim] ✅ 自動変換成功Phase 27.1");
}
@ -98,14 +120,82 @@ fn mir_joinir_funcscanner_trim_type_sanity() {
// trim 用の JoinFunction が作成できることを確認
let trim_main_id = JoinFuncId::new(10);
let trim_main_func = JoinFunction::new(
trim_main_id,
"trim_main_test".to_string(),
vec![ValueId(1)],
);
let trim_main_func =
JoinFunction::new(trim_main_id, "trim_main_test".to_string(), vec![ValueId(1)]);
assert_eq!(trim_main_func.id, trim_main_id);
assert_eq!(trim_main_func.name, "trim_main_test");
assert_eq!(trim_main_func.params.len(), 1);
assert_eq!(trim_main_func.body.len(), 0);
}
#[test]
#[ignore] // 手動実行: generic_case_a トグル検証trim minimal
fn mir_joinir_funcscanner_trim_generic_matches_handwritten() {
if std::env::var("NYASH_JOINIR_EXPERIMENT").ok().as_deref() != Some("1") {
eprintln!("[joinir/trim] NYASH_JOINIR_EXPERIMENT=1 not set, skipping generic test");
return;
}
std::env::set_var("NYASH_PARSER_STAGE3", "1");
std::env::set_var("HAKO_PARSER_STAGE3", "1");
std::env::set_var("NYASH_ENABLE_USING", "1");
std::env::set_var("HAKO_ENABLE_USING", "1");
let func_scanner_src = include_str!("../../lang/src/compiler/entry/func_scanner.hako");
let test_file = "lang/src/compiler/tests/funcscanner_trim_min.hako";
let test_src = std::fs::read_to_string(test_file)
.unwrap_or_else(|_| panic!("Failed to read {}", test_file));
let src = format!("{func_scanner_src}\n\n{test_src}");
let ast: ASTNode = NyashParser::parse_from_string(&src).expect("trim generic: parse failed");
let mut mc = MirCompiler::with_options(false);
let compiled = mc.compile(ast).expect("trim generic: MIR compile failed");
fn params_by_name(jm: &JoinModule) -> BTreeMap<String, usize> {
jm.functions
.values()
.map(|f| (f.name.clone(), f.params.len()))
.collect()
}
// Baseline (generic OFF)
std::env::set_var("NYASH_JOINIR_LOWER_GENERIC", "0");
let baseline =
lower_funcscanner_trim_to_joinir(&compiled.module).expect("baseline trim lowering failed");
// Generic ON
std::env::set_var("NYASH_JOINIR_LOWER_GENERIC", "1");
let generic =
lower_funcscanner_trim_to_joinir(&compiled.module).expect("generic trim lowering failed");
let baseline_params = params_by_name(&baseline);
let generic_params = params_by_name(&generic);
assert_eq!(baseline_params.len(), 3, "baseline should have 3 functions");
assert_eq!(generic_params.len(), 3, "generic should have 3 functions");
assert_eq!(
baseline_params.len(),
generic_params.len(),
"function count mismatch"
);
let expected_funcs = ["trim_main", "loop_step", "skip_leading"];
for name in expected_funcs {
let b_params = baseline_params
.get(name)
.copied()
.unwrap_or_else(|| panic!("baseline missing function {}", name));
let g_params = generic_params
.get(name)
.copied()
.unwrap_or_else(|| panic!("generic missing function {}", name));
assert_eq!(
b_params, g_params,
"param count differs for function {}",
name
);
}
eprintln!("[joinir/trim] ✅ generic_case_a JoinIR matches baseline");
}

View File

@ -23,7 +23,9 @@ fn mir_joinir_min_manual_construction() {
// 環境変数トグルチェック
if std::env::var("NYASH_JOINIR_EXPERIMENT").ok().as_deref() != Some("1") {
eprintln!("[joinir/min] NYASH_JOINIR_EXPERIMENT=1 not set, skipping manual construction test");
eprintln!(
"[joinir/min] NYASH_JOINIR_EXPERIMENT=1 not set, skipping manual construction test"
);
return;
}
@ -36,8 +38,7 @@ fn mir_joinir_min_manual_construction() {
let src = std::fs::read_to_string(test_file)
.unwrap_or_else(|_| panic!("Failed to read {}", test_file));
let ast: ASTNode = NyashParser::parse_from_string(&src)
.expect("joinir_min: parse failed");
let ast: ASTNode = NyashParser::parse_from_string(&src).expect("joinir_min: parse failed");
let mut mc = MirCompiler::with_options(false);
let compiled = mc.compile(ast).expect("joinir_min: MIR compile failed");
@ -85,18 +86,22 @@ fn mir_joinir_min_manual_construction() {
let i_plus_1 = ValueId(202);
// cmp_result = (i >= 2)
loop_step_func.body.push(JoinInst::Compute(MirLikeInst::Compare {
dst: cmp_result,
op: CompareOp::Ge,
lhs: i_param,
rhs: ValueId(203), // const 2
}));
loop_step_func
.body
.push(JoinInst::Compute(MirLikeInst::Compare {
dst: cmp_result,
op: CompareOp::Ge,
lhs: i_param,
rhs: ValueId(203), // const 2
}));
// const 2
loop_step_func.body.push(JoinInst::Compute(MirLikeInst::Const {
dst: ValueId(203),
value: ConstValue::Integer(2),
}));
loop_step_func
.body
.push(JoinInst::Compute(MirLikeInst::Const {
dst: ValueId(203),
value: ConstValue::Integer(2),
}));
// if cmp_result { k_exit(i) } else { loop_step(i+1, k_exit) }
// ここでは簡略化して Jump 命令だけ書く(実際は分岐制御が必要だが Phase 26-H では型チェックのみ)
@ -107,12 +112,14 @@ fn mir_joinir_min_manual_construction() {
});
// i_plus_1 = i + 1
loop_step_func.body.push(JoinInst::Compute(MirLikeInst::BinOp {
dst: i_plus_1,
op: BinOpKind::Add,
lhs: i_param,
rhs: ValueId(204), // const 1
}));
loop_step_func
.body
.push(JoinInst::Compute(MirLikeInst::BinOp {
dst: i_plus_1,
op: BinOpKind::Add,
lhs: i_param,
rhs: ValueId(204), // const 1
}));
join_module.add_function(loop_step_func);
@ -148,8 +155,7 @@ fn mir_joinir_min_auto_lowering() {
let src = std::fs::read_to_string(test_file)
.unwrap_or_else(|_| panic!("Failed to read {}", test_file));
let ast: ASTNode = NyashParser::parse_from_string(&src)
.expect("joinir_min: parse failed");
let ast: ASTNode = NyashParser::parse_from_string(&src).expect("joinir_min: parse failed");
let mut mc = MirCompiler::with_options(false);
let compiled = mc.compile(ast).expect("joinir_min: MIR compile failed");
@ -160,31 +166,49 @@ fn mir_joinir_min_auto_lowering() {
);
// Step 2: MIR → JoinIR 自動変換
let join_module = lower_min_loop_to_joinir(&compiled.module)
.expect("lower_min_loop_to_joinir failed");
let join_module =
lower_min_loop_to_joinir(&compiled.module).expect("lower_min_loop_to_joinir failed");
eprintln!("[joinir/auto] JoinIR module generated:");
eprintln!("{:#?}", join_module);
// Step 3: 妥当性検証
assert_eq!(join_module.functions.len(), 2, "Expected 2 functions (main + loop_step)");
assert_eq!(
join_module.functions.len(),
2,
"Expected 2 functions (main + loop_step)"
);
let main_id = JoinFuncId::new(0);
let loop_step_id = JoinFuncId::new(1);
// main 関数の検証
let main_func = join_module.functions.get(&main_id)
let main_func = join_module
.functions
.get(&main_id)
.expect("main function not found");
assert_eq!(main_func.name, "main");
assert_eq!(main_func.params.len(), 0, "main has no parameters");
assert!(main_func.body.len() >= 2, "main should have at least 2 instructions (const + call)");
assert!(
main_func.body.len() >= 2,
"main should have at least 2 instructions (const + call)"
);
// loop_step 関数の検証
let loop_step_func = join_module.functions.get(&loop_step_id)
let loop_step_func = join_module
.functions
.get(&loop_step_id)
.expect("loop_step function not found");
assert_eq!(loop_step_func.name, "loop_step");
assert_eq!(loop_step_func.params.len(), 1, "loop_step has 1 parameter (i)");
assert!(loop_step_func.body.len() >= 4, "loop_step should have multiple instructions");
assert_eq!(
loop_step_func.params.len(),
1,
"loop_step has 1 parameter (i)"
);
assert!(
loop_step_func.body.len() >= 4,
"loop_step should have multiple instructions"
);
eprintln!("[joinir/auto] ✅ 自動変換成功Phase 26-H Step 2");
}

View File

@ -24,6 +24,7 @@ use crate::ast::ASTNode;
use crate::mir::join_ir::*;
use crate::mir::{MirCompiler, ValueId};
use crate::parser::NyashParser;
use std::collections::BTreeMap;
#[test]
#[ignore] // 手動実行用Phase 27.1 実験段階)
@ -32,7 +33,9 @@ fn mir_joinir_skip_ws_auto_lowering() {
// 環境変数トグルチェック
if std::env::var("NYASH_JOINIR_EXPERIMENT").ok().as_deref() != Some("1") {
eprintln!("[joinir/skip_ws] NYASH_JOINIR_EXPERIMENT=1 not set, skipping auto-lowering test");
eprintln!(
"[joinir/skip_ws] NYASH_JOINIR_EXPERIMENT=1 not set, skipping auto-lowering test"
);
return;
}
@ -45,8 +48,7 @@ fn mir_joinir_skip_ws_auto_lowering() {
let src = std::fs::read_to_string(test_file)
.unwrap_or_else(|_| panic!("Failed to read {}", test_file));
let ast: ASTNode = NyashParser::parse_from_string(&src)
.expect("skip_ws: parse failed");
let ast: ASTNode = NyashParser::parse_from_string(&src).expect("skip_ws: parse failed");
let mut mc = MirCompiler::with_options(false);
let compiled = mc.compile(ast).expect("skip_ws: MIR compile failed");
@ -57,30 +59,45 @@ fn mir_joinir_skip_ws_auto_lowering() {
);
// Step 2: MIR → JoinIR 自動変換
let join_module = lower_skip_ws_to_joinir(&compiled.module)
.expect("lower_skip_ws_to_joinir failed");
let join_module =
lower_skip_ws_to_joinir(&compiled.module).expect("lower_skip_ws_to_joinir failed");
eprintln!("[joinir/skip_ws] JoinIR module generated:");
eprintln!("{:#?}", join_module);
// Step 3: 妥当性検証
assert_eq!(join_module.functions.len(), 2, "Expected 2 functions (skip + loop_step)");
assert_eq!(
join_module.functions.len(),
2,
"Expected 2 functions (skip + loop_step)"
);
let skip_id = JoinFuncId::new(0);
let loop_step_id = JoinFuncId::new(1);
// skip 関数の検証
let skip_func = join_module.functions.get(&skip_id)
let skip_func = join_module
.functions
.get(&skip_id)
.expect("skip function not found");
assert_eq!(skip_func.name, "skip");
assert_eq!(skip_func.params.len(), 1, "skip has 1 parameter (s)");
assert!(skip_func.body.len() >= 3, "skip should have at least 3 instructions (const 0, length call, loop_step call)");
assert!(
skip_func.body.len() >= 3,
"skip should have at least 3 instructions (const 0, length call, loop_step call)"
);
// loop_step 関数の検証
let loop_step_func = join_module.functions.get(&loop_step_id)
let loop_step_func = join_module
.functions
.get(&loop_step_id)
.expect("loop_step function not found");
assert_eq!(loop_step_func.name, "loop_step");
assert_eq!(loop_step_func.params.len(), 3, "loop_step has 3 parameters (s, i, n)");
assert_eq!(
loop_step_func.params.len(),
3,
"loop_step has 3 parameters (s, i, n)"
);
assert!(loop_step_func.body.len() >= 8, "loop_step should have multiple instructions (comparisons, substring, recursive call, etc.)");
eprintln!("[joinir/skip_ws] ✅ 自動変換成功Phase 27.1");
@ -103,3 +120,97 @@ fn mir_joinir_skip_ws_type_sanity() {
assert_eq!(skip_func.params.len(), 3);
assert_eq!(skip_func.body.len(), 0);
}
#[test]
fn mir_joinir_skip_ws_generic_matches_handwritten() {
if std::env::var("NYASH_JOINIR_EXPERIMENT").ok().as_deref() != Some("1") {
eprintln!("[joinir/skip_ws] NYASH_JOINIR_EXPERIMENT=1 not set, skipping generic test");
return;
}
// Stage-3 parserを有効化
std::env::set_var("NYASH_PARSER_STAGE3", "1");
std::env::set_var("HAKO_PARSER_STAGE3", "1");
let test_file = "apps/tests/minimal_ssa_skip_ws.hako";
let src = std::fs::read_to_string(test_file)
.unwrap_or_else(|_| panic!("Failed to read {}", test_file));
let ast: ASTNode = NyashParser::parse_from_string(&src).expect("skip_ws generic: parse failed");
let mut mc = MirCompiler::with_options(false);
let compiled = mc
.compile(ast)
.expect("skip_ws generic: MIR compile failed");
fn params_by_name(jm: &JoinModule) -> BTreeMap<String, usize> {
jm.functions
.values()
.map(|f| (f.name.clone(), f.params.len()))
.collect()
}
fn has_jump_to_cont(jm: &JoinModule, func_name: &str, cont: JoinContId) -> bool {
jm.functions
.values()
.find(|f| f.name == func_name)
.map(|f| {
f.body.iter().any(|inst| match inst {
JoinInst::Jump { cont: c, .. } => *c == cont,
_ => false,
})
})
.unwrap_or(false)
}
// Baseline (generic OFF)
std::env::set_var("NYASH_JOINIR_LOWER_GENERIC", "0");
let baseline =
lower_skip_ws_to_joinir(&compiled.module).expect("baseline skip_ws lowering failed");
// Generic ON
std::env::set_var("NYASH_JOINIR_LOWER_GENERIC", "1");
let generic =
lower_skip_ws_to_joinir(&compiled.module).expect("generic skip_ws lowering failed");
// Compare shape (function count + params + loop_step/k_exit 相当の存在確認)
let baseline_params = params_by_name(&baseline);
let generic_params = params_by_name(&generic);
assert_eq!(baseline_params.len(), 2, "baseline should have 2 functions");
assert_eq!(generic_params.len(), 2, "generic should have 2 functions");
assert_eq!(
baseline_params.len(),
generic_params.len(),
"function count mismatch"
);
let expected_funcs = ["skip", "loop_step"];
for name in expected_funcs {
let b_params = baseline_params
.get(name)
.copied()
.unwrap_or_else(|| panic!("baseline missing function {}", name));
let g_params = generic_params
.get(name)
.copied()
.unwrap_or_else(|| panic!("generic missing function {}", name));
assert_eq!(
b_params, g_params,
"param count differs for function {}",
name
);
}
let exit_cont = JoinContId::new(0);
assert!(
has_jump_to_cont(&baseline, "loop_step", exit_cont),
"baseline loop_step should jump to k_exit(cont0)"
);
assert!(
has_jump_to_cont(&generic, "loop_step", exit_cont),
"generic loop_step should jump to k_exit(cont0)"
);
eprintln!("[joinir/skip_ws] ✅ generic_case_a JoinIR matches baseline");
}

View File

@ -25,9 +25,10 @@ use crate::mir::join_ir::lowering::stage1_using_resolver::lower_stage1_usingreso
use crate::mir::join_ir::*;
use crate::mir::{MirCompiler, ValueId};
use crate::parser::NyashParser;
use std::collections::BTreeMap;
#[test]
#[ignore] // 手動実行用(Phase 27.12 実験段階
#[ignore] // 手動実行用(Stage-1 minimal
fn mir_joinir_stage1_using_resolver_auto_lowering() {
// Phase 27.12: Stage1UsingResolverBox.resolve_for_source の MIR → JoinIR 自動変換
@ -47,11 +48,13 @@ fn mir_joinir_stage1_using_resolver_auto_lowering() {
let src = std::fs::read_to_string(test_file)
.unwrap_or_else(|_| panic!("Failed to read {}", test_file));
let ast: ASTNode = NyashParser::parse_from_string(&src)
.expect("stage1_using_resolver: parse failed");
let ast: ASTNode =
NyashParser::parse_from_string(&src).expect("stage1_using_resolver: parse failed");
let mut mc = MirCompiler::with_options(false);
let compiled = mc.compile(ast).expect("stage1_using_resolver: MIR compile failed");
let compiled = mc
.compile(ast)
.expect("stage1_using_resolver: MIR compile failed");
eprintln!(
"[joinir/stage1_using_resolver] MIR module compiled, {} functions",
@ -66,22 +69,38 @@ fn mir_joinir_stage1_using_resolver_auto_lowering() {
eprintln!("{:#?}", join_module);
// Step 3: 妥当性検証Phase 27.13 以降で実装)
assert_eq!(join_module.functions.len(), 2, "Expected 2 functions (resolve_entries + loop_step)");
assert_eq!(
join_module.functions.len(),
2,
"Expected 2 functions (resolve_entries + loop_step)"
);
let resolve_id = JoinFuncId::new(0);
let loop_step_id = JoinFuncId::new(1);
// resolve_entries 関数の検証
let resolve_func = join_module.functions.get(&resolve_id)
let resolve_func = join_module
.functions
.get(&resolve_id)
.expect("resolve_entries function not found");
assert_eq!(resolve_func.name, "resolve_entries");
assert_eq!(resolve_func.params.len(), 5, "resolve_entries has 5 parameters (entries, n, modules, seen, prefix_init)");
assert_eq!(
resolve_func.params.len(),
5,
"resolve_entries has 5 parameters (entries, n, modules, seen, prefix_init)"
);
// loop_step 関数の検証
let loop_step_func = join_module.functions.get(&loop_step_id)
let loop_step_func = join_module
.functions
.get(&loop_step_id)
.expect("loop_step function not found");
assert_eq!(loop_step_func.name, "loop_step");
assert_eq!(loop_step_func.params.len(), 6, "loop_step has 6 parameters (entries, n, modules, seen, prefix, i)");
assert_eq!(
loop_step_func.params.len(),
6,
"loop_step has 6 parameters (entries, n, modules, seen, prefix, i)"
);
eprintln!("[joinir/stage1_using_resolver] ✅ 自動変換成功Phase 27.12/27.13");
}
@ -117,5 +136,80 @@ fn mir_joinir_stage1_using_resolver_empty_module_returns_none() {
let result = lower_stage1_usingresolver_to_joinir(&test_module);
eprintln!("[joinir/stage1_using_resolver] empty_module test: result is None (expected)");
assert!(result.is_none(), "Empty MirModule should return None (target function not found)");
assert!(
result.is_none(),
"Empty MirModule should return None (target function not found)"
);
}
#[test]
#[ignore] // 手動実行: generic_case_a トグル検証stage1_using_resolver minimal
fn mir_joinir_stage1_using_resolver_generic_matches_handwritten() {
if std::env::var("NYASH_JOINIR_EXPERIMENT").ok().as_deref() != Some("1") {
eprintln!(
"[joinir/stage1_using_resolver] NYASH_JOINIR_EXPERIMENT=1 not set, skipping generic test"
);
return;
}
std::env::set_var("NYASH_PARSER_STAGE3", "1");
std::env::set_var("HAKO_PARSER_STAGE3", "1");
let test_file = "apps/tests/stage1_usingresolver_minimal.hako";
let src = std::fs::read_to_string(test_file)
.unwrap_or_else(|_| panic!("Failed to read {}", test_file));
let ast: ASTNode =
NyashParser::parse_from_string(&src).expect("stage1_using_resolver generic: parse failed");
let mut mc = MirCompiler::with_options(false);
let compiled = mc
.compile(ast)
.expect("stage1_using_resolver generic: MIR compile failed");
fn params_by_name(jm: &JoinModule) -> BTreeMap<String, usize> {
jm.functions
.values()
.map(|f| (f.name.clone(), f.params.len()))
.collect()
}
// Baseline (generic OFF)
std::env::set_var("NYASH_JOINIR_LOWER_GENERIC", "0");
let baseline = lower_stage1_usingresolver_to_joinir(&compiled.module)
.expect("baseline stage1_using_resolver lowering failed");
// Generic ON
std::env::set_var("NYASH_JOINIR_LOWER_GENERIC", "1");
let generic = lower_stage1_usingresolver_to_joinir(&compiled.module)
.expect("generic stage1_using_resolver lowering failed");
let baseline_params = params_by_name(&baseline);
let generic_params = params_by_name(&generic);
assert_eq!(baseline_params.len(), 2, "baseline should have 2 functions");
assert_eq!(generic_params.len(), 2, "generic should have 2 functions");
assert_eq!(
baseline_params.len(),
generic_params.len(),
"function count mismatch"
);
let expected_funcs = ["resolve_entries", "loop_step"];
for name in expected_funcs {
let b_params = baseline_params
.get(name)
.copied()
.unwrap_or_else(|| panic!("baseline missing function {}", name));
let g_params = generic_params
.get(name)
.copied()
.unwrap_or_else(|| panic!("generic missing function {}", name));
assert_eq!(
b_params, g_params,
"param count differs for function {}",
name
);
}
eprintln!("[joinir/stage1_using_resolver] ✅ generic_case_a JoinIR matches baseline");
}

View File

@ -0,0 +1,101 @@
// mir_joinir_stageb_body.rs
// Phase 28: StageBBodyExtractorBox.build_body_src JoinIR 変換テスト
//
// 目的:
// - StageBBodyExtractorBox.build_body_src/2 の Case A ループを JoinIR に落とせることを確認
// - Pinned/Carrier/Exit の構造を固定化Pinned: src/args/n, Carrier: acc/i, Exit: acc
//
// 実行条件:
// - #[ignore] で手動実行。環境変数 NYASH_JOINIR_EXPERIMENT=1 が必要。
use crate::ast::ASTNode;
use crate::mir::join_ir::lowering::stageb_body::lower_stageb_body_to_joinir;
use crate::mir::join_ir::*;
use crate::mir::{MirCompiler, ValueId};
use crate::parser::NyashParser;
#[test]
#[ignore] // 手動実行用(実験モードのみ)
fn mir_joinir_stageb_body_auto_lowering() {
if std::env::var("NYASH_JOINIR_EXPERIMENT").ok().as_deref() != Some("1") {
eprintln!(
"[joinir/stageb_body] NYASH_JOINIR_EXPERIMENT=1 not set, skipping auto-lowering test"
);
return;
}
// Stage-3 パーサを有効化local/loop を安全に扱うため)
std::env::set_var("NYASH_PARSER_STAGE3", "1");
std::env::set_var("HAKO_PARSER_STAGE3", "1");
let test_file = "apps/tests/stageb_body_extract_minimal.hako";
let src = std::fs::read_to_string(test_file)
.unwrap_or_else(|_| panic!("Failed to read {}", test_file));
let ast: ASTNode = NyashParser::parse_from_string(&src).expect("stageb_body: parse failed");
let mut mc = MirCompiler::with_options(false);
let compiled = mc.compile(ast).expect("stageb_body: MIR compile failed");
eprintln!(
"[joinir/stageb_body] MIR module compiled, {} functions",
compiled.module.functions.len()
);
let join_module = lower_stageb_body_to_joinir(&compiled.module)
.expect("StageBBodyExtractorBox.build_body_src should lower to JoinIR");
eprintln!("[joinir/stageb_body] JoinIR module generated:");
eprintln!("{:#?}", join_module);
assert_eq!(join_module.functions.len(), 2, "Expected entry + loop_step");
let entry_id = JoinFuncId::new(0);
let loop_id = JoinFuncId::new(1);
let entry_func = join_module
.functions
.get(&entry_id)
.expect("build_body_src function not found");
assert_eq!(entry_func.name, "build_body_src");
assert_eq!(
entry_func.params.len(),
2,
"build_body_src should take (src, args)"
);
let loop_func = join_module
.functions
.get(&loop_id)
.expect("loop_step function not found");
assert_eq!(loop_func.name, "loop_step");
assert_eq!(
loop_func.params.len(),
5,
"loop_step should take (src, args, n, acc, i)"
);
eprintln!("[joinir/stageb_body] ✅ 自動変換成功Phase 28");
}
#[test]
fn mir_joinir_stageb_body_type_sanity() {
let entry_id = JoinFuncId::new(42);
let f = JoinFunction::new(
entry_id,
"stageb_body_test".to_string(),
vec![ValueId(1), ValueId(2)],
);
assert_eq!(f.id, entry_id);
assert_eq!(f.name, "stageb_body_test");
assert_eq!(f.params.len(), 2);
}
#[test]
fn mir_joinir_stageb_body_empty_module_returns_none() {
use crate::mir::MirModule;
let test_module = MirModule::new("empty".to_string());
let result = lower_stageb_body_to_joinir(&test_module);
eprintln!("[joinir/stageb_body] empty_module test => {:?}", result);
assert!(result.is_none());
}

View File

@ -0,0 +1,105 @@
// mir_joinir_stageb_funcscanner.rs
// Phase 28: StageBFuncScannerBox.scan_all_boxes JoinIR 変換テスト
//
// 目的:
// - StageBFuncScannerBox.scan_all_boxes/1 の Case A ループを JoinIR に落とせることを確認
// - Pinned/Carrier/Exit の構造を固定化Pinned: src/n, Carrier: defs/i, Exit: defs
//
// 実行条件:
// - #[ignore] で手動実行。環境変数 NYASH_JOINIR_EXPERIMENT=1 が必要。
use crate::ast::ASTNode;
use crate::mir::join_ir::lowering::stageb_funcscanner::lower_stageb_funcscanner_to_joinir;
use crate::mir::join_ir::*;
use crate::mir::{MirCompiler, ValueId};
use crate::parser::NyashParser;
#[test]
#[ignore] // 手動実行用(実験モードのみ)
fn mir_joinir_stageb_funcscanner_auto_lowering() {
if std::env::var("NYASH_JOINIR_EXPERIMENT").ok().as_deref() != Some("1") {
eprintln!("[joinir/stageb_funcscanner] NYASH_JOINIR_EXPERIMENT=1 not set, skipping auto-lowering test");
return;
}
// Stage-3 パーサを有効化
std::env::set_var("NYASH_PARSER_STAGE3", "1");
std::env::set_var("HAKO_PARSER_STAGE3", "1");
let test_file = "apps/tests/stageb_funcscanner_scan_boxes_minimal.hako";
let src = std::fs::read_to_string(test_file)
.unwrap_or_else(|_| panic!("Failed to read {}", test_file));
let ast: ASTNode =
NyashParser::parse_from_string(&src).expect("stageb_funcscanner: parse failed");
let mut mc = MirCompiler::with_options(false);
let compiled = mc
.compile(ast)
.expect("stageb_funcscanner: MIR compile failed");
eprintln!(
"[joinir/stageb_funcscanner] MIR module compiled, {} functions",
compiled.module.functions.len()
);
let join_module = lower_stageb_funcscanner_to_joinir(&compiled.module)
.expect("StageBFuncScannerBox.scan_all_boxes should lower to JoinIR");
eprintln!("[joinir/stageb_funcscanner] JoinIR module generated:");
eprintln!("{:#?}", join_module);
assert_eq!(join_module.functions.len(), 2, "Expected entry + loop_step");
let entry_id = JoinFuncId::new(0);
let loop_id = JoinFuncId::new(1);
let entry_func = join_module
.functions
.get(&entry_id)
.expect("scan_all_boxes function not found");
assert_eq!(entry_func.name, "scan_all_boxes");
assert_eq!(
entry_func.params.len(),
1,
"scan_all_boxes should take (src)"
);
let loop_func = join_module
.functions
.get(&loop_id)
.expect("loop_step function not found");
assert_eq!(loop_func.name, "loop_step");
assert_eq!(
loop_func.params.len(),
4,
"loop_step should take (src, n, defs, i)"
);
eprintln!("[joinir/stageb_funcscanner] ✅ 自動変換成功Phase 28");
}
#[test]
fn mir_joinir_stageb_funcscanner_type_sanity() {
let entry_id = JoinFuncId::new(24);
let f = JoinFunction::new(
entry_id,
"stageb_funcscanner_test".to_string(),
vec![ValueId(1)],
);
assert_eq!(f.id, entry_id);
assert_eq!(f.name, "stageb_funcscanner_test");
assert_eq!(f.params.len(), 1);
}
#[test]
fn mir_joinir_stageb_funcscanner_empty_module_returns_none() {
use crate::mir::MirModule;
let test_module = MirModule::new("empty".to_string());
let result = lower_stageb_funcscanner_to_joinir(&test_module);
eprintln!(
"[joinir/stageb_funcscanner] empty_module test => {:?}",
result
);
assert!(result.is_none());
}

View File

@ -82,4 +82,3 @@ fn mir_loopform_nested_region_verify() {
}
teardown_stage3_env();
}

View File

@ -104,11 +104,7 @@ fn mir_stage1_cli_emit_program_min_exec_hits_type_error() {
let cr = mc.compile(ast).expect("compile");
// Optional: scan for Compare::Ge instructions to locate suspicious comparisons
if std::env::var("NYASH_STAGE1_SCAN_GE")
.ok()
.as_deref()
== Some("1")
{
if std::env::var("NYASH_STAGE1_SCAN_GE").ok().as_deref() == Some("1") {
for (fname, func) in cr.module.functions.iter() {
for (bb_id, bb) in func.blocks.iter() {
for inst in bb.instructions.iter() {

View File

@ -40,8 +40,7 @@ fn ensure_stage3_env() {
/// Stage1 CLI 全体を読み込まずに、StringHelpers 内部の `.length()` 正規化だけを確認する。
fn stage1_staticcompiler_fixture_src() -> String {
// StringHelpers 本体を直接バンドルして using 依存を排除。
let string_helpers =
include_str!("../../lang/src/shared/common/string_helpers.hako");
let string_helpers = include_str!("../../lang/src/shared/common/string_helpers.hako");
let test_main_src = r#"
using lang.src.shared.common.string_helpers as StringHelpers

View File

@ -743,8 +743,6 @@ static box Stage1UsingResolverModulesMapContinueBreakLookup {
for e in &errors {
eprintln!("[rust-mir-verify] {}", e);
}
panic!(
"MIR verification failed for Stage1UsingResolverModulesMapContinueBreakLookup"
);
panic!("MIR verification failed for Stage1UsingResolverModulesMapContinueBreakLookup");
}
}

View File

@ -76,11 +76,7 @@ fn mir_static_main_box_executes_void_path_with_guard() {
// Just ensure the symbol exists; methodization may optimize away the actual call.
assert!(
compiled
.module
.functions
.keys()
.any(|k| k == "Main._nop/0"),
compiled.module.functions.keys().any(|k| k == "Main._nop/0"),
"Main._nop/0 should remain defined"
);
}

View File

@ -6,38 +6,40 @@ pub mod identical_exec;
pub mod identical_exec_collections;
pub mod identical_exec_instance;
pub mod identical_exec_string;
pub mod mir_breakfinder_ssa;
pub mod mir_funcscanner_skip_ws;
pub mod mir_funcscanner_parse_params_trim_min;
pub mod mir_funcscanner_trim_min;
pub mod mir_funcscanner_ssa;
pub mod mir_joinir_min; // Phase 26-H: JoinIR型定義妥当性確認
pub mod mir_joinir_skip_ws; // Phase 27.0: minimal_ssa_skip_ws JoinIR変換
pub mod mir_joinir_funcscanner_trim; // Phase 27.1: FuncScannerBox.trim JoinIR変換
pub mod mir_joinir_stage1_using_resolver_min; // Phase 27.12: Stage1UsingResolverBox.resolve_for_source JoinIR変換
pub mod mir_joinir_funcscanner_append_defs; // Phase 27.14: FuncScannerBox._append_defs JoinIR変換
pub mod joinir_runner_min; // Phase 27.2: JoinIR 実行器 A/B 比較テスト
pub mod joinir_runner_standalone; // Phase 27-shortterm S-3.2: JoinIR Runner 単体テスト
pub mod joinir_vm_bridge_skip_ws; // Phase 27-shortterm S-4.4: JoinIR → Rust VM Bridge A/B Test
pub mod json_lint_stringutils_min_vm; // Phase 21.7++: using StringUtils alias resolution fix
pub mod mir_breakfinder_ssa;
pub mod mir_funcscanner_parse_params_trim_min;
pub mod mir_funcscanner_skip_ws;
pub mod mir_funcscanner_ssa;
pub mod mir_funcscanner_trim_min;
pub mod mir_joinir_funcscanner_append_defs; // Phase 27.14: FuncScannerBox._append_defs JoinIR変換
pub mod mir_joinir_funcscanner_trim; // Phase 27.1: FuncScannerBox.trim JoinIR変換
pub mod mir_joinir_min; // Phase 26-H: JoinIR型定義妥当性確認
pub mod mir_joinir_skip_ws; // Phase 27.0: minimal_ssa_skip_ws JoinIR変換
pub mod mir_joinir_stage1_using_resolver_min; // Phase 27.12: Stage1UsingResolverBox.resolve_for_source JoinIR変換
pub mod mir_joinir_stageb_body; // Phase 28: StageBBodyExtractorBox.build_body_src JoinIR変換
pub mod mir_joinir_stageb_funcscanner; // Phase 28: StageBFuncScannerBox.scan_all_boxes JoinIR変換
pub mod mir_locals_ssa;
pub mod mir_loopform_complex;
pub mod mir_loopform_conditional_reassign;
pub mod mir_loopform_exit_phi;
pub mod mir_loopform_complex;
pub mod mir_static_box_naming;
pub mod mir_stage1_cli_emit_program_min;
pub mod mir_stage1_staticcompiler_receiver; // Phase 25.1: StaticCompiler receiver型推論バグ回帰防止
pub mod mir_stage1_using_resolver_verify;
pub mod json_lint_stringutils_min_vm; // Phase 21.7++: using StringUtils alias resolution fix
pub mod namingbox_static_method_id; // Phase 21.7++ Phase 1: StaticMethodId structure tests
pub mod stage1_cli_entry_ssa_smoke;
pub mod mir_stageb_like_args_length;
pub mod mir_stageb_loop_break_continue;
pub mod mir_stageb_string_utils_skip_ws; // Phase 25.1: skip_ws Void < 0 TypeError 再現
pub mod mir_static_box_naming;
pub mod mir_value_kind; // Phase 26-A-5: ValueId型安全化統合テスト
pub mod namingbox_static_method_id; // Phase 21.7++ Phase 1: StaticMethodId structure tests
pub mod nyash_abi_basic;
pub mod parser_static_box_members;
pub mod plugin_hygiene;
pub mod policy_mutdeny;
pub mod stage1_cli_entry_ssa_smoke;
pub mod sugar_basic_test;
pub mod sugar_coalesce_test;
pub mod sugar_comp_assign_test;

View File

@ -59,11 +59,7 @@ fn test_with_arity() {
#[test]
fn test_round_trip() {
let cases = vec![
"Main._nop/0",
"StringUtils.starts_with/2",
"Console.log/1",
];
let cases = vec!["Main._nop/0", "StringUtils.starts_with/2", "Console.log/1"];
for case in cases {
let id = StaticMethodId::parse(case).unwrap();