Add operator to scopebinop, add some typechecking for binops
This commit is contained in:
		
							parent
							
								
									aec7d55e9b
								
							
						
					
					
						commit
						9f7022b4c0
					
				| @ -400,8 +400,9 @@ impl mir::Module { | ||||
| 
 | ||||
|             binops.insert( | ||||
|                 ScopeBinopKey { | ||||
|                     operators: (binop.lhs.1.clone(), binop.rhs.1.clone()), | ||||
|                     params: (binop.lhs.1.clone(), binop.rhs.1.clone()), | ||||
|                     commutative: mir::pass::CommutativeKind::True, | ||||
|                     operator: binop.op, | ||||
|                 }, | ||||
|                 StackBinopDefinition { | ||||
|                     parameters: (binop.lhs.clone(), binop.rhs.clone()), | ||||
|  | ||||
| @ -110,13 +110,13 @@ impl TypeKind { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn binop_type<'o>( | ||||
|     pub fn binop_type( | ||||
|         lhs: &TypeKind, | ||||
|         rhs: &TypeKind, | ||||
|         binop: &ScopeBinopDef, | ||||
|     ) -> Option<(TypeKind, TypeKind, TypeKind)> { | ||||
|         let lhs_ty = lhs.collapse_into(&binop.operators.0); | ||||
|         let rhs_ty = rhs.collapse_into(&binop.operators.1); | ||||
|         let lhs_ty = lhs.collapse_into(&binop.hands.0); | ||||
|         let rhs_ty = rhs.collapse_into(&binop.hands.1); | ||||
|         if let (Ok(lhs_ty), Ok(rhs_ty)) = (lhs_ty, rhs_ty) { | ||||
|             Some((lhs_ty, rhs_ty, binop.return_ty.clone())) | ||||
|         } else { | ||||
| @ -126,7 +126,7 @@ impl TypeKind { | ||||
| 
 | ||||
|     /// Reverse of binop_type, where the given hint is the known required output
 | ||||
|     /// type of the binop, and the output is the hint for the lhs/rhs type.
 | ||||
|     pub fn binop_hint(&self, op: &BinaryOperator) -> Option<TypeKind> { | ||||
|     pub fn simple_binop_hint(&self, op: &BinaryOperator) -> Option<TypeKind> { | ||||
|         match op { | ||||
|             BinaryOperator::Add | ||||
|             | BinaryOperator::Minus | ||||
| @ -138,6 +138,22 @@ impl TypeKind { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn binop_hint( | ||||
|         &self, | ||||
|         lhs: &TypeKind, | ||||
|         rhs: &TypeKind, | ||||
|         binop: &ScopeBinopDef, | ||||
|     ) -> Option<(TypeKind, TypeKind)> { | ||||
|         self.collapse_into(&binop.return_ty).ok()?; | ||||
|         let lhs_ty = lhs.collapse_into(&binop.hands.0); | ||||
|         let rhs_ty = rhs.collapse_into(&binop.hands.1); | ||||
|         if let (Ok(lhs_ty), Ok(rhs_ty)) = (lhs_ty, rhs_ty) { | ||||
|             Some((lhs_ty, rhs_ty)) | ||||
|         } else { | ||||
|             None | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn signed(&self) -> bool { | ||||
|         match self { | ||||
|             TypeKind::Bool => false, | ||||
|  | ||||
| @ -214,7 +214,7 @@ impl VagueLiteral { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] | ||||
| #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | ||||
| pub enum BinaryOperator { | ||||
|     Add, | ||||
|     Minus, | ||||
| @ -226,7 +226,7 @@ pub enum BinaryOperator { | ||||
| } | ||||
| 
 | ||||
| /// Specifically the operators that LLVM likes to take in as "icmp" parameters
 | ||||
| #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] | ||||
| #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | ||||
| pub enum CmpOperator { | ||||
|     LT, | ||||
|     LE, | ||||
|  | ||||
| @ -170,7 +170,8 @@ pub struct ScopeVariable { | ||||
| 
 | ||||
| #[derive(Clone, Debug, Eq)] | ||||
| pub struct ScopeBinopKey { | ||||
|     pub operators: (TypeKind, TypeKind), | ||||
|     pub params: (TypeKind, TypeKind), | ||||
|     pub operator: BinaryOperator, | ||||
|     pub commutative: CommutativeKind, | ||||
| } | ||||
| 
 | ||||
| @ -183,14 +184,16 @@ pub enum CommutativeKind { | ||||
| 
 | ||||
| impl PartialEq for ScopeBinopKey { | ||||
|     fn eq(&self, other: &Self) -> bool { | ||||
|         if self.operator != other.operator { | ||||
|             return false; | ||||
|         } | ||||
|         if self.commutative != CommutativeKind::Any && other.commutative != CommutativeKind::Any { | ||||
|             if self.commutative != other.commutative { | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|         let operators_eq = self.operators == other.operators; | ||||
|         let swapped_ops_eq = | ||||
|             (self.operators.1.clone(), self.operators.0.clone()) == other.operators; | ||||
|         let operators_eq = self.params == other.params; | ||||
|         let swapped_ops_eq = (self.params.1.clone(), self.params.0.clone()) == other.params; | ||||
|         if self.commutative == CommutativeKind::True || other.commutative == CommutativeKind::True { | ||||
|             operators_eq || swapped_ops_eq | ||||
|         } else { | ||||
| @ -202,18 +205,20 @@ impl PartialEq for ScopeBinopKey { | ||||
| impl std::hash::Hash for ScopeBinopKey { | ||||
|     fn hash<H: std::hash::Hasher>(&self, state: &mut H) { | ||||
|         if self.commutative == CommutativeKind::True { | ||||
|             let mut sorted = vec![&self.operators.0, &self.operators.1]; | ||||
|             let mut sorted = vec![&self.params.0, &self.params.1]; | ||||
|             sorted.sort(); | ||||
|             sorted.hash(state); | ||||
|             self.operator.hash(state); | ||||
|         } else { | ||||
|             self.operators.hash(state); | ||||
|             self.params.hash(state); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug)] | ||||
| pub struct ScopeBinopDef { | ||||
|     pub operators: (TypeKind, TypeKind), | ||||
|     pub hands: (TypeKind, TypeKind), | ||||
|     pub operator: BinaryOperator, | ||||
|     pub commutative: bool, | ||||
|     pub return_ty: TypeKind, | ||||
| } | ||||
| @ -358,17 +363,22 @@ impl Module { | ||||
|         } | ||||
| 
 | ||||
|         for binop in &self.binop_defs { | ||||
|             scope.binops.set( | ||||
|                 ScopeBinopKey { | ||||
|                     operators: (binop.lhs.1.clone(), binop.rhs.1.clone()), | ||||
|                     commutative: CommutativeKind::True, | ||||
|                 }, | ||||
|                 ScopeBinopDef { | ||||
|                     operators: (binop.lhs.1.clone(), binop.rhs.1.clone()), | ||||
|                     commutative: true, | ||||
|                     return_ty: binop.return_type.clone(), | ||||
|                 }, | ||||
|             ); | ||||
|             scope | ||||
|                 .binops | ||||
|                 .set( | ||||
|                     ScopeBinopKey { | ||||
|                         params: (binop.lhs.1.clone(), binop.rhs.1.clone()), | ||||
|                         commutative: CommutativeKind::True, | ||||
|                         operator: binop.op, | ||||
|                     }, | ||||
|                     ScopeBinopDef { | ||||
|                         hands: (binop.lhs.1.clone(), binop.rhs.1.clone()), | ||||
|                         operator: binop.op, | ||||
|                         commutative: true, | ||||
|                         return_ty: binop.return_type.clone(), | ||||
|                     }, | ||||
|                 ) | ||||
|                 .ok(); | ||||
|         } | ||||
| 
 | ||||
|         for function in &self.functions { | ||||
|  | ||||
| @ -513,7 +513,7 @@ impl Expression { | ||||
|                 let lhs_res = lhs.typecheck( | ||||
|                     state, | ||||
|                     &typerefs, | ||||
|                     hint_t.and_then(|t| t.binop_hint(op)).as_ref(), | ||||
|                     hint_t.and_then(|t| t.simple_binop_hint(op)).as_ref(), | ||||
|                 ); | ||||
|                 let lhs_type = state.or_else(lhs_res, TypeKind::Vague(Vague::Unknown), lhs.1); | ||||
|                 let rhs_res = rhs.typecheck(state, &typerefs, Some(&lhs_type)); | ||||
|  | ||||
| @ -62,8 +62,9 @@ impl<'t> Pass for TypeInference<'t> { | ||||
|         let mut seen_binops = HashSet::new(); | ||||
|         for binop in &module.binop_defs { | ||||
|             let binop_key = ScopeBinopKey { | ||||
|                 operators: (binop.lhs.1.clone(), binop.rhs.1.clone()), | ||||
|                 params: (binop.lhs.1.clone(), binop.rhs.1.clone()), | ||||
|                 commutative: pass::CommutativeKind::True, | ||||
|                 operator: binop.op, | ||||
|             }; | ||||
|             if seen_binops.contains(&binop_key) { | ||||
|                 state.note_errors( | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user