Fix a significant problem in how the typerefs aren't narrowed properly
This commit is contained in:
		
							parent
							
								
									63f48f7df9
								
							
						
					
					
						commit
						307137d0d9
					
				
							
								
								
									
										6
									
								
								examples/a.reid
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								examples/a.reid
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | |||||||
|  | pub fn abs(f: f32) -> f32 { | ||||||
|  |     if f < 0.0 { | ||||||
|  |         return f * (0.0 - 1.0); | ||||||
|  |     } | ||||||
|  |     return f; | ||||||
|  | } | ||||||
| @ -3,8 +3,8 @@ use std::path::PathBuf; | |||||||
| use crate::{ | use crate::{ | ||||||
|     ast::{self}, |     ast::{self}, | ||||||
|     mir::{ |     mir::{ | ||||||
|         self, CustomTypeKey, ModuleMap, NamedVariableRef, ReturnKind, SourceModuleId, StmtKind, |         self, CustomTypeKey, ModuleMap, NamedVariableRef, ReturnKind, SourceModuleId, StmtKind, StructField, | ||||||
|         StructField, StructType, WhileStatement, |         StructType, WhileStatement, | ||||||
|     }, |     }, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -162,9 +162,7 @@ impl ast::Block { | |||||||
|                     *range, |                     *range, | ||||||
|                 ), |                 ), | ||||||
|                 ast::BlockLevelStatement::Import { _i } => todo!(), |                 ast::BlockLevelStatement::Import { _i } => todo!(), | ||||||
|                 ast::BlockLevelStatement::Expression(e) => { |                 ast::BlockLevelStatement::Expression(e) => (StmtKind::Expression(e.process(module_id)), e.1), | ||||||
|                     (StmtKind::Expression(e.process(module_id)), e.1) |  | ||||||
|                 } |  | ||||||
|                 ast::BlockLevelStatement::Return(_, e) => { |                 ast::BlockLevelStatement::Return(_, e) => { | ||||||
|                     if let Some(e) = e { |                     if let Some(e) = e { | ||||||
|                         (StmtKind::Expression(e.process(module_id)), e.1) |                         (StmtKind::Expression(e.process(module_id)), e.1) | ||||||
| @ -197,11 +195,10 @@ impl ast::Block { | |||||||
|                                         counter_range.as_meta(module_id), |                                         counter_range.as_meta(module_id), | ||||||
|                                     )), |                                     )), | ||||||
|                                     Box::new(mir::Expression( |                                     Box::new(mir::Expression( | ||||||
|                                         mir::ExprKind::Literal(mir::Literal::Vague( |                                         mir::ExprKind::Literal(mir::Literal::Vague(mir::VagueLiteral::Number(1))), | ||||||
|                                             mir::VagueLiteral::Number(1), |  | ||||||
|                                         )), |  | ||||||
|                                         counter_range.as_meta(module_id), |                                         counter_range.as_meta(module_id), | ||||||
|                                     )), |                                     )), | ||||||
|  |                                     mir::TypeKind::Vague(mir::VagueType::Unknown), | ||||||
|                                 ), |                                 ), | ||||||
|                                 counter_range.as_meta(module_id), |                                 counter_range.as_meta(module_id), | ||||||
|                             ), |                             ), | ||||||
| @ -220,6 +217,7 @@ impl ast::Block { | |||||||
|                                         counter_range.as_meta(module_id), |                                         counter_range.as_meta(module_id), | ||||||
|                                     )), |                                     )), | ||||||
|                                     Box::new(end.process(module_id)), |                                     Box::new(end.process(module_id)), | ||||||
|  |                                     mir::TypeKind::Vague(mir::VagueType::Unknown), | ||||||
|                                 ), |                                 ), | ||||||
|                                 counter_range.as_meta(module_id), |                                 counter_range.as_meta(module_id), | ||||||
|                             ), |                             ), | ||||||
| @ -292,22 +290,15 @@ impl ast::Expression { | |||||||
|                 binary_operator.mir(), |                 binary_operator.mir(), | ||||||
|                 Box::new(lhs.process(module_id)), |                 Box::new(lhs.process(module_id)), | ||||||
|                 Box::new(rhs.process(module_id)), |                 Box::new(rhs.process(module_id)), | ||||||
|  |                 mir::TypeKind::Vague(mir::VagueType::Unknown), | ||||||
|             ), |             ), | ||||||
|             ast::ExpressionKind::FunctionCall(fn_call_expr) => { |             ast::ExpressionKind::FunctionCall(fn_call_expr) => mir::ExprKind::FunctionCall(mir::FunctionCall { | ||||||
|                 mir::ExprKind::FunctionCall(mir::FunctionCall { |                 name: fn_call_expr.0.clone(), | ||||||
|                     name: fn_call_expr.0.clone(), |                 return_type: mir::TypeKind::Vague(mir::VagueType::Unknown), | ||||||
|                     return_type: mir::TypeKind::Vague(mir::VagueType::Unknown), |                 parameters: fn_call_expr.1.iter().map(|e| e.process(module_id)).collect(), | ||||||
|                     parameters: fn_call_expr |                 meta: fn_call_expr.2.as_meta(module_id), | ||||||
|                         .1 |             }), | ||||||
|                         .iter() |             ast::ExpressionKind::BlockExpr(block) => mir::ExprKind::Block(block.into_mir(module_id)), | ||||||
|                         .map(|e| e.process(module_id)) |  | ||||||
|                         .collect(), |  | ||||||
|                     meta: fn_call_expr.2.as_meta(module_id), |  | ||||||
|                 }) |  | ||||||
|             } |  | ||||||
|             ast::ExpressionKind::BlockExpr(block) => { |  | ||||||
|                 mir::ExprKind::Block(block.into_mir(module_id)) |  | ||||||
|             } |  | ||||||
|             ast::ExpressionKind::IfExpr(if_expression) => { |             ast::ExpressionKind::IfExpr(if_expression) => { | ||||||
|                 let cond = if_expression.0.process(module_id); |                 let cond = if_expression.0.process(module_id); | ||||||
|                 let then_block = if_expression.1.process(module_id); |                 let then_block = if_expression.1.process(module_id); | ||||||
| @ -364,6 +355,7 @@ impl ast::Expression { | |||||||
|                         expr.1.as_meta(module_id), |                         expr.1.as_meta(module_id), | ||||||
|                     )), |                     )), | ||||||
|                     Box::new(expr.process(module_id)), |                     Box::new(expr.process(module_id)), | ||||||
|  |                     mir::TypeKind::Vague(mir::VagueType::Unknown), | ||||||
|                 ), |                 ), | ||||||
|                 ast::UnaryOperator::Minus => mir::ExprKind::BinOp( |                 ast::UnaryOperator::Minus => mir::ExprKind::BinOp( | ||||||
|                     mir::BinaryOperator::Minus, |                     mir::BinaryOperator::Minus, | ||||||
| @ -372,6 +364,7 @@ impl ast::Expression { | |||||||
|                         expr.1.as_meta(module_id), |                         expr.1.as_meta(module_id), | ||||||
|                     )), |                     )), | ||||||
|                     Box::new(expr.process(module_id)), |                     Box::new(expr.process(module_id)), | ||||||
|  |                     mir::TypeKind::Vague(mir::VagueType::Unknown), | ||||||
|                 ), |                 ), | ||||||
|             }, |             }, | ||||||
|             ast::ExpressionKind::CastTo(expression, ty) => mir::ExprKind::CastTo( |             ast::ExpressionKind::CastTo(expression, ty) => mir::ExprKind::CastTo( | ||||||
| @ -457,15 +450,11 @@ impl ast::TypeKind { | |||||||
|             ast::TypeKind::Array(type_kind, length) => { |             ast::TypeKind::Array(type_kind, length) => { | ||||||
|                 mir::TypeKind::Array(Box::new(type_kind.clone().into_mir(source_mod)), *length) |                 mir::TypeKind::Array(Box::new(type_kind.clone().into_mir(source_mod)), *length) | ||||||
|             } |             } | ||||||
|             ast::TypeKind::Custom(name) => { |             ast::TypeKind::Custom(name) => mir::TypeKind::CustomType(CustomTypeKey(name.clone(), source_mod)), | ||||||
|                 mir::TypeKind::CustomType(CustomTypeKey(name.clone(), source_mod)) |  | ||||||
|             } |  | ||||||
|             ast::TypeKind::Borrow(type_kind, mutable) => { |             ast::TypeKind::Borrow(type_kind, mutable) => { | ||||||
|                 mir::TypeKind::Borrow(Box::new(type_kind.clone().into_mir(source_mod)), *mutable) |                 mir::TypeKind::Borrow(Box::new(type_kind.clone().into_mir(source_mod)), *mutable) | ||||||
|             } |             } | ||||||
|             ast::TypeKind::Ptr(type_kind) => { |             ast::TypeKind::Ptr(type_kind) => mir::TypeKind::UserPtr(Box::new(type_kind.clone().into_mir(source_mod))), | ||||||
|                 mir::TypeKind::UserPtr(Box::new(type_kind.clone().into_mir(source_mod))) |  | ||||||
|             } |  | ||||||
|             ast::TypeKind::F16 => mir::TypeKind::F16, |             ast::TypeKind::F16 => mir::TypeKind::F16, | ||||||
|             ast::TypeKind::F32B => mir::TypeKind::F32B, |             ast::TypeKind::F32B => mir::TypeKind::F32B, | ||||||
|             ast::TypeKind::F32 => mir::TypeKind::F32, |             ast::TypeKind::F32 => mir::TypeKind::F32, | ||||||
|  | |||||||
| @ -6,8 +6,7 @@ use reid_lib::{ | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| use crate::mir::{ | use crate::mir::{ | ||||||
|     self, CustomTypeKey, FunctionCall, FunctionDefinitionKind, IfExpression, SourceModuleId, |     self, CustomTypeKey, FunctionCall, FunctionDefinitionKind, IfExpression, SourceModuleId, TypeKind, WhileStatement, | ||||||
|     TypeKind, WhileStatement, |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| @ -74,9 +73,7 @@ impl mir::FunctionDefinitionKind { | |||||||
|             mir::FunctionDefinitionKind::Intrinsic(_) => {} |             mir::FunctionDefinitionKind::Intrinsic(_) => {} | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         Allocator { |         Allocator { allocations: allocated } | ||||||
|             allocations: allocated, |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -126,9 +123,7 @@ impl mir::Statement { | |||||||
|             crate::mir::StmtKind::Expression(expression) => { |             crate::mir::StmtKind::Expression(expression) => { | ||||||
|                 allocated.extend(expression.allocate(scope)); |                 allocated.extend(expression.allocate(scope)); | ||||||
|             } |             } | ||||||
|             crate::mir::StmtKind::While(WhileStatement { |             crate::mir::StmtKind::While(WhileStatement { condition, block, .. }) => { | ||||||
|                 condition, block, .. |  | ||||||
|             }) => { |  | ||||||
|                 allocated.extend(condition.allocate(scope)); |                 allocated.extend(condition.allocate(scope)); | ||||||
|                 allocated.extend(block.allocate(scope)); |                 allocated.extend(block.allocate(scope)); | ||||||
|             } |             } | ||||||
| @ -162,7 +157,7 @@ impl mir::Expression { | |||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             crate::mir::ExprKind::Literal(_) => {} |             crate::mir::ExprKind::Literal(_) => {} | ||||||
|             crate::mir::ExprKind::BinOp(_, lhs, rhs) => { |             crate::mir::ExprKind::BinOp(_, lhs, rhs, _) => { | ||||||
|                 allocated.extend(lhs.allocate(scope)); |                 allocated.extend(lhs.allocate(scope)); | ||||||
|                 allocated.extend(rhs.allocate(scope)); |                 allocated.extend(rhs.allocate(scope)); | ||||||
|             } |             } | ||||||
|  | |||||||
| @ -5,20 +5,18 @@ use intrinsics::*; | |||||||
| use reid_lib::{ | use reid_lib::{ | ||||||
|     compile::CompiledModule, |     compile::CompiledModule, | ||||||
|     debug_information::{ |     debug_information::{ | ||||||
|         DebugFileData, DebugLocalVariable, DebugLocation, DebugMetadata, DebugRecordKind, |         DebugFileData, DebugLocalVariable, DebugLocation, DebugMetadata, DebugRecordKind, DebugSubprogramData, | ||||||
|         DebugSubprogramData, DebugSubprogramOptionals, DebugSubprogramType, DebugTypeData, |         DebugSubprogramOptionals, DebugSubprogramType, DebugTypeData, DwarfFlags, InstructionDebugRecordData, | ||||||
|         DwarfFlags, InstructionDebugRecordData, |  | ||||||
|     }, |     }, | ||||||
|     CmpPredicate, ConstValue, Context, CustomTypeKind, Function, FunctionFlags, Instr, Module, |     CmpPredicate, ConstValue, Context, CustomTypeKind, Function, FunctionFlags, Instr, Module, NamedStruct, | ||||||
|     NamedStruct, TerminatorKind as Term, Type, |     TerminatorKind as Term, Type, | ||||||
| }; | }; | ||||||
| use scope::*; | use scope::*; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     mir::{ |     mir::{ | ||||||
|         self, implement::TypeCategory, pass::ScopeBinopKey, CustomTypeKey, FunctionDefinitionKind, |         self, implement::TypeCategory, pass::ScopeBinopKey, CustomTypeKey, FunctionDefinitionKind, NamedVariableRef, | ||||||
|         NamedVariableRef, SourceModuleId, StructField, StructType, TypeDefinitionKind, TypeKind, |         SourceModuleId, StructField, StructType, TypeDefinitionKind, TypeKind, WhileStatement, | ||||||
|         WhileStatement, |  | ||||||
|     }, |     }, | ||||||
|     util::try_all, |     util::try_all, | ||||||
| }; | }; | ||||||
| @ -83,9 +81,7 @@ struct State { | |||||||
| impl State { | impl State { | ||||||
|     /// Sets should load, returning a new state
 |     /// Sets should load, returning a new state
 | ||||||
|     fn load(self, should: bool) -> State { |     fn load(self, should: bool) -> State { | ||||||
|         State { |         State { should_load: should } | ||||||
|             should_load: should, |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -235,10 +231,7 @@ impl mir::Module { | |||||||
|                             let ir_function = module.function( |                             let ir_function = module.function( | ||||||
|                                 &binop_fn_name, |                                 &binop_fn_name, | ||||||
|                                 binop.return_type.get_type(&type_values), |                                 binop.return_type.get_type(&type_values), | ||||||
|                                 vec![ |                                 vec![binop.lhs.1.get_type(&type_values), binop.rhs.1.get_type(&type_values)], | ||||||
|                                     binop.lhs.1.get_type(&type_values), |  | ||||||
|                                     binop.rhs.1.get_type(&type_values), |  | ||||||
|                                 ], |  | ||||||
|                                 FunctionFlags { |                                 FunctionFlags { | ||||||
|                                     inline: true, |                                     inline: true, | ||||||
|                                     ..Default::default() |                                     ..Default::default() | ||||||
| @ -287,9 +280,7 @@ impl mir::Module { | |||||||
|                                     &binop.return_type, |                                     &binop.return_type, | ||||||
|                                     &ir_function, |                                     &ir_function, | ||||||
|                                     match &binop.fn_kind { |                                     match &binop.fn_kind { | ||||||
|                                         FunctionDefinitionKind::Local(_, meta) => { |                                         FunctionDefinitionKind::Local(_, meta) => meta.into_debug(tokens, compile_unit), | ||||||
|                                             meta.into_debug(tokens, compile_unit) |  | ||||||
|                                         } |  | ||||||
|                                         FunctionDefinitionKind::Extern(_) => None, |                                         FunctionDefinitionKind::Extern(_) => None, | ||||||
|                                         FunctionDefinitionKind::Intrinsic(_) => None, |                                         FunctionDefinitionKind::Intrinsic(_) => None, | ||||||
|                                     }, |                                     }, | ||||||
| @ -352,9 +343,7 @@ impl mir::Module { | |||||||
|                     &mir_function.return_type, |                     &mir_function.return_type, | ||||||
|                     &function, |                     &function, | ||||||
|                     match &mir_function.kind { |                     match &mir_function.kind { | ||||||
|                         FunctionDefinitionKind::Local(..) => { |                         FunctionDefinitionKind::Local(..) => mir_function.signature().into_debug(tokens, compile_unit), | ||||||
|                             mir_function.signature().into_debug(tokens, compile_unit) |  | ||||||
|                         } |  | ||||||
|                         FunctionDefinitionKind::Extern(_) => None, |                         FunctionDefinitionKind::Extern(_) => None, | ||||||
|                         FunctionDefinitionKind::Intrinsic(_) => None, |                         FunctionDefinitionKind::Intrinsic(_) => None, | ||||||
|                     }, |                     }, | ||||||
| @ -386,13 +375,10 @@ impl FunctionDefinitionKind { | |||||||
| 
 | 
 | ||||||
|                         let fn_param_ty = &return_type.get_debug_type(&debug, scope); |                         let fn_param_ty = &return_type.get_debug_type(&debug, scope); | ||||||
| 
 | 
 | ||||||
|                         let debug_ty = |                         let debug_ty = debug.info.debug_type(DebugTypeData::Subprogram(DebugSubprogramType { | ||||||
|                             debug |                             parameters: vec![*fn_param_ty], | ||||||
|                                 .info |                             flags: DwarfFlags, | ||||||
|                                 .debug_type(DebugTypeData::Subprogram(DebugSubprogramType { |                         })); | ||||||
|                                     parameters: vec![*fn_param_ty], |  | ||||||
|                                     flags: DwarfFlags, |  | ||||||
|                                 })); |  | ||||||
| 
 | 
 | ||||||
|                         let subprogram = debug.info.subprogram(DebugSubprogramData { |                         let subprogram = debug.info.subprogram(DebugSubprogramData { | ||||||
|                             name: name.clone(), |                             name: name.clone(), | ||||||
| @ -477,9 +463,7 @@ impl FunctionDefinitionKind { | |||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 if let Some(debug) = &scope.debug { |                 if let Some(debug) = &scope.debug { | ||||||
|                     if let Some(location) = |                     if let Some(location) = &block.return_meta().into_debug(scope.tokens, debug.scope) { | ||||||
|                         &block.return_meta().into_debug(scope.tokens, debug.scope) |  | ||||||
|                     { |  | ||||||
|                         let location = debug.info.location(&debug.scope, *location); |                         let location = debug.info.location(&debug.scope, *location); | ||||||
|                         scope.block.set_terminator_location(location).unwrap(); |                         scope.block.set_terminator_location(location).unwrap(); | ||||||
|                     } |                     } | ||||||
| @ -536,11 +520,7 @@ impl mir::Block { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl mir::Statement { | impl mir::Statement { | ||||||
|     fn codegen<'ctx, 'a>( |     fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, state: &State) -> Result<Option<StackValue>, ErrorKind> { | ||||||
|         &self, |  | ||||||
|         scope: &mut Scope<'ctx, 'a>, |  | ||||||
|         state: &State, |  | ||||||
|     ) -> Result<Option<StackValue>, ErrorKind> { |  | ||||||
|         let location = scope.debug.clone().map(|d| { |         let location = scope.debug.clone().map(|d| { | ||||||
|             let location = self.1.into_debug(scope.tokens, d.scope).unwrap(); |             let location = self.1.into_debug(scope.tokens, d.scope).unwrap(); | ||||||
|             d.info.location(&d.scope, location) |             d.info.location(&d.scope, location) | ||||||
| @ -557,10 +537,7 @@ impl mir::Statement { | |||||||
| 
 | 
 | ||||||
|                 let store = scope |                 let store = scope | ||||||
|                     .block |                     .block | ||||||
|                     .build_named( |                     .build_named(format!("{}.store", name), Instr::Store(alloca, value.instr())) | ||||||
|                         format!("{}.store", name), |  | ||||||
|                         Instr::Store(alloca, value.instr()), |  | ||||||
|                     ) |  | ||||||
|                     .unwrap() |                     .unwrap() | ||||||
|                     .maybe_location(&mut scope.block, location); |                     .maybe_location(&mut scope.block, location); | ||||||
| 
 | 
 | ||||||
| @ -632,17 +609,12 @@ impl mir::Statement { | |||||||
|             } |             } | ||||||
|             mir::StmtKind::Import(_) => todo!(), |             mir::StmtKind::Import(_) => todo!(), | ||||||
|             mir::StmtKind::Expression(expression) => expression.codegen(scope, state), |             mir::StmtKind::Expression(expression) => expression.codegen(scope, state), | ||||||
|             mir::StmtKind::While(WhileStatement { |             mir::StmtKind::While(WhileStatement { condition, block, .. }) => { | ||||||
|                 condition, block, .. |  | ||||||
|             }) => { |  | ||||||
|                 let condition_block = scope.function.block("while.cond"); |                 let condition_block = scope.function.block("while.cond"); | ||||||
|                 let condition_true_block = scope.function.block("while.body"); |                 let condition_true_block = scope.function.block("while.body"); | ||||||
|                 let condition_failed_block = scope.function.block("while.end"); |                 let condition_failed_block = scope.function.block("while.end"); | ||||||
| 
 | 
 | ||||||
|                 scope |                 scope.block.terminate(Term::Br(condition_block.value())).unwrap(); | ||||||
|                     .block |  | ||||||
|                     .terminate(Term::Br(condition_block.value())) |  | ||||||
|                     .unwrap(); |  | ||||||
|                 let mut condition_scope = scope.with_block(condition_block); |                 let mut condition_scope = scope.with_block(condition_block); | ||||||
|                 let condition_res = condition.codegen(&mut condition_scope, state)?.unwrap(); |                 let condition_res = condition.codegen(&mut condition_scope, state)?.unwrap(); | ||||||
|                 let true_instr = condition_scope |                 let true_instr = condition_scope | ||||||
| @ -651,11 +623,7 @@ impl mir::Statement { | |||||||
|                     .unwrap(); |                     .unwrap(); | ||||||
|                 let check = condition_scope |                 let check = condition_scope | ||||||
|                     .block |                     .block | ||||||
|                     .build(Instr::ICmp( |                     .build(Instr::ICmp(CmpPredicate::EQ, condition_res.instr(), true_instr)) | ||||||
|                         CmpPredicate::EQ, |  | ||||||
|                         condition_res.instr(), |  | ||||||
|                         true_instr, |  | ||||||
|                     )) |  | ||||||
|                     .unwrap(); |                     .unwrap(); | ||||||
| 
 | 
 | ||||||
|                 condition_scope |                 condition_scope | ||||||
| @ -685,16 +653,13 @@ impl mir::Statement { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl mir::Expression { | impl mir::Expression { | ||||||
|     fn codegen<'ctx, 'a>( |     fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, state: &State) -> Result<Option<StackValue>, ErrorKind> { | ||||||
|         &self, |  | ||||||
|         scope: &mut Scope<'ctx, 'a>, |  | ||||||
|         state: &State, |  | ||||||
|     ) -> Result<Option<StackValue>, ErrorKind> { |  | ||||||
|         let location = if let Some(debug) = &scope.debug { |         let location = if let Some(debug) = &scope.debug { | ||||||
|             Some(debug.info.location( |             Some( | ||||||
|                 &debug.scope, |                 debug | ||||||
|                 self.1.into_debug(scope.tokens, debug.scope).unwrap(), |                     .info | ||||||
|             )) |                     .location(&debug.scope, self.1.into_debug(scope.tokens, debug.scope).unwrap()), | ||||||
|  |             ) | ||||||
|         } else { |         } else { | ||||||
|             None |             None | ||||||
|         }; |         }; | ||||||
| @ -715,10 +680,7 @@ impl mir::Expression { | |||||||
|                                         .block |                                         .block | ||||||
|                                         .build_named( |                                         .build_named( | ||||||
|                                             format!("{}", varref.1), |                                             format!("{}", varref.1), | ||||||
|                                             Instr::Load( |                                             Instr::Load(v.0.instr(), inner.get_type(scope.type_values)), | ||||||
|                                                 v.0.instr(), |  | ||||||
|                                                 inner.get_type(scope.type_values), |  | ||||||
|                                             ), |  | ||||||
|                                         ) |                                         ) | ||||||
|                                         .unwrap(), |                                         .unwrap(), | ||||||
|                                 ), |                                 ), | ||||||
| @ -736,13 +698,9 @@ impl mir::Expression { | |||||||
|                 StackValueKind::Literal(lit.as_const(&mut scope.block)), |                 StackValueKind::Literal(lit.as_const(&mut scope.block)), | ||||||
|                 lit.as_type(), |                 lit.as_type(), | ||||||
|             )), |             )), | ||||||
|             mir::ExprKind::BinOp(binop, lhs_exp, rhs_exp) => { |             mir::ExprKind::BinOp(binop, lhs_exp, rhs_exp, return_ty) => { | ||||||
|                 let lhs_val = lhs_exp |                 let lhs_val = lhs_exp.codegen(scope, state)?.expect("lhs has no return value"); | ||||||
|                     .codegen(scope, state)? |                 let rhs_val = rhs_exp.codegen(scope, state)?.expect("rhs has no return value"); | ||||||
|                     .expect("lhs has no return value"); |  | ||||||
|                 let rhs_val = rhs_exp |  | ||||||
|                     .codegen(scope, state)? |  | ||||||
|                     .expect("rhs has no return value"); |  | ||||||
|                 let lhs = lhs_val.instr(); |                 let lhs = lhs_val.instr(); | ||||||
|                 let rhs = rhs_val.instr(); |                 let rhs = rhs_val.instr(); | ||||||
| 
 | 
 | ||||||
| @ -755,15 +713,8 @@ impl mir::Expression { | |||||||
|                     let a = operation.codegen(&lhs_val, &rhs_val, scope)?; |                     let a = operation.codegen(&lhs_val, &rhs_val, scope)?; | ||||||
|                     Some(a) |                     Some(a) | ||||||
|                 } else { |                 } else { | ||||||
|                     let lhs_type = lhs_exp |                     let lhs_type = lhs_exp.return_type(&Default::default(), scope.module_id).unwrap().1; | ||||||
|                         .return_type(&Default::default(), scope.module_id) |                     let instr = match (binop, lhs_type.signed(), lhs_type.category() == TypeCategory::Real) { | ||||||
|                         .unwrap() |  | ||||||
|                         .1; |  | ||||||
|                     let instr = match ( |  | ||||||
|                         binop, |  | ||||||
|                         lhs_type.signed(), |  | ||||||
|                         lhs_type.category() == TypeCategory::Real, |  | ||||||
|                     ) { |  | ||||||
|                         (mir::BinaryOperator::Add, _, false) => Instr::Add(lhs, rhs), |                         (mir::BinaryOperator::Add, _, false) => Instr::Add(lhs, rhs), | ||||||
|                         (mir::BinaryOperator::Add, _, true) => Instr::FAdd(lhs, rhs), |                         (mir::BinaryOperator::Add, _, true) => Instr::FAdd(lhs, rhs), | ||||||
|                         (mir::BinaryOperator::Minus, _, false) => Instr::Sub(lhs, rhs), |                         (mir::BinaryOperator::Minus, _, false) => Instr::Sub(lhs, rhs), | ||||||
| @ -771,12 +722,8 @@ impl mir::Expression { | |||||||
|                         (mir::BinaryOperator::Mult, _, false) => Instr::Mul(lhs, rhs), |                         (mir::BinaryOperator::Mult, _, false) => Instr::Mul(lhs, rhs), | ||||||
|                         (mir::BinaryOperator::Mult, _, true) => Instr::FMul(lhs, rhs), |                         (mir::BinaryOperator::Mult, _, true) => Instr::FMul(lhs, rhs), | ||||||
|                         (mir::BinaryOperator::And, _, _) => Instr::And(lhs, rhs), |                         (mir::BinaryOperator::And, _, _) => Instr::And(lhs, rhs), | ||||||
|                         (mir::BinaryOperator::Cmp(i), _, false) => { |                         (mir::BinaryOperator::Cmp(i), _, false) => Instr::ICmp(i.predicate(), lhs, rhs), | ||||||
|                             Instr::ICmp(i.predicate(), lhs, rhs) |                         (mir::BinaryOperator::Cmp(i), _, true) => Instr::FCmp(i.predicate(), lhs, rhs), | ||||||
|                         } |  | ||||||
|                         (mir::BinaryOperator::Cmp(i), _, true) => { |  | ||||||
|                             Instr::FCmp(i.predicate(), lhs, rhs) |  | ||||||
|                         } |  | ||||||
|                         (mir::BinaryOperator::Div, false, false) => Instr::UDiv(lhs, rhs), |                         (mir::BinaryOperator::Div, false, false) => Instr::UDiv(lhs, rhs), | ||||||
|                         (mir::BinaryOperator::Div, true, false) => Instr::SDiv(lhs, rhs), |                         (mir::BinaryOperator::Div, true, false) => Instr::SDiv(lhs, rhs), | ||||||
|                         (mir::BinaryOperator::Div, _, true) => Instr::FDiv(lhs, rhs), |                         (mir::BinaryOperator::Div, _, true) => Instr::FDiv(lhs, rhs), | ||||||
| @ -828,15 +775,12 @@ impl mir::Expression { | |||||||
|                                 .unwrap() |                                 .unwrap() | ||||||
|                                 .maybe_location(&mut scope.block, location), |                                 .maybe_location(&mut scope.block, location), | ||||||
|                         ), |                         ), | ||||||
|                         lhs_type, |                         return_ty.clone(), | ||||||
|                     )) |                     )) | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             mir::ExprKind::FunctionCall(call) => { |             mir::ExprKind::FunctionCall(call) => { | ||||||
|                 let ret_type_kind = call |                 let ret_type_kind = call.return_type.known().expect("function return type unknown"); | ||||||
|                     .return_type |  | ||||||
|                     .known() |  | ||||||
|                     .expect("function return type unknown"); |  | ||||||
| 
 | 
 | ||||||
|                 let ret_type = ret_type_kind.get_type(scope.type_values); |                 let ret_type = ret_type_kind.get_type(scope.type_values); | ||||||
| 
 | 
 | ||||||
| @ -852,17 +796,11 @@ impl mir::Expression { | |||||||
|                 .collect::<Vec<_>>(); |                 .collect::<Vec<_>>(); | ||||||
| 
 | 
 | ||||||
|                 let param_instrs = params.iter().map(|e| e.instr()).collect(); |                 let param_instrs = params.iter().map(|e| e.instr()).collect(); | ||||||
|                 let callee = scope |                 let callee = scope.functions.get(&call.name).expect("function not found!"); | ||||||
|                     .functions |  | ||||||
|                     .get(&call.name) |  | ||||||
|                     .expect("function not found!"); |  | ||||||
| 
 | 
 | ||||||
|                 let val = scope |                 let val = scope | ||||||
|                     .block |                     .block | ||||||
|                     .build_named( |                     .build_named(call.name.clone(), Instr::FunctionCall(callee.value(), param_instrs)) | ||||||
|                         call.name.clone(), |  | ||||||
|                         Instr::FunctionCall(callee.value(), param_instrs), |  | ||||||
|                     ) |  | ||||||
|                     .unwrap(); |                     .unwrap(); | ||||||
| 
 | 
 | ||||||
|                 if let Some(debug) = &scope.debug { |                 if let Some(debug) = &scope.debug { | ||||||
| @ -939,10 +877,7 @@ impl mir::Expression { | |||||||
|                 let (ptr, contained_ty) = if let TypeKind::UserPtr(further_inner) = *inner.clone() { |                 let (ptr, contained_ty) = if let TypeKind::UserPtr(further_inner) = *inner.clone() { | ||||||
|                     let loaded = scope |                     let loaded = scope | ||||||
|                         .block |                         .block | ||||||
|                         .build_named( |                         .build_named("load", Instr::Load(kind.instr(), inner.get_type(scope.type_values))) | ||||||
|                             "load", |  | ||||||
|                             Instr::Load(kind.instr(), inner.get_type(scope.type_values)), |  | ||||||
|                         ) |  | ||||||
|                         .unwrap(); |                         .unwrap(); | ||||||
|                     ( |                     ( | ||||||
|                         scope |                         scope | ||||||
| @ -960,10 +895,7 @@ impl mir::Expression { | |||||||
|                     ( |                     ( | ||||||
|                         scope |                         scope | ||||||
|                             .block |                             .block | ||||||
|                             .build_named( |                             .build_named(format!("array.gep"), Instr::GetElemPtr(kind.instr(), vec![idx])) | ||||||
|                                 format!("array.gep"), |  | ||||||
|                                 Instr::GetElemPtr(kind.instr(), vec![idx]), |  | ||||||
|                             ) |  | ||||||
|                             .unwrap() |                             .unwrap() | ||||||
|                             .maybe_location(&mut scope.block, location), |                             .maybe_location(&mut scope.block, location), | ||||||
|                         val_t.clone(), |                         val_t.clone(), | ||||||
| @ -980,10 +912,7 @@ impl mir::Expression { | |||||||
|                     ( |                     ( | ||||||
|                         scope |                         scope | ||||||
|                             .block |                             .block | ||||||
|                             .build_named( |                             .build_named(format!("array.gep"), Instr::GetElemPtr(kind.instr(), vec![first, idx])) | ||||||
|                                 format!("array.gep"), |  | ||||||
|                                 Instr::GetElemPtr(kind.instr(), vec![first, idx]), |  | ||||||
|                             ) |  | ||||||
|                             .unwrap() |                             .unwrap() | ||||||
|                             .maybe_location(&mut scope.block, location), |                             .maybe_location(&mut scope.block, location), | ||||||
|                         val_t.clone(), |                         val_t.clone(), | ||||||
| @ -995,10 +924,7 @@ impl mir::Expression { | |||||||
|                         kind.derive( |                         kind.derive( | ||||||
|                             scope |                             scope | ||||||
|                                 .block |                                 .block | ||||||
|                                 .build_named( |                                 .build_named("array.load", Instr::Load(ptr, contained_ty.get_type(scope.type_values))) | ||||||
|                                     "array.load", |  | ||||||
|                                     Instr::Load(ptr, contained_ty.get_type(scope.type_values)), |  | ||||||
|                                 ) |  | ||||||
|                                 .unwrap() |                                 .unwrap() | ||||||
|                                 .maybe_location(&mut scope.block, location), |                                 .maybe_location(&mut scope.block, location), | ||||||
|                         ), |                         ), | ||||||
| @ -1012,21 +938,14 @@ impl mir::Expression { | |||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             mir::ExprKind::Array(expressions) => { |             mir::ExprKind::Array(expressions) => { | ||||||
|                 let stack_value_list: Vec<_> = try_all( |                 let stack_value_list: Vec<_> = | ||||||
|                     expressions |                     try_all(expressions.iter().map(|e| e.codegen(scope, state)).collect::<Vec<_>>()) | ||||||
|                         .iter() |                         .map_err(|e| e.first().cloned().unwrap())? | ||||||
|                         .map(|e| e.codegen(scope, state)) |                         .into_iter() | ||||||
|                         .collect::<Vec<_>>(), |                         .map(|v| v.unwrap()) | ||||||
|                 ) |                         .collect(); | ||||||
|                 .map_err(|e| e.first().cloned().unwrap())? |  | ||||||
|                 .into_iter() |  | ||||||
|                 .map(|v| v.unwrap()) |  | ||||||
|                 .collect(); |  | ||||||
| 
 | 
 | ||||||
|                 let instr_list = stack_value_list |                 let instr_list = stack_value_list.iter().map(|s| s.instr()).collect::<Vec<_>>(); | ||||||
|                     .iter() |  | ||||||
|                     .map(|s| s.instr()) |  | ||||||
|                     .collect::<Vec<_>>(); |  | ||||||
| 
 | 
 | ||||||
|                 let elem_ty_kind = stack_value_list |                 let elem_ty_kind = stack_value_list | ||||||
|                     .iter() |                     .iter() | ||||||
| @ -1053,10 +972,7 @@ impl mir::Expression { | |||||||
| 
 | 
 | ||||||
|                     let index_expr = scope |                     let index_expr = scope | ||||||
|                         .block |                         .block | ||||||
|                         .build_named( |                         .build_named(index.to_string(), Instr::Constant(ConstValue::U32(index as u32))) | ||||||
|                             index.to_string(), |  | ||||||
|                             Instr::Constant(ConstValue::U32(index as u32)), |  | ||||||
|                         ) |  | ||||||
|                         .unwrap(); |                         .unwrap(); | ||||||
|                     let first = scope |                     let first = scope | ||||||
|                         .block |                         .block | ||||||
| @ -1094,8 +1010,7 @@ impl mir::Expression { | |||||||
|                 let TypeKind::CustomType(key) = *inner.clone() else { |                 let TypeKind::CustomType(key) = *inner.clone() else { | ||||||
|                     panic!("tried accessing non-custom-type"); |                     panic!("tried accessing non-custom-type"); | ||||||
|                 }; |                 }; | ||||||
|                 let TypeDefinitionKind::Struct(struct_ty) = |                 let TypeDefinitionKind::Struct(struct_ty) = scope.get_typedef(&key).unwrap().kind.clone(); | ||||||
|                     scope.get_typedef(&key).unwrap().kind.clone(); |  | ||||||
|                 let idx = struct_ty.find_index(field).unwrap(); |                 let idx = struct_ty.find_index(field).unwrap(); | ||||||
| 
 | 
 | ||||||
|                 let gep_n = format!("{}.{}.gep", key.0, field); |                 let gep_n = format!("{}.{}.gep", key.0, field); | ||||||
| @ -1103,10 +1018,7 @@ impl mir::Expression { | |||||||
| 
 | 
 | ||||||
|                 let value = scope |                 let value = scope | ||||||
|                     .block |                     .block | ||||||
|                     .build_named( |                     .build_named(gep_n, Instr::GetStructElemPtr(struct_val.instr(), idx as u32)) | ||||||
|                         gep_n, |  | ||||||
|                         Instr::GetStructElemPtr(struct_val.instr(), idx as u32), |  | ||||||
|                     ) |  | ||||||
|                     .unwrap(); |                     .unwrap(); | ||||||
| 
 | 
 | ||||||
|                 // value.maybe_location(&mut scope.block, location);
 |                 // value.maybe_location(&mut scope.block, location);
 | ||||||
| @ -1116,10 +1028,7 @@ impl mir::Expression { | |||||||
|                         struct_val.0.derive( |                         struct_val.0.derive( | ||||||
|                             scope |                             scope | ||||||
|                                 .block |                                 .block | ||||||
|                                 .build_named( |                                 .build_named(load_n, Instr::Load(value, type_kind.get_type(scope.type_values))) | ||||||
|                                     load_n, |  | ||||||
|                                     Instr::Load(value, type_kind.get_type(scope.type_values)), |  | ||||||
|                                 ) |  | ||||||
|                                 .unwrap(), |                                 .unwrap(), | ||||||
|                         ), |                         ), | ||||||
|                         struct_ty.get_field_ty(&field).unwrap().clone(), |                         struct_ty.get_field_ty(&field).unwrap().clone(), | ||||||
| @ -1127,9 +1036,7 @@ impl mir::Expression { | |||||||
|                 } else { |                 } else { | ||||||
|                     Some(StackValue( |                     Some(StackValue( | ||||||
|                         struct_val.0.derive(value), |                         struct_val.0.derive(value), | ||||||
|                         TypeKind::CodegenPtr(Box::new( |                         TypeKind::CodegenPtr(Box::new(struct_ty.get_field_ty(&field).unwrap().clone())), | ||||||
|                             struct_ty.get_field_ty(&field).unwrap().clone(), |  | ||||||
|                         )), |  | ||||||
|                     )) |                     )) | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @ -1222,10 +1129,7 @@ impl mir::Expression { | |||||||
|                                         .block |                                         .block | ||||||
|                                         .build_named( |                                         .build_named( | ||||||
|                                             format!("{}.deref.inner", varref.1), |                                             format!("{}.deref.inner", varref.1), | ||||||
|                                             Instr::Load( |                                             Instr::Load(var_ptr_instr, inner.get_type(scope.type_values)), | ||||||
|                                                 var_ptr_instr, |  | ||||||
|                                                 inner.get_type(scope.type_values), |  | ||||||
|                                             ), |  | ||||||
|                                         ) |                                         ) | ||||||
|                                         .unwrap(), |                                         .unwrap(), | ||||||
|                                 ), |                                 ), | ||||||
| @ -1253,17 +1157,14 @@ impl mir::Expression { | |||||||
|                     Some(val) |                     Some(val) | ||||||
|                 } else { |                 } else { | ||||||
|                     match (&val.1, type_kind) { |                     match (&val.1, type_kind) { | ||||||
|                         (TypeKind::CodegenPtr(inner), TypeKind::UserPtr(_)) => match *inner.clone() |                         (TypeKind::CodegenPtr(inner), TypeKind::UserPtr(_)) => match *inner.clone() { | ||||||
|                         { |  | ||||||
|                             TypeKind::UserPtr(_) => Some(StackValue( |                             TypeKind::UserPtr(_) => Some(StackValue( | ||||||
|                                 val.0.derive( |                                 val.0.derive( | ||||||
|                                     scope |                                     scope | ||||||
|                                         .block |                                         .block | ||||||
|                                         .build(Instr::BitCast( |                                         .build(Instr::BitCast( | ||||||
|                                             val.instr(), |                                             val.instr(), | ||||||
|                                             Type::Ptr(Box::new( |                                             Type::Ptr(Box::new(type_kind.get_type(scope.type_values))), | ||||||
|                                                 type_kind.get_type(scope.type_values), |  | ||||||
|                                             )), |  | ||||||
|                                         )) |                                         )) | ||||||
|                                         .unwrap(), |                                         .unwrap(), | ||||||
|                                 ), |                                 ), | ||||||
| @ -1278,10 +1179,7 @@ impl mir::Expression { | |||||||
|                             val.0.derive( |                             val.0.derive( | ||||||
|                                 scope |                                 scope | ||||||
|                                     .block |                                     .block | ||||||
|                                     .build(Instr::BitCast( |                                     .build(Instr::BitCast(val.instr(), type_kind.get_type(scope.type_values))) | ||||||
|                                         val.instr(), |  | ||||||
|                                         type_kind.get_type(scope.type_values), |  | ||||||
|                                     )) |  | ||||||
|                                     .unwrap(), |                                     .unwrap(), | ||||||
|                             ), |                             ), | ||||||
|                             type_kind.clone(), |                             type_kind.clone(), | ||||||
| @ -1290,10 +1188,7 @@ impl mir::Expression { | |||||||
|                             let cast_instr = val |                             let cast_instr = val | ||||||
|                                 .1 |                                 .1 | ||||||
|                                 .get_type(scope.type_values) |                                 .get_type(scope.type_values) | ||||||
|                                 .cast_instruction( |                                 .cast_instruction(val.instr(), &type_kind.get_type(scope.type_values)) | ||||||
|                                     val.instr(), |  | ||||||
|                                     &type_kind.get_type(scope.type_values), |  | ||||||
|                                 ) |  | ||||||
|                                 .unwrap(); |                                 .unwrap(); | ||||||
| 
 | 
 | ||||||
|                             Some(StackValue( |                             Some(StackValue( | ||||||
| @ -1313,11 +1208,7 @@ impl mir::Expression { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl mir::IfExpression { | impl mir::IfExpression { | ||||||
|     fn codegen<'ctx, 'a>( |     fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, state: &State) -> Result<Option<StackValue>, ErrorKind> { | ||||||
|         &self, |  | ||||||
|         scope: &mut Scope<'ctx, 'a>, |  | ||||||
|         state: &State, |  | ||||||
|     ) -> Result<Option<StackValue>, ErrorKind> { |  | ||||||
|         let condition = self.0.codegen(scope, state)?.unwrap(); |         let condition = self.0.codegen(scope, state)?.unwrap(); | ||||||
| 
 | 
 | ||||||
|         // Create blocks
 |         // Create blocks
 | ||||||
| @ -1389,10 +1280,7 @@ impl mir::IfExpression { | |||||||
|             incoming.extend(else_res.clone()); |             incoming.extend(else_res.clone()); | ||||||
|             let instr = scope |             let instr = scope | ||||||
|                 .block |                 .block | ||||||
|                 .build_named( |                 .build_named("phi", Instr::Phi(incoming.iter().map(|i| i.instr()).collect())) | ||||||
|                     "phi", |  | ||||||
|                     Instr::Phi(incoming.iter().map(|i| i.instr()).collect()), |  | ||||||
|                 ) |  | ||||||
|                 .unwrap(); |                 .unwrap(); | ||||||
| 
 | 
 | ||||||
|             use StackValueKind::*; |             use StackValueKind::*; | ||||||
|  | |||||||
| @ -182,7 +182,7 @@ pub fn perform_all_passes<'map>( | |||||||
|     #[cfg(debug_assertions)] |     #[cfg(debug_assertions)] | ||||||
|     println!("{}", &refs); |     println!("{}", &refs); | ||||||
|     #[cfg(debug_assertions)] |     #[cfg(debug_assertions)] | ||||||
|     println!("{}", &context); |     println!("{:#}", &context); | ||||||
|     #[cfg(debug_assertions)] |     #[cfg(debug_assertions)] | ||||||
|     dbg!(&state); |     dbg!(&state); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -152,24 +152,14 @@ impl Display for StmtKind { | |||||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||||
|         match self { |         match self { | ||||||
|             StmtKind::Let(var, mutable, block) => { |             StmtKind::Let(var, mutable, block) => { | ||||||
|                 write!( |                 write!(f, "let{} {} = {}", if *mutable { " mut" } else { "" }, var, block) | ||||||
|                     f, |  | ||||||
|                     "let{} {} = {}", |  | ||||||
|                     if *mutable { " mut" } else { "" }, |  | ||||||
|                     var, |  | ||||||
|                     block |  | ||||||
|                 ) |  | ||||||
|             } |             } | ||||||
|             StmtKind::Set(var, expr) => write!(f, "{} = {}", var, expr), |             StmtKind::Set(var, expr) => write!(f, "{} = {}", var, expr), | ||||||
|             StmtKind::Import(n) => write!(f, "import {}", n), |             StmtKind::Import(n) => write!(f, "import {}", n), | ||||||
|             StmtKind::Expression(exp) => Display::fmt(exp, f), |             StmtKind::Expression(exp) => Display::fmt(exp, f), | ||||||
| 
 | 
 | ||||||
|             StmtKind::While(while_statement) => { |             StmtKind::While(while_statement) => { | ||||||
|                 write!( |                 write!(f, "while {} {}", while_statement.condition, while_statement.block,) | ||||||
|                     f, |  | ||||||
|                     "while {} {}", |  | ||||||
|                     while_statement.condition, while_statement.block, |  | ||||||
|                 ) |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -189,7 +179,12 @@ impl Display for ExprKind { | |||||||
|         match self { |         match self { | ||||||
|             ExprKind::Variable(var) => Display::fmt(var, f), |             ExprKind::Variable(var) => Display::fmt(var, f), | ||||||
|             ExprKind::Literal(lit) => Display::fmt(lit, f), |             ExprKind::Literal(lit) => Display::fmt(lit, f), | ||||||
|             ExprKind::BinOp(op, lhs, rhs) => write!(f, "{} {} {}", lhs, op, rhs), |             ExprKind::BinOp(op, lhs, rhs, ty) => { | ||||||
|  |                 write!(f, "{} {} {} (= ", lhs, op, rhs)?; | ||||||
|  |                 Debug::fmt(ty, f)?; | ||||||
|  |                 f.write_char(')')?; | ||||||
|  |                 Ok(()) | ||||||
|  |             } | ||||||
|             ExprKind::FunctionCall(fc) => Display::fmt(fc, f), |             ExprKind::FunctionCall(fc) => Display::fmt(fc, f), | ||||||
|             ExprKind::If(if_exp) => Display::fmt(&if_exp, f), |             ExprKind::If(if_exp) => Display::fmt(&if_exp, f), | ||||||
|             ExprKind::Block(block) => Display::fmt(block, f), |             ExprKind::Block(block) => Display::fmt(block, f), | ||||||
|  | |||||||
| @ -359,10 +359,7 @@ impl Statement { | |||||||
|                 expr.return_type(refs, mod_id)?, |                 expr.return_type(refs, mod_id)?, | ||||||
|                 Err(ReturnTypeOther::Let(var.2 + expr.1)), |                 Err(ReturnTypeOther::Let(var.2 + expr.1)), | ||||||
|             ), |             ), | ||||||
|             Set(lhs, rhs) => if_hard( |             Set(lhs, rhs) => if_hard(rhs.return_type(refs, mod_id)?, Err(ReturnTypeOther::Set(lhs.1 + rhs.1))), | ||||||
|                 rhs.return_type(refs, mod_id)?, |  | ||||||
|                 Err(ReturnTypeOther::Set(lhs.1 + rhs.1)), |  | ||||||
|             ), |  | ||||||
|             Import(_) => todo!(), |             Import(_) => todo!(), | ||||||
|             Expression(expression) => expression.return_type(refs, mod_id), |             Expression(expression) => expression.return_type(refs, mod_id), | ||||||
|             While(_) => Err(ReturnTypeOther::Loop), |             While(_) => Err(ReturnTypeOther::Loop), | ||||||
| @ -390,11 +387,14 @@ impl Expression { | |||||||
|         match &self.0 { |         match &self.0 { | ||||||
|             Literal(lit) => Ok((ReturnKind::Soft, lit.as_type())), |             Literal(lit) => Ok((ReturnKind::Soft, lit.as_type())), | ||||||
|             Variable(var) => var.return_type(), |             Variable(var) => var.return_type(), | ||||||
|             BinOp(_, then_e, else_e) => { |             BinOp(_, then_e, else_e, return_ty) => { | ||||||
|                 let then_r = then_e.return_type(refs, mod_id)?; |                 let then_r = then_e.return_type(refs, mod_id)?; | ||||||
|                 let else_r = else_e.return_type(refs, mod_id)?; |                 let else_r = else_e.return_type(refs, mod_id)?; | ||||||
| 
 | 
 | ||||||
|                 Ok(pick_return(then_r, else_r)) |                 Ok(match (then_r.0, else_r.0) { | ||||||
|  |                     (ReturnKind::Hard, ReturnKind::Hard) => (ReturnKind::Hard, return_ty.clone()), | ||||||
|  |                     _ => (ReturnKind::Soft, return_ty.clone()), | ||||||
|  |                 }) | ||||||
|             } |             } | ||||||
|             Block(block) => block.return_type(refs, mod_id), |             Block(block) => block.return_type(refs, mod_id), | ||||||
|             FunctionCall(fcall) => fcall.return_type(), |             FunctionCall(fcall) => fcall.return_type(), | ||||||
| @ -457,7 +457,7 @@ impl Expression { | |||||||
|             ExprKind::Array(_) => None, |             ExprKind::Array(_) => None, | ||||||
|             ExprKind::Struct(_, _) => None, |             ExprKind::Struct(_, _) => None, | ||||||
|             ExprKind::Literal(_) => None, |             ExprKind::Literal(_) => None, | ||||||
|             ExprKind::BinOp(_, _, _) => None, |             ExprKind::BinOp(_, _, _, _) => None, | ||||||
|             ExprKind::FunctionCall(_) => None, |             ExprKind::FunctionCall(_) => None, | ||||||
|             ExprKind::If(_) => None, |             ExprKind::If(_) => None, | ||||||
|             ExprKind::CastTo(expression, _) => expression.backing_var(), |             ExprKind::CastTo(expression, _) => expression.backing_var(), | ||||||
| @ -472,7 +472,7 @@ impl Expression { | |||||||
|             ExprKind::Array(_) => None, |             ExprKind::Array(_) => None, | ||||||
|             ExprKind::Struct(..) => None, |             ExprKind::Struct(..) => None, | ||||||
|             ExprKind::Literal(literal) => literal.num_value(), |             ExprKind::Literal(literal) => literal.num_value(), | ||||||
|             ExprKind::BinOp(op, lhs, rhs) => match op { |             ExprKind::BinOp(op, lhs, rhs, _) => match op { | ||||||
|                 BinaryOperator::Add => maybe(lhs.num_value()?, rhs.num_value()?, |a, b| a + b), |                 BinaryOperator::Add => maybe(lhs.num_value()?, rhs.num_value()?, |a, b| a + b), | ||||||
|                 BinaryOperator::Minus => maybe(lhs.num_value()?, rhs.num_value()?, |a, b| a - b), |                 BinaryOperator::Minus => maybe(lhs.num_value()?, rhs.num_value()?, |a, b| a - b), | ||||||
|                 BinaryOperator::Mult => maybe(lhs.num_value()?, rhs.num_value()?, |a, b| a * b), |                 BinaryOperator::Mult => maybe(lhs.num_value()?, rhs.num_value()?, |a, b| a * b), | ||||||
| @ -604,9 +604,7 @@ pub enum EqualsIssue { | |||||||
| impl FunctionDefinition { | impl FunctionDefinition { | ||||||
|     pub fn equals_as_imported(&self, other: &FunctionDefinition) -> Result<(), EqualsIssue> { |     pub fn equals_as_imported(&self, other: &FunctionDefinition) -> Result<(), EqualsIssue> { | ||||||
|         match &self.kind { |         match &self.kind { | ||||||
|             FunctionDefinitionKind::Local(_, metadata) => { |             FunctionDefinitionKind::Local(_, metadata) => Err(EqualsIssue::ExistsLocally(*metadata)), | ||||||
|                 Err(EqualsIssue::ExistsLocally(*metadata)) |  | ||||||
|             } |  | ||||||
|             FunctionDefinitionKind::Extern(imported) => { |             FunctionDefinitionKind::Extern(imported) => { | ||||||
|                 if *imported { |                 if *imported { | ||||||
|                     Err(EqualsIssue::ConflictWithImport(self.name.clone())) |                     Err(EqualsIssue::ConflictWithImport(self.name.clone())) | ||||||
| @ -618,10 +616,7 @@ impl FunctionDefinition { | |||||||
|                     { |                     { | ||||||
|                         Ok(()) |                         Ok(()) | ||||||
|                     } else { |                     } else { | ||||||
|                         Err(EqualsIssue::AlreadyExtern( |                         Err(EqualsIssue::AlreadyExtern(self.name.clone(), self.signature())) | ||||||
|                             self.name.clone(), |  | ||||||
|                             self.signature(), |  | ||||||
|                         )) |  | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  | |||||||
| @ -256,7 +256,7 @@ pub enum ExprKind { | |||||||
|     Array(Vec<Expression>), |     Array(Vec<Expression>), | ||||||
|     Struct(String, Vec<(String, Expression)>), |     Struct(String, Vec<(String, Expression)>), | ||||||
|     Literal(Literal), |     Literal(Literal), | ||||||
|     BinOp(BinaryOperator, Box<Expression>, Box<Expression>), |     BinOp(BinaryOperator, Box<Expression>, Box<Expression>, TypeKind), | ||||||
|     FunctionCall(FunctionCall), |     FunctionCall(FunctionCall), | ||||||
|     If(IfExpression), |     If(IfExpression), | ||||||
|     Block(Block), |     Block(Block), | ||||||
| @ -270,11 +270,7 @@ pub struct Expression(pub ExprKind, pub Metadata); | |||||||
| 
 | 
 | ||||||
| /// Condition, Then, Else
 | /// Condition, Then, Else
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub struct IfExpression( | pub struct IfExpression(pub Box<Expression>, pub Box<Expression>, pub Box<Option<Expression>>); | ||||||
|     pub Box<Expression>, |  | ||||||
|     pub Box<Expression>, |  | ||||||
|     pub Box<Option<Expression>>, |  | ||||||
| ); |  | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub struct FunctionCall { | pub struct FunctionCall { | ||||||
|  | |||||||
| @ -85,50 +85,41 @@ impl TypeKind { | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         match (self, other) { |         match (self, other) { | ||||||
|             (TypeKind::Vague(Vague::Integer), other) | (other, TypeKind::Vague(Vague::Integer)) => { |             (TypeKind::Vague(Vague::Integer), other) | (other, TypeKind::Vague(Vague::Integer)) => match other { | ||||||
|                 match other { |                 TypeKind::Vague(Vague::Unknown) => Ok(TypeKind::Vague(Vague::Integer)), | ||||||
|                     TypeKind::Vague(Vague::Unknown) => Ok(TypeKind::Vague(Vague::Integer)), |                 TypeKind::Vague(Vague::Integer) => Ok(TypeKind::Vague(Vague::Integer)), | ||||||
|                     TypeKind::Vague(Vague::Integer) => Ok(TypeKind::Vague(Vague::Integer)), |                 TypeKind::I8 | ||||||
|                     TypeKind::I8 |                 | TypeKind::I16 | ||||||
|                     | TypeKind::I16 |                 | TypeKind::I32 | ||||||
|                     | TypeKind::I32 |                 | TypeKind::I64 | ||||||
|                     | TypeKind::I64 |                 | TypeKind::I128 | ||||||
|                     | TypeKind::I128 |                 | TypeKind::U8 | ||||||
|                     | TypeKind::U8 |                 | TypeKind::U16 | ||||||
|                     | TypeKind::U16 |                 | TypeKind::U32 | ||||||
|                     | TypeKind::U32 |                 | TypeKind::U64 | ||||||
|                     | TypeKind::U64 |                 | TypeKind::U128 => Ok(other.clone()), | ||||||
|                     | TypeKind::U128 => Ok(other.clone()), |                 _ => Err(ErrorKind::TypesIncompatible(self.clone(), other.clone())), | ||||||
|                     _ => Err(ErrorKind::TypesIncompatible(self.clone(), other.clone())), |             }, | ||||||
|                 } |             (TypeKind::Vague(Vague::Decimal), other) | (other, TypeKind::Vague(Vague::Decimal)) => match other { | ||||||
|             } |                 TypeKind::Vague(Vague::Unknown) => Ok(TypeKind::Vague(Vague::Decimal)), | ||||||
|             (TypeKind::Vague(Vague::Decimal), other) | (other, TypeKind::Vague(Vague::Decimal)) => { |                 TypeKind::Vague(Vague::Decimal) => Ok(TypeKind::Vague(Vague::Decimal)), | ||||||
|                 match other { |                 TypeKind::F16 | ||||||
|                     TypeKind::Vague(Vague::Unknown) => Ok(TypeKind::Vague(Vague::Decimal)), |                 | TypeKind::F32B | ||||||
|                     TypeKind::Vague(Vague::Decimal) => Ok(TypeKind::Vague(Vague::Decimal)), |                 | TypeKind::F32 | ||||||
|                     TypeKind::F16 |                 | TypeKind::F64 | ||||||
|                     | TypeKind::F32B |                 | TypeKind::F80 | ||||||
|                     | TypeKind::F32 |                 | TypeKind::F128 | ||||||
|                     | TypeKind::F64 |                 | TypeKind::F128PPC => Ok(other.clone()), | ||||||
|                     | TypeKind::F80 |                 _ => Err(ErrorKind::TypesIncompatible(self.clone(), other.clone())), | ||||||
|                     | TypeKind::F128 |             }, | ||||||
|                     | TypeKind::F128PPC => Ok(other.clone()), |             (TypeKind::Vague(Vague::Unknown), other) | (other, TypeKind::Vague(Vague::Unknown)) => Ok(other.clone()), | ||||||
|                     _ => Err(ErrorKind::TypesIncompatible(self.clone(), other.clone())), |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             (TypeKind::Vague(Vague::Unknown), other) | (other, TypeKind::Vague(Vague::Unknown)) => { |  | ||||||
|                 Ok(other.clone()) |  | ||||||
|             } |  | ||||||
|             (TypeKind::Borrow(val1, mut1), TypeKind::Borrow(val2, mut2)) => { |             (TypeKind::Borrow(val1, mut1), TypeKind::Borrow(val2, mut2)) => { | ||||||
|                 // Extracted to give priority for other collapse-error
 |                 // Extracted to give priority for other collapse-error
 | ||||||
|                 let collapsed = val1.narrow_into(val2)?; |                 let collapsed = val1.narrow_into(val2)?; | ||||||
|                 if mut1 == mut2 { |                 if mut1 == mut2 { | ||||||
|                     Ok(TypeKind::Borrow(Box::new(collapsed), *mut1 && *mut2)) |                     Ok(TypeKind::Borrow(Box::new(collapsed), *mut1 && *mut2)) | ||||||
|                 } else { |                 } else { | ||||||
|                     Err(ErrorKind::TypesDifferMutability( |                     Err(ErrorKind::TypesDifferMutability(self.clone(), other.clone())) | ||||||
|                         self.clone(), |  | ||||||
|                         other.clone(), |  | ||||||
|                     )) |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             (TypeKind::UserPtr(val1), TypeKind::UserPtr(val2)) => { |             (TypeKind::UserPtr(val1), TypeKind::UserPtr(val2)) => { | ||||||
| @ -146,36 +137,30 @@ impl TypeKind { | |||||||
|             (TypeKind::Vague(Vague::Unknown), other) | (other, TypeKind::Vague(Vague::Unknown)) => { |             (TypeKind::Vague(Vague::Unknown), other) | (other, TypeKind::Vague(Vague::Unknown)) => { | ||||||
|                 TypeKind::Vague(VagueType::Unknown) |                 TypeKind::Vague(VagueType::Unknown) | ||||||
|             } |             } | ||||||
|             (TypeKind::Vague(Vague::Integer), other) | (other, TypeKind::Vague(Vague::Integer)) => { |             (TypeKind::Vague(Vague::Integer), other) | (other, TypeKind::Vague(Vague::Integer)) => match other { | ||||||
|                 match other { |                 TypeKind::I8 | ||||||
|                     TypeKind::I8 |                 | TypeKind::I16 | ||||||
|                     | TypeKind::I16 |                 | TypeKind::I32 | ||||||
|                     | TypeKind::I32 |                 | TypeKind::I64 | ||||||
|                     | TypeKind::I64 |                 | TypeKind::I128 | ||||||
|                     | TypeKind::I128 |                 | TypeKind::U8 | ||||||
|                     | TypeKind::U8 |                 | TypeKind::U16 | ||||||
|                     | TypeKind::U16 |                 | TypeKind::U32 | ||||||
|                     | TypeKind::U32 |                 | TypeKind::U64 | ||||||
|                     | TypeKind::U64 |                 | TypeKind::U128 => TypeKind::Vague(VagueType::Integer), | ||||||
|                     | TypeKind::U128 => TypeKind::Vague(VagueType::Integer), |                 _ => TypeKind::Vague(VagueType::Unknown), | ||||||
|                     _ => TypeKind::Vague(VagueType::Unknown), |             }, | ||||||
|                 } |             (TypeKind::Vague(Vague::Decimal), other) | (other, TypeKind::Vague(Vague::Decimal)) => match other { | ||||||
|             } |                 TypeKind::F16 | ||||||
|             (TypeKind::Vague(Vague::Decimal), other) | (other, TypeKind::Vague(Vague::Decimal)) => { |                 | TypeKind::F32B | ||||||
|                 match other { |                 | TypeKind::F32 | ||||||
|                     TypeKind::F16 |                 | TypeKind::F64 | ||||||
|                     | TypeKind::F32B |                 | TypeKind::F80 | ||||||
|                     | TypeKind::F32 |                 | TypeKind::F128 | ||||||
|                     | TypeKind::F64 |                 | TypeKind::F128PPC => TypeKind::Vague(VagueType::Decimal), | ||||||
|                     | TypeKind::F80 |                 _ => TypeKind::Vague(VagueType::Unknown), | ||||||
|                     | TypeKind::F128 |             }, | ||||||
|                     | TypeKind::F128PPC => TypeKind::Vague(VagueType::Decimal), |             (TypeKind::UserPtr(val1), TypeKind::UserPtr(val2)) => TypeKind::UserPtr(Box::new(val1.widen_into(val2))), | ||||||
|                     _ => TypeKind::Vague(VagueType::Unknown), |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             (TypeKind::UserPtr(val1), TypeKind::UserPtr(val2)) => { |  | ||||||
|                 TypeKind::UserPtr(Box::new(val1.widen_into(val2))) |  | ||||||
|             } |  | ||||||
|             (TypeKind::CodegenPtr(val1), TypeKind::CodegenPtr(val2)) => { |             (TypeKind::CodegenPtr(val1), TypeKind::CodegenPtr(val2)) => { | ||||||
|                 TypeKind::CodegenPtr(Box::new(val1.widen_into(val2))) |                 TypeKind::CodegenPtr(Box::new(val1.widen_into(val2))) | ||||||
|             } |             } | ||||||
| @ -245,16 +230,10 @@ impl TypeKind { | |||||||
|                 Vague::TypeRef(_) => panic!("Hinted default!"), |                 Vague::TypeRef(_) => panic!("Hinted default!"), | ||||||
|                 VagueType::Decimal => TypeKind::F32, |                 VagueType::Decimal => TypeKind::F32, | ||||||
|             }, |             }, | ||||||
|             TypeKind::Array(type_kind, len) => { |             TypeKind::Array(type_kind, len) => TypeKind::Array(Box::new(type_kind.or_default()?), *len), | ||||||
|                 TypeKind::Array(Box::new(type_kind.or_default()?), *len) |             TypeKind::Borrow(type_kind, mutable) => TypeKind::Borrow(Box::new(type_kind.or_default()?), *mutable), | ||||||
|             } |  | ||||||
|             TypeKind::Borrow(type_kind, mutable) => { |  | ||||||
|                 TypeKind::Borrow(Box::new(type_kind.or_default()?), *mutable) |  | ||||||
|             } |  | ||||||
|             TypeKind::UserPtr(type_kind) => TypeKind::UserPtr(Box::new(type_kind.or_default()?)), |             TypeKind::UserPtr(type_kind) => TypeKind::UserPtr(Box::new(type_kind.or_default()?)), | ||||||
|             TypeKind::CodegenPtr(type_kind) => { |             TypeKind::CodegenPtr(type_kind) => TypeKind::CodegenPtr(Box::new(type_kind.or_default()?)), | ||||||
|                 TypeKind::CodegenPtr(Box::new(type_kind.or_default()?)) |  | ||||||
|             } |  | ||||||
|             _ => self.clone(), |             _ => self.clone(), | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
| @ -270,37 +249,29 @@ impl TypeKind { | |||||||
|         let resolved = self.resolve_weak(refs); |         let resolved = self.resolve_weak(refs); | ||||||
|         match resolved { |         match resolved { | ||||||
|             TypeKind::Array(t, len) => TypeKind::Array(Box::new(t.resolve_ref(refs)), len), |             TypeKind::Array(t, len) => TypeKind::Array(Box::new(t.resolve_ref(refs)), len), | ||||||
|             TypeKind::Borrow(inner, mutable) => { |             TypeKind::Borrow(inner, mutable) => TypeKind::Borrow(Box::new(inner.resolve_ref(refs)), mutable), | ||||||
|                 TypeKind::Borrow(Box::new(inner.resolve_ref(refs)), mutable) |  | ||||||
|             } |  | ||||||
|             _ => resolved, |             _ => resolved, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub(super) fn assert_known( |     pub(super) fn assert_known(&self, refs: &TypeRefs, state: &TypecheckPassState) -> Result<TypeKind, ErrorKind> { | ||||||
|         &self, |  | ||||||
|         refs: &TypeRefs, |  | ||||||
|         state: &TypecheckPassState, |  | ||||||
|     ) -> Result<TypeKind, ErrorKind> { |  | ||||||
|         self.is_known(refs, state).map(|_| self.clone()) |         self.is_known(refs, state).map(|_| self.clone()) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub(super) fn is_known( |     pub(super) fn is_known(&self, refs: &TypeRefs, state: &TypecheckPassState) -> Result<(), ErrorKind> { | ||||||
|         &self, |  | ||||||
|         refs: &TypeRefs, |  | ||||||
|         state: &TypecheckPassState, |  | ||||||
|     ) -> Result<(), ErrorKind> { |  | ||||||
|         match &self { |         match &self { | ||||||
|             TypeKind::Array(type_kind, _) => type_kind.as_ref().is_known(refs, state), |             TypeKind::Array(type_kind, _) => type_kind.as_ref().is_known(refs, state), | ||||||
|             TypeKind::CustomType(custom_type_key) => state |             TypeKind::CustomType(custom_type_key) => { | ||||||
|                 .scope |                 state | ||||||
|                 .types |                     .scope | ||||||
|                 .get(custom_type_key) |                     .types | ||||||
|                 .map(|_| ()) |                     .get(custom_type_key) | ||||||
|                 .ok_or(ErrorKind::NoSuchType( |                     .map(|_| ()) | ||||||
|                     custom_type_key.0.clone(), |                     .ok_or(ErrorKind::NoSuchType( | ||||||
|                     state.module_id.unwrap(), |                         custom_type_key.0.clone(), | ||||||
|                 )), |                         state.module_id.unwrap(), | ||||||
|  |                     )) | ||||||
|  |             } | ||||||
|             TypeKind::Borrow(type_kind, _) => type_kind.is_known(refs, state), |             TypeKind::Borrow(type_kind, _) => type_kind.is_known(refs, state), | ||||||
|             TypeKind::UserPtr(type_kind) => type_kind.is_known(refs, state), |             TypeKind::UserPtr(type_kind) => type_kind.is_known(refs, state), | ||||||
|             TypeKind::CodegenPtr(type_kind) => type_kind.is_known(refs, state), |             TypeKind::CodegenPtr(type_kind) => type_kind.is_known(refs, state), | ||||||
|  | |||||||
| @ -410,28 +410,34 @@ impl Expression { | |||||||
|                 *literal = literal.clone().try_coerce(hint_t.cloned())?; |                 *literal = literal.clone().try_coerce(hint_t.cloned())?; | ||||||
|                 Ok(literal.as_type()) |                 Ok(literal.as_type()) | ||||||
|             } |             } | ||||||
|             ExprKind::BinOp(op, lhs, rhs) => { |             ExprKind::BinOp(op, lhs, rhs, ret_ty) => { | ||||||
|                 // First find unfiltered parameters to binop
 |                 // First find unfiltered parameters to binop
 | ||||||
|                 let lhs_res = lhs.typecheck(state, &typerefs, None); |                 let lhs_res = lhs.typecheck(state, &typerefs, None); | ||||||
|                 let lhs_type = state.or_else(lhs_res, TypeKind::Vague(Vague::Unknown), lhs.1); |                 let lhs_type = state.or_else(lhs_res, TypeKind::Vague(Vague::Unknown), lhs.1); | ||||||
|                 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); | ||||||
|  |                 let expected_return_ty = ret_ty.resolve_ref(typerefs); | ||||||
| 
 | 
 | ||||||
|                 if let Some(binop) = typerefs |                 let binops = typerefs.binop_types.filter(&pass::ScopeBinopKey { | ||||||
|                     .binop_types |                     params: (lhs_type.clone(), rhs_type.clone()), | ||||||
|                     .find(&pass::ScopeBinopKey { |                     operator: *op, | ||||||
|                         params: (lhs_type.clone(), rhs_type.clone()), |                 }); | ||||||
|                         operator: *op, |                 if let Some(binop) = binops | ||||||
|                     }) |                     .iter() | ||||||
|  |                     .filter(|f| f.1.return_ty == expected_return_ty) | ||||||
|                     .map(|v| (v.1.clone())) |                     .map(|v| (v.1.clone())) | ||||||
|  |                     .next() | ||||||
|                 { |                 { | ||||||
|                     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) |                     *ret_ty = binop.narrow(&lhs_type, &rhs_type).unwrap().2; | ||||||
|  |                     Ok(ret_ty.clone()) | ||||||
|                 } else { |                 } else { | ||||||
|  |                     dbg!(&binops); | ||||||
|                     dbg!(&op, &lhs, &rhs); |                     dbg!(&op, &lhs, &rhs); | ||||||
|                     dbg!(&lhs_type); |                     dbg!(&lhs_type); | ||||||
|                     dbg!(&rhs_type); |                     dbg!(&rhs_type); | ||||||
|  |                     dbg!(&expected_return_ty); | ||||||
|                     panic!() |                     panic!() | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  | |||||||
| @ -291,7 +291,7 @@ impl Expression { | |||||||
|                 type_ref |                 type_ref | ||||||
|             } |             } | ||||||
|             ExprKind::Literal(literal) => Ok(type_refs.from_type(&literal.as_type()).unwrap()), |             ExprKind::Literal(literal) => Ok(type_refs.from_type(&literal.as_type()).unwrap()), | ||||||
|             ExprKind::BinOp(op, lhs, rhs) => { |             ExprKind::BinOp(op, lhs, rhs, return_ty) => { | ||||||
|                 // Infer LHS and RHS, and return binop type
 |                 // Infer LHS and RHS, and return binop type
 | ||||||
|                 let mut lhs_ref = lhs.infer_types(state, type_refs)?; |                 let mut lhs_ref = lhs.infer_types(state, type_refs)?; | ||||||
|                 let mut rhs_ref = rhs.infer_types(state, type_refs)?; |                 let mut rhs_ref = rhs.infer_types(state, type_refs)?; | ||||||
| @ -306,11 +306,17 @@ impl Expression { | |||||||
|                         widened_lhs = widened_lhs.widen_into(&binop.hands.0); |                         widened_lhs = widened_lhs.widen_into(&binop.hands.0); | ||||||
|                         widened_rhs = widened_rhs.widen_into(&binop.hands.1); |                         widened_rhs = widened_rhs.widen_into(&binop.hands.1); | ||||||
|                     } |                     } | ||||||
|  |                     let binop_res = type_refs.from_binop(*op, &lhs_ref, &rhs_ref); | ||||||
|                     lhs_ref.narrow(&type_refs.from_type(&widened_lhs).unwrap()); |                     lhs_ref.narrow(&type_refs.from_type(&widened_lhs).unwrap()); | ||||||
|                     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)) |                     *return_ty = binop_res.as_type(); | ||||||
|  |                     Ok(binop_res) | ||||||
|                 } else { |                 } else { | ||||||
|                     panic!(); |                     Err(ErrorKind::InvalidBinop( | ||||||
|  |                         *op, | ||||||
|  |                         lhs_ref.resolve_deep().unwrap(), | ||||||
|  |                         rhs_ref.resolve_deep().unwrap(), | ||||||
|  |                     )) | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             ExprKind::FunctionCall(function_call) => { |             ExprKind::FunctionCall(function_call) => { | ||||||
|  | |||||||
| @ -71,7 +71,10 @@ impl TypeRefKind { | |||||||
|                     .binop_types |                     .binop_types | ||||||
|                     .iter() |                     .iter() | ||||||
|                     .filter(|b| b.1.operator == *op) |                     .filter(|b| b.1.operator == *op) | ||||||
|                     .map(|b| b.1.narrow(&lhs, &rhs).map(|b| b.2)) |                     .map(|b| { | ||||||
|  |                         b.1.narrow(&lhs.resolve_ref(types), &rhs.resolve_ref(types)) | ||||||
|  |                             .map(|b| b.2) | ||||||
|  |                     }) | ||||||
|                     .filter_map(|s| s); |                     .filter_map(|s| s); | ||||||
|                 if let Some(mut ty) = binops.next() { |                 if let Some(mut ty) = binops.next() { | ||||||
|                     while let Some(other) = binops.next() { |                     while let Some(other) = binops.next() { | ||||||
| @ -105,11 +108,11 @@ impl std::fmt::Display for TypeRefs { | |||||||
|             let idx = *typeref.borrow(); |             let idx = *typeref.borrow(); | ||||||
|             writeln!( |             writeln!( | ||||||
|                 f, |                 f, | ||||||
|                 "{:<3} = {:<3} = {:?} = {}", |                 "{:<3} = {:<3} = {:?} = {:?}", | ||||||
|                 i, |                 i, | ||||||
|                 unsafe { *self.recurse_type_ref(idx).borrow() }, |                 unsafe { *self.recurse_type_ref(idx).borrow() }, | ||||||
|  |                 self.retrieve_typeref(idx), | ||||||
|                 self.retrieve_wide_type(idx), |                 self.retrieve_wide_type(idx), | ||||||
|                 TypeKind::Vague(VagueType::TypeRef(idx)).resolve_ref(self) |  | ||||||
|             )?; |             )?; | ||||||
|         } |         } | ||||||
|         Ok(()) |         Ok(()) | ||||||
| @ -176,9 +179,13 @@ impl TypeRefs { | |||||||
|         return refs.get_unchecked(idx).clone(); |         return refs.get_unchecked(idx).clone(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn retrieve_wide_type(&self, idx: usize) -> Option<TypeKind> { |     pub fn retrieve_typeref(&self, idx: usize) -> Option<TypeRefKind> { | ||||||
|         let inner_idx = unsafe { *self.recurse_type_ref(idx).borrow() }; |         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() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn retrieve_wide_type(&self, idx: usize) -> Option<TypeKind> { | ||||||
|  |         self.retrieve_typeref(idx).map(|t| t.widen(self)) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -248,22 +255,45 @@ impl<'outer> ScopeTypeRefs<'outer> { | |||||||
|         unsafe { |         unsafe { | ||||||
|             let mut hints = self.types.hints.borrow_mut(); |             let mut hints = self.types.hints.borrow_mut(); | ||||||
|             let existing = hints.get_unchecked_mut(*hint.0.borrow()); |             let existing = hints.get_unchecked_mut(*hint.0.borrow()); | ||||||
|  | 
 | ||||||
|             match existing { |             match existing { | ||||||
|                 TypeRefKind::Direct(type_kind) => { |                 TypeRefKind::Direct(type_kind) => { | ||||||
|                     *type_kind = type_kind.narrow_into(&ty).ok()?; |                     *type_kind = type_kind.narrow_into(&ty).ok()?; | ||||||
|                 } |                 } | ||||||
|                 TypeRefKind::BinOp(op, lhs, rhs) => { |                 TypeRefKind::BinOp(op, lhs, rhs) => { | ||||||
|  |                     let op = op.clone(); | ||||||
|  |                     let lhs = lhs.clone(); | ||||||
|  |                     let rhs = rhs.clone(); | ||||||
|  |                     drop(hints); | ||||||
|  | 
 | ||||||
|  |                     let lhs_resolved = lhs.resolve_ref(self.types); | ||||||
|  |                     let rhs_resolved = rhs.resolve_ref(self.types); | ||||||
|  | 
 | ||||||
|                     let binops = self |                     let binops = self | ||||||
|                         .types |                         .types | ||||||
|                         .binop_types |                         .binop_types | ||||||
|                         .iter() |                         .iter() | ||||||
|                         .filter(|b| b.1.operator == *op && b.1.return_ty == *ty); |                         .filter(|b| b.1.operator == op && b.1.return_ty == *ty) | ||||||
|  |                         .collect::<Vec<_>>(); | ||||||
|                     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), rhs.narrow_into(&binop.1.hands.1)) |                             lhs_resolved.narrow_into(&binop.1.hands.0), | ||||||
|                         { |                             rhs_resolved.narrow_into(&binop.1.hands.1), | ||||||
|                             *lhs = lhs_narrow; |                         ) { | ||||||
|                             *rhs = rhs_narrow |                             match &lhs { | ||||||
|  |                                 TypeKind::Vague(VagueType::TypeRef(idx)) => { | ||||||
|  |                                     let mut lhs_ref = TypeRef(Rc::new(RefCell::new(*idx)), self); | ||||||
|  |                                     let narrowed = self.narrow_to_type(&mut lhs_ref, &lhs_narrow).unwrap_or(lhs_ref); | ||||||
|  |                                 } | ||||||
|  |                                 _ => {} | ||||||
|  |                             }; | ||||||
|  |                             match &rhs { | ||||||
|  |                                 TypeKind::Vague(VagueType::TypeRef(idx)) => { | ||||||
|  |                                     let mut rhs_ref = TypeRef(Rc::new(RefCell::new(*idx)), self); | ||||||
|  |                                     let narrowed = self.narrow_to_type(&mut rhs_ref, &rhs_narrow).unwrap_or(rhs_ref); | ||||||
|  |                                 } | ||||||
|  |                                 _ => {} | ||||||
|  |                             } | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user