From 27db67dd9966889da54382da4790db7835922ab3 Mon Sep 17 00:00:00 2001 From: sofia Date: Thu, 24 Jul 2025 18:42:10 +0300 Subject: [PATCH] Possibly fix typechecking for binops --- examples/hello_world.reid | 2 +- reid/src/ast/parse.rs | 2 +- reid/src/mir/pass.rs | 6 ++++-- reid/src/mir/typecheck.rs | 32 +++++++++++++++++++++++--------- reid/src/mir/typeinference.rs | 1 + reid/src/mir/typerefs.rs | 7 ++++++- 6 files changed, 36 insertions(+), 14 deletions(-) diff --git a/examples/hello_world.reid b/examples/hello_world.reid index bf34034..1e97fe6 100644 --- a/examples/hello_world.reid +++ b/examples/hello_world.reid @@ -21,5 +21,5 @@ fn main() -> u8 { free_string(&test); - return addition(5, 3); + return 8; } diff --git a/reid/src/ast/parse.rs b/reid/src/ast/parse.rs index a44e2a2..4bf5e82 100644 --- a/reid/src/ast/parse.rs +++ b/reid/src/ast/parse.rs @@ -314,7 +314,7 @@ fn parse_binop_rhs( lhs = Expression( ExpressionKind::Binop(op, Box::new(lhs), Box::new(rhs)), - stream.get_range().unwrap(), + stream.get_range_prev().unwrap(), ); } diff --git a/reid/src/mir/pass.rs b/reid/src/mir/pass.rs index 9595166..9f085c6 100644 --- a/reid/src/mir/pass.rs +++ b/reid/src/mir/pass.rs @@ -115,6 +115,10 @@ impl Storage { pub fn iter(&self) -> impl Iterator { self.0.iter() } + + pub fn find(&self, key: &Key) -> Option<(&Key, &T)> { + self.0.iter().find(|(k, _)| *k == key) + } } #[derive(Clone, Default, Debug)] @@ -216,7 +220,6 @@ impl std::hash::Hash for ScopeBinopKey { pub struct ScopeBinopDef { pub hands: (TypeKind, TypeKind), pub operator: BinaryOperator, - pub commutative: bool, pub return_ty: TypeKind, } @@ -370,7 +373,6 @@ impl Module { ScopeBinopDef { hands: (binop.lhs.1.clone(), binop.rhs.1.clone()), operator: binop.op, - commutative: true, return_ty: binop.return_type.clone(), }, ) diff --git a/reid/src/mir/typecheck.rs b/reid/src/mir/typecheck.rs index 08d5ddc..d05e33e 100644 --- a/reid/src/mir/typecheck.rs +++ b/reid/src/mir/typecheck.rs @@ -514,14 +514,28 @@ impl Expression { let rhs_res = rhs.typecheck(state, &typerefs, None); let rhs_type = state.or_else(rhs_res, TypeKind::Vague(Vague::Unknown), rhs.1); - let operator = state - .scope - .binops - .get(&pass::ScopeBinopKey { - params: (lhs_type.clone(), rhs_type.clone()), - operator: *op, - }) - .cloned(); + let cloned = state.scope.binops.clone(); + let mut iter = cloned.iter(); + let operator = loop { + let Some((_, binop)) = iter.next() else { + break None; + }; + if binop.operator != *op { + continue; + } + if let Some(hint_t) = hint_t { + if binop.return_ty == *hint_t { + if let Some(_) = TypeKind::binop_type(&lhs_type, &rhs_type, binop) { + break Some(binop); + } + } else { + continue; + } + } + if let Some(_) = TypeKind::binop_type(&lhs_type, &rhs_type, binop) { + break Some(binop); + } + }; if let Some(operator) = operator { // Re-typecheck with found operator hints @@ -534,7 +548,7 @@ impl Expression { let rhs_res = rhs.typecheck(state, &typerefs, Some(&rhs_ty)); state.or_else(lhs_res, TypeKind::Vague(Vague::Unknown), lhs.1); state.or_else(rhs_res, TypeKind::Vague(Vague::Unknown), rhs.1); - Ok(operator.return_ty) + Ok(operator.return_ty.clone()) } else { // Re-typecheck with typical everyday binop let lhs_res = lhs.typecheck( diff --git a/reid/src/mir/typeinference.rs b/reid/src/mir/typeinference.rs index 395c932..55a99df 100644 --- a/reid/src/mir/typeinference.rs +++ b/reid/src/mir/typeinference.rs @@ -311,6 +311,7 @@ impl Expression { // Infer LHS and RHS, and return binop type let mut lhs_ref = lhs.infer_types(state, type_refs)?; let mut rhs_ref = rhs.infer_types(state, type_refs)?; + type_refs .binop(op, &mut lhs_ref, &mut rhs_ref, &state.scope.binops) .ok_or(ErrorKind::TypesIncompatible( diff --git a/reid/src/mir/typerefs.rs b/reid/src/mir/typerefs.rs index e000e84..801664e 100644 --- a/reid/src/mir/typerefs.rs +++ b/reid/src/mir/typerefs.rs @@ -233,11 +233,16 @@ impl<'outer> ScopeTypeRefs<'outer> { rhs: &mut TypeRef<'outer>, binops: &Storage, ) -> Option> { + if lhs.resolve_deep().unwrap().known().is_err() + && rhs.resolve_deep().unwrap().known().is_err() + { + return self.from_type(&TypeKind::Vague(VagueType::Unknown)); + } for (_, binop) in binops.iter() { if let Some(ret) = try_binop(lhs, rhs, binop) { return Some(ret); } - if binop.commutative { + if binop.operator.is_commutative() { if let Some(ret) = try_binop(rhs, lhs, binop) { return Some(ret); }