diff --git a/src/mir/builder.rs b/src/mir/builder.rs index 130568f5..ec7aabf8 100644 --- a/src/mir/builder.rs +++ b/src/mir/builder.rs @@ -52,6 +52,7 @@ mod router; // RouterPolicyBox(Unified vs BoxCall) mod schedule; // BlockScheduleBox(物理順序: PHI→materialize→body) mod ssa; // LocalSSA helpers (in-block materialization) mod stmts; +mod type_facts; // Phase 136 follow-up: Type inference facts box pub(crate) mod type_registry; mod types; // types::annotation / inference(型注釈/推論の箱: 推論は後段) mod utils; diff --git a/src/mir/builder/ops.rs b/src/mir/builder/ops.rs index c91252dc..46defa1c 100644 --- a/src/mir/builder/ops.rs +++ b/src/mir/builder/ops.rs @@ -10,40 +10,7 @@ enum BinaryOpType { Comparison(CompareOp), } -// Phase 131-11-E: TypeFacts - operand type classification -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -enum OperandTypeClass { - String, - Integer, - Unknown, -} - impl super::MirBuilder { - // Phase 131-11-E: TypeFacts - classify operand type for BinOp inference - fn classify_operand_type(&self, vid: ValueId) -> OperandTypeClass { - let result = match self.value_types.get(&vid) { - Some(MirType::String) => OperandTypeClass::String, - Some(MirType::Box(bt)) if bt == "StringBox" => OperandTypeClass::String, - Some(MirType::Integer) => OperandTypeClass::Integer, - Some(MirType::Bool) => OperandTypeClass::Integer, // Bool can be used as integer - _ => { - // Check value_origin_newbox for StringBox - if self - .value_origin_newbox - .get(&vid) - .map(|s| s == "StringBox") - .unwrap_or(false) - { - return OperandTypeClass::String; - } - OperandTypeClass::Unknown - } - }; - if std::env::var("NYASH_TYPEFACTS_DEBUG").is_ok() { - eprintln!("[typefacts] classify {:?} -> {:?}", vid, result); - } - result - } // Build a binary operation pub(super) fn build_binary_op( &mut self, @@ -101,11 +68,15 @@ impl super::MirBuilder { vec![lhs, rhs], )?; // Phase 196: TypeFacts SSOT - AddOperator call type annotation - // Phase 131-11-E: TypeFacts - classify operand types - let lhs_type = self.classify_operand_type(lhs); - let rhs_type = self.classify_operand_type(rhs); + // Phase 131-11-E: TypeFacts - classify operand types (Phase 136: use TypeFactsBox) + let type_facts = super::type_facts::TypeFactsBox::new( + &self.value_types, + &self.value_origin_newbox, + ); + let lhs_type = type_facts.classify_operand_type(lhs); + let rhs_type = type_facts.classify_operand_type(rhs); - use OperandTypeClass::*; + use super::type_facts::OperandTypeClass::*; match (lhs_type, rhs_type) { (String, String) => { // BOTH are strings: result is string @@ -189,11 +160,15 @@ impl super::MirBuilder { // Phase 196: TypeFacts SSOT - BinOp type is determined by operands only // String concatenation is handled at use-site in LLVM lowering if matches!(op, crate::mir::BinaryOp::Add) { - // Phase 131-11-E: TypeFacts - classify operand types - let lhs_type = self.classify_operand_type(lhs); - let rhs_type = self.classify_operand_type(rhs); + // Phase 131-11-E: TypeFacts - classify operand types (Phase 136: use TypeFactsBox) + let type_facts = super::type_facts::TypeFactsBox::new( + &self.value_types, + &self.value_origin_newbox, + ); + let lhs_type = type_facts.classify_operand_type(lhs); + let rhs_type = type_facts.classify_operand_type(rhs); - use OperandTypeClass::*; + use super::type_facts::OperandTypeClass::*; match (lhs_type, rhs_type) { (String, String) => { // BOTH are strings: result is definitely a string diff --git a/src/mir/builder/type_facts.rs b/src/mir/builder/type_facts.rs new file mode 100644 index 00000000..7ddebc8b --- /dev/null +++ b/src/mir/builder/type_facts.rs @@ -0,0 +1,80 @@ +//! Type inference facts for MIR operands +//! +//! Provides type classification and inference for binary operations. +//! +//! Phase 136 follow-up: Extracted from ops.rs to improve testability +//! and responsibility separation. + +use crate::mir::{MirType, ValueId}; +use std::collections::BTreeMap; + +/// Operand type classification for binary operation type inference +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum OperandTypeClass { + Integer, + String, + Unknown, +} + +/// Type facts box for type inference +/// +/// Provides type classification services for MIR operands during lowering. +/// Immutable by design - operates on borrowed type maps. +pub struct TypeFactsBox<'a> { + value_types: &'a BTreeMap, + value_origin_newbox: &'a BTreeMap, +} + +impl<'a> TypeFactsBox<'a> { + /// Create a new TypeFacts Box with borrowed type information + pub fn new( + value_types: &'a BTreeMap, + value_origin_newbox: &'a BTreeMap, + ) -> Self { + Self { + value_types, + value_origin_newbox, + } + } + + /// Classify operand type for binary operation inference + /// + /// Phase 131-11-E: TypeFacts - operand type classification + /// (Extracted from ops.rs:23-46) + /// + /// # Classification Strategy + /// 1. Check explicit type annotation first (value_types) + /// 2. Infer from NewBox origin (value_origin_newbox) + /// 3. Default to Unknown + /// + /// # Returns + /// - `OperandTypeClass::Integer` - Integer or Bool type + /// - `OperandTypeClass::String` - String or StringBox type + /// - `OperandTypeClass::Unknown` - Unable to infer + pub fn classify_operand_type(&self, vid: ValueId) -> OperandTypeClass { + let result = match self.value_types.get(&vid) { + Some(MirType::String) => OperandTypeClass::String, + Some(MirType::Box(bt)) if bt == "StringBox" => OperandTypeClass::String, + Some(MirType::Integer) => OperandTypeClass::Integer, + Some(MirType::Bool) => OperandTypeClass::Integer, // Bool can be used as integer + _ => { + // Check value_origin_newbox for StringBox + if self + .value_origin_newbox + .get(&vid) + .map(|s| s == "StringBox") + .unwrap_or(false) + { + return OperandTypeClass::String; + } + OperandTypeClass::Unknown + } + }; + + if std::env::var("NYASH_TYPEFACTS_DEBUG").is_ok() { + eprintln!("[typefacts] classify {:?} -> {:?}", vid, result); + } + + result + } +}