Implement a bunch of intrinsic binops
This commit is contained in:
		
							parent
							
								
									7ba3204803
								
							
						
					
					
						commit
						63f48f7df9
					
				| @ -0,0 +1 @@ | |||||||
|  | max_width = 120 | ||||||
| @ -1,98 +1,161 @@ | |||||||
| use std::marker::PhantomData; | use std::marker::PhantomData; | ||||||
| 
 | 
 | ||||||
| use reid_lib::{builder::InstructionValue, Instr}; | use reid_lib::{builder::InstructionValue, CmpPredicate, Instr}; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     codegen::{ErrorKind, StackValueKind}, |     codegen::{ErrorKind, StackValueKind}, | ||||||
|     mir::{BinaryOperator, BinopDefinition, FunctionDefinition, FunctionDefinitionKind, TypeKind}, |     mir::{BinaryOperator, BinopDefinition, CmpOperator, FunctionDefinition, FunctionDefinitionKind, TypeKind}, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| use super::scope::{Scope, StackValue}; | use super::scope::{Scope, StackValue}; | ||||||
| 
 | 
 | ||||||
|  | const INTEGERS: [TypeKind; 10] = [ | ||||||
|  |     TypeKind::U8, | ||||||
|  |     TypeKind::U16, | ||||||
|  |     TypeKind::U32, | ||||||
|  |     TypeKind::U64, | ||||||
|  |     TypeKind::U128, | ||||||
|  |     TypeKind::I8, | ||||||
|  |     TypeKind::I16, | ||||||
|  |     TypeKind::I32, | ||||||
|  |     TypeKind::I64, | ||||||
|  |     TypeKind::I128, | ||||||
|  | ]; | ||||||
|  | 
 | ||||||
|  | const FLOATS: [TypeKind; 7] = [ | ||||||
|  |     TypeKind::F16, | ||||||
|  |     TypeKind::F32, | ||||||
|  |     TypeKind::F32B, | ||||||
|  |     TypeKind::F64, | ||||||
|  |     TypeKind::F80, | ||||||
|  |     TypeKind::F128, | ||||||
|  |     TypeKind::F128PPC, | ||||||
|  | ]; | ||||||
|  | 
 | ||||||
