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