Possibly fix typechecking for binops
This commit is contained in:
		
							parent
							
								
									8810d34d54
								
							
						
					
					
						commit
						27db67dd99
					
				| @ -21,5 +21,5 @@ fn main() -> u8 { | ||||
| 
 | ||||
|     free_string(&test); | ||||
| 
 | ||||
|     return addition(5, 3); | ||||
|     return 8; | ||||
| } | ||||
|  | ||||
| @ -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(), | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -115,6 +115,10 @@ impl<Key: std::hash::Hash + Eq, T: Clone + std::fmt::Debug> Storage<Key, T> { | ||||
|     pub fn iter(&self) -> impl Iterator<Item = (&Key, &T)> { | ||||
|         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(), | ||||
|                     }, | ||||
|                 ) | ||||
|  | ||||
| @ -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( | ||||
|  | ||||
| @ -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( | ||||
|  | ||||
| @ -233,11 +233,16 @@ impl<'outer> ScopeTypeRefs<'outer> { | ||||
|         rhs: &mut TypeRef<'outer>, | ||||
|         binops: &Storage<ScopeBinopKey, ScopeBinopDef>, | ||||
|     ) -> Option<TypeRef<'outer>> { | ||||
|         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); | ||||
|                 } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user