| pub fn form_intrinsics() -> Vec<FunctionDefinition> { | pub fn form_intrinsics() -> Vec<FunctionDefinition> { | ||||||
|     let intrinsics = Vec::new(); |     let intrinsics = Vec::new(); | ||||||
| 
 | 
 | ||||||
|     intrinsics |     intrinsics | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | fn simple_binop_def<T: Clone + 'static>(op: BinaryOperator, ty: &TypeKind, fun: T) -> BinopDefinition | ||||||
|  | where | ||||||
|  |     T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue, | ||||||
|  | { | ||||||
|  |     BinopDefinition { | ||||||
|  |         lhs: ("lhs".to_owned(), ty.clone()), | ||||||
|  |         op, | ||||||
|  |         rhs: ("rhs".to_owned(), ty.clone()), | ||||||
|  |         return_type: ty.clone(), | ||||||
|  |         fn_kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSimpleInstr(fun))), | ||||||
|  |         meta: Default::default(), | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn boolean_binop_def<T: Clone + 'static>(op: BinaryOperator, ty: &TypeKind, fun: T) -> BinopDefinition | ||||||
|  | where | ||||||
|  |     T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue, | ||||||
|  | { | ||||||
|  |     BinopDefinition { | ||||||
|  |         lhs: ("lhs".to_owned(), ty.clone()), | ||||||
|  |         op, | ||||||
|  |         rhs: ("rhs".to_owned(), ty.clone()), | ||||||
|  |         return_type: TypeKind::Bool, | ||||||
|  |         fn_kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicBooleanInstr(fun))), | ||||||
|  |         meta: Default::default(), | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| pub fn form_intrinsic_binops() -> Vec<BinopDefinition> { | pub fn form_intrinsic_binops() -> Vec<BinopDefinition> { | ||||||
|     let mut intrinsics = Vec::new(); |     let mut intrinsics = Vec::new(); | ||||||
| 
 | 
 | ||||||
|     intrinsics.push(BinopDefinition { |     use BinaryOperator::*; | ||||||
|         lhs: ("lhs".to_owned(), TypeKind::U32), |  | ||||||
|         op: BinaryOperator::Add, |  | ||||||
|         rhs: ("rhs".to_owned(), TypeKind::U32), |  | ||||||
|         return_type: TypeKind::U32, |  | ||||||
|         fn_kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSimpleInstr( |  | ||||||
|             |scope, lhs, rhs| scope.block.build(Instr::Add(lhs, rhs)).unwrap(), |  | ||||||
|         ))), |  | ||||||
|         meta: Default::default(), |  | ||||||
|     }); |  | ||||||
| 
 | 
 | ||||||
|     intrinsics.push(BinopDefinition { |     for ty in INTEGERS { | ||||||
|         lhs: ("lhs".to_owned(), TypeKind::U16), |         intrinsics.push(simple_binop_def(Add, &ty, |scope, lhs, rhs| { | ||||||
|         op: BinaryOperator::Add, |             scope.block.build(Instr::Add(lhs, rhs)).unwrap() | ||||||
|         rhs: ("rhs".to_owned(), TypeKind::U16), |         })); | ||||||
|         return_type: TypeKind::U16, |         intrinsics.push(simple_binop_def(Mult, &ty, |scope, lhs, rhs| { | ||||||
|         fn_kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSimpleInstr( |             scope.block.build(Instr::Mul(lhs, rhs)).unwrap() | ||||||
|             |scope, lhs, rhs| scope.block.build(Instr::Add(lhs, rhs)).unwrap(), |         })); | ||||||
|         ))), |         intrinsics.push(simple_binop_def(Minus, &ty, |scope, lhs, rhs| { | ||||||
|         meta: Default::default(), |             scope.block.build(Instr::Sub(lhs, rhs)).unwrap() | ||||||
|     }); |         })); | ||||||
| 
 |         if ty.signed() { | ||||||
|     intrinsics.push(BinopDefinition { |             intrinsics.push(simple_binop_def(Div, &ty, |scope, lhs, rhs| { | ||||||
|         lhs: ("lhs".to_owned(), TypeKind::U32), |                 scope.block.build(Instr::SDiv(lhs, rhs)).unwrap() | ||||||
|         op: BinaryOperator::Mult, |             })); | ||||||
|         rhs: ("rhs".to_owned(), TypeKind::U32), |             intrinsics.push(simple_binop_def(Mod, &ty, |scope, lhs, rhs| { | ||||||
|         return_type: TypeKind::U32, |                 let div = scope.block.build(Instr::SDiv(lhs, rhs)).unwrap(); | ||||||
|         fn_kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSimpleInstr( |                 let mul = scope.block.build(Instr::Mul(rhs, div)).unwrap(); | ||||||
|             |scope, lhs, rhs| scope.block.build(Instr::Mul(lhs, rhs)).unwrap(), |                 scope.block.build(Instr::Sub(lhs, mul)).unwrap() | ||||||
|         ))), |             })); | ||||||
|         meta: Default::default(), |         } else { | ||||||
|     }); |             intrinsics.push(simple_binop_def(Div, &ty, |scope, lhs, rhs| { | ||||||
| 
 |                 scope.block.build(Instr::UDiv(lhs, rhs)).unwrap() | ||||||
|     intrinsics.push(BinopDefinition { |             })); | ||||||
|         lhs: ("lhs".to_owned(), TypeKind::U16), |             intrinsics.push(simple_binop_def(Mod, &ty, |scope, lhs, rhs| { | ||||||
|         op: BinaryOperator::Mult, |                 let div = scope.block.build(Instr::UDiv(lhs, rhs)).unwrap(); | ||||||
|         rhs: ("rhs".to_owned(), TypeKind::U16), |                 let mul = scope.block.build(Instr::Mul(rhs, div)).unwrap(); | ||||||
|         return_type: TypeKind::U16, |                 scope.block.build(Instr::Sub(lhs, mul)).unwrap() | ||||||
|         fn_kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSimpleInstr( |             })); | ||||||
|             |scope, lhs, rhs| scope.block.build(Instr::Mul(lhs, rhs)).unwrap(), |         } | ||||||
|         ))), |         intrinsics.push(boolean_binop_def(Cmp(CmpOperator::GT), &ty, |scope, lhs, rhs| { | ||||||
|         meta: Default::default(), |             scope.block.build(Instr::ICmp(CmpPredicate::GT, lhs, rhs)).unwrap() | ||||||
|     }); |         })); | ||||||
| 
 |         intrinsics.push(boolean_binop_def(Cmp(CmpOperator::GE), &ty, |scope, lhs, rhs| { | ||||||
|     intrinsics.push(BinopDefinition { |             scope.block.build(Instr::ICmp(CmpPredicate::GE, lhs, rhs)).unwrap() | ||||||
|         lhs: ("lhs".to_owned(), TypeKind::U32), |         })); | ||||||
|         op: BinaryOperator::Minus, |         intrinsics.push(boolean_binop_def(Cmp(CmpOperator::LT), &ty, |scope, lhs, rhs| { | ||||||
|         rhs: ("rhs".to_owned(), TypeKind::U32), |             scope.block.build(Instr::ICmp(CmpPredicate::LT, lhs, rhs)).unwrap() | ||||||
|         return_type: TypeKind::U32, |         })); | ||||||
|         fn_kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSimpleInstr( |         intrinsics.push(boolean_binop_def(Cmp(CmpOperator::LE), &ty, |scope, lhs, rhs| { | ||||||
|             |scope, lhs, rhs| scope.block.build(Instr::Sub(lhs, rhs)).unwrap(), |             scope.block.build(Instr::ICmp(CmpPredicate::LE, lhs, rhs)).unwrap() | ||||||
|         ))), |         })); | ||||||
|         meta: Default::default(), |     } | ||||||
|     }); |     for ty in INTEGERS.iter().chain(&[TypeKind::Bool, TypeKind::Char]) { | ||||||
| 
 |         intrinsics.push(boolean_binop_def(Cmp(CmpOperator::EQ), &ty, |scope, lhs, rhs| { | ||||||
|     intrinsics.push(BinopDefinition { |             scope.block.build(Instr::ICmp(CmpPredicate::EQ, lhs, rhs)).unwrap() | ||||||
|         lhs: ("lhs".to_owned(), TypeKind::U16), |         })); | ||||||
|         op: BinaryOperator::Minus, |         intrinsics.push(boolean_binop_def(Cmp(CmpOperator::NE), &ty, |scope, lhs, rhs| { | ||||||
|         rhs: ("rhs".to_owned(), TypeKind::U16), |             scope.block.build(Instr::ICmp(CmpPredicate::NE, lhs, rhs)).unwrap() | ||||||
|         return_type: TypeKind::U16, |         })); | ||||||
|         fn_kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSimpleInstr( |     } | ||||||
|             |scope, lhs, rhs| scope.block.build(Instr::Sub(lhs, rhs)).unwrap(), |     for ty in FLOATS { | ||||||
|         ))), |         intrinsics.push(simple_binop_def(BinaryOperator::Add, &ty, |scope, lhs, rhs| { | ||||||
|         meta: Default::default(), |             scope.block.build(Instr::FAdd(lhs, rhs)).unwrap() | ||||||
|     }); |         })); | ||||||
|  |         intrinsics.push(simple_binop_def(BinaryOperator::Mult, &ty, |scope, lhs, rhs| { | ||||||
|  |             scope.block.build(Instr::FMul(lhs, rhs)).unwrap() | ||||||
|  |         })); | ||||||
|  |         intrinsics.push(simple_binop_def(BinaryOperator::Minus, &ty, |scope, lhs, rhs| { | ||||||
|  |             scope.block.build(Instr::FSub(lhs, rhs)).unwrap() | ||||||
|  |         })); | ||||||
|  |         intrinsics.push(boolean_binop_def(Cmp(CmpOperator::EQ), &ty, |scope, lhs, rhs| { | ||||||
|  |             scope.block.build(Instr::FCmp(CmpPredicate::EQ, lhs, rhs)).unwrap() | ||||||
|  |         })); | ||||||
|  |         intrinsics.push(boolean_binop_def(Cmp(CmpOperator::NE), &ty, |scope, lhs, rhs| { | ||||||
|  |             scope.block.build(Instr::FCmp(CmpPredicate::NE, lhs, rhs)).unwrap() | ||||||
|  |         })); | ||||||
|  |         intrinsics.push(boolean_binop_def(Cmp(CmpOperator::GT), &ty, |scope, lhs, rhs| { | ||||||
|  |             scope.block.build(Instr::FCmp(CmpPredicate::GT, lhs, rhs)).unwrap() | ||||||
|  |         })); | ||||||
|  |         intrinsics.push(boolean_binop_def(Cmp(CmpOperator::GE), &ty, |scope, lhs, rhs| { | ||||||
|  |             scope.block.build(Instr::FCmp(CmpPredicate::GE, lhs, rhs)).unwrap() | ||||||
|  |         })); | ||||||
|  |         intrinsics.push(boolean_binop_def(Cmp(CmpOperator::LT), &ty, |scope, lhs, rhs| { | ||||||
|  |             scope.block.build(Instr::FCmp(CmpPredicate::LT, lhs, rhs)).unwrap() | ||||||
|  |         })); | ||||||
|  |         intrinsics.push(boolean_binop_def(Cmp(CmpOperator::LE), &ty, |scope, lhs, rhs| { | ||||||
|  |             scope.block.build(Instr::FCmp(CmpPredicate::LE, lhs, rhs)).unwrap() | ||||||
|  |         })); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     intrinsics |     intrinsics | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub trait IntrinsicFunction: std::fmt::Debug { | pub trait IntrinsicFunction: std::fmt::Debug { | ||||||
|     fn codegen<'ctx, 'a>( |     fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, params: &[&StackValue]) -> Result<StackValue, ErrorKind>; | ||||||
|         &self, |  | ||||||
|         scope: &mut Scope<'ctx, 'a>, |  | ||||||
|         params: &[&StackValue], |  | ||||||
|     ) -> Result<StackValue, ErrorKind>; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Clone)] | #[derive(Clone)] | ||||||
| @ -113,11 +176,7 @@ impl<T: Clone> IntrinsicFunction for IntrinsicSimpleInstr<T> | |||||||
| where | where | ||||||
|     T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue, |     T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue, | ||||||
| { | { | ||||||
|     fn codegen<'b, 'c>( |     fn codegen<'b, 'c>(&self, scope: &mut Scope<'b, 'c>, params: &[&StackValue]) -> Result<StackValue, ErrorKind> { | ||||||
|         &self, |  | ||||||
|         scope: &mut Scope<'b, 'c>, |  | ||||||
|         params: &[&StackValue], |  | ||||||
|     ) -> Result<StackValue, ErrorKind> { |  | ||||||
|         let lhs = params.get(0).unwrap(); |         let lhs = params.get(0).unwrap(); | ||||||
|         let rhs = params.get(1).unwrap(); |         let rhs = params.get(1).unwrap(); | ||||||
|         let instr = self.clone().0(scope, lhs.instr(), rhs.instr()); |         let instr = self.clone().0(scope, lhs.instr(), rhs.instr()); | ||||||
| @ -125,6 +184,32 @@ where | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #[derive(Clone)] | ||||||
|  | pub struct IntrinsicBooleanInstr<T>(T) | ||||||
|  | where | ||||||
|  |     T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue; | ||||||
|  | 
 | ||||||
|  | impl<T> std::fmt::Debug for IntrinsicBooleanInstr<T> | ||||||
|  | where | ||||||
|  |     T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue, | ||||||
|  | { | ||||||
|  |     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||||
|  |         f.debug_tuple("IntrinsicBooleanInstr").finish() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<T: Clone> IntrinsicFunction for IntrinsicBooleanInstr<T> | ||||||
|  | where | ||||||
|  |     T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue, | ||||||
|  | { | ||||||
|  |     fn codegen<'b, 'c>(&self, scope: &mut Scope<'b, 'c>, params: &[&StackValue]) -> Result<StackValue, ErrorKind> { | ||||||
|  |         let lhs = params.get(0).unwrap(); | ||||||
|  |         let rhs = params.get(1).unwrap(); | ||||||
|  |         let instr = self.clone().0(scope, lhs.instr(), rhs.instr()); | ||||||
|  |         Ok(StackValue(StackValueKind::Literal(instr), TypeKind::Bool)) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // impl IntrinsicFunction for IntrinsicIAdd {
 | // impl IntrinsicFunction for IntrinsicIAdd {
 | ||||||
| //     fn codegen<'ctx, 'a>(
 | //     fn codegen<'ctx, 'a>(
 | ||||||
| //         &self,
 | //         &self,
 | ||||||
|  | |||||||
| @ -98,11 +98,7 @@ pub fn compile_module<'map>( | |||||||
|     let mut statements = Vec::new(); |     let mut statements = Vec::new(); | ||||||
| 
 | 
 | ||||||
|     while !matches!(token_stream.peek().unwrap_or(Token::Eof), Token::Eof) { |     while !matches!(token_stream.peek().unwrap_or(Token::Eof), Token::Eof) { | ||||||
|         let statement = ReidError::from_parser( |         let statement = ReidError::from_parser(token_stream.parse::<TopLevelStatement>(), map.clone(), module_id)?; | ||||||
|             token_stream.parse::<TopLevelStatement>(), |  | ||||||
|             map.clone(), |  | ||||||
|             module_id, |  | ||||||
|         )?; |  | ||||||
|         statements.push(statement); |         statements.push(statement); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -189,8 +185,6 @@ pub fn perform_all_passes<'map>( | |||||||
|     println!("{}", &context); |     println!("{}", &context); | ||||||
|     #[cfg(debug_assertions)] |     #[cfg(debug_assertions)] | ||||||
|     dbg!(&state); |     dbg!(&state); | ||||||
|     dbg!("asd!"); |  | ||||||
|     thread::sleep(Duration::from_millis(100)); |  | ||||||
| 
 | 
 | ||||||
|     if !state.errors.is_empty() { |     if !state.errors.is_empty() { | ||||||
|         return Err(ReidError::from_kind( |         return Err(ReidError::from_kind( | ||||||
|  | |||||||
| @ -56,10 +56,7 @@ impl<'t> Pass for TypeCheck<'t> { | |||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if let Some(_) = defmap.insert(&typedef.name, typedef) { |             if let Some(_) = defmap.insert(&typedef.name, typedef) { | ||||||
|                 state.ok::<_, Infallible>( |                 state.ok::<_, Infallible>(Err(ErrorKind::DuplicateTypeName(name.clone())), meta.clone()); | ||||||
|                     Err(ErrorKind::DuplicateTypeName(name.clone())), |  | ||||||
|                     meta.clone(), |  | ||||||
|                 ); |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -94,10 +91,7 @@ fn check_typedefs_for_recursion<'a, 'b>( | |||||||
|                 if let TypeKind::CustomType(CustomTypeKey(name, _)) = field_ty { |                 if let TypeKind::CustomType(CustomTypeKey(name, _)) = field_ty { | ||||||
|                     if seen.contains(name) { |                     if seen.contains(name) { | ||||||
|                         state.ok::<_, Infallible>( |                         state.ok::<_, Infallible>( | ||||||
|                             Err(ErrorKind::RecursiveTypeDefinition( |                             Err(ErrorKind::RecursiveTypeDefinition(typedef.name.clone(), name.clone())), | ||||||
|                                 typedef.name.clone(), |  | ||||||
|                                 name.clone(), |  | ||||||
|                             )), |  | ||||||
|                             typedef.meta, |                             typedef.meta, | ||||||
|                         ); |                         ); | ||||||
|                     } else { |                     } else { | ||||||
| @ -113,11 +107,7 @@ fn check_typedefs_for_recursion<'a, 'b>( | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl BinopDefinition { | impl BinopDefinition { | ||||||
|     fn typecheck( |     fn typecheck(&mut self, typerefs: &TypeRefs, state: &mut TypecheckPassState) -> Result<TypeKind, ErrorKind> { | ||||||
|         &mut self, |  | ||||||
|         typerefs: &TypeRefs, |  | ||||||
|         state: &mut TypecheckPassState, |  | ||||||
|     ) -> Result<TypeKind, ErrorKind> { |  | ||||||
|         for param in vec![&self.lhs, &self.rhs] { |         for param in vec![&self.lhs, &self.rhs] { | ||||||
|             let param_t = state.or_else( |             let param_t = state.or_else( | ||||||
|                 param.1.assert_known(typerefs, state), |                 param.1.assert_known(typerefs, state), | ||||||
| @ -141,29 +131,21 @@ impl BinopDefinition { | |||||||
|         let return_type = self.return_type.clone().assert_known(typerefs, state)?; |         let return_type = self.return_type.clone().assert_known(typerefs, state)?; | ||||||
| 
 | 
 | ||||||
|         state.scope.return_type_hint = Some(self.return_type.clone()); |         state.scope.return_type_hint = Some(self.return_type.clone()); | ||||||
|         let inferred = |         let inferred = self | ||||||
|             self.fn_kind |             .fn_kind | ||||||
|             .typecheck(&typerefs, &mut state.inner(), Some(return_type.clone())); |             .typecheck(&typerefs, &mut state.inner(), Some(return_type.clone())); | ||||||
| 
 | 
 | ||||||
|         match inferred { |         match inferred { | ||||||
|             Ok(t) => return_type |             Ok(t) => return_type | ||||||
|                 .narrow_into(&t.1) |                 .narrow_into(&t.1) | ||||||
|                 .or(Err(ErrorKind::ReturnTypeMismatch(return_type, t.1))), |                 .or(Err(ErrorKind::ReturnTypeMismatch(return_type, t.1))), | ||||||
|             Err(e) => Ok(state.or_else( |             Err(e) => Ok(state.or_else(Err(e), return_type, self.block_meta().unwrap_or(self.signature()))), | ||||||
|                 Err(e), |  | ||||||
|                 return_type, |  | ||||||
|                 self.block_meta().unwrap_or(self.signature()), |  | ||||||
|             )), |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl FunctionDefinition { | impl FunctionDefinition { | ||||||
|     fn typecheck( |     fn typecheck(&mut self, typerefs: &TypeRefs, state: &mut TypecheckPassState) -> Result<TypeKind, ErrorKind> { | ||||||
|         &mut self, |  | ||||||
|         typerefs: &TypeRefs, |  | ||||||
|         state: &mut TypecheckPassState, |  | ||||||
|     ) -> Result<TypeKind, ErrorKind> { |  | ||||||
|         for param in &self.parameters { |         for param in &self.parameters { | ||||||
|             let param_t = state.or_else( |             let param_t = state.or_else( | ||||||
|                 param.1.assert_known(typerefs, state), |                 param.1.assert_known(typerefs, state), | ||||||
| @ -185,9 +167,7 @@ impl FunctionDefinition { | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         let return_type = self.return_type.clone().assert_known(typerefs, state)?; |         let return_type = self.return_type.clone().assert_known(typerefs, state)?; | ||||||
|         let inferred = self |         let inferred = self.kind.typecheck(typerefs, state, Some(self.return_type.clone())); | ||||||
|             .kind |  | ||||||
|             .typecheck(typerefs, state, Some(self.return_type.clone())); |  | ||||||
| 
 | 
 | ||||||
|         match inferred { |         match inferred { | ||||||
|             Ok(t) => return_type |             Ok(t) => return_type | ||||||
| @ -210,12 +190,8 @@ impl FunctionDefinitionKind { | |||||||
|                 state.scope.return_type_hint = hint.clone(); |                 state.scope.return_type_hint = hint.clone(); | ||||||
|                 block.typecheck(&mut state.inner(), &typerefs, hint.as_ref()) |                 block.typecheck(&mut state.inner(), &typerefs, hint.as_ref()) | ||||||
|             } |             } | ||||||
|             FunctionDefinitionKind::Extern(_) => { |             FunctionDefinitionKind::Extern(_) => Ok((ReturnKind::Soft, TypeKind::Vague(Vague::Unknown))), | ||||||
|                 Ok((ReturnKind::Soft, TypeKind::Vague(Vague::Unknown))) |             FunctionDefinitionKind::Intrinsic(..) => Ok((ReturnKind::Soft, TypeKind::Vague(Vague::Unknown))), | ||||||
|             } |  | ||||||
|             FunctionDefinitionKind::Intrinsic(..) => { |  | ||||||
|                 Ok((ReturnKind::Soft, TypeKind::Vague(Vague::Unknown))) |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -293,9 +269,7 @@ impl Block { | |||||||
|                                 mutable: *mutable, |                                 mutable: *mutable, | ||||||
|                             }, |                             }, | ||||||
|                         ) |                         ) | ||||||
|                         .or(Err(ErrorKind::VariableAlreadyDefined( |                         .or(Err(ErrorKind::VariableAlreadyDefined(variable_reference.1.clone()))); | ||||||
|                             variable_reference.1.clone(), |  | ||||||
|                         ))); |  | ||||||
|                     state.ok(res, variable_reference.2); |                     state.ok(res, variable_reference.2); | ||||||
|                     None |                     None | ||||||
|                 } |                 } | ||||||
| @ -344,26 +318,16 @@ impl Block { | |||||||
|                 StmtKind::Expression(expression) => { |                 StmtKind::Expression(expression) => { | ||||||
|                     let res = expression.typecheck(&mut state, &typerefs, None); |                     let res = expression.typecheck(&mut state, &typerefs, None); | ||||||
|                     state.or_else(res, TypeKind::Void, expression.1); |                     state.or_else(res, TypeKind::Void, expression.1); | ||||||
|                     if let Ok((kind, _)) = |                     if let Ok((kind, _)) = expression.return_type(typerefs, state.module_id.unwrap()) { | ||||||
|                         expression.return_type(typerefs, state.module_id.unwrap()) |  | ||||||
|                     { |  | ||||||
|                         Some((kind, expression)) |                         Some((kind, expression)) | ||||||
|                     } else { |                     } else { | ||||||
|                         None |                         None | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 StmtKind::While(WhileStatement { |                 StmtKind::While(WhileStatement { condition, block, meta }) => { | ||||||
|                     condition, |                     let condition_ty = condition.typecheck(&mut state, typerefs, Some(&TypeKind::Bool))?; | ||||||
|                     block, |  | ||||||
|                     meta, |  | ||||||
|                 }) => { |  | ||||||
|                     let condition_ty = |  | ||||||
|                         condition.typecheck(&mut state, typerefs, Some(&TypeKind::Bool))?; |  | ||||||
|                     if condition_ty.assert_known(typerefs, &state)? != TypeKind::Bool { |                     if condition_ty.assert_known(typerefs, &state)? != TypeKind::Bool { | ||||||
|                         state.note_errors( |                         state.note_errors(&vec![ErrorKind::TypesIncompatible(condition_ty, TypeKind::Bool)], *meta); | ||||||
|                             &vec![ErrorKind::TypesIncompatible(condition_ty, TypeKind::Bool)], |  | ||||||
|                             *meta, |  | ||||||
|                         ); |  | ||||||
|                     } |                     } | ||||||
| 
 | 
 | ||||||
|                     block.typecheck(&mut state, typerefs, None)?; |                     block.typecheck(&mut state, typerefs, None)?; | ||||||
| @ -453,93 +417,23 @@ impl Expression { | |||||||
|                 let rhs_res = rhs.typecheck(state, &typerefs, None); |                 let rhs_res = rhs.typecheck(state, &typerefs, None); | ||||||
|                 let rhs_type = state.or_else(rhs_res, TypeKind::Vague(Vague::Unknown), rhs.1); |                 let rhs_type = state.or_else(rhs_res, TypeKind::Vague(Vague::Unknown), rhs.1); | ||||||
| 
 | 
 | ||||||
|                 if let Some(binop) = state |                 if let Some(binop) = typerefs | ||||||
|                     .scope |                     .binop_types | ||||||
|                     .binops |  | ||||||
|                     .find(&pass::ScopeBinopKey { |                     .find(&pass::ScopeBinopKey { | ||||||
|                         params: (lhs_type.clone(), rhs_type.clone()), |                         params: (lhs_type.clone(), rhs_type.clone()), | ||||||
|                         operator: *op, |                         operator: *op, | ||||||
|                     }) |                     }) | ||||||
|                     .map(|v| (v.1.clone())) |                     .map(|v| (v.1.clone())) | ||||||
|                 { |                 { | ||||||
|                     dbg!(&lhs, &rhs); |  | ||||||
|                     dbg!(&lhs_type.resolve_ref(typerefs)); |  | ||||||
|                     dbg!(&rhs_type.resolve_ref(typerefs)); |  | ||||||
|                     lhs.typecheck(state, &typerefs, Some(&binop.hands.0))?; |                     lhs.typecheck(state, &typerefs, Some(&binop.hands.0))?; | ||||||
|                     rhs.typecheck(state, &typerefs, Some(&binop.hands.1))?; |                     rhs.typecheck(state, &typerefs, Some(&binop.hands.1))?; | ||||||
|                     Ok(binop.narrow(&lhs_type, &rhs_type).unwrap().2) |                     Ok(binop.narrow(&lhs_type, &rhs_type).unwrap().2) | ||||||
|                 } else { |                 } else { | ||||||
|                     Err(ErrorKind::InvalidBinop(*op, lhs_type, rhs_type)) |                     dbg!(&op, &lhs, &rhs); | ||||||
|  |                     dbg!(&lhs_type); | ||||||
|  |                     dbg!(&rhs_type); | ||||||
|  |                     panic!() | ||||||
|                 } |                 } | ||||||
| 
 |  | ||||||
|                 // 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::narrow_to_binop(&lhs_type, &rhs_type, binop)
 |  | ||||||
|                 //             {
 |  | ||||||
|                 //                 break Some(binop);
 |  | ||||||
|                 //             }
 |  | ||||||
|                 //         } else {
 |  | ||||||
|                 //             continue;
 |  | ||||||
|                 //         }
 |  | ||||||
|                 //     }
 |  | ||||||
|                 //     if let Some(_) = TypeKind::narrow_to_binop(&lhs_type, &rhs_type, binop) {
 |  | ||||||
|                 //         break Some(binop);
 |  | ||||||
|                 //     }
 |  | ||||||
|                 // };
 |  | ||||||
| 
 |  | ||||||
|                 // if let Some(operator) = operator {
 |  | ||||||
|                 //     // Re-typecheck with found operator hints
 |  | ||||||
|                 //     let (lhs_ty, rhs_ty) = TypeKind::try_collapse_two(
 |  | ||||||
|                 //         (&lhs_type, &rhs_type),
 |  | ||||||
|                 //         (&operator.hands.0, &operator.hands.1),
 |  | ||||||
|                 //     )
 |  | ||||||
|                 //     .unwrap();
 |  | ||||||
|                 //     let lhs_res = lhs.typecheck(state, &typerefs, Some(&lhs_ty));
 |  | ||||||
|                 //     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.clone())
 |  | ||||||
|                 // } else {
 |  | ||||||
|                 //     // Re-typecheck with typical everyday binop
 |  | ||||||
|                 //     let lhs_res = lhs.typecheck(
 |  | ||||||
|                 //         state,
 |  | ||||||
|                 //         &typerefs,
 |  | ||||||
|                 //         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));
 |  | ||||||
|                 //     let rhs_type = state.or_else(rhs_res, TypeKind::Vague(Vague::Unknown), rhs.1);
 |  | ||||||
| 
 |  | ||||||
|                 //     let both_t = lhs_type.narrow_into(&rhs_type)?;
 |  | ||||||
| 
 |  | ||||||
|                 //     if *op == BinaryOperator::Minus && !lhs_type.signed() {
 |  | ||||||
|                 //         if let (Some(lhs_val), Some(rhs_val)) = (lhs.num_value()?, rhs.num_value()?)
 |  | ||||||
|                 //         {
 |  | ||||||
|                 //             if lhs_val < rhs_val {
 |  | ||||||
|                 //                 return Err(ErrorKind::NegativeUnsignedValue(lhs_type));
 |  | ||||||
|                 //             }
 |  | ||||||
|                 //         }
 |  | ||||||
|                 //     }
 |  | ||||||
| 
 |  | ||||||
|                 //     if let Some(collapsed) = state.ok(rhs_type.narrow_into(&rhs_type), self.1) {
 |  | ||||||
|                 //         // Try to coerce both sides again with collapsed type
 |  | ||||||
|                 //         lhs.typecheck(state, &typerefs, Some(&collapsed)).ok();
 |  | ||||||
|                 //         rhs.typecheck(state, &typerefs, Some(&collapsed)).ok();
 |  | ||||||
|                 //     }
 |  | ||||||
| 
 |  | ||||||
|                 //     both_t
 |  | ||||||
|                 //         .simple_binop_type(op)
 |  | ||||||
|                 //         .ok_or(ErrorKind::InvalidBinop(*op, lhs_type, rhs_type))
 |  | ||||||
|                 // }
 |  | ||||||
|             } |             } | ||||||
|             ExprKind::FunctionCall(function_call) => { |             ExprKind::FunctionCall(function_call) => { | ||||||
|                 let true_function = state |                 let true_function = state | ||||||
| @ -571,21 +465,16 @@ impl Expression { | |||||||
|                         .into_iter() |                         .into_iter() | ||||||
|                         .chain(iter::repeat(TypeKind::Vague(Vague::Unknown))); |                         .chain(iter::repeat(TypeKind::Vague(Vague::Unknown))); | ||||||
| 
 | 
 | ||||||
|                     for (param, true_param_t) in |                     for (param, true_param_t) in function_call.parameters.iter_mut().zip(true_params_iter) { | ||||||
|                         function_call.parameters.iter_mut().zip(true_params_iter) |  | ||||||
|                     { |  | ||||||
|                         // Typecheck every param separately
 |                         // Typecheck every param separately
 | ||||||
|                         let param_res = param.typecheck(state, &typerefs, Some(&true_param_t)); |                         let param_res = param.typecheck(state, &typerefs, Some(&true_param_t)); | ||||||
|                         let param_t = |                         let param_t = state.or_else(param_res, TypeKind::Vague(Vague::Unknown), param.1); | ||||||
|                             state.or_else(param_res, TypeKind::Vague(Vague::Unknown), param.1); |  | ||||||
|                         state.ok(param_t.narrow_into(&true_param_t), param.1); |                         state.ok(param_t.narrow_into(&true_param_t), param.1); | ||||||
|                     } |                     } | ||||||
| 
 | 
 | ||||||
|                     // Make sure function return type is the same as the claimed
 |                     // Make sure function return type is the same as the claimed
 | ||||||
|                     // return type
 |                     // return type
 | ||||||
|                     let ret_t = f |                     let ret_t = f.ret.narrow_into(&function_call.return_type.resolve_ref(typerefs))?; | ||||||
|                         .ret |  | ||||||
|                         .narrow_into(&function_call.return_type.resolve_ref(typerefs))?; |  | ||||||
|                     // Update typing to be more accurate
 |                     // Update typing to be more accurate
 | ||||||
|                     function_call.return_type = ret_t.clone(); |                     function_call.return_type = ret_t.clone(); | ||||||
|                     Ok(ret_t.resolve_ref(typerefs)) |                     Ok(ret_t.resolve_ref(typerefs)) | ||||||
| @ -604,8 +493,7 @@ impl Expression { | |||||||
|                 let then_ret_t = state.or_else(then_res, TypeKind::Vague(Vague::Unknown), lhs.1); |                 let then_ret_t = state.or_else(then_res, TypeKind::Vague(Vague::Unknown), lhs.1); | ||||||
|                 let else_ret_t = if let Some(else_expr) = rhs.as_mut() { |                 let else_ret_t = if let Some(else_expr) = rhs.as_mut() { | ||||||
|                     let res = else_expr.typecheck(state, &typerefs, hint_t); |                     let res = else_expr.typecheck(state, &typerefs, hint_t); | ||||||
|                     let else_ret_t = |                     let else_ret_t = state.or_else(res, TypeKind::Vague(Vague::Unknown), else_expr.1); | ||||||
|                         state.or_else(res, TypeKind::Vague(Vague::Unknown), else_expr.1); |  | ||||||
| 
 | 
 | ||||||
|                     else_ret_t |                     else_ret_t | ||||||
|                 } else { |                 } else { | ||||||
| @ -682,10 +570,7 @@ impl Expression { | |||||||
|                             for other in iter { |                             for other in iter { | ||||||
|                                 state.ok(first.narrow_into(other), self.1); |                                 state.ok(first.narrow_into(other), self.1); | ||||||
|                             } |                             } | ||||||
|                             Ok(TypeKind::Array( |                             Ok(TypeKind::Array(Box::new(first.clone()), expressions.len() as u64)) | ||||||
|                                 Box::new(first.clone()), |  | ||||||
|                                 expressions.len() as u64, |  | ||||||
|                             )) |  | ||||||
|                         } else { |                         } else { | ||||||
|                             Ok(TypeKind::Array(Box::new(TypeKind::Void), 0)) |                             Ok(TypeKind::Array(Box::new(TypeKind::Void), 0)) | ||||||
|                         } |                         } | ||||||
| @ -705,8 +590,7 @@ impl Expression { | |||||||
| 
 | 
 | ||||||
|                 // Typecheck expression
 |                 // Typecheck expression
 | ||||||
|                 let expr_res = expression.typecheck(state, typerefs, Some(&expected_ty)); |                 let expr_res = expression.typecheck(state, typerefs, Some(&expected_ty)); | ||||||
|                 let expr_ty = |                 let expr_ty = state.or_else(expr_res, TypeKind::Vague(Vague::Unknown), expression.1); | ||||||
|                     state.or_else(expr_res, TypeKind::Vague(Vague::Unknown), expression.1); |  | ||||||
| 
 | 
 | ||||||
|                 if let TypeKind::CustomType(key) = expr_ty { |                 if let TypeKind::CustomType(key) = expr_ty { | ||||||
|                     let struct_type = state |                     let struct_type = state | ||||||
| @ -742,18 +626,14 @@ impl Expression { | |||||||
|                     let expected_ty = state.or_else( |                     let expected_ty = state.or_else( | ||||||
|                         struct_def |                         struct_def | ||||||
|                             .get_field_ty(field_name) |                             .get_field_ty(field_name) | ||||||
|                             .ok_or(ErrorKind::NoSuchField(format!( |                             .ok_or(ErrorKind::NoSuchField(format!("{}.{}", struct_name, field_name))), | ||||||
|                                 "{}.{}", |  | ||||||
|                                 struct_name, field_name |  | ||||||
|                             ))), |  | ||||||
|                         &TypeKind::Vague(VagueType::Unknown), |                         &TypeKind::Vague(VagueType::Unknown), | ||||||
|                         field_expr.1, |                         field_expr.1, | ||||||
|                     ); |                     ); | ||||||
| 
 | 
 | ||||||
|                     // Typecheck the actual expression
 |                     // Typecheck the actual expression
 | ||||||
|                     let expr_res = field_expr.typecheck(state, typerefs, Some(expected_ty)); |                     let expr_res = field_expr.typecheck(state, typerefs, Some(expected_ty)); | ||||||
|                     let expr_ty = |                     let expr_ty = state.or_else(expr_res, TypeKind::Vague(Vague::Unknown), field_expr.1); | ||||||
|                         state.or_else(expr_res, TypeKind::Vague(Vague::Unknown), field_expr.1); |  | ||||||
| 
 | 
 | ||||||
|                     // Make sure both are the same type, report error if not
 |                     // Make sure both are the same type, report error if not
 | ||||||
|                     state.ok(expr_ty.narrow_into(&expr_ty), field_expr.1); |                     state.ok(expr_ty.narrow_into(&expr_ty), field_expr.1); | ||||||
| @ -829,7 +709,6 @@ impl Literal { | |||||||
|     /// Try to coerce this literal, ie. convert it to a more specific type in
 |     /// Try to coerce this literal, ie. convert it to a more specific type in
 | ||||||
|     /// regards to the given hint if any.
 |     /// regards to the given hint if any.
 | ||||||
|     fn try_coerce(self, hint: Option<TypeKind>) -> Result<Self, ErrorKind> { |     fn try_coerce(self, hint: Option<TypeKind>) -> Result<Self, ErrorKind> { | ||||||
|         dbg!(&self, &hint); |  | ||||||
|         if let Some(hint) = &hint { |         if let Some(hint) = &hint { | ||||||
|             use Literal as L; |             use Literal as L; | ||||||
|             use VagueLiteral as VagueL; |             use VagueLiteral as VagueL; | ||||||
|  | |||||||
| @ -12,9 +12,8 @@ use std::{ | |||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     mir::{ |     mir::{ | ||||||
|         BinopDefinition, Block, CustomTypeKey, ExprKind, Expression, FunctionDefinition, |         BinopDefinition, Block, CustomTypeKey, ExprKind, Expression, FunctionDefinition, FunctionDefinitionKind, | ||||||
|         FunctionDefinitionKind, IfExpression, Module, ReturnKind, StmtKind, TypeKind, |         IfExpression, Module, ReturnKind, StmtKind, TypeKind, WhileStatement, | ||||||
|         WhileStatement, |  | ||||||
|     }, |     }, | ||||||
|     util::try_all, |     util::try_all, | ||||||
| }; | }; | ||||||
| @ -46,10 +45,7 @@ impl<'t> Pass for TypeInference<'t> { | |||||||
|         for function in &mut module.functions { |         for function in &mut module.functions { | ||||||
|             if let Some(kind) = seen_functions.get(&function.name) { |             if let Some(kind) = seen_functions.get(&function.name) { | ||||||
|                 state.note_errors( |                 state.note_errors( | ||||||
|                     &vec![ErrorKind::FunctionAlreadyDefined( |                     &vec![ErrorKind::FunctionAlreadyDefined(function.name.clone(), *kind)], | ||||||
|                         function.name.clone(), |  | ||||||
|                         *kind, |  | ||||||
|                     )], |  | ||||||
|                     function.signature(), |                     function.signature(), | ||||||
|                 ); |                 ); | ||||||
|             } else { |             } else { | ||||||
| @ -70,8 +66,7 @@ impl<'t> Pass for TypeInference<'t> { | |||||||
|                 params: (binop.lhs.1.clone(), binop.rhs.1.clone()), |                 params: (binop.lhs.1.clone(), binop.rhs.1.clone()), | ||||||
|                 operator: binop.op, |                 operator: binop.op, | ||||||
|             }; |             }; | ||||||
|             if seen_binops.contains(&binop_key) |             if seen_binops.contains(&binop_key) || (binop.lhs == binop.rhs && binop.lhs.1.category().is_simple_maths()) | ||||||
|                 || (binop.lhs == binop.rhs && binop.lhs.1.category().is_simple_maths()) |  | ||||||
|             { |             { | ||||||
|                 state.note_errors( |                 state.note_errors( | ||||||
|                     &vec![ErrorKind::BinaryOpAlreadyDefined( |                     &vec![ErrorKind::BinaryOpAlreadyDefined( | ||||||
| @ -100,18 +95,10 @@ impl<'t> Pass for TypeInference<'t> { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl BinopDefinition { | impl BinopDefinition { | ||||||
|     fn infer_types( |     fn infer_types(&mut self, type_refs: &TypeRefs, state: &mut TypecheckPassState) -> Result<(), ErrorKind> { | ||||||
|         &mut self, |  | ||||||
|         type_refs: &TypeRefs, |  | ||||||
|         state: &mut TypecheckPassState, |  | ||||||
|     ) -> Result<(), ErrorKind> { |  | ||||||
|         let scope_hints = ScopeTypeRefs::from(type_refs); |         let scope_hints = ScopeTypeRefs::from(type_refs); | ||||||
| 
 | 
 | ||||||
|         let lhs_ty = state.or_else( |         let lhs_ty = state.or_else(self.lhs.1.assert_unvague(), Vague(Unknown), self.signature()); | ||||||
|             self.lhs.1.assert_unvague(), |  | ||||||
|             Vague(Unknown), |  | ||||||
|             self.signature(), |  | ||||||
|         ); |  | ||||||
|         state.ok( |         state.ok( | ||||||
|             scope_hints |             scope_hints | ||||||
|                 .new_var(self.lhs.0.clone(), false, &lhs_ty) |                 .new_var(self.lhs.0.clone(), false, &lhs_ty) | ||||||
| @ -119,11 +106,7 @@ impl BinopDefinition { | |||||||
|             self.signature(), |             self.signature(), | ||||||
|         ); |         ); | ||||||
| 
 | 
 | ||||||
|         let rhs_ty = state.or_else( |         let rhs_ty = state.or_else(self.rhs.1.assert_unvague(), Vague(Unknown), self.signature()); | ||||||
|             self.rhs.1.assert_unvague(), |  | ||||||
|             Vague(Unknown), |  | ||||||
|             self.signature(), |  | ||||||
|         ); |  | ||||||
| 
 | 
 | ||||||
|         state.ok( |         state.ok( | ||||||
|             scope_hints |             scope_hints | ||||||
| @ -132,8 +115,8 @@ impl BinopDefinition { | |||||||
|             self.signature(), |             self.signature(), | ||||||
|         ); |         ); | ||||||
| 
 | 
 | ||||||
|         let ret_ty = |         let ret_ty = self | ||||||
|             self.fn_kind |             .fn_kind | ||||||
|             .infer_types(state, &scope_hints, Some(self.return_type.clone()))?; |             .infer_types(state, &scope_hints, Some(self.return_type.clone()))?; | ||||||
|         if let Some(mut ret_ty) = ret_ty { |         if let Some(mut ret_ty) = ret_ty { | ||||||
|             ret_ty.narrow(&scope_hints.from_type(&self.return_type).unwrap()); |             ret_ty.narrow(&scope_hints.from_type(&self.return_type).unwrap()); | ||||||
| @ -144,11 +127,7 @@ impl BinopDefinition { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl FunctionDefinition { | impl FunctionDefinition { | ||||||
|     fn infer_types( |     fn infer_types(&mut self, type_refs: &TypeRefs, state: &mut TypecheckPassState) -> Result<(), ErrorKind> { | ||||||
|         &mut self, |  | ||||||
|         type_refs: &TypeRefs, |  | ||||||
|         state: &mut TypecheckPassState, |  | ||||||
|     ) -> Result<(), ErrorKind> { |  | ||||||
|         let scope_refs = ScopeTypeRefs::from(type_refs); |         let scope_refs = ScopeTypeRefs::from(type_refs); | ||||||
|         for param in &self.parameters { |         for param in &self.parameters { | ||||||
|             let param_t = state.or_else(param.1.assert_unvague(), Vague(Unknown), self.signature()); |             let param_t = state.or_else(param.1.assert_unvague(), Vague(Unknown), self.signature()); | ||||||
| @ -221,8 +200,7 @@ impl Block { | |||||||
|             match &mut statement.0 { |             match &mut statement.0 { | ||||||
|                 StmtKind::Let(var, mutable, expr) => { |                 StmtKind::Let(var, mutable, expr) => { | ||||||
|                     // Get the TypeRef for this variable declaration
 |                     // Get the TypeRef for this variable declaration
 | ||||||
|                     let mut var_ref = |                     let mut var_ref = state.ok(inner_refs.new_var(var.1.clone(), *mutable, &var.0), var.2); | ||||||
|                         state.ok(inner_refs.new_var(var.1.clone(), *mutable, &var.0), var.2); |  | ||||||
| 
 | 
 | ||||||
|                     // If ok, update the MIR type to this TypeRef
 |                     // If ok, update the MIR type to this TypeRef
 | ||||||
|                     if let Some(var_ref) = &var_ref { |                     if let Some(var_ref) = &var_ref { | ||||||
| @ -235,9 +213,7 @@ impl Block { | |||||||
| 
 | 
 | ||||||
|                     // Try to narrow the variable type declaration with the
 |                     // Try to narrow the variable type declaration with the
 | ||||||
|                     // expression
 |                     // expression
 | ||||||
|                     if let (Some(var_ref), Some(expr_ty_ref)) = |                     if let (Some(var_ref), Some(expr_ty_ref)) = (var_ref.as_mut(), expr_ty_ref.as_mut()) { | ||||||
|                         (var_ref.as_mut(), expr_ty_ref.as_mut()) |  | ||||||
|                     { |  | ||||||
|                         var_ref.narrow(&expr_ty_ref); |                         var_ref.narrow(&expr_ty_ref); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
| @ -260,9 +236,7 @@ impl Block { | |||||||
|                     let expr_res = expr.infer_types(&mut state, &inner_refs); |                     let expr_res = expr.infer_types(&mut state, &inner_refs); | ||||||
|                     state.ok(expr_res, expr.1); |                     state.ok(expr_res, expr.1); | ||||||
|                 } |                 } | ||||||
|                 StmtKind::While(WhileStatement { |                 StmtKind::While(WhileStatement { condition, block, .. }) => { | ||||||
|                     condition, block, .. |  | ||||||
|                 }) => { |  | ||||||
|                     condition.infer_types(&mut state, &inner_refs)?; |                     condition.infer_types(&mut state, &inner_refs)?; | ||||||
|                     block.infer_types(&mut state, &inner_refs)?; |                     block.infer_types(&mut state, &inner_refs)?; | ||||||
|                 } |                 } | ||||||
| @ -336,11 +310,7 @@ impl Expression { | |||||||
|                     rhs_ref.narrow(&type_refs.from_type(&widened_rhs).unwrap()); |                     rhs_ref.narrow(&type_refs.from_type(&widened_rhs).unwrap()); | ||||||
|                     Ok(type_refs.from_binop(*op, &lhs_ref, &rhs_ref)) |                     Ok(type_refs.from_binop(*op, &lhs_ref, &rhs_ref)) | ||||||
|                 } else { |                 } else { | ||||||
|                     Err(ErrorKind::InvalidBinop( |                     panic!(); | ||||||
|                         *op, |  | ||||||
|                         lhs_ref.resolve_deep().unwrap(), |  | ||||||
|                         rhs_ref.resolve_deep().unwrap(), |  | ||||||
|                     )) |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             ExprKind::FunctionCall(function_call) => { |             ExprKind::FunctionCall(function_call) => { | ||||||
| @ -357,9 +327,7 @@ impl Expression { | |||||||
|                 // many were provided)
 |                 // many were provided)
 | ||||||
|                 let true_params_iter = fn_call.params.iter().chain(iter::repeat(&Vague(Unknown))); |                 let true_params_iter = fn_call.params.iter().chain(iter::repeat(&Vague(Unknown))); | ||||||
| 
 | 
 | ||||||
|                 for (param_expr, param_t) in |                 for (param_expr, param_t) in function_call.parameters.iter_mut().zip(true_params_iter) { | ||||||
|                     function_call.parameters.iter_mut().zip(true_params_iter) |  | ||||||
|                 { |  | ||||||
|                     let expr_res = param_expr.infer_types(state, type_refs); |                     let expr_res = param_expr.infer_types(state, type_refs); | ||||||
|                     if let Some(mut param_ref) = state.ok(expr_res, param_expr.1) { |                     if let Some(mut param_ref) = state.ok(expr_res, param_expr.1) { | ||||||
|                         param_ref.narrow(&mut type_refs.from_type(param_t).unwrap()); |                         param_ref.narrow(&mut type_refs.from_type(param_t).unwrap()); | ||||||
| @ -390,9 +358,7 @@ impl Expression { | |||||||
| 
 | 
 | ||||||
|                     // Narrow LHS to the same type as RHS and return it's return type
 |                     // Narrow LHS to the same type as RHS and return it's return type
 | ||||||
|                     if let (Some(mut lhs_hints), Some(mut rhs_hints)) = (lhs_hints, rhs_hints) { |                     if let (Some(mut lhs_hints), Some(mut rhs_hints)) = (lhs_hints, rhs_hints) { | ||||||
|                         lhs_hints |                         lhs_hints.narrow(&mut rhs_hints).ok_or(ErrorKind::TypesIncompatible( | ||||||
|                             .narrow(&mut rhs_hints) |  | ||||||
|                             .ok_or(ErrorKind::TypesIncompatible( |  | ||||||
|                             lhs_hints.resolve_deep().unwrap(), |                             lhs_hints.resolve_deep().unwrap(), | ||||||
|                             rhs_hints.resolve_deep().unwrap(), |                             rhs_hints.resolve_deep().unwrap(), | ||||||
|                         )) |                         )) | ||||||
| @ -451,15 +417,10 @@ impl Expression { | |||||||
|                             } |                             } | ||||||
| 
 | 
 | ||||||
|                             Ok(type_refs |                             Ok(type_refs | ||||||
|                                 .from_type(&Array( |                                 .from_type(&Array(Box::new(first.as_type()), expressions.len() as u64)) | ||||||
|                                     Box::new(first.as_type()), |  | ||||||
|                                     expressions.len() as u64, |  | ||||||
|                                 )) |  | ||||||
|                                 .unwrap()) |                                 .unwrap()) | ||||||
|                         } else { |                         } else { | ||||||
|                             Ok(type_refs |                             Ok(type_refs.from_type(&Array(Box::new(TypeKind::Void), 0)).unwrap()) | ||||||
|                                 .from_type(&Array(Box::new(TypeKind::Void), 0)) |  | ||||||
|                                 .unwrap()) |  | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                     Err(errors) => { |                     Err(errors) => { | ||||||
| @ -503,10 +464,7 @@ impl Expression { | |||||||
|                 let expected_struct_ty = state |                 let expected_struct_ty = state | ||||||
|                     .scope |                     .scope | ||||||
|                     .get_struct_type(&type_key) |                     .get_struct_type(&type_key) | ||||||
|                     .ok_or(ErrorKind::NoSuchType( |                     .ok_or(ErrorKind::NoSuchType(struct_name.clone(), state.module_id.unwrap()))? | ||||||
|                         struct_name.clone(), |  | ||||||
|                         state.module_id.unwrap(), |  | ||||||
|                     ))? |  | ||||||
|                     .clone(); |                     .clone(); | ||||||
|                 for field in fields { |                 for field in fields { | ||||||
|                     if let Some(expected_field_ty) = expected_struct_ty.get_field_ty(&field.0) { |                     if let Some(expected_field_ty) = expected_struct_ty.get_field_ty(&field.0) { | ||||||
| @ -516,17 +474,12 @@ impl Expression { | |||||||
|                         } |                         } | ||||||
|                     } else { |                     } else { | ||||||
|                         state.ok::<_, Infallible>( |                         state.ok::<_, Infallible>( | ||||||
|                             Err(ErrorKind::NoSuchField(format!( |                             Err(ErrorKind::NoSuchField(format!("{}.{}", struct_name, field.0))), | ||||||
|                                 "{}.{}", |  | ||||||
|                                 struct_name, field.0 |  | ||||||
|                             ))), |  | ||||||
|                             field.1 .1, |                             field.1 .1, | ||||||
|                         ); |                         ); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 Ok(type_refs |                 Ok(type_refs.from_type(&TypeKind::CustomType(type_key.clone())).unwrap()) | ||||||
|                     .from_type(&TypeKind::CustomType(type_key.clone())) |  | ||||||
|                     .unwrap()) |  | ||||||
|             } |             } | ||||||
|             ExprKind::Borrow(var, mutable) => { |             ExprKind::Borrow(var, mutable) => { | ||||||
|                 // Find variable type
 |                 // Find variable type
 | ||||||
|  | |||||||
| @ -15,10 +15,7 @@ use super::{ | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #[derive(Clone)] | #[derive(Clone)] | ||||||
| pub struct TypeRef<'scope>( | pub struct TypeRef<'scope>(pub(super) TypeIdRef, pub(super) &'scope ScopeTypeRefs<'scope>); | ||||||
|     pub(super) TypeIdRef, |  | ||||||
|     pub(super) &'scope ScopeTypeRefs<'scope>, |  | ||||||
| ); |  | ||||||
| 
 | 
 | ||||||
| impl<'scope> TypeRef<'scope> { | impl<'scope> TypeRef<'scope> { | ||||||
|     /// Resolve current type in a weak manner, not resolving any Arrays or
 |     /// Resolve current type in a weak manner, not resolving any Arrays or
 | ||||||
| @ -99,7 +96,7 @@ pub struct TypeRefs { | |||||||
|     pub(super) hints: RefCell<Vec<TypeRefKind>>, |     pub(super) hints: RefCell<Vec<TypeRefKind>>, | ||||||
|     /// Indirect ID-references, referring to hints-vec
 |     /// Indirect ID-references, referring to hints-vec
 | ||||||
|     pub(super) type_refs: RefCell<Vec<TypeIdRef>>, |     pub(super) type_refs: RefCell<Vec<TypeIdRef>>, | ||||||
|     binop_types: BinopMap, |     pub(super) binop_types: BinopMap, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl std::fmt::Display for TypeRefs { | impl std::fmt::Display for TypeRefs { | ||||||
| @ -132,9 +129,7 @@ impl TypeRefs { | |||||||
|         let idx = self.hints.borrow().len(); |         let idx = self.hints.borrow().len(); | ||||||
|         let typecell = Rc::new(RefCell::new(idx)); |         let typecell = Rc::new(RefCell::new(idx)); | ||||||
|         self.type_refs.borrow_mut().push(typecell.clone()); |         self.type_refs.borrow_mut().push(typecell.clone()); | ||||||
|         self.hints |         self.hints.borrow_mut().push(TypeRefKind::Direct(ty.clone())); | ||||||
|             .borrow_mut() |  | ||||||
|             .push(TypeRefKind::Direct(ty.clone())); |  | ||||||
|         typecell |         typecell | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -183,11 +178,7 @@ impl TypeRefs { | |||||||
| 
 | 
 | ||||||
|     pub fn retrieve_wide_type(&self, idx: usize) -> Option<TypeKind> { |     pub fn retrieve_wide_type(&self, idx: usize) -> Option<TypeKind> { | ||||||
|         let inner_idx = unsafe { *self.recurse_type_ref(idx).borrow() }; |         let inner_idx = unsafe { *self.recurse_type_ref(idx).borrow() }; | ||||||
|         self.hints |         self.hints.borrow().get(inner_idx).cloned().map(|t| t.widen(self)) | ||||||
|             .borrow() |  | ||||||
|             .get(inner_idx) |  | ||||||
|             .cloned() |  | ||||||
|             .map(|t| t.widen(self)) |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -218,9 +209,7 @@ impl<'outer> ScopeTypeRefs<'outer> { | |||||||
|             return Err(ErrorKind::VariableAlreadyDefined(name)); |             return Err(ErrorKind::VariableAlreadyDefined(name)); | ||||||
|         } |         } | ||||||
|         let type_ref = self.from_type(&initial_ty).unwrap(); |         let type_ref = self.from_type(&initial_ty).unwrap(); | ||||||
|         self.variables |         self.variables.borrow_mut().insert(name, (mutable, type_ref.0.clone())); | ||||||
|             .borrow_mut() |  | ||||||
|             .insert(name, (mutable, type_ref.0.clone())); |  | ||||||
|         Ok(type_ref) |         Ok(type_ref) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -233,8 +222,7 @@ impl<'outer> ScopeTypeRefs<'outer> { | |||||||
|             TypeKind::Vague(_) => self.types.new(ty), |             TypeKind::Vague(_) => self.types.new(ty), | ||||||
|             TypeKind::Array(elem_ty, length) => { |             TypeKind::Array(elem_ty, length) => { | ||||||
|                 let elem_ty = self.from_type(elem_ty)?; |                 let elem_ty = self.from_type(elem_ty)?; | ||||||
|                 self.types |                 self.types.new(&TypeKind::Array(Box::new(elem_ty.as_type()), *length)) | ||||||
|                     .new(&TypeKind::Array(Box::new(elem_ty.as_type()), *length)) |  | ||||||
|             } |             } | ||||||
|             TypeKind::Borrow(ty, mutable) => { |             TypeKind::Borrow(ty, mutable) => { | ||||||
|                 let inner_ty = self.from_type(ty)?; |                 let inner_ty = self.from_type(ty)?; | ||||||
| @ -252,12 +240,7 @@ impl<'outer> ScopeTypeRefs<'outer> { | |||||||
|         Some(TypeRef(idx, self)) |         Some(TypeRef(idx, self)) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn from_binop( |     pub fn from_binop(&'outer self, op: BinaryOperator, lhs: &TypeRef, rhs: &TypeRef) -> TypeRef<'outer> { | ||||||
|         &'outer self, |  | ||||||
|         op: BinaryOperator, |  | ||||||
|         lhs: &TypeRef, |  | ||||||
|         rhs: &TypeRef, |  | ||||||
|     ) -> TypeRef<'outer> { |  | ||||||
|         TypeRef(self.types.binop(op, lhs, rhs), self) |         TypeRef(self.types.binop(op, lhs, rhs), self) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -276,10 +259,9 @@ impl<'outer> ScopeTypeRefs<'outer> { | |||||||
|                         .iter() |                         .iter() | ||||||
|                         .filter(|b| b.1.operator == *op && b.1.return_ty == *ty); |                         .filter(|b| b.1.operator == *op && b.1.return_ty == *ty); | ||||||
|                     for binop in binops { |                     for binop in binops { | ||||||
|                         if let (Ok(lhs_narrow), Ok(rhs_narrow)) = ( |                         if let (Ok(lhs_narrow), Ok(rhs_narrow)) = | ||||||
|                             lhs.narrow_into(&binop.1.hands.0), |                             (lhs.narrow_into(&binop.1.hands.0), rhs.narrow_into(&binop.1.hands.1)) | ||||||
|                             rhs.narrow_into(&binop.1.hands.1), |                         { | ||||||
|                         ) { |  | ||||||
|                             *lhs = lhs_narrow; |                             *lhs = lhs_narrow; | ||||||
|                             *rhs = rhs_narrow |                             *rhs = rhs_narrow | ||||||
|                         } |                         } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user