From e93727dd37126b65384e2d931413bf09d0d760c6 Mon Sep 17 00:00:00 2001 From: nyash-codex Date: Tue, 25 Nov 2025 13:33:01 +0900 Subject: [PATCH] =?UTF-8?q?fix(joinir):=20Stage-1=20string=20concat=20BinO?= =?UTF-8?q?p::Or=20=E2=86=92=20Add=20+=20ArrayBox=20support?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: 1. BinOp::Or → BinOp::Add for string concatenation in Stage-1 lowering 2. ArrayBox/MapBox support via JoinValue::BoxRef (ChatGPT implementation) Results: - n=0: JoinIR → "init" ✅ (VM → "void" PHI bug) - n=3: JoinIR → "ABC" ✅ (VM → "void" PHI bug) Stage-1 JoinIR VM Bridge now fully working! 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../join_ir/lowering/stage1_using_resolver.rs | 2 +- .../joinir_vm_bridge_stage1_usingresolver.rs | 66 +++++++++++-------- 2 files changed, 39 insertions(+), 29 deletions(-) diff --git a/src/mir/join_ir/lowering/stage1_using_resolver.rs b/src/mir/join_ir/lowering/stage1_using_resolver.rs index c758d70e..590d8fc8 100644 --- a/src/mir/join_ir/lowering/stage1_using_resolver.rs +++ b/src/mir/join_ir/lowering/stage1_using_resolver.rs @@ -252,7 +252,7 @@ fn build_stage1_using_resolver_joinir(module: &crate::mir::MirModule) -> Option< .body .push(JoinInst::Compute(MirLikeInst::BinOp { dst: new_prefix, - op: BinOpKind::Or, // String concatenation uses Or in JoinIR + op: BinOpKind::Add, // String concatenation uses Add lhs: prefix_loop, rhs: entry_value, })); diff --git a/src/tests/joinir_vm_bridge_stage1_usingresolver.rs b/src/tests/joinir_vm_bridge_stage1_usingresolver.rs index ed0d1712..03cfabab 100644 --- a/src/tests/joinir_vm_bridge_stage1_usingresolver.rs +++ b/src/tests/joinir_vm_bridge_stage1_usingresolver.rs @@ -12,7 +12,10 @@ // - Phase 30.x: Stage-1 UsingResolver minimal A/B test use crate::ast::ASTNode; -use crate::backend::VM; +use crate::backend::{VM, VMValue}; +use crate::boxes::array::ArrayBox; +use crate::boxes::basic::StringBox; +use crate::boxes::map_box::MapBox; use crate::mir::join_ir::lowering::stage1_using_resolver::lower_stage1_usingresolver_to_joinir; use crate::mir::join_ir::JoinFuncId; use crate::mir::join_ir_ops::JoinValue; @@ -20,6 +23,24 @@ use crate::mir::join_ir_vm_bridge::run_joinir_via_vm; use crate::mir::MirCompiler; use crate::parser::NyashParser; +fn join_value_from_box(b: Box) -> JoinValue { + let vm_val = VMValue::from_nyash_box(b); + JoinValue::from_vm_value(&vm_val).expect("box conversion failed") +} + +fn make_entries(values: &[&str]) -> JoinValue { + let mut arr = ArrayBox::new(); + for v in values { + let _ = arr.push(Box::new(StringBox::new(*v))); + } + join_value_from_box(Box::new(arr)) +} + +fn make_empty_map() -> JoinValue { + let map = MapBox::new(); + join_value_from_box(Box::new(map)) +} + /// 実験トグルチェック(モジュール内に閉じ込め) fn require_experiment_toggle() -> bool { if std::env::var("NYASH_JOINIR_VM_BRIDGE").ok().as_deref() != Some("1") { @@ -245,28 +266,16 @@ fn joinir_vm_bridge_stage1_usingresolver_route_b_execution() { eprintln!("[joinir_vm_bridge_test/stage1/route_b] JoinIR module created: {} functions", join_module.functions.len()); - // Stage-1 JoinIR の引数: - // resolve_entries(entries, n, modules, seen, prefix_init) - // - entries: ArrayBox (JoinValue 未対応) - // - n: Integer - // - modules: MapBox (JoinValue 未対応) - // - seen: MapBox (JoinValue 未対応) - // - prefix_init: String - // - // n=0 の場合、ループは実行されないので entries/modules/seen にアクセスしない - // → Int(0) で呼び出してみて、何が起こるか確認 - eprintln!("[joinir_vm_bridge_test/stage1/route_b] Attempting run_joinir_via_vm with n=0"); - eprintln!("[joinir_vm_bridge_test/stage1/route_b] Note: ArrayBox/MapBox args passed as Int(0) placeholder"); + eprintln!("[joinir_vm_bridge_test/stage1/route_b] Attempting run_joinir_via_vm with n=0 (Array/Map supported)"); - // JoinIR bridge 呼び出し - どこで止まるか観察 let result = run_joinir_via_vm( &join_module, JoinFuncId::new(0), &[ - JoinValue::Int(0), // entries placeholder (should not be accessed if n=0) - JoinValue::Int(0), // n = 0 (loop won't execute) - JoinValue::Int(0), // modules placeholder - JoinValue::Int(0), // seen placeholder + make_entries(&[]), + JoinValue::Int(0), // n = 0 (loop won't execute) + make_empty_map(), + make_empty_map(), JoinValue::Str("init".to_string()), // prefix_init ], ); @@ -275,22 +284,24 @@ fn joinir_vm_bridge_stage1_usingresolver_route_b_execution() { Ok(value) => { eprintln!("[joinir_vm_bridge_test/stage1/route_b] ✅ Execution succeeded: {:?}", value); // n=0 の場合、ループは実行されず prefix_init がそのまま返るはず - match value { + match &value { JoinValue::Str(s) => { eprintln!("[joinir_vm_bridge_test/stage1/route_b] Result: {:?}", s); if s == "init" { eprintln!("[joinir_vm_bridge_test/stage1/route_b] ✅ JoinIR returned correct 'init'!"); + } else { + panic!("expected 'init', got {}", s); } } _ => { - eprintln!("[joinir_vm_bridge_test/stage1/route_b] Unexpected result type: {:?}", value); + panic!("Unexpected result type: {:?}", value); } } } Err(e) => { eprintln!("[joinir_vm_bridge_test/stage1/route_b] ❌ Execution failed: {:?}", e); eprintln!("[joinir_vm_bridge_test/stage1/route_b] This error shows where VM bridge needs extension"); - // エラーが出ても panic しない - 何が足りないかの情報を得るため + panic!("JoinIR bridge failed: {:?}", e); } } @@ -337,10 +348,10 @@ fn joinir_vm_bridge_stage1_usingresolver_route_b_with_entries() { &join_module, JoinFuncId::new(0), &[ - JoinValue::Int(0), // entries - Int(0) では get() 失敗するはず + make_entries(&["A", "B", "C"]), JoinValue::Int(3), // n = 3 (loop will execute 3 times) - JoinValue::Int(0), // modules placeholder - JoinValue::Int(0), // seen placeholder + make_empty_map(), + make_empty_map(), JoinValue::Str("".to_string()), // prefix_init = "" ], ); @@ -354,18 +365,17 @@ fn joinir_vm_bridge_stage1_usingresolver_route_b_with_entries() { if s == "ABC" { eprintln!("[joinir_vm_bridge_test/stage1/route_b_with_entries] ✅ JoinIR returned correct 'ABC'!"); } else { - eprintln!("[joinir_vm_bridge_test/stage1/route_b_with_entries] ⚠️ Got '{}' (possibly partial or wrong)", s); + panic!("expected 'ABC', got {}", s); } } _ => { - eprintln!("[joinir_vm_bridge_test/stage1/route_b_with_entries] Unexpected result type: {:?}", value); + panic!("[joinir_vm_bridge_test/stage1/route_b_with_entries] Unexpected result type: {:?}", value); } } } Err(e) => { eprintln!("[joinir_vm_bridge_test/stage1/route_b_with_entries] ❌ Execution failed: {:?}", e); - eprintln!("[joinir_vm_bridge_test/stage1/route_b_with_entries] This shows ArrayBox/BoxCall needs JoinIR extension"); - // エラーを期待通り - ArrayBox サポートが必要なことを確認 + panic!("JoinIR bridge failed: {:?}", e); } }