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("i32: ") + i32::test(54) as u64); | ||||||
|     print(from_str("sizeof i32: ") + i32::sizeof()); |     print(from_str("sizeof i32: ") + i32::sizeof()); | ||||||
| 
 | 
 | ||||||
|     return Otus::test(&otus); |     return i32::sizeof() as u32; | ||||||
| } | } | ||||||
|  | |||||||
| @ -18,7 +18,7 @@ use crate::{ | |||||||
|         self, |         self, | ||||||
|         implement::TypeCategory, |         implement::TypeCategory, | ||||||
|         pass::{AssociatedFunctionKey, BinopKey}, |         pass::{AssociatedFunctionKey, BinopKey}, | ||||||
|         CustomTypeKey, FunctionDefinitionKind, NamedVariableRef, SourceModuleId, StructField, StructType, |         CustomTypeKey, FunctionCall, FunctionDefinitionKind, NamedVariableRef, SourceModuleId, StructField, StructType, | ||||||
|         TypeDefinition, TypeDefinitionKind, TypeKind, WhileStatement, |         TypeDefinition, TypeDefinitionKind, TypeKind, WhileStatement, | ||||||
|     }, |     }, | ||||||
|     util::try_all, |     util::try_all, | ||||||
| @ -898,72 +898,7 @@ impl mir::Expression { | |||||||
|                     )) |                     )) | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             mir::ExprKind::FunctionCall(call) => { |             mir::ExprKind::FunctionCall(call) => codegen_function_call(None, call, scope, state)?, | ||||||
|                 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::If(if_expression) => if_expression.codegen(scope, state)?, |             mir::ExprKind::If(if_expression) => if_expression.codegen(scope, state)?, | ||||||
|             mir::ExprKind::Block(block) => { |             mir::ExprKind::Block(block) => { | ||||||
|                 let inner = scope.function.block("inner"); |                 let inner = scope.function.block("inner"); | ||||||
| @ -1323,83 +1258,7 @@ impl mir::Expression { | |||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             mir::ExprKind::AssociatedFunctionCall(ty, call) => { |             mir::ExprKind::AssociatedFunctionCall(ty, call) => codegen_function_call(Some(ty), call, scope, state)?, | ||||||
|                 let ret_type_kind = call.return_type.known().expect("function return type unknown"); |  | ||||||
|                 let call_name = format!("{}::{}", ty, call.name); |  | ||||||
| 
 |  | ||||||
|                 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 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 FunctionDefinitionKind::Intrinsic(intrinsic) = func_def.kind else { |  | ||||||
|                         panic!(); |  | ||||||
|                     }; |  | ||||||
|                     ScopeFunctionKind::IntrinsicOwned(intrinsic) |  | ||||||
|                 }); |  | ||||||
|                 let callee = scope |  | ||||||
|                     .assoc_functions |  | ||||||
|                     .get(&assoc_key) |  | ||||||
|                     .or(intrinsic_owned.as_ref()) |  | ||||||
|                     .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 |  | ||||||
|                     .codegen(&call_name, params.as_slice(), &call.return_type, location, scope) |  | ||||||
|                     .unwrap(); |  | ||||||
| 
 |  | ||||||
|                 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 |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         }; |         }; | ||||||
|         if let Some(value) = &value { |         if let Some(value) = &value { | ||||||
|             value.instr().maybe_location(&mut scope.block, location); |             value.instr().maybe_location(&mut scope.block, location); | ||||||
| @ -1408,6 +1267,103 @@ impl mir::Expression { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 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 = 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); | ||||||
|  | 
 | ||||||
|  |     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 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_def = get_intrinsic_assoc_func(&ty, &call.name); | ||||||
|  |         let intrinsic = intrinsic_def.map(|func_def| { | ||||||
|  |             let FunctionDefinitionKind::Intrinsic(intrinsic) = func_def.kind else { | ||||||
|  |                 panic!(); | ||||||
|  |             }; | ||||||
|  |             ScopeFunctionKind::IntrinsicOwned(intrinsic) | ||||||
|  |         }); | ||||||
|  |         let callee = scope | ||||||
|  |             .assoc_functions | ||||||
|  |             .get(&assoc_key) | ||||||
|  |             .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)); | ||||||
|  | 
 | ||||||
|  |         callee | ||||||
|  |             .codegen(&call_name, params.as_slice(), &call.return_type, location, scope) | ||||||
|  |             .unwrap() | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     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 | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     Ok(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 | ||||||
|  |     }) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| impl mir::IfExpression { | impl mir::IfExpression { | ||||||
|     fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, state: &State) -> Result<Option<StackValue>, ErrorKind> { |     fn codegen<'ctx, 'a>(&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(); | ||||||
|  | |||||||
| @ -143,3 +143,12 @@ fn array_short_compiles_well() { | |||||||
| fn imported_type_compiles_well() { | fn imported_type_compiles_well() { | ||||||
|     test(include_str!("../../examples/imported_type.reid"), "test", Some(0)); |     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