Typecheck custom binops
This commit is contained in:
		
							parent
							
								
									974c7e98f1
								
							
						
					
					
						commit
						50af50c43f
					
				| @ -1,7 +1,7 @@ | |||||||
| // Arithmetic, function calls and imports! | // Arithmetic, function calls and imports! | ||||||
| 
 | 
 | ||||||
| impl binop (lhs: u32) + (rhs: u32) -> u32 { | impl binop (lhs: u16) + (rhs: u32) -> u32 { | ||||||
| 
 |   return (lhs as u32) + rhs; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn main() -> u32 { | fn main() -> u32 { | ||||||
|  | |||||||
| @ -217,6 +217,7 @@ pub struct BinopDefinition { | |||||||
|     pub rhs: (String, Type), |     pub rhs: (String, Type), | ||||||
|     pub return_ty: Type, |     pub return_ty: Type, | ||||||
|     pub block: Block, |     pub block: Block, | ||||||
|  |     pub signature_range: TokenRange, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
|  | |||||||
| @ -554,7 +554,11 @@ impl Parse for Block { | |||||||
|             statements.push(statement); |             statements.push(statement); | ||||||
|         } |         } | ||||||
|         stream.expect(Token::BraceClose)?; |         stream.expect(Token::BraceClose)?; | ||||||
|         Ok(Block(statements, return_stmt, stream.get_range().unwrap())) |         Ok(Block( | ||||||
|  |             statements, | ||||||
|  |             return_stmt, | ||||||
|  |             stream.get_range_prev().unwrap(), | ||||||
|  |         )) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -814,6 +818,8 @@ impl Parse for BinopDefinition { | |||||||
|         let rhs_type = stream.parse()?; |         let rhs_type = stream.parse()?; | ||||||
|         stream.expect(Token::ParenClose)?; |         stream.expect(Token::ParenClose)?; | ||||||
| 
 | 
 | ||||||
|  |         let signature_range = stream.get_range().unwrap(); | ||||||
|  | 
 | ||||||
|         stream.expect(Token::Arrow)?; |         stream.expect(Token::Arrow)?; | ||||||
| 
 | 
 | ||||||
|         Ok(BinopDefinition { |         Ok(BinopDefinition { | ||||||
| @ -822,6 +828,7 @@ impl Parse for BinopDefinition { | |||||||
|             rhs: (rhs_name, rhs_type), |             rhs: (rhs_name, rhs_type), | ||||||
|             return_ty: stream.parse()?, |             return_ty: stream.parse()?, | ||||||
|             block: stream.parse()?, |             block: stream.parse()?, | ||||||
|  |             signature_range, | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -104,6 +104,7 @@ impl ast::Module { | |||||||
|                     rhs, |                     rhs, | ||||||
|                     return_ty, |                     return_ty, | ||||||
|                     block, |                     block, | ||||||
|  |                     signature_range, | ||||||
|                 }) => { |                 }) => { | ||||||
|                     binops.push(mir::BinopDefinition { |                     binops.push(mir::BinopDefinition { | ||||||
|                         lhs: (lhs.0.clone(), lhs.1 .0.into_mir(module_id)), |                         lhs: (lhs.0.clone(), lhs.1 .0.into_mir(module_id)), | ||||||
| @ -111,6 +112,7 @@ impl ast::Module { | |||||||
|                         rhs: (rhs.0.clone(), rhs.1 .0.into_mir(module_id)), |                         rhs: (rhs.0.clone(), rhs.1 .0.into_mir(module_id)), | ||||||
|                         return_ty: return_ty.0.into_mir(module_id), |                         return_ty: return_ty.0.into_mir(module_id), | ||||||
|                         block: block.into_mir(module_id), |                         block: block.into_mir(module_id), | ||||||
|  |                         meta: signature_range.as_meta(module_id), | ||||||
|                     }); |                     }); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  | |||||||
| @ -40,6 +40,9 @@ impl Display for Module { | |||||||
|         for import in &self.imports { |         for import in &self.imports { | ||||||
|             writeln!(inner_f, "{}", import)?; |             writeln!(inner_f, "{}", import)?; | ||||||
|         } |         } | ||||||
|  |         for binop in &self.binop_defs { | ||||||
|  |             writeln!(inner_f, "{}", binop)?; | ||||||
|  |         } | ||||||
|         for typedef in &self.typedefs { |         for typedef in &self.typedefs { | ||||||
|             writeln!(inner_f, "{}", typedef)?; |             writeln!(inner_f, "{}", typedef)?; | ||||||
|         } |         } | ||||||
| @ -56,6 +59,17 @@ impl Display for Import { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | impl Display for BinopDefinition { | ||||||
|  |     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||||
|  |         write!( | ||||||
|  |             f, | ||||||
|  |             "impl binop ({}: {:#}) {} ({}: {:#}) -> {:#} ", | ||||||
|  |             self.lhs.0, self.lhs.1, self.op, self.rhs.0, self.rhs.1, self.return_ty | ||||||
|  |         )?; | ||||||
|  |         Display::fmt(&self.block, f) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| impl Display for TypeDefinition { | impl Display for TypeDefinition { | ||||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||||
|         write!(f, "type {} = ", self.name)?; |         write!(f, "type {} = ", self.name)?; | ||||||
|  | |||||||
| @ -372,6 +372,17 @@ pub struct BinopDefinition { | |||||||
|     pub rhs: (String, TypeKind), |     pub rhs: (String, TypeKind), | ||||||
|     pub return_ty: TypeKind, |     pub return_ty: TypeKind, | ||||||
|     pub block: Block, |     pub block: Block, | ||||||
|  |     pub meta: Metadata, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl BinopDefinition { | ||||||
|  |     pub fn block_meta(&self) -> Metadata { | ||||||
|  |         self.block.meta | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn signature(&self) -> Metadata { | ||||||
|  |         self.meta | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
|  | |||||||
| @ -132,6 +132,11 @@ impl<'t> Pass for TypeCheck<'t> { | |||||||
|             check_typedefs_for_recursion(&defmap, typedef, HashSet::new(), &mut state); |             check_typedefs_for_recursion(&defmap, typedef, HashSet::new(), &mut state); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         for binop in &mut module.binop_defs { | ||||||
|  |             let res = binop.typecheck(&self.refs, &mut state.inner()); | ||||||
|  |             state.ok(res, binop.block_meta()); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         for function in &mut module.functions { |         for function in &mut module.functions { | ||||||
|             let res = function.typecheck(&self.refs, &mut state.inner()); |             let res = function.typecheck(&self.refs, &mut state.inner()); | ||||||
|             state.ok(res, function.block_meta()); |             state.ok(res, function.block_meta()); | ||||||
| @ -170,6 +175,48 @@ fn check_typedefs_for_recursion<'a, 'b>( | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | impl BinopDefinition { | ||||||
|  |     fn typecheck( | ||||||
|  |         &mut self, | ||||||
|  |         typerefs: &TypeRefs, | ||||||
|  |         state: &mut TypecheckPassState, | ||||||
|  |     ) -> Result<TypeKind, ErrorKind> { | ||||||
|  |         for param in vec![&self.lhs, &self.rhs] { | ||||||
|  |             let param_t = state.or_else( | ||||||
|  |                 param.1.assert_known(typerefs, state), | ||||||
|  |                 TypeKind::Vague(Vague::Unknown), | ||||||
|  |                 self.signature(), | ||||||
|  |             ); | ||||||
|  |             let res = state | ||||||
|  |                 .scope | ||||||
|  |                 .variables | ||||||
|  |                 .set( | ||||||
|  |                     param.0.clone(), | ||||||
|  |                     ScopeVariable { | ||||||
|  |                         ty: param_t.clone(), | ||||||
|  |                         mutable: param_t.is_mutable(), | ||||||
|  |                     }, | ||||||
|  |                 ) | ||||||
|  |                 .or(Err(ErrorKind::VariableAlreadyDefined(param.0.clone()))); | ||||||
|  |             state.ok(res, self.signature()); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         let return_type = self.return_ty.clone().assert_known(typerefs, state)?; | ||||||
|  | 
 | ||||||
|  |         state.scope.return_type_hint = Some(self.return_ty.clone()); | ||||||
|  |         let inferred = self | ||||||
|  |             .block | ||||||
|  |             .typecheck(&mut state.inner(), &typerefs, Some(&return_type)); | ||||||
|  | 
 | ||||||
|  |         match inferred { | ||||||
|  |             Ok(t) => return_type | ||||||
|  |                 .collapse_into(&t.1) | ||||||
|  |                 .or(Err(ErrorKind::ReturnTypeMismatch(return_type, t.1))), | ||||||
|  |             Err(e) => Ok(state.or_else(Err(e), return_type, self.block_meta())), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| impl FunctionDefinition { | impl FunctionDefinition { | ||||||
|     fn typecheck( |     fn typecheck( | ||||||
|         &mut self, |         &mut self, | ||||||
|  | |||||||
| @ -12,8 +12,8 @@ use super::{ | |||||||
|     pass::{Pass, PassResult, PassState}, |     pass::{Pass, PassResult, PassState}, | ||||||
|     typecheck::{ErrorKind, ErrorTypedefKind}, |     typecheck::{ErrorKind, ErrorTypedefKind}, | ||||||
|     typerefs::{ScopeTypeRefs, TypeRef, TypeRefs}, |     typerefs::{ScopeTypeRefs, TypeRef, TypeRefs}, | ||||||
|     Block, CustomTypeKey, ExprKind, Expression, FunctionDefinition, FunctionDefinitionKind, |     BinopDefinition, Block, CustomTypeKey, ExprKind, Expression, FunctionDefinition, | ||||||
|     IfExpression, Module, ReturnKind, StmtKind, |     FunctionDefinitionKind, IfExpression, Module, ReturnKind, StmtKind, | ||||||
|     TypeKind::*, |     TypeKind::*, | ||||||
|     VagueType::*, |     VagueType::*, | ||||||
|     WhileStatement, |     WhileStatement, | ||||||
| @ -55,6 +55,11 @@ impl<'t> Pass for TypeInference<'t> { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         for binop in &mut module.binop_defs { | ||||||
|  |             let res = binop.infer_types(&self.refs, &mut state.inner()); | ||||||
|  |             state.ok(res, binop.block_meta()); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         for function in &mut module.functions { |         for function in &mut module.functions { | ||||||
|             let res = function.infer_types(&self.refs, &mut state.inner()); |             let res = function.infer_types(&self.refs, &mut state.inner()); | ||||||
|             state.ok(res, function.block_meta()); |             state.ok(res, function.block_meta()); | ||||||
| @ -63,6 +68,56 @@ impl<'t> Pass for TypeInference<'t> { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | impl BinopDefinition { | ||||||
|  |     fn infer_types( | ||||||
|  |         &mut self, | ||||||
|  |         type_refs: &TypeRefs, | ||||||
|  |         state: &mut TypeInferencePassState, | ||||||
|  |     ) -> Result<(), ErrorKind> { | ||||||
|  |         let scope_hints = ScopeTypeRefs::from(type_refs); | ||||||
|  | 
 | ||||||
|  |         let lhs_ty = state.or_else( | ||||||
|  |             self.lhs.1.assert_unvague(), | ||||||
|  |             Vague(Unknown), | ||||||
|  |             self.signature(), | ||||||
|  |         ); | ||||||
|  |         state.ok( | ||||||
|  |             scope_hints | ||||||
|  |                 .new_var(self.lhs.0.clone(), false, &lhs_ty) | ||||||
|  |                 .or(Err(ErrorKind::VariableAlreadyDefined(self.lhs.0.clone()))), | ||||||
|  |             self.signature(), | ||||||
|  |         ); | ||||||
|  | 
 | ||||||
|  |         let rhs_ty = state.or_else( | ||||||
|  |             self.rhs.1.assert_unvague(), | ||||||
|  |             Vague(Unknown), | ||||||
|  |             self.signature(), | ||||||
|  |         ); | ||||||
|  | 
 | ||||||
|  |         state.ok( | ||||||
|  |             scope_hints | ||||||
|  |                 .new_var(self.rhs.0.clone(), false, &rhs_ty) | ||||||
|  |                 .or(Err(ErrorKind::VariableAlreadyDefined(self.rhs.0.clone()))), | ||||||
|  |             self.signature(), | ||||||
|  |         ); | ||||||
|  | 
 | ||||||
|  |         state.scope.return_type_hint = Some(self.return_ty.clone()); | ||||||
|  |         let ret_res = self.block.infer_types(state, &scope_hints); | ||||||
|  |         let (_, mut ret_ty) = state.or_else( | ||||||
|  |             ret_res, | ||||||
|  |             ( | ||||||
|  |                 ReturnKind::Soft, | ||||||
|  |                 scope_hints.from_type(&Vague(Unknown)).unwrap(), | ||||||
|  |             ), | ||||||
|  |             self.block_meta(), | ||||||
|  |         ); | ||||||
|  | 
 | ||||||
|  |         ret_ty.narrow(&scope_hints.from_type(&self.return_ty).unwrap()); | ||||||
|  | 
 | ||||||
|  |         Ok(()) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| impl FunctionDefinition { | impl FunctionDefinition { | ||||||
|     fn infer_types( |     fn infer_types( | ||||||
|         &mut self, |         &mut self, | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user