use crate::{ty::infer::InferTy, ty::TyKind, ArithOp, BinaryOp, Ty};
pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty {
match op {
BinaryOp::LogicOp(..) => TyKind::Bool.intern(),
BinaryOp::CmpOp(..) => match lhs_ty.interned() {
TyKind::Int(_)
| TyKind::Float(_)
| TyKind::Bool
| TyKind::InferenceVar(InferTy::Float(_))
| TyKind::InferenceVar(InferTy::Int(_)) => lhs_ty,
_ => TyKind::Unknown.intern(),
},
BinaryOp::Assignment { op: None } => match lhs_ty.interned() {
TyKind::Int(_)
| TyKind::Float(_)
| TyKind::Bool
| TyKind::Struct(_)
| TyKind::Array(_)
| TyKind::InferenceVar(InferTy::Float(_))
| TyKind::InferenceVar(InferTy::Int(_)) => lhs_ty,
_ => TyKind::Unknown.intern(),
},
BinaryOp::Assignment {
op: Some(ArithOp::LeftShift),
}
| BinaryOp::Assignment {
op: Some(ArithOp::RightShift),
}
| BinaryOp::Assignment {
op: Some(ArithOp::BitAnd),
}
| BinaryOp::Assignment {
op: Some(ArithOp::BitOr),
}
| BinaryOp::Assignment {
op: Some(ArithOp::BitXor),
}
| BinaryOp::ArithOp(ArithOp::LeftShift)
| BinaryOp::ArithOp(ArithOp::RightShift)
| BinaryOp::ArithOp(ArithOp::BitAnd)
| BinaryOp::ArithOp(ArithOp::BitOr)
| BinaryOp::ArithOp(ArithOp::BitXor) => match lhs_ty.interned() {
TyKind::Int(_) | TyKind::Bool | TyKind::InferenceVar(InferTy::Int(_)) => lhs_ty,
_ => TyKind::Unknown.intern(),
},
BinaryOp::Assignment { op: Some(_) } | BinaryOp::ArithOp(_) => match lhs_ty.interned() {
TyKind::Int(_)
| TyKind::Float(_)
| TyKind::InferenceVar(InferTy::Float(_))
| TyKind::InferenceVar(InferTy::Int(_)) => lhs_ty,
_ => TyKind::Unknown.intern(),
},
}
}
pub(super) fn binary_op_return_ty(op: BinaryOp, rhs_ty: Ty) -> Ty {
match op {
BinaryOp::ArithOp(_) => match rhs_ty.interned() {
TyKind::Int(_)
| TyKind::Float(_)
| TyKind::InferenceVar(InferTy::Float(_))
| TyKind::InferenceVar(InferTy::Int(_)) => rhs_ty,
_ => TyKind::Unknown.intern(),
},
BinaryOp::CmpOp(_) | BinaryOp::LogicOp(_) => TyKind::Bool.intern(),
BinaryOp::Assignment { .. } => Ty::unit(),
}
}