Test associated functions, cleanup codegen a bit
This commit is contained in:
		
							parent
							
								
									537167fe4f
								
							
						
					
					
						commit
						f3471473a2
					
				| @ -24,5 +24,5 @@ fn main() -> u32 { | ||||
|     print(from_str("i32: ") + i32::test(54) as u64); | ||||
|     print(from_str("sizeof i32: ") + i32::sizeof()); | ||||
| 
 | ||||
|     return Otus::test(&otus); | ||||
|     return i32::sizeof() as u32; | ||||
| } | ||||
|  | ||||
| @ -18,7 +18,7 @@ use crate::{ | ||||
|         self, | ||||
|         implement::TypeCategory, | ||||
|         pass::{AssociatedFunctionKey, BinopKey}, | ||||
|         CustomTypeKey, FunctionDefinitionKind, NamedVariableRef, SourceModuleId, StructField, StructType, | ||||
|         CustomTypeKey, FunctionCall, FunctionDefinitionKind, NamedVariableRef, SourceModuleId, StructField, StructType, | ||||
|         TypeDefinition, TypeDefinitionKind, TypeKind, WhileStatement, | ||||
|     }, | ||||
|     util::try_all, | ||||
| @ -898,72 +898,7 @@ impl mir::Expression { | ||||
|                     )) | ||||
|                 } | ||||
|             } | ||||
|             mir::ExprKind::FunctionCall(call) => { | ||||
|                 let ret_type_kind = call.return_type.known().expect("function return type unknown"); | ||||
| 
 | ||||
|                 let ret_type = ret_type_kind.get_type(scope.type_values); | ||||
| 
 | ||||
|                 let params = try_all( | ||||
|                     call.parameters | ||||
|                         .iter() | ||||
|                         .map(|e| e.codegen(scope, state)) | ||||
|                         .collect::<Vec<_>>(), | ||||
|                 ) | ||||
|                 .map_err(|e| e.first().cloned().unwrap())? | ||||
|                 .into_iter() | ||||
|                 .map(|v| v.unwrap()) | ||||
|                 .collect::<Vec<_>>(); | ||||
| 
 | ||||
|                 let callee = scope.functions.get(&call.name).expect("function not found!"); | ||||
| 
 | ||||
|                 let val = callee.codegen( | ||||
|                     &call.name, | ||||
|                     params.as_slice(), | ||||
|                     &call.return_type, | ||||
|                     if let Some(debug) = &scope.debug { | ||||
|                         call.meta.into_debug(scope.tokens, debug.scope) | ||||
|                     } else { | ||||
|                         None | ||||
|                     }, | ||||
|                     scope, | ||||
|                 )?; | ||||
| 
 | ||||
|                 let ptr = if ret_type_kind != TypeKind::Void { | ||||
|                     let ptr = scope | ||||
|                         .block | ||||
|                         .build_named(&call.name, Instr::Alloca(ret_type.clone())) | ||||
|                         .unwrap(); | ||||
|                     scope | ||||
|                         .block | ||||
|                         .build_named(format!("{}.store", call.name), Instr::Store(ptr, val.instr())) | ||||
|                         .unwrap(); | ||||
| 
 | ||||
|                     Some(ptr) | ||||
|                 } else { | ||||
|                     None | ||||
|                 }; | ||||
| 
 | ||||
|                 if let Some(ptr) = ptr { | ||||
|                     if state.should_load { | ||||
|                         Some(StackValue( | ||||
|                             StackValueKind::Immutable( | ||||
|                                 scope | ||||
|                                     .block | ||||
|                                     .build_named(call.name.clone(), Instr::Load(ptr, ret_type)) | ||||
|                                     .unwrap(), | ||||
|                             ), | ||||
|                             ret_type_kind, | ||||
|                         )) | ||||
|                     } else { | ||||
|                         Some(StackValue( | ||||
|                             StackValueKind::Immutable(ptr), | ||||
|                             TypeKind::CodegenPtr(Box::new(ret_type_kind)), | ||||
|                         )) | ||||
|                     } | ||||
|                 } else { | ||||
|                     None | ||||
|                 } | ||||
|             } | ||||
|             mir::ExprKind::FunctionCall(call) => codegen_function_call(None, call, scope, state)?, | ||||
|             mir::ExprKind::If(if_expression) => if_expression.codegen(scope, state)?, | ||||
|             mir::ExprKind::Block(block) => { | ||||
|                 let inner = scope.function.block("inner"); | ||||
| @ -1323,9 +1258,27 @@ impl mir::Expression { | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             mir::ExprKind::AssociatedFunctionCall(ty, call) => { | ||||
|             mir::ExprKind::AssociatedFunctionCall(ty, call) => codegen_function_call(Some(ty), call, scope, state)?, | ||||
|         }; | ||||
|         if let Some(value) = &value { | ||||
|             value.instr().maybe_location(&mut scope.block, location); | ||||
|         } | ||||
|         Ok(value) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn codegen_function_call<'ctx, 'a>( | ||||
|     associated_type: Option<&TypeKind>, | ||||
|     call: &FunctionCall, | ||||
|     scope: &mut Scope<'ctx, 'a>, | ||||
|     state: &State, | ||||
| ) -> Result<Option<StackValue>, ErrorKind> { | ||||
|     let ret_type_kind = call.return_type.known().expect("function return type unknown"); | ||||
|                 let call_name = format!("{}::{}", ty, call.name); | ||||
|     let call_name = if let Some(ty) = &associated_type { | ||||
|         format!("{}::{}", ty, call.name) | ||||
|     } else { | ||||
|         String::from(call.name.clone()) | ||||
|     }; | ||||
| 
 | ||||
|     let ret_type = ret_type_kind.get_type(scope.type_values); | ||||
| 
 | ||||
| @ -1340,9 +1293,16 @@ impl mir::Expression { | ||||
|     .map(|v| v.unwrap()) | ||||
|     .collect::<Vec<_>>(); | ||||
| 
 | ||||
|     let location = if let Some(debug) = &scope.debug { | ||||
|         call.meta.into_debug(scope.tokens, debug.scope) | ||||
|     } else { | ||||
|         None | ||||
|     }; | ||||
| 
 | ||||
|     let val = if let Some(ty) = associated_type { | ||||
|         let assoc_key = AssociatedFunctionKey(ty.clone(), call.name.clone()); | ||||
|                 let intrinsic = get_intrinsic_assoc_func(&ty, &call.name); | ||||
|                 let intrinsic_owned = intrinsic.map(|func_def| { | ||||
|         let intrinsic_def = get_intrinsic_assoc_func(&ty, &call.name); | ||||
|         let intrinsic = intrinsic_def.map(|func_def| { | ||||
|             let FunctionDefinitionKind::Intrinsic(intrinsic) = func_def.kind else { | ||||
|                 panic!(); | ||||
|             }; | ||||
| @ -1351,18 +1311,21 @@ impl mir::Expression { | ||||
|         let callee = scope | ||||
|             .assoc_functions | ||||
|             .get(&assoc_key) | ||||
|                     .or(intrinsic_owned.as_ref()) | ||||
|             .or(intrinsic.as_ref()) | ||||
|             .expect(&format!("Function {} does not exist!", call_name)); | ||||
|         callee | ||||
|             .codegen(&call_name, params.as_slice(), &call.return_type, location, scope) | ||||
|             .unwrap() | ||||
|     } else { | ||||
|         let callee = scope | ||||
|             .functions | ||||
|             .get(&call.name) | ||||
|             .expect(&format!("Function {} does not exist!", call_name)); | ||||
| 
 | ||||
|                 let location = if let Some(debug) = &scope.debug { | ||||
|                     call.meta.into_debug(scope.tokens, debug.scope) | ||||
|                 } else { | ||||
|                     None | ||||
|                 }; | ||||
| 
 | ||||
|                 let val = callee | ||||
|         callee | ||||
|             .codegen(&call_name, params.as_slice(), &call.return_type, location, scope) | ||||
|                     .unwrap(); | ||||
|             .unwrap() | ||||
|     }; | ||||
| 
 | ||||
|     let ptr = if ret_type_kind != TypeKind::Void { | ||||
|         let ptr = scope | ||||
| @ -1379,7 +1342,7 @@ impl mir::Expression { | ||||
|         None | ||||
|     }; | ||||
| 
 | ||||
|                 if let Some(ptr) = ptr { | ||||
|     Ok(if let Some(ptr) = ptr { | ||||
|         if state.should_load { | ||||
|             Some(StackValue( | ||||
|                 StackValueKind::Immutable( | ||||
| @ -1398,14 +1361,7 @@ impl mir::Expression { | ||||
|         } | ||||
|     } else { | ||||
|         None | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
|         if let Some(value) = &value { | ||||
|             value.instr().maybe_location(&mut scope.block, location); | ||||
|         } | ||||
|         Ok(value) | ||||
|     } | ||||
|     }) | ||||
| } | ||||
| 
 | ||||
| impl mir::IfExpression { | ||||
|  | ||||
| @ -143,3 +143,12 @@ fn array_short_compiles_well() { | ||||
| fn imported_type_compiles_well() { | ||||
|     test(include_str!("../../examples/imported_type.reid"), "test", Some(0)); | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn associated_functions() { | ||||
|     test( | ||||
|         include_str!("../../examples/associated_functions.reid"), | ||||
|         "test", | ||||
|         Some(32), | ||||
|     ); | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user