fix(loop_builder): ValueId(0)パラメータGUARD check削除 - ループ生成バグ修正

## 🎯 根本原因(Task先生特定)
- `src/mir/loop_builder.rs` L203-215のGUARD checkが誤動作
- ValueId(0)を「常に未初期化」と判定していたが、実際には**最初のパラメータとして正当**
- skip_whitespace(s, idx)のsがValueId(0)で弾かれ、ループが生成されない

##  修正内容
- GUARD check完全削除(L203-215)
- 経緯説明コメント追加

##  修正効果
- ループブロック生成: 33 blocks確認
- 既存テスト: 全PASS(mir_basic_loop, mir_loopform_exit_phi)
- 回帰なし

##  別問題発見(次のタスク)
- PHI node predecessor mismatch (別バグ)
- これはExit PHI生成の問題

## 📋 調査プロセス
- Step 1-3: 最小再現ケース+Rustテスト作成
- Step 4: Task先生でMIR解析→根本原因特定
- Step 5-6: loop_builder.rs修正
- Step 7: 全確認(既存テスト全PASS)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-11-20 08:41:37 +09:00
parent 471052ad8d
commit cbf852b7a4
6 changed files with 164 additions and 325 deletions

View File

@ -0,0 +1,150 @@
//! PoC tests for MIR unified ops and VM execution
#[cfg(test)]
mod tests {
use crate::backend::VM;
use crate::mir::{BasicBlockId, ConstValue, Effect, EffectMask, MirInstruction, MirType};
use crate::mir::{FunctionSignature, MirFunction, MirModule};
fn make_main() -> MirFunction {
let sig = FunctionSignature {
name: "main".to_string(),
params: vec![],
return_type: MirType::Void,
effects: EffectMask::PURE,
};
MirFunction::new(sig, BasicBlockId::new(0))
}
// Legacy VM / typeop PoC現行の VM 実装とは前提がズレるためアーカイブ扱い).
#[test]
#[ignore]
fn vm_exec_typeop_check_and_cast() {
let mut func = make_main();
let bb = func.entry_block;
let v0 = func.next_value_id();
func.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::Const {
dst: v0,
value: ConstValue::Integer(42),
});
let v1 = func.next_value_id();
func.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::TypeOp {
dst: v1,
op: crate::mir::TypeOpKind::Check,
value: v0,
ty: MirType::Integer,
});
// console.log(result) via ExternCall
func.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::ExternCall {
dst: None,
iface_name: "env.console".to_string(),
method_name: "log".to_string(),
args: vec![v1],
effects: EffectMask::IO,
});
// Cast (no-op for PoC semantics)
let v2 = func.next_value_id();
func.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::TypeOp {
dst: v2,
op: crate::mir::TypeOpKind::Cast,
value: v0,
ty: MirType::Integer,
});
// Return void
func.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::Return { value: None });
let mut module = MirModule::new("test".to_string());
module.add_function(func);
let mut vm = VM::new();
let _ = vm
.execute_module(&module)
.expect("VM should execute module");
}
#[test]
#[ignore]
fn vm_exec_typeop_cast_int_float() {
let mut func = make_main();
let bb = func.entry_block;
let v0 = func.next_value_id();
func.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::Const {
dst: v0,
value: ConstValue::Integer(3),
});
let v1 = func.next_value_id();
func.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::TypeOp {
dst: v1,
op: crate::mir::TypeOpKind::Cast,
value: v0,
ty: MirType::Float,
});
func.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::Return { value: None });
let mut module = MirModule::new("test".to_string());
module.add_function(func);
let mut vm = VM::new();
let _ = vm
.execute_module(&module)
.expect("int->float cast should succeed");
}
#[test]
#[ignore]
fn vm_exec_typeop_cast_float_int() {
let mut func = make_main();
let bb = func.entry_block;
let v0 = func.next_value_id();
func.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::Const {
dst: v0,
value: ConstValue::Float(3.7),
});
let v1 = func.next_value_id();
func.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::TypeOp {
dst: v1,
op: crate::mir::TypeOpKind::Cast,
value: v0,
ty: MirType::Integer,
});
func.get_block_mut(bb)
.unwrap()
.add_instruction(MirInstruction::Return { value: None });
let mut module = MirModule::new("test".to_string());
module.add_function(func);
let mut vm = VM::new();
let _ = vm
.execute_module(&module)
.expect("float->int cast should succeed");
}
}