refactor(mir): Extract TypeFacts Box from ops.rs (Phase 136 follow-up 1/3)
## Summary Extracts type inference logic from ops.rs into independent TypeFacts Box, improving testability and responsibility separation. ## Changes - New file: src/mir/builder/type_facts.rs (TypeFactsBox + OperandTypeClass) - Modified: src/mir/builder/ops.rs - Use TypeFacts Box instead of method - Modified: src/mir/builder.rs - Add type_facts module ## Effect - Type inference logic is now independently testable - ops.rs responsibility simplified to "operator lowering only" - Enables future sharing with lifecycle.rs:repropagate_binop_types() 🤖 Generated with Claude Code Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -52,6 +52,7 @@ mod router; // RouterPolicyBox(Unified vs BoxCall)
|
|||||||
mod schedule; // BlockScheduleBox(物理順序: PHI→materialize→body)
|
mod schedule; // BlockScheduleBox(物理順序: PHI→materialize→body)
|
||||||
mod ssa; // LocalSSA helpers (in-block materialization)
|
mod ssa; // LocalSSA helpers (in-block materialization)
|
||||||
mod stmts;
|
mod stmts;
|
||||||
|
mod type_facts; // Phase 136 follow-up: Type inference facts box
|
||||||
pub(crate) mod type_registry;
|
pub(crate) mod type_registry;
|
||||||
mod types; // types::annotation / inference(型注釈/推論の箱: 推論は後段)
|
mod types; // types::annotation / inference(型注釈/推論の箱: 推論は後段)
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|||||||
@ -10,40 +10,7 @@ enum BinaryOpType {
|
|||||||
Comparison(CompareOp),
|
Comparison(CompareOp),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Phase 131-11-E: TypeFacts - operand type classification
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
enum OperandTypeClass {
|
|
||||||
String,
|
|
||||||
Integer,
|
|
||||||
Unknown,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl super::MirBuilder {
|
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
|
// Build a binary operation
|
||||||
pub(super) fn build_binary_op(
|
pub(super) fn build_binary_op(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -101,11 +68,15 @@ impl super::MirBuilder {
|
|||||||
vec![lhs, rhs],
|
vec![lhs, rhs],
|
||||||
)?;
|
)?;
|
||||||
// Phase 196: TypeFacts SSOT - AddOperator call type annotation
|
// Phase 196: TypeFacts SSOT - AddOperator call type annotation
|
||||||
// Phase 131-11-E: TypeFacts - classify operand types
|
// Phase 131-11-E: TypeFacts - classify operand types (Phase 136: use TypeFactsBox)
|
||||||
let lhs_type = self.classify_operand_type(lhs);
|
let type_facts = super::type_facts::TypeFactsBox::new(
|
||||||
let rhs_type = self.classify_operand_type(rhs);
|
&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) {
|
match (lhs_type, rhs_type) {
|
||||||
(String, String) => {
|
(String, String) => {
|
||||||
// BOTH are strings: result is 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
|
// Phase 196: TypeFacts SSOT - BinOp type is determined by operands only
|
||||||
// String concatenation is handled at use-site in LLVM lowering
|
// String concatenation is handled at use-site in LLVM lowering
|
||||||
if matches!(op, crate::mir::BinaryOp::Add) {
|
if matches!(op, crate::mir::BinaryOp::Add) {
|
||||||
// Phase 131-11-E: TypeFacts - classify operand types
|
// Phase 131-11-E: TypeFacts - classify operand types (Phase 136: use TypeFactsBox)
|
||||||
let lhs_type = self.classify_operand_type(lhs);
|
let type_facts = super::type_facts::TypeFactsBox::new(
|
||||||
let rhs_type = self.classify_operand_type(rhs);
|
&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) {
|
match (lhs_type, rhs_type) {
|
||||||
(String, String) => {
|
(String, String) => {
|
||||||
// BOTH are strings: result is definitely a string
|
// BOTH are strings: result is definitely a string
|
||||||
|
|||||||
80
src/mir/builder/type_facts.rs
Normal file
80
src/mir/builder/type_facts.rs
Normal file
@ -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<ValueId, MirType>,
|
||||||
|
value_origin_newbox: &'a BTreeMap<ValueId, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> TypeFactsBox<'a> {
|
||||||
|
/// Create a new TypeFacts Box with borrowed type information
|
||||||
|
pub fn new(
|
||||||
|
value_types: &'a BTreeMap<ValueId, MirType>,
|
||||||
|
value_origin_newbox: &'a BTreeMap<ValueId, String>,
|
||||||
|
) -> 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
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user