From 269de327b8ceec577d0bec9211e7bf01c844cf1d Mon Sep 17 00:00:00 2001 From: sofia Date: Sat, 26 Jul 2025 00:56:51 +0300 Subject: [PATCH] Allow importing types --- examples/a.reid | 16 +- foo.reid | 469 ---------------------------- reid/src/ast/process.rs | 1 + reid/src/mir/fmt.rs | 12 +- reid/src/mir/linker.rs | 288 ++++++++--------- reid/src/mir/mod.rs | 1 + reid/src/mir/typecheck/typecheck.rs | 9 +- 7 files changed, 173 insertions(+), 623 deletions(-) delete mode 100644 foo.reid diff --git a/examples/a.reid b/examples/a.reid index 8b53d10..aea7789 100644 --- a/examples/a.reid +++ b/examples/a.reid @@ -1,6 +1,12 @@ -pub fn abs(f: f32) -> f32 { - if f < 0.0 { - return f * (0.0 - 1.0); - } - return f; + +import std::print; +import std::new_string; +import std::String; + +fn otus() -> String { + return new_string(); } + +fn main() -> u8 { + return 0; +} \ No newline at end of file diff --git a/foo.reid b/foo.reid deleted file mode 100644 index 5d6e980..0000000 --- a/foo.reid +++ /dev/null @@ -1,469 +0,0 @@ -import std::concat_strings; -import std::print; -import std::from_str; -import std::free_string; -import std::add_num_to_str; - -/////////////////// -/// SDL externs /// -/////////////////// - -// Helper struct for stack allocated const sized strings, because structs are -// easier to create uninit than arrays. -struct SDL_Window {} -struct SDL_Renderer {} -struct SDL_Texture {} -struct SDL_Event { type: u32, reserved: [u8; 124] } -struct SDL_FRect { x: f32, y: f32, w: f32, h: f32 } -struct SDL_Rect { x: i32, y: i32, w: i32, h: i32 } -extern fn SDL_malloc(size: u64) -> *u8; -extern fn SDL_Init(flags: u32) -> bool; -extern fn SDL_Quit(); -extern fn SDL_CreateWindowAndRenderer(title: *char, width: i32, height: i32, flags: i32, - window_out: &mut *SDL_Window, renderer_out: &mut *SDL_Renderer) -> bool; -extern fn SDL_Delay(ms: u32); -extern fn SDL_SetRenderDrawColor(renderer: *SDL_Renderer, r: u8, g: u8, b: u8, a: u8); -extern fn SDL_RenderClear(renderer: *SDL_Renderer); -extern fn SDL_RenderPresent(renderer: *SDL_Renderer); -extern fn SDL_HasEvent(event_type: u32) -> bool; -extern fn SDL_PollEvent(event: &mut SDL_Event) -> bool; -extern fn SDL_PumpEvents(); -extern fn SDL_FlushEvents(min_type: u32, max_type: u32); -extern fn SDL_GetTicks() -> u64; -extern fn SDL_SetWindowTitle(window: *SDL_Window, title: *char) -> bool; -extern fn SDL_CreateTexture(renderer: *SDL_Renderer, - pixel_format: u32, texture_access: u32, width: u32, height: u32) -> *SDL_Texture; -extern fn SDL_RenderTexture(renderer: *SDL_Renderer, - texture: *SDL_Texture, srcfrect: &SDL_FRect, dstfrect: &SDL_FRect) -> bool; -extern fn SDL_UpdateTexture(texture: *SDL_Texture, rect: &SDL_Rect, pixels: *u8, pitch: u32) -> bool; -extern fn SDL_GetError() -> *char; -extern fn SDL_GetWindowSize(window: *SDL_Window, w: &mut i32, h: &mut i32) -> bool; -extern fn SDL_rand(max_exclusive: u32) -> u32; -extern fn SDL_SetTextureScaleMode(texture: *SDL_Texture, scale_mode: i32) -> bool; -extern fn SDL_sqrtf(value: f32) -> f32; -extern fn SDL_randf() -> f32; -extern fn SDL_powf(value: f32, power: f32) -> f32; - -// SDL error reporting helper -fn print_sdl_error(context: *char) { - let mut message = from_str(context); - - let delim = from_str(": "); - concat_strings(&mut message, delim); - free_string(&delim); - - let error_msg = from_str(SDL_GetError()); - concat_strings(&mut message, error_msg); - free_string(&error_msg); - - print(message); - - free_string(&message); -} - -///////////////////////////////// -/// Main setup and frame loop /// -///////////////////////////////// - -struct GameState { - renderer: *SDL_Renderer, - window: *SDL_Window, - render_texture: *SDL_Texture, - frame_counter: u32, - last_fps_reset: u64, - pixels: *u8, - pixels_w: u32, - pixels_h: u32, - pixels_bpp: u32, -} - -fn main() -> i32 { - let SDL_INIT_VIDEO = 32; - let SDL_WINDOW_RESIZABLE = 32; - let SDL_PIXELFORMAT_RGBA8888 = 373694468; - let SDL_PIXELFORMAT_ABGR8888 = 376840196; - let SDL_PIXELFORMAT_RGB24 = 386930691; - let SDL_PIXELFORMAT_BGR24 = 390076419; - let SDL_PIXELFORMAT_RGB96_FLOAT = 454057996; - let SDL_PIXELFORMAT_BGR96_FLOAT = 457203724; - let SDL_TEXTUREACCESS_STREAMING = 1; - let SDL_SCALEMODE_NEAREST = 0; - let SDL_SCALEMODE_LINEAR = 1; - let SDL_SCALEMODE_PIXELART = 2; - - let init_success = SDL_Init(SDL_INIT_VIDEO); - if init_success == false { - print_sdl_error("SDL init failed"); - return 1; - } - - let mut window = SDL_malloc(1) as *SDL_Window; - let mut renderer = SDL_malloc(1) as *SDL_Renderer; - let gfx_init_success = SDL_CreateWindowAndRenderer( - "graphical reid program", 640, 480, SDL_WINDOW_RESIZABLE, - &mut window, &mut renderer - ); - if gfx_init_success == false { - print_sdl_error("SDL renderer and window creation failed"); - return 1; - } - - let width = 320; - let height = 240; - let bpp = 4; - let render_texture = SDL_CreateTexture(renderer, - SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, width, height); - SDL_SetTextureScaleMode(render_texture, SDL_SCALEMODE_NEAREST); - - let pixels_len = (width * height * bpp) as u64; - let pixels = SDL_malloc(pixels_len); - let mut game_state = GameState { - renderer: renderer, - window: window, - render_texture: render_texture, - frame_counter: 0, - last_fps_reset: 0, - pixels: pixels, - pixels_w: width, - pixels_h: height, - pixels_bpp: bpp, - }; - - while frame_loop(&mut game_state) {} - - SDL_Quit(); - return 0; -} - -fn frame_loop(game_state: &mut GameState) -> bool { - let mut event = SDL_Event {}; - while (SDL_PollEvent(&mut event)) { - if event.type == 256 { // SDL_EVENT_QUIT - return false; - } - } - - let mut screen_width = 0; - let mut screen_height = 0; - SDL_GetWindowSize(*game_state.window, &mut screen_width, &mut screen_height); - - let renderer = *game_state.renderer; - SDL_SetRenderDrawColor(renderer, 0, 50, 90, 255); - SDL_RenderClear(renderer); - - let w = *game_state.pixels_w; - let h = *game_state.pixels_h; - let bpp = *game_state.pixels_bpp; - for y in 0..h { - for x in 0..w { - render_pixel(x, y, game_state); - } - } - - let texture_area = SDL_Rect { x: 0, y: 0, w: w as i32, h: h as i32 }; - if SDL_UpdateTexture(*game_state.render_texture, &texture_area, *game_state.pixels as *u8, bpp * w) == false { - print_sdl_error("UpdateTexture error"); - } - let src = SDL_FRect { x: 0.0, y: 0.0, w: w as f32, h: h as f32 }; - let aspect_ratio = src.w / src.h; - let scaled_width = screen_height as f32 * aspect_ratio; - let dst = SDL_FRect { x: (screen_width as f32 - scaled_width) / 2.0, y: 0.0, w: scaled_width, h: screen_height as f32 }; - if SDL_RenderTexture(renderer, *game_state.render_texture, &src, &dst) == false { - print_sdl_error("RenderTexture error"); - } - - SDL_RenderPresent(renderer); - SDL_Delay(1); - - *game_state.frame_counter = *game_state.frame_counter + 1; - let t = SDL_GetTicks(); - if (t - *game_state.last_fps_reset) >= 1000 { - let mut title = from_str("graphical reid program "); - add_num_to_str(&mut title, *game_state.frame_counter as u64); - let fps_unit = from_str(" fps"); - concat_strings(&mut title, fps_unit); - free_string(&fps_unit); - SDL_SetWindowTitle(*game_state.window, title.inner); - free_string(&title); - *game_state.frame_counter = 0; - *game_state.last_fps_reset = t; - } - - return true; -} - -fn render_pixel(x: u32, y: u32, game_state: &mut GameState) { - let w = *game_state.pixels_w; - let h = *game_state.pixels_h; - let bpp = *game_state.pixels_bpp; - - let samples = 1; - let old_sample_weight = 0.75; - let new_sample_weight = 0.25 / samples as f32; - let mut rgb = vec_mul_scalar(old_sample_weight, [ - srgb_to_linear(*game_state.pixels[(x + y * w) * bpp + 0]), - srgb_to_linear(*game_state.pixels[(x + y * w) * bpp + 1]), - srgb_to_linear(*game_state.pixels[(x + y * w) * bpp + 2]) - ]); - for sample in 0..samples { - rgb = vec_add(rgb, vec_mul_scalar(new_sample_weight, shade(x, y, *game_state.frame_counter, w, h))); - } - *game_state.pixels[(x + y * w) * bpp + 0] = linear_to_srgb(rgb[0]); - *game_state.pixels[(x + y * w) * bpp + 1] = linear_to_srgb(rgb[1]); - *game_state.pixels[(x + y * w) * bpp + 2] = linear_to_srgb(rgb[2]); - *game_state.pixels[(x + y * w) * bpp + 3] = 255; -} - - -///////////////// -/// Rendering /// -///////////////// - -struct Ray { - origin: [f32; 3], - direction: [f32; 3], -} - -struct Material { - // 0 = lambertian diffuse - // 1 = mirror - type: u32, - // Generally the "color" of the surface (linear factors of how much of each - // color channel this surface does not absorb), but the idea is that the - // type governs what this means. - linear_color: [f32; 3], -} - -struct Hit { - hit: bool, - front_face: bool, - distance: f32, - normal: [f32; 3], - position: [f32; 3], - material: Material, -} - -struct Sphere { - center: [f32; 3], - radius: f32, - material: Material, -} - -fn shade(x: u32, y: u32, t: u32, w: u32, h: u32) -> [f32; 3] { - let jitter_x = SDL_randf() - 0.5; - let jitter_y = SDL_randf() - 0.5; - - let pixel_scale = 1.0 / h as f32; - let pixel_pos = [ - (x as f32 + jitter_x) * pixel_scale, - 1.0 - (y as f32 + jitter_y) * pixel_scale, - 0.0 - 1.0 - ]; - let camera_pos = [w as f32 * 0.5f32 * pixel_scale, h as f32 * 0.5f32 * pixel_scale, 0.0f32]; - let dir = vec_normalize(vec_sub(pixel_pos, camera_pos)); - let ray = Ray { origin: camera_pos, direction: dir }; - let beige_lambertian = Material { type: 0, linear_color: [0.3, 0.2, 0.1] }; - let green_lambertian = Material { type: 0, linear_color: [0.1, 0.5, 0.06] }; - let greenish_mirror = Material { type: 1, linear_color: [0.9, 1.0, 0.95] }; - let spheres = [ - // Ground - Sphere { center: vec_sub(camera_pos, [0.0, 100001.0, 0.0]), radius: 100000.0, material: beige_lambertian }, - // Centered unit sphere - Sphere { center: vec_add(camera_pos, [0.0, 0.0, 0.0 - 5.0]), radius: 1.0, material: green_lambertian }, - // The unit sphere on the right - Sphere { center: vec_add(camera_pos, [2.0, 0.0, 0.0 - 6.0]), radius: 1.0, material: greenish_mirror } - ]; - return shade_world(ray, &spheres, 3); -} - -fn shade_world(ray: Ray, spheres: &[Sphere; 3], bounces_left: u8) -> [f32; 3] { - if bounces_left == 0 { - return [0.0, 0.0, 0.0]; - } - - let ray_distance = 100.0; - let mut closest_hit = Hit { hit: false, front_face: false, distance: ray_distance }; - for i in 0..3 { - let sphere_hit = ray_sphere_closest_hit(ray, *spheres[i], [0.001, closest_hit.distance]); - if sphere_hit.hit { - closest_hit = sphere_hit; - } - } - - if closest_hit.hit { - //return vec_mul_scalar(0.5, vec_add(closest_hit.normal, [1.0, 1.0, 1.0])); // normal - //return vec_mul_scalar(closest_hit.distance / 10.0, [1.0, 1.0, 1.0]); // depth - if closest_hit.material.type == 0 { - let bounce_dir = vec_normalize(vec_add(closest_hit.normal, random_unit_vec())); - let bounce_ray = Ray { origin: closest_hit.position, direction: bounce_dir }; - return vec_mul_componentwise( - closest_hit.material.linear_color, - shade_world(bounce_ray, spheres, bounces_left - 1) - ); - } else if closest_hit.material.type == 1 { - let bounce_dir = vec_reflect(ray.direction, closest_hit.normal); - let bounce_ray = Ray { origin: closest_hit.position, direction: bounce_dir }; - return vec_mul_componentwise( - closest_hit.material.linear_color, - shade_world(bounce_ray, spheres, bounces_left - 1) - ); - } else { - return [1.0, 0.0, 1.0]; - } - } - - return shade_sky(ray); -} - -fn shade_sky(ray: Ray) -> [f32; 3] { - let a = 0.5 * (ray.direction[1] + 1.0); - return vec_add( - vec_mul_scalar(1.0 - a, [1.0, 1.0, 1.0]), - vec_mul_scalar(a, [0.5, 0.7, 1.0]) - ); -} - -// Returns the distance from the ray origin to the sphere, or -1.0 if the ray doesn't hit. -fn ray_sphere_closest_hit(ray: Ray, sphere: Sphere, interval: [f32; 2]) -> Hit { - let to_sphere = vec_sub(sphere.center, ray.origin); - let h = vec_dot(ray.direction, to_sphere); - let c = vec_length_squared(to_sphere) - sphere.radius * sphere.radius; - let discriminant = h * h - c; - if discriminant < 0.0 { - return Hit { hit: false }; - } - - let discriminant_sqrt = SDL_sqrtf(discriminant); - let mut distance = h - discriminant_sqrt; - if interval_surrounds(interval, distance) == false { - distance = h - discriminant_sqrt; - if interval_surrounds(interval, distance) == false { - return Hit { hit: false }; - } - } - let hit_position = vec_add(ray.origin, vec_mul_scalar(distance, ray.direction)); - let mut front_face = true; - let mut normal = vec_normalize(vec_sub(hit_position, sphere.center)); - if vec_dot(normal, ray.direction) > 0.0 { - normal = vec_mul_scalar(0.0 - 1.0, normal); - front_face = false; - } - - return Hit { - hit: true, - front_face: front_face, - distance: distance, - normal: normal, - position: hit_position, - material: sphere.material, - }; -} - - -////////////////// -/// Other math /// -////////////////// - -fn clamp(min: f32, max: f32, value: f32) -> f32 { - if value > max { - return max; - } - if value < min { - return min; - } - return value; -} - -fn abs(f: f32) -> f32 { - if f < 0.0 { - return f * (0.0 - 1.0); - } - return f; -} - -fn vec_add(lhs: [f32; 3], rhs: [f32; 3]) -> [f32; 3] { - return [lhs[0] + rhs[0], lhs[1] + rhs[1], lhs[2] + rhs[2]]; -} - -fn vec_sub(lhs: [f32; 3], rhs: [f32; 3]) -> [f32; 3] { - return [lhs[0] - rhs[0], lhs[1] - rhs[1], lhs[2] - rhs[2]]; -} - -fn vec_dot(lhs: [f32; 3], rhs: [f32; 3]) -> f32 { - return lhs[0] * rhs[0] + lhs[1] * rhs[1] + lhs[2] * rhs[2]; -} - -fn vec_mul_componentwise(lhs: [f32; 3], rhs: [f32; 3]) -> [f32; 3] { - return [lhs[0] * rhs[0], lhs[1] * rhs[1], lhs[2] * rhs[2]]; -} - -fn vec_mul_scalar(lhs: f32, rhs: [f32; 3]) -> [f32; 3] { - return [lhs * rhs[0], lhs * rhs[1], lhs * rhs[2]]; -} - -fn vec_normalize(v: [f32; 3]) -> [f32; 3] { - let len_reciprocal = 1.0f32 / SDL_sqrtf(vec_length_squared(v)); - return vec_mul_scalar(len_reciprocal, v); -} - -fn vec_length_squared(v: [f32; 3]) -> f32 { - return v[0] * v[0] + v[1] * v[1] + v[2] * v[2]; -} - -fn vec_abs(v: [f32; 3]) -> [f32; 3] { - return [abs(v[0]), abs(v[1]), abs(v[2])]; -} - -fn vec_reflect(direction: [f32; 3], normal: [f32; 3]) -> [f32; 3] { - return vec_sub(direction, vec_mul_scalar(2.0f32 * vec_dot(direction, normal), normal)); -} - -fn interval_surrounds(interval: [f32; 2], value: f32) -> bool { - return (interval[0] < value) && (value < interval[1]); -} - -fn random_unit_vec() -> [f32; 3] { - let mut point = [ - SDL_randf() * 2.0f32 - 1.0f32, - SDL_randf() * 2.0f32 - 1.0f32, - SDL_randf() * 2.0f32 - 1.0f32 - ]; - let mut lensq = vec_length_squared(point); - while lensq > 1.0 { - point = [ - SDL_randf() * 2.0f32 - 1.0f32, - SDL_randf() * 2.0f32 - 1.0f32, - SDL_randf() * 2.0f32 - 1.0f32 - ]; - lensq = vec_length_squared(point); - } - let len_reciprocal = 1.0f32 / SDL_sqrtf(lensq); - return vec_mul_scalar(len_reciprocal, point); -} - -fn random_unit_vec_on_hemi(normal: [f32; 3]) -> [f32; 3] { - let rand_vec = random_unit_vec(); - if vec_dot(rand_vec, normal) < 0.0f32 { - return vec_mul_scalar(0.0f32 - 1.0f32, rand_vec); - } - return rand_vec; -} - -fn linear_to_srgb(linear: f32) -> u8 { - let mut floating_srgb = 0.0; - if linear <= 0.0031308f32 { - floating_srgb = 12.92f32 * linear; - } else { - floating_srgb = SDL_powf(linear as f32, 1.0 / 2.4) * 1.055f32 - 0.055f32; - } - let clamped = clamp(0.0, 1.0, floating_srgb); - return (clamped * 255.999) as u8; -} - -fn srgb_to_linear(srgb: u8) -> f32 { - let floating_srgb = srgb as f32 / 255.0; - if floating_srgb <= 0.04045f32 { - return floating_srgb / 12.92f32; - } - return SDL_powf((floating_srgb as f32 + 0.055) / 1.055, 2.4); -} diff --git a/reid/src/ast/process.rs b/reid/src/ast/process.rs index 5f670c4..6d161fc 100644 --- a/reid/src/ast/process.rs +++ b/reid/src/ast/process.rs @@ -95,6 +95,7 @@ impl ast::Module { }, meta: (*range).as_meta(module_id), source_module: module_id, + importer: None, }; typedefs.push(def); } diff --git a/reid/src/mir/fmt.rs b/reid/src/mir/fmt.rs index d247bf4..52b05bc 100644 --- a/reid/src/mir/fmt.rs +++ b/reid/src/mir/fmt.rs @@ -75,7 +75,17 @@ impl Display for BinopDefinition { impl Display for TypeDefinition { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "type {} = ", self.name)?; + write!( + f, + "type {} (mod {}{}) = ", + self.name, + self.source_module, + if let Some(mod_id) = self.importer { + format!("; imported to {}", mod_id) + } else { + String::new() + } + )?; Display::fmt(&self.kind, f) } } diff --git a/reid/src/mir/linker.rs b/reid/src/mir/linker.rs index b962249..cccb093 100644 --- a/reid/src/mir/linker.rs +++ b/reid/src/mir/linker.rs @@ -31,8 +31,8 @@ pub enum ErrorKind { ModuleNotFound(String), #[error("Error while compiling module {0}: {1}")] ModuleCompilationError(String, String), - #[error("No such function {0} found in module {1}")] - NoSuchFunctionInModule(String, String), + #[error("No such value {0} found in module {1}")] + ImportDoesNotExist(String, String), #[error("Importing function {0}::{1} not possible: {2}")] FunctionImportIssue(String, String, EqualsIssue), #[error("Tried linking another main module: {0}")] @@ -111,10 +111,7 @@ impl<'map> Pass for LinkerPass<'map> { for import in importer_module.imports.clone() { let Import(path, _) = &import; if path.len() != 2 { - state.ok::<_, Infallible>( - Err(ErrorKind::InnerModulesNotYetSupported(import.clone())), - import.1, - ); + state.ok::<_, Infallible>(Err(ErrorKind::InnerModulesNotYetSupported(import.clone())), import.1); } let module_name = unsafe { path.get_unchecked(0) }; @@ -123,38 +120,30 @@ impl<'map> Pass for LinkerPass<'map> { modules.get(mod_id).unwrap() } else if module_name == STD_NAME { let std = compile_std(&mut self.module_map)?; - modules.insert( - std.module_id, - Rc::new(RefCell::new(compile_std(&mut self.module_map)?)), - ); + modules.insert(std.module_id, Rc::new(RefCell::new(compile_std(&mut self.module_map)?))); module_ids.insert(std.name, std.module_id); modules.get(&std.module_id).unwrap() } else { - let file_path = - PathBuf::from(&context.base.clone()).join(module_name.to_owned() + ".reid"); + let file_path = PathBuf::from(&context.base.clone()).join(module_name.to_owned() + ".reid"); let Ok(source) = fs::read_to_string(&file_path) else { - state.ok::<_, Infallible>( - Err(ErrorKind::ModuleNotFound(module_name.clone())), - import.1, - ); + state.ok::<_, Infallible>(Err(ErrorKind::ModuleNotFound(module_name.clone())), import.1); continue; }; - let (id, tokens) = - match parse_module(&source, module_name.clone(), &mut self.module_map) { - Ok(val) => val, - Err(err) => { - state.ok::<_, Infallible>( - Err(ErrorKind::ModuleCompilationError( - module_name.clone(), - format!("{}", err), - )), - import.1, - ); - continue; - } - }; + let (id, tokens) = match parse_module(&source, module_name.clone(), &mut self.module_map) { + Ok(val) => val, + Err(err) => { + state.ok::<_, Infallible>( + Err(ErrorKind::ModuleCompilationError( + module_name.clone(), + format!("{}", err), + )), + import.1, + ); + continue; + } + }; match compile_module(id, tokens, &mut self.module_map, Some(file_path), false) { Ok(imported_module) => { @@ -166,8 +155,7 @@ impl<'map> Pass for LinkerPass<'map> { continue; } let module_id = imported_module.module_id; - module_ids - .insert(imported_module.name.clone(), imported_module.module_id); + module_ids.insert(imported_module.name.clone(), imported_module.module_id); modules.insert(module_id, Rc::new(RefCell::new(imported_module))); let imported = modules.get_mut(&module_id).unwrap(); modules_to_process.push(imported.clone()); @@ -187,112 +175,74 @@ impl<'map> Pass for LinkerPass<'map> { } .borrow_mut(); - let func_name = unsafe { path.get_unchecked(1) }; - - let Some(func) = imported.functions.iter_mut().find(|f| f.name == *func_name) - else { - state.ok::<_, Infallible>( - Err(ErrorKind::NoSuchFunctionInModule( - module_name.clone(), - func_name.clone(), - )), - import.1, - ); - continue; - }; - - let func_name = func.name.clone(); - - if !func.is_pub { - state.ok::<_, Infallible>( - Err(ErrorKind::FunctionIsPrivate( - module_name.clone(), - func_name.clone(), - )), - import.1, - ); - continue; - } - - func.is_imported = true; - - if let Some(existing) = importer_module - .functions - .iter() - .find(|f| f.name == *func_name) - { - if let Err(e) = existing.equals_as_imported(func) { - state.ok::<_, Infallible>( - Err(ErrorKind::FunctionImportIssue( - module_name.clone(), - func_name.clone(), - e, - )), - import.1, - ); - } - } - - fn import_type(ty: &TypeKind) -> Vec { - let mut imported_types = Vec::new(); - match &ty { - TypeKind::CustomType(key) => imported_types.push(key.clone()), - TypeKind::Borrow(ty, _) => imported_types.extend(import_type(ty)), - TypeKind::Array(ty, _) => imported_types.extend(import_type(ty)), - TypeKind::UserPtr(ty) => imported_types.extend(import_type(ty)), - TypeKind::CodegenPtr(ty) => imported_types.extend(import_type(ty)), - _ => {} - }; - imported_types - } + let import_name = unsafe { path.get_unchecked(1) }; let mut imported_types = Vec::new(); - let types = import_type(&func.return_type); - let return_type = func.return_type.clone(); - imported_types.extend(types); + if let Some(func) = imported.functions.iter_mut().find(|f| f.name == *import_name) { + let func_name = func.name.clone(); - let mut param_tys = Vec::new(); - for (param_name, param_ty) in &func.parameters { - let types = import_type(¶m_ty); - imported_types.extend(types); - param_tys.push((param_name.clone(), param_ty.clone())); - } + if !func.is_pub { + state.ok::<_, Infallible>( + Err(ErrorKind::FunctionIsPrivate(module_name.clone(), func_name.clone())), + import.1, + ); + continue; + } - fn find_inner_types( - typedef: &TypeDefinition, - mut seen: HashSet, - mod_id: SourceModuleId, - ) -> Vec { - match &typedef.kind { - crate::mir::TypeDefinitionKind::Struct(struct_type) => { - let typenames = struct_type - .0 - .iter() - .filter(|t| matches!(t.1, TypeKind::CustomType(..))) - .map(|t| match &t.1 { - TypeKind::CustomType(CustomTypeKey(t, _)) => t, - _ => panic!(), - }) - .cloned() - .collect::>(); + func.is_imported = true; - for typename in typenames { - if seen.contains(&CustomTypeKey(typename.clone(), mod_id)) { - continue; - } - let inner = find_inner_types(typedef, seen.clone(), mod_id); - seen.insert(CustomTypeKey(typename, mod_id)); - seen.extend(inner); - } - - seen.into_iter().collect() + if let Some(existing) = importer_module.functions.iter().find(|f| f.name == *func_name) { + if let Err(e) = existing.equals_as_imported(func) { + state.ok::<_, Infallible>( + Err(ErrorKind::FunctionImportIssue( + module_name.clone(), + func_name.clone(), + e, + )), + import.1, + ); } } + + let types = import_type(&func.return_type, false); + let return_type = func.return_type.clone(); + imported_types.extend(types); + + let mut param_tys = Vec::new(); + for (param_name, param_ty) in &func.parameters { + let types = import_type(¶m_ty, false); + imported_types.extend(types); + param_tys.push((param_name.clone(), param_ty.clone())); + } + + importer_module.functions.push(FunctionDefinition { + name: func_name, + is_pub: false, + is_imported: false, + return_type, + parameters: param_tys, + kind: super::FunctionDefinitionKind::Extern(true), + }); + } else if let Some(ty) = imported.typedefs.iter_mut().find(|f| f.name == *import_name) { + dbg!("hello??"); + let external_key = CustomTypeKey(ty.name.clone(), ty.source_module); + imported_types.push((external_key, true)); + dbg!(&imported_types); + } else { + state.ok::<_, Infallible>( + Err(ErrorKind::ImportDoesNotExist(module_name.clone(), import_name.clone())), + import.1, + ); + continue; } let mut seen = HashSet::new(); - seen.extend(imported_types.clone()); + let mut extern_types = HashSet::new(); + seen.extend(imported_types.clone().iter().map(|t| t.0.clone())); + extern_types.extend(imported_types.clone().iter().filter(|t| t.1).map(|t| t.0.clone())); + dbg!(&imported_types); + dbg!(&extern_types); let imported_mod_id = imported.module_id; let imported_mod_typedefs = &mut imported.typedefs; @@ -300,10 +250,10 @@ 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) + .find(|ty| CustomTypeKey(ty.name.clone(), imported_mod_id) == typekey.0) .unwrap(); let inner = find_inner_types(typedef, seen.clone(), imported_mod_id); - seen.extend(inner); + seen.extend(inner.iter().cloned()); } // TODO: Unable to import same-named type from multiple places.. @@ -314,24 +264,37 @@ impl<'map> Pass for LinkerPass<'map> { already_imported_types.extend(seen.clone()); + for typekey in &already_imported_types { + if extern_types.contains(typekey) { + let module_id = importer_module.module_id; + let typedef = importer_module + .typedefs + .iter_mut() + .find(|t| t.name == typekey.0 && t.source_module == typekey.1); + if let Some(typedef) = typedef { + typedef.importer = Some(module_id); + } + } + } + for typekey in seen.into_iter() { - let typedef = imported_mod_typedefs + dbg!(&typekey); + let mut typedef = imported_mod_typedefs .iter() .find(|ty| CustomTypeKey(ty.name.clone(), imported_mod_id) == typekey) .unwrap() .clone(); - importer_module.typedefs.push(typedef.clone()); - } + if extern_types.contains(&typekey) { + typedef = TypeDefinition { + importer: Some(importer_module.module_id), + ..typedef + }; + } - importer_module.functions.push(FunctionDefinition { - name: func_name, - is_pub: false, - is_imported: false, - return_type, - parameters: param_tys, - kind: super::FunctionDefinitionKind::Extern(true), - }); + importer_module.typedefs.push(typedef); + } + dbg!(&importer_module.typedefs); } } @@ -347,3 +310,48 @@ impl<'map> Pass for LinkerPass<'map> { Ok(()) } } + +fn import_type(ty: &TypeKind, usable_import: bool) -> Vec<(CustomTypeKey, bool)> { + let mut imported_types = Vec::new(); + match &ty { + TypeKind::CustomType(key) => imported_types.push((key.clone(), usable_import)), + TypeKind::Borrow(ty, _) => imported_types.extend(import_type(ty, usable_import)), + TypeKind::Array(ty, _) => imported_types.extend(import_type(ty, usable_import)), + TypeKind::UserPtr(ty) => imported_types.extend(import_type(ty, usable_import)), + TypeKind::CodegenPtr(ty) => imported_types.extend(import_type(ty, usable_import)), + _ => {} + }; + imported_types +} + +fn find_inner_types( + typedef: &TypeDefinition, + mut seen: HashSet, + mod_id: SourceModuleId, +) -> Vec { + match &typedef.kind { + crate::mir::TypeDefinitionKind::Struct(struct_type) => { + let typenames = struct_type + .0 + .iter() + .filter(|t| matches!(t.1, TypeKind::CustomType(..))) + .map(|t| match &t.1 { + TypeKind::CustomType(CustomTypeKey(t, _)) => t, + _ => panic!(), + }) + .cloned() + .collect::>(); + + for typename in typenames { + if seen.contains(&CustomTypeKey(typename.clone(), mod_id)) { + continue; + } + let inner = find_inner_types(typedef, seen.clone(), mod_id); + seen.insert(CustomTypeKey(typename, mod_id)); + seen.extend(inner); + } + + seen.into_iter().collect() + } + } +} diff --git a/reid/src/mir/mod.rs b/reid/src/mir/mod.rs index 2871072..5b72174 100644 --- a/reid/src/mir/mod.rs +++ b/reid/src/mir/mod.rs @@ -354,6 +354,7 @@ pub struct TypeDefinition { pub kind: TypeDefinitionKind, pub meta: Metadata, pub source_module: SourceModuleId, + pub importer: Option, } #[derive(Debug, Clone)] diff --git a/reid/src/mir/typecheck/typecheck.rs b/reid/src/mir/typecheck/typecheck.rs index 6e69024..6dc089a 100644 --- a/reid/src/mir/typecheck/typecheck.rs +++ b/reid/src/mir/typecheck/typecheck.rs @@ -34,12 +34,7 @@ impl<'t> Pass for TypeCheck<'t> { fn module(&mut self, module: &mut Module, mut state: TypecheckPassState) -> PassResult { let mut defmap = HashMap::new(); for typedef in &module.typedefs { - let TypeDefinition { - name, - kind, - meta, - source_module: _, - } = &typedef; + let TypeDefinition { name, kind, meta, .. } = &typedef; match kind { TypeDefinitionKind::Struct(StructType(fields)) => { @@ -217,8 +212,6 @@ impl Block { variable_reference.2, ); - dbg!(&var_t_resolved); - // Typecheck (and coerce) expression with said type let res = expression.typecheck(&mut state, &typerefs, HintKind::Coerce(var_t_resolved.clone())); // If expression resolution itself was erronous, resolve as