Improve type inferrence for binops

This commit is contained in:
Sofia 2025-07-28 13:02:02 +03:00
parent 2709eb8749
commit 469ce3ce77
5 changed files with 44 additions and 17 deletions

View File

@ -1,17 +1,6 @@
// Arithmetic, function calls and imports! // Arithmetic, function calls and imports!
import std::print;
import std::from_str;
import std::add_num_to_str;
import std::free_string;
fn main() -> u32 { fn main() -> u32 {
for i in 0 .. 15 {
let mut text = from_str("num: ");
add_num_to_str(&mut text, i);
print(text);
free_string(&text);
}
let mut num = 0; let mut num = 0;
while num < 10 { while num < 10 {

View File

@ -2,9 +2,9 @@
fn main() -> bool { fn main() -> bool {
let bwand = (0xffu32 & 0xf0) >> 4; let bwand = (0xff & 0xf0) >> 4;
let bwor = (0x0fu32 | 0x00) << 4; let bwor = (0x0fu32 | 0x00) << 4;
let bwxor = (0xf0u32 | 0x0f); let bwxor = (0xf0 | 0x0f);
return (bwxor == 255) && ((bwand == 15) || false) && (bwor == 240); return (bwxor == 255) && ((bwand == 15) || false) && (bwor == 240);
} }

View File

@ -431,7 +431,7 @@ impl Expression {
params: (lhs_type.clone(), rhs_type.clone()), params: (lhs_type.clone(), rhs_type.clone()),
operator: *op, operator: *op,
}); });
dbg!(&binops, &expected_return_ty); // dbg!(&lhs_type, &rhs_type, &binops, &ret_ty, &expected_return_ty);
if let Some(binop) = binops if let Some(binop) = binops
.iter() .iter()
.filter(|f| f.1.return_ty.narrow_into(&expected_return_ty).is_ok()) .filter(|f| f.1.return_ty.narrow_into(&expected_return_ty).is_ok())

View File

@ -390,6 +390,9 @@ impl Expression {
widened_rhs = widened_rhs.widen_into(&binop.hands.1); widened_rhs = widened_rhs.widen_into(&binop.hands.1);
} }
let binop_res = type_refs.from_binop(*op, &lhs_ref, &rhs_ref); let binop_res = type_refs.from_binop(*op, &lhs_ref, &rhs_ref);
// dbg!(&return_ty);
// dbg!(&binop_res);
// dbg!(&lhs_ref, &rhs_ref, &binops, &widened_lhs, &widened_rhs);
lhs_ref.narrow(&type_refs.from_type(&widened_lhs).unwrap()); lhs_ref.narrow(&type_refs.from_type(&widened_lhs).unwrap());
rhs_ref.narrow(&type_refs.from_type(&widened_rhs).unwrap()); rhs_ref.narrow(&type_refs.from_type(&widened_rhs).unwrap());
*return_ty = binop_res.as_type(); *return_ty = binop_res.as_type();

View File

@ -332,21 +332,56 @@ impl<'outer> ScopeTypeRefs<'outer> {
.widen(self.types); .widen(self.types);
self.narrow_to_type(&hint1, &ty)?; self.narrow_to_type(&hint1, &ty)?;
let hint1_typeref = self.types.retrieve_typeref(*hint1.0.borrow()).unwrap(); let hint1_typeref = self.types.retrieve_typeref(*hint1.0.borrow()).unwrap();
let hint2_typeref = self.types.retrieve_typeref(*hint2.0.borrow()).unwrap();
match (&hint1_typeref, &hint2_typeref) {
(TypeRefKind::Direct(ret_ty), TypeRefKind::BinOp(op, lhs, rhs)) => {
let mut lhs_ref = self.from_type(&lhs).unwrap();
let mut rhs_ref = self.from_type(&rhs).unwrap();
let binops = self.available_binops(op, &mut lhs_ref, &mut rhs_ref);
let mut binops = binops
.iter()
.filter(|b| b.return_ty.narrow_into(ret_ty).is_ok())
.into_iter();
if let Some(binop) = binops.next() {
let mut lhs_widened = binop.hands.0.clone();
let mut rhs_widened = binop.hands.1.clone();
while let Some(binop) = binops.next() {
lhs_widened = lhs_widened.widen_into(&binop.hands.0);
rhs_widened = rhs_widened.widen_into(&binop.hands.1);
}
lhs_ref.narrow(&self.from_type(&lhs_widened).unwrap());
rhs_ref.narrow(&self.from_type(&rhs_widened).unwrap());
}
}
_ => {}
}
for idx in self.types.type_refs.borrow_mut().iter_mut() { for idx in self.types.type_refs.borrow_mut().iter_mut() {
match hint1_typeref { match (&hint1_typeref, &hint2_typeref) {
TypeRefKind::Direct(_) => { (TypeRefKind::Direct(_), TypeRefKind::Direct(_)) => {
if *idx == hint2.0 && idx != &hint1.0 { if *idx == hint2.0 && idx != &hint1.0 {
*idx.borrow_mut() = *hint1.0.borrow(); *idx.borrow_mut() = *hint1.0.borrow();
} }
} }
TypeRefKind::BinOp(_, _, _) => { (TypeRefKind::Direct(_), TypeRefKind::BinOp(..)) => {}
(TypeRefKind::BinOp(..), TypeRefKind::Direct(..)) => {
// TODO may not be good ? // TODO may not be good ?
// if *idx == hint2.0 && idx != &hint1.0 { // if *idx == hint2.0 && idx != &hint1.0 {
// *idx.borrow_mut() = *hint1.0.borrow(); // *idx.borrow_mut() = *hint1.0.borrow();
// } // }
} }
(TypeRefKind::BinOp(..), TypeRefKind::BinOp(..)) => {
// TODO may not be good ?
if *idx == hint2.0 && idx != &hint1.0 {
*idx.borrow_mut() = *hint1.0.borrow();
}
}
} }
} }
Some(TypeRef(hint1.0.clone(), self)) Some(TypeRef(hint1.0.clone(), self))
} }
} }