Fix triple-importing
This commit is contained in:
		
							parent
							
								
									8a178387ca
								
							
						
					
					
						commit
						1c3386bc9a
					
				
							
								
								
									
										5
									
								
								examples/triple_import_main.reid
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								examples/triple_import_main.reid
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| 
 | ||||
| import triple_import_vec2::Vec2; | ||||
| import triple_import_ship::Ship; | ||||
| 
 | ||||
| fn main() -> i32 { return 0; } | ||||
							
								
								
									
										3
									
								
								examples/triple_import_ship.reid
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								examples/triple_import_ship.reid
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| 
 | ||||
| import triple_import_vec2::Vec2; | ||||
| struct Ship { position: Vec2 } | ||||
							
								
								
									
										2
									
								
								examples/triple_import_vec2.reid
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								examples/triple_import_vec2.reid
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | ||||
| 
 | ||||
| struct Vec2 { x: f32, y: f32 } | ||||
| @ -743,7 +743,6 @@ pub fn analyze_block( | ||||
|                 analyze_expr(context, source_module, expression, scope); | ||||
|             } | ||||
|             mir::StmtKind::While(WhileStatement { condition, block, .. }) => { | ||||
|                 dbg!(condition); | ||||
|                 analyze_expr(context, source_module, condition, scope); | ||||
|                 analyze_block(context, source_module, block, scope); | ||||
|             } | ||||
| @ -852,8 +851,8 @@ pub fn analyze_expr( | ||||
|                 analyze_expr(context, source_module, expr, scope); | ||||
|             } | ||||
|         } | ||||
|         mir::ExprKind::Struct(struct_name, items) => { | ||||
|             let struct_type = TypeKind::CustomType(CustomTypeKey(struct_name.clone(), source_module.module_id)); | ||||
|         mir::ExprKind::Struct(key, items) => { | ||||
|             let struct_type = TypeKind::CustomType(key.clone()); | ||||
|             let struct_idx = scope | ||||
|                 .token_idx(&expr.1, |t| matches!(t, Token::Identifier(_))) | ||||
|                 .unwrap_or(expr.1.range.end); | ||||
|  | ||||
| @ -703,7 +703,6 @@ impl IntrinsicFunction for IntrinsicMemcpy { | ||||
|             .unwrap(); | ||||
|         let bytes = scope.block.build(Instr::Mul(sizeof, length.instr())).unwrap(); | ||||
| 
 | ||||
|         dbg!(self.0.size_of(&scope.type_map) / 8); | ||||
|         let params = vec![ | ||||
|             dest.instr(), | ||||
|             src.instr(), | ||||
|  | ||||
| @ -1,4 +1,8 @@ | ||||
| use std::{cell::RefCell, collections::HashMap, rc::Rc}; | ||||
| use std::{ | ||||
|     cell::RefCell, | ||||
|     collections::{HashMap, HashSet}, | ||||
|     rc::Rc, | ||||
| }; | ||||
| 
 | ||||
| use allocator::{Allocator, AllocatorScope}; | ||||
| use intrinsics::*; | ||||
| @ -180,7 +184,40 @@ impl mir::Module { | ||||
|         let mut typedefs = self.typedefs.clone(); | ||||
|         typedefs.sort_by(|a, b| b.source_module.cmp(&a.source_module)); | ||||
| 
 | ||||
|         for typedef in typedefs { | ||||
|         // Since we know by this point that no types are recursive, we can
 | ||||
|         // somewhat easily sort the type-definitions such that we can process
 | ||||
|         // the ones with no depencencies first, and later the ones that depend
 | ||||
|         // on the earlier ones.
 | ||||
|         let mut typekeys_seen = HashSet::new(); | ||||
|         let mut typedefs_sorted = Vec::new(); | ||||
|         let mut typedefs_left = typedefs.clone(); | ||||
|         typedefs_left.reverse(); | ||||
|         while let Some(typedef) = typedefs_left.pop() { | ||||
|             match &typedef.kind { | ||||
|                 TypeDefinitionKind::Struct(StructType(fields)) => { | ||||
|                     let mut is_ok = true; | ||||
|                     for field in fields { | ||||
|                         match &field.1 { | ||||
|                             TypeKind::CustomType(type_key) => { | ||||
|                                 if !typekeys_seen.contains(type_key) { | ||||
|                                     is_ok = false; | ||||
|                                     break; | ||||
|                                 } | ||||
|                             } | ||||
|                             _ => {} | ||||
|                         } | ||||
|                     } | ||||
|                     if is_ok { | ||||
|                         typekeys_seen.insert(CustomTypeKey(typedef.name.clone(), typedef.source_module)); | ||||
|                         typedefs_sorted.push(typedef); | ||||
|                     } else { | ||||
|                         typedefs_left.insert(0, typedef.clone()); | ||||
|                     } | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
| 
 | ||||
|         for typedef in typedefs_sorted { | ||||
|             let type_key = CustomTypeKey(typedef.name.clone(), typedef.source_module); | ||||
|             type_map.insert(type_key.clone(), typedef.clone()); | ||||
| 
 | ||||
| @ -190,9 +227,6 @@ impl mir::Module { | ||||
|                         typedef.name.clone(), | ||||
|                         fields | ||||
|                             .iter() | ||||
|                             // TODO: Reorder custom-type definitions such that
 | ||||
|                             // inner types get evaluated first. Otherwise this
 | ||||
|                             // will cause a panic!
 | ||||
|                             .map(|StructField(_, t, _)| t.get_type(&type_values)) | ||||
|                             .collect(), | ||||
|                     ))) | ||||
|  | ||||
| @ -111,11 +111,12 @@ impl<'map> Pass for LinkerPass<'map> { | ||||
| 
 | ||||
|         let mut modules_to_process: Vec<Rc<RefCell<_>>> = modules.values().cloned().collect(); | ||||
| 
 | ||||
|         let mut already_imported_types = HashSet::<CustomTypeKey>::new(); | ||||
|         let mut already_imported_binops = HashSet::<BinopKey>::new(); | ||||
|         let mut still_required_types = HashSet::<CustomTypeKey>::new(); | ||||
| 
 | ||||
|         while let Some(module) = modules_to_process.pop() { | ||||
|             let mut extern_types = HashMap::new(); | ||||
|             let mut already_imported_binops = HashSet::<BinopKey>::new(); | ||||
|             let mut already_imported_types = HashSet::<CustomTypeKey>::new(); | ||||
|             let mut importer_module = module.borrow_mut(); | ||||
| 
 | ||||
|             for import in importer_module.imports.clone() { | ||||
| @ -208,7 +209,7 @@ impl<'map> Pass for LinkerPass<'map> { | ||||
|                 let Some((import_name, _)) = path.get(1) else { | ||||
|                     continue; | ||||
|                 }; | ||||
|                 let import_id = imported.module_id; | ||||
|                 let imported_id = imported.module_id; | ||||
| 
 | ||||
|                 let mut imported_types = Vec::new(); | ||||
| 
 | ||||
| @ -351,7 +352,7 @@ impl<'map> Pass for LinkerPass<'map> { | ||||
|                                 return_type, | ||||
|                                 parameters: param_tys, | ||||
|                                 kind: super::FunctionDefinitionKind::Extern(true), | ||||
|                                 source: Some(import_id), | ||||
|                                 source: Some(imported_id), | ||||
|                                 signature_meta: func.signature_meta, | ||||
|                             }, | ||||
|                         )); | ||||
| @ -367,6 +368,13 @@ impl<'map> Pass for LinkerPass<'map> { | ||||
|                 let mut seen = HashSet::new(); | ||||
|                 let mut current_extern_types = HashSet::new(); | ||||
|                 seen.extend(imported_types.clone().iter().map(|t| t.0.clone())); | ||||
| 
 | ||||
|                 for ty in still_required_types.clone() { | ||||
|                     if ty.1 == imported_id && !seen.contains(&ty) { | ||||
|                         imported_types.push((ty, false)); | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 current_extern_types.extend(imported_types.clone().iter().filter(|t| t.1).map(|t| t.0.clone())); | ||||
|                 for extern_type in ¤t_extern_types { | ||||
|                     extern_types.insert(extern_type.0.clone(), extern_type.1); | ||||
| @ -378,10 +386,16 @@ impl<'map> Pass for LinkerPass<'map> { | ||||
|                 for typekey in imported_types.clone() { | ||||
|                     let typedef = imported_mod_typedefs | ||||
|                         .iter() | ||||
|                         .find(|ty| CustomTypeKey(ty.name.clone(), imported_mod_id) == typekey.0) | ||||
|                         .find(|ty| CustomTypeKey(ty.name.clone(), ty.source_module) == typekey.0) | ||||
|                         .unwrap(); | ||||
|                     let inner = find_inner_types(typedef, seen.clone(), imported_mod_id); | ||||
|                     seen.extend(inner.iter().cloned()); | ||||
|                     let inner = find_inner_types(typedef, seen.clone(), imported_mod_typedefs); | ||||
|                     for ty in inner { | ||||
|                         if ty.1 == imported_id && imported_mod_typedefs.iter().find(|t| t.name == ty.0).is_some() { | ||||
|                             seen.insert(ty); | ||||
|                         } else { | ||||
|                             still_required_types.insert(ty); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 // TODO: Unable to import same-named type from multiple places..
 | ||||
| @ -573,28 +587,31 @@ fn import_type(ty: &TypeKind, usable_import: bool) -> Vec<(CustomTypeKey, bool)> | ||||
| fn find_inner_types( | ||||
|     typedef: &TypeDefinition, | ||||
|     mut seen: HashSet<CustomTypeKey>, | ||||
|     mod_id: SourceModuleId, | ||||
|     typedefs: &Vec<TypeDefinition>, | ||||
| ) -> Vec<CustomTypeKey> { | ||||
|     match &typedef.kind { | ||||
|         crate::mir::TypeDefinitionKind::Struct(struct_type) => { | ||||
|             let typenames = struct_type | ||||
|             let typekeys = struct_type | ||||
|                 .0 | ||||
|                 .iter() | ||||
|                 .filter(|t| matches!(t.1, TypeKind::CustomType(..))) | ||||
|                 .map(|t| match &t.1 { | ||||
|                     TypeKind::CustomType(CustomTypeKey(t, _)) => t, | ||||
|                     _ => panic!(), | ||||
|                 .filter_map(|t| match &t.1 { | ||||
|                     TypeKind::CustomType(key) => Some(key), | ||||
|                     _ => None, | ||||
|                 }) | ||||
|                 .cloned() | ||||
|                 .collect::<Vec<_>>(); | ||||
| 
 | ||||
|             for typename in typenames { | ||||
|                 if seen.contains(&CustomTypeKey(typename.clone(), mod_id)) { | ||||
|             for typekey in typekeys { | ||||
|                 if seen.contains(&typekey) { | ||||
|                     continue; | ||||
|                 } | ||||
|                 let inner = find_inner_types(typedef, seen.clone(), mod_id); | ||||
|                 seen.insert(CustomTypeKey(typename, mod_id)); | ||||
|                 seen.extend(inner); | ||||
|                 seen.insert(typekey.clone()); | ||||
|                 if typekey.1 == typedef.source_module { | ||||
|                     if let Some(inner) = typedefs.iter().find(|t| t.name == typekey.0) { | ||||
|                         let ret = find_inner_types(inner, seen.clone(), typedefs); | ||||
|                         seen.extend(ret); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             seen.into_iter().collect() | ||||
|  | ||||
| @ -1,171 +0,0 @@ | ||||
| use std::{path::PathBuf, process::Command, time::SystemTime}; | ||||
| 
 | ||||
| use reid::{ | ||||
|     compile_module, | ||||
|     ld::LDRunner, | ||||
|     mir::{self}, | ||||
|     parse_module, perform_all_passes, | ||||
| }; | ||||
| use reid_lib::{compile::CompileOutput, Context}; | ||||
| use util::assert_err; | ||||
| 
 | ||||
| mod util; | ||||
| 
 | ||||
| fn test_compile(source: &str, name: &str) -> CompileOutput { | ||||
|     assert_err(assert_err(std::panic::catch_unwind(|| { | ||||
|         let mut map = Default::default(); | ||||
|         let (id, tokens) = assert_err(parse_module(source, name, None, &mut map, None)); | ||||
| 
 | ||||
|         let module = assert_err(assert_err(compile_module(id, tokens, &mut map, None, true)).map_err(|(_, e)| e)); | ||||
|         let mut mir_context = mir::Context::from(vec![module], Default::default()); | ||||
|         assert_err(perform_all_passes(&mut mir_context, &mut map)); | ||||
| 
 | ||||
|         let context = Context::new(format!("Reid ({})", env!("CARGO_PKG_VERSION"))); | ||||
| 
 | ||||
|         let codegen = assert_err(mir_context.codegen(&context)); | ||||
| 
 | ||||
|         Ok::<_, ()>(codegen.compile(None, Vec::new()).output()) | ||||
|     }))) | ||||
| } | ||||
| 
 | ||||
| fn test(source: &str, name: &str, expected_exit_code: Option<i32>) { | ||||
|     assert_err(assert_err(std::panic::catch_unwind(|| { | ||||
|         let output = test_compile(source, name); | ||||
| 
 | ||||
|         let time = SystemTime::now(); | ||||
|         let in_path = PathBuf::from(format!( | ||||
|             "/tmp/temp-{}.o", | ||||
|             time.duration_since(SystemTime::UNIX_EPOCH).unwrap().as_nanos() | ||||
|         )); | ||||
| 
 | ||||
|         std::fs::write(&in_path, &output.obj_buffer).expect("Could not write OBJ-file!"); | ||||
| 
 | ||||
|         let out_path = in_path.with_extension("out"); | ||||
|         LDRunner::from_command("ld") | ||||
|             .with_library("c") | ||||
|             .invoke(&in_path, &out_path); | ||||
|         std::fs::remove_file(in_path).unwrap(); | ||||
| 
 | ||||
|         let executed = Command::new(&out_path).output(); | ||||
|         std::fs::remove_file(out_path).unwrap(); | ||||
| 
 | ||||
|         if let Some(expected_exit_code) = expected_exit_code { | ||||
|             assert_eq!(expected_exit_code, executed.unwrap().status.code().unwrap()); | ||||
|         } | ||||
| 
 | ||||
|         Ok::<(), ()>(()) | ||||
|     }))) | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn arithmetic_compiles_well() { | ||||
|     test(include_str!("../../examples/arithmetic.reid"), "test", Some(48)); | ||||
| } | ||||
| #[test] | ||||
| fn array_structs_compiles_well() { | ||||
|     test(include_str!("../../examples/array_structs.reid"), "test", Some(5)); | ||||
| } | ||||
| #[test] | ||||
| fn array_compiles_well() { | ||||
|     test(include_str!("../../examples/array.reid"), "test", Some(3)); | ||||
| } | ||||
| #[test] | ||||
| fn borrow_compiles_well() { | ||||
|     test(include_str!("../../examples/borrow.reid"), "test", Some(17)); | ||||
| } | ||||
| #[test] | ||||
| fn borrow_hard_compiles_well() { | ||||
|     test(include_str!("../../examples/borrow_hard.reid"), "test", Some(17)); | ||||
| } | ||||
| #[test] | ||||
| fn cast_compiles_well() { | ||||
|     test(include_str!("../../examples/cast.reid"), "test", Some(6)); | ||||
| } | ||||
| #[test] | ||||
| fn char_compiles_well() { | ||||
|     test(include_str!("../../examples/char.reid"), "test", Some(98)); | ||||
| } | ||||
| #[test] | ||||
| fn div_mod_compiles_well() { | ||||
|     test(include_str!("../../examples/div_mod.reid"), "test", Some(12)); | ||||
| } | ||||
| #[test] | ||||
| fn fibonacci_compiles_well() { | ||||
|     test(include_str!("../../examples/fibonacci.reid"), "test", Some(1)); | ||||
| } | ||||
| #[test] | ||||
| fn float_compiles_well() { | ||||
|     test(include_str!("../../examples/float.reid"), "test", Some(1)); | ||||
| } | ||||
| #[test] | ||||
| fn hello_world_compiles_well() { | ||||
|     test(include_str!("../../examples/hello_world.reid"), "test", None); | ||||
| } | ||||
| #[test] | ||||
| fn hello_world_harder_compiles_well() { | ||||
|     test(include_str!("../../examples/hello_world_harder.reid"), "test", None); | ||||
| } | ||||
| #[test] | ||||
| fn mutable_compiles_well() { | ||||
|     test(include_str!("../../examples/mutable.reid"), "test", Some(21)); | ||||
| } | ||||
| #[test] | ||||
| fn ptr_compiles_well() { | ||||
|     test(include_str!("../../examples/ptr.reid"), "test", Some(5)); | ||||
| } | ||||
| #[test] | ||||
| fn std_test_compiles_well() { | ||||
|     test(include_str!("../../examples/std_test.reid"), "test", Some(3)); | ||||
| } | ||||
| #[test] | ||||
| fn strings_compiles_well() { | ||||
|     test(include_str!("../../examples/strings.reid"), "test", Some(5)); | ||||
| } | ||||
| #[test] | ||||
| fn struct_compiles_well() { | ||||
|     test(include_str!("../../examples/struct.reid"), "test", Some(17)); | ||||
| } | ||||
| #[test] | ||||
| fn loops_compiles_well() { | ||||
|     test(include_str!("../../examples/loops.reid"), "test", Some(10)); | ||||
| } | ||||
| #[test] | ||||
| fn ptr_hard_compiles_well() { | ||||
|     test(include_str!("../../examples/ptr_hard.reid"), "test", Some(0)); | ||||
| } | ||||
| #[test] | ||||
| fn loop_hard_compiles_well() { | ||||
|     test(include_str!("../../examples/loop_hard.reid"), "test", Some(0)); | ||||
| } | ||||
| #[test] | ||||
| fn custom_binop_compiles_well() { | ||||
|     test(include_str!("../../examples/custom_binop.reid"), "test", Some(21)); | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn array_short_compiles_well() { | ||||
|     test(include_str!("../../examples/array_short.reid"), "test", Some(5)); | ||||
| } | ||||
| #[test] | ||||
| 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(4), | ||||
|     ); | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn mutable_inner_functions() { | ||||
|     test(include_str!("../../examples/mutable_inner.reid"), "test", Some(0)); | ||||
| } | ||||
| 
 | ||||
| #[test] | ||||
| fn cpu_raytracer_compiles() { | ||||
|     test_compile(include_str!("../../examples/cpu_raytracer.reid"), "test"); | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user