diff --git a/src/grammar/generated.rs b/src/grammar/generated.rs index 25bb6e51..d94cb9c1 100644 --- a/src/grammar/generated.rs +++ b/src/grammar/generated.rs @@ -36,15 +36,37 @@ pub static OPERATORS_DIV_RULES: &[(&str, &str, &str, &str)] = &[ ]; pub fn lookup_keyword(word: &str) -> Option<&'static str> { for (k, t) in KEYWORDS { - if *k == word { - return Some(*t); - } + if *k == word { return Some(*t); } } None } pub static SYNTAX_ALLOWED_STATEMENTS: &[&str] = &[ - "box", "global", "function", "static", "if", "loop", "break", "return", "print", "nowait", - "include", "local", "outbox", "try", "throw", "using", "from", + "box", + "global", + "function", + "static", + "if", + "loop", + "break", + "return", + "print", + "nowait", + "include", + "local", + "outbox", + "try", + "throw", + "using", + "from", ]; -pub static SYNTAX_ALLOWED_BINOPS: &[&str] = &["add", "sub", "mul", "div", "and", "or", "eq", "ne"]; +pub static SYNTAX_ALLOWED_BINOPS: &[&str] = &[ + "add", + "sub", + "mul", + "div", + "and", + "or", + "eq", + "ne", +]; \ No newline at end of file diff --git a/src/mir/join_ir/frontend/ast_lowerer/read_quoted.rs b/src/mir/join_ir/frontend/ast_lowerer/read_quoted.rs index 57cddfe3..9f28a0c1 100644 --- a/src/mir/join_ir/frontend/ast_lowerer/read_quoted.rs +++ b/src/mir/join_ir/frontend/ast_lowerer/read_quoted.rs @@ -401,15 +401,15 @@ impl AstToJoinIrLowerer { merges: vec![ MergePair { dst: i_after_esc, - then_val: i_esc, - else_val: step_i, - type_hint: None, // Phase 63-3 + then_val: i_esc, // i + 1 (BinOp::Add, Integer) + else_val: step_i, // i (Integer param) + type_hint: Some(crate::mir::MirType::Integer), // Phase 64-2: ループカウンタ型確定 }, MergePair { dst: ch_merged, - then_val: ch_esc, - else_val: step_ch, - type_hint: None, // Phase 63-3 + then_val: ch_esc, // substring 結果 (String) + else_val: step_ch, // substring 結果 (String) + type_hint: Some(crate::mir::MirType::String), // Phase 64-2: 文字列型確定 }, ], k_next: None, diff --git a/src/mir/join_ir/lowering/if_merge.rs b/src/mir/join_ir/lowering/if_merge.rs index 9194f6ec..a086df6d 100644 --- a/src/mir/join_ir/lowering/if_merge.rs +++ b/src/mir/join_ir/lowering/if_merge.rs @@ -15,7 +15,7 @@ //! - Loop の PHI には触らない(Loop lowering の責務) use crate::mir::join_ir::{JoinInst, MergePair}; -use crate::mir::{BasicBlockId, MirFunction, MirInstruction, ValueId}; +use crate::mir::{BasicBlockId, MirFunction, MirInstruction, MirType, ValueId}; use std::collections::HashSet; // Phase 61-1: If-in-loop context support @@ -198,11 +198,15 @@ impl IfMergeLowerer { // else ブロックで dst に書き込まれる値を探す let else_val = self.find_written_value(&else_block.instructions, dst)?; + // Phase 64-2: then_val / else_val から型ヒント推論 + let type_hint = infer_type_from_mir_pattern(func, then_val) + .or_else(|| infer_type_from_mir_pattern(func, else_val)); + merge_pairs.push(MergePair { dst, then_val, else_val, - type_hint: None, // Phase 63-3: 現時点では型ヒントなし + type_hint, // Phase 64-2: Const 命令から型推論 }); } @@ -272,6 +276,34 @@ impl IfMergeLowerer { } } +/// Phase 64-2: MIR から ValueId の型を推論 +/// +/// Const 命令を探して、ValueId に対応する MirType を返す。 +/// IfMerge の then_val / else_val から型ヒントを埋めるために使用。 +fn infer_type_from_mir_pattern(func: &MirFunction, val_id: ValueId) -> Option { + use crate::mir::{ConstValue, MirInstruction, MirType}; + + // 全ブロックの全命令を走査して Const 命令を探す + for block in func.blocks.values() { + for inst in &block.instructions { + if let MirInstruction::Const { dst, value } = inst { + if *dst == val_id { + return Some(match value { + ConstValue::Integer(_) => MirType::Integer, + ConstValue::Bool(_) => MirType::Bool, + ConstValue::String(_) => MirType::String, + ConstValue::Void => MirType::Void, + ConstValue::Null => MirType::Unknown, // Null は Unknown として扱う + // Float は現状未サポート + _ => return None, + }); + } + } + } + } + None +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/tests/mir_joinir_if_select.rs b/src/tests/mir_joinir_if_select.rs index 5c9c1ce1..d77a40f2 100644 --- a/src/tests/mir_joinir_if_select.rs +++ b/src/tests/mir_joinir_if_select.rs @@ -719,4 +719,59 @@ mod tests { std::env::remove_var("NYASH_JOINIR_IF_SELECT"); } + + /// Phase 64-2-2: A/B テスト - P2 IfMerge Simple 型ヒント検証 + /// + /// IfMerge Simple パターンで MergePair の type_hint が正しく設定されることを確認。 + /// Phase 64-2 で追加した `infer_type_from_mir_pattern()` の動作確認。 + #[test] + fn test_p2_if_merge_type_hint() { + use crate::mir::join_ir::lowering::if_merge::IfMergeLowerer; + use crate::mir::MirType; + + std::env::set_var("NYASH_JOINIR_IF_MERGE", "1"); + + // P2 IfMerge Simple pattern で IfMerge 生成 + let func = create_if_merge_simple_pattern_mir(); + let entry_block = func.entry_block; + + let lowerer = IfMergeLowerer::new(2); // debug_level=2 + let join_inst = lowerer + .lower_if_to_if_merge(&func, entry_block) + .expect("P2 IfMerge Simple should lower to IfMerge"); + + // IfMerge instruction から merge_pairs を取り出す + use crate::mir::join_ir::JoinInst; + if let JoinInst::IfMerge { merges, .. } = join_inst { + eprintln!("✅ Phase 64-2-2 Step 1: IfMerge instruction found"); + + // MergePair の型ヒント確認(Const 命令から Integer を推論) + assert!( + !merges.is_empty(), + "IfMerge should have at least one MergePair" + ); + + // 最初の MergePair の型ヒントを確認(x に Integer 代入) + let first_pair = &merges[0]; + if let Some(type_hint) = &first_pair.type_hint { + eprintln!( + "✅ Phase 64-2-2 Step 2: MergePair[0] type_hint = Some({:?})", + type_hint + ); + assert_eq!( + *type_hint, + MirType::Integer, + "P2 IfMerge Simple should infer Integer type from Const" + ); + } else { + panic!("P2 IfMerge Simple should have type_hint=Some(Integer), got None"); + } + } else { + panic!("Expected IfMerge instruction, got: {:?}", join_inst); + } + + eprintln!("✅ Phase 64-2-2: P2 IfMerge type hint test passed - infer_type_from_mir_pattern() works!"); + + std::env::remove_var("NYASH_JOINIR_IF_MERGE"); + } }