use super::{MirInstruction, MirType, ValueId}; use crate::ast::{ASTNode, BinaryOperator}; use crate::mir::{BinaryOp, CompareOp, TypeOpKind, UnaryOp}; // Internal classification for binary operations #[derive(Debug)] enum BinaryOpType { Arithmetic(BinaryOp), Comparison(CompareOp), } impl super::MirBuilder { // Build a binary operation pub(super) fn build_binary_op( &mut self, left: ASTNode, operator: BinaryOperator, right: ASTNode, ) -> Result { let lhs = self.build_expression(left)?; let rhs = self.build_expression(right)?; let dst = self.value_gen.next(); let mir_op = self.convert_binary_operator(operator)?; match mir_op { // Arithmetic operations BinaryOpType::Arithmetic(op) => { self.emit_instruction(MirInstruction::BinOp { dst, op, lhs, rhs })?; // '+' は文字列連結の可能性がある。オペランドが String/StringBox なら結果を String と注釈。 if matches!(op, crate::mir::BinaryOp::Add) { let lhs_is_str = match self.value_types.get(&lhs) { Some(MirType::String) => true, Some(MirType::Box(bt)) if bt == "StringBox" => true, _ => false, }; let rhs_is_str = match self.value_types.get(&rhs) { Some(MirType::String) => true, Some(MirType::Box(bt)) if bt == "StringBox" => true, _ => false, }; if lhs_is_str || rhs_is_str { self.value_types.insert(dst, MirType::String); } else { self.value_types.insert(dst, MirType::Integer); } } else { // その他の算術は整数 self.value_types.insert(dst, MirType::Integer); } } // Comparison operations BinaryOpType::Comparison(op) => { // 80/20: If both operands originate from IntegerBox, cast to integer first let (lhs2, rhs2) = if self .value_origin_newbox .get(&lhs) .map(|s| s == "IntegerBox") .unwrap_or(false) && self .value_origin_newbox .get(&rhs) .map(|s| s == "IntegerBox") .unwrap_or(false) { let li = self.value_gen.next(); let ri = self.value_gen.next(); self.emit_instruction(MirInstruction::TypeOp { dst: li, op: TypeOpKind::Cast, value: lhs, ty: MirType::Integer, })?; self.emit_instruction(MirInstruction::TypeOp { dst: ri, op: TypeOpKind::Cast, value: rhs, ty: MirType::Integer, })?; (li, ri) } else { (lhs, rhs) }; self.emit_instruction(MirInstruction::Compare { dst, op, lhs: lhs2, rhs: rhs2, })?; self.value_types.insert(dst, MirType::Bool); } } Ok(dst) } // Build a unary operation pub(super) fn build_unary_op( &mut self, operator: String, operand: ASTNode, ) -> Result { let operand_val = self.build_expression(operand)?; // Core-13 純化: UnaryOp を直接 展開(Neg/Not/BitNot) if crate::config::env::mir_core13_pure() { match operator.as_str() { "-" => { let zero = self.value_gen.next(); self.emit_instruction(MirInstruction::Const { dst: zero, value: crate::mir::ConstValue::Integer(0), })?; let dst = self.value_gen.next(); self.emit_instruction(MirInstruction::BinOp { dst, op: crate::mir::BinaryOp::Sub, lhs: zero, rhs: operand_val, })?; return Ok(dst); } "!" | "not" => { let f = self.value_gen.next(); self.emit_instruction(MirInstruction::Const { dst: f, value: crate::mir::ConstValue::Bool(false), })?; let dst = self.value_gen.next(); self.emit_instruction(MirInstruction::Compare { dst, op: crate::mir::CompareOp::Eq, lhs: operand_val, rhs: f, })?; return Ok(dst); } "~" => { let all1 = self.value_gen.next(); self.emit_instruction(MirInstruction::Const { dst: all1, value: crate::mir::ConstValue::Integer(-1), })?; let dst = self.value_gen.next(); self.emit_instruction(MirInstruction::BinOp { dst, op: crate::mir::BinaryOp::BitXor, lhs: operand_val, rhs: all1, })?; return Ok(dst); } _ => {} } } let dst = self.value_gen.next(); let mir_op = self.convert_unary_operator(operator)?; self.emit_instruction(MirInstruction::UnaryOp { dst, op: mir_op, operand: operand_val, })?; Ok(dst) } // Convert AST binary operator to MIR enum or compare fn convert_binary_operator(&self, op: BinaryOperator) -> Result { match op { BinaryOperator::Add => Ok(BinaryOpType::Arithmetic(BinaryOp::Add)), BinaryOperator::Subtract => Ok(BinaryOpType::Arithmetic(BinaryOp::Sub)), BinaryOperator::Multiply => Ok(BinaryOpType::Arithmetic(BinaryOp::Mul)), BinaryOperator::Divide => Ok(BinaryOpType::Arithmetic(BinaryOp::Div)), BinaryOperator::Modulo => Ok(BinaryOpType::Arithmetic(BinaryOp::Mod)), BinaryOperator::Shl => Ok(BinaryOpType::Arithmetic(BinaryOp::Shl)), BinaryOperator::Shr => Ok(BinaryOpType::Arithmetic(BinaryOp::Shr)), BinaryOperator::BitAnd => Ok(BinaryOpType::Arithmetic(BinaryOp::BitAnd)), BinaryOperator::BitOr => Ok(BinaryOpType::Arithmetic(BinaryOp::BitOr)), BinaryOperator::BitXor => Ok(BinaryOpType::Arithmetic(BinaryOp::BitXor)), BinaryOperator::Equal => Ok(BinaryOpType::Comparison(CompareOp::Eq)), BinaryOperator::NotEqual => Ok(BinaryOpType::Comparison(CompareOp::Ne)), BinaryOperator::Less => Ok(BinaryOpType::Comparison(CompareOp::Lt)), BinaryOperator::LessEqual => Ok(BinaryOpType::Comparison(CompareOp::Le)), BinaryOperator::Greater => Ok(BinaryOpType::Comparison(CompareOp::Gt)), BinaryOperator::GreaterEqual => Ok(BinaryOpType::Comparison(CompareOp::Ge)), BinaryOperator::And => Ok(BinaryOpType::Arithmetic(BinaryOp::And)), BinaryOperator::Or => Ok(BinaryOpType::Arithmetic(BinaryOp::Or)), } } // Convert AST unary operator to MIR operator fn convert_unary_operator(&self, op: String) -> Result { match op.as_str() { "-" => Ok(UnaryOp::Neg), "!" | "not" => Ok(UnaryOp::Not), "~" => Ok(UnaryOp::BitNot), _ => Err(format!("Unsupported unary operator: {}", op)), } } }