Allow importing types
This commit is contained in:
		
							parent
							
								
									12e2851a8b
								
							
						
					
					
						commit
						269de327b8
					
				| @ -1,6 +1,12 @@ | |||||||
| pub fn abs(f: f32) -> f32 { | 
 | ||||||
|     if f < 0.0 { | import std::print; | ||||||
|         return f * (0.0 - 1.0); | import std::new_string; | ||||||
|     } | import std::String; | ||||||
|     return f; | 
 | ||||||
|  | fn otus() -> String { | ||||||
|  |     return new_string(); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | fn main() -> u8 { | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
							
								
								
									
										469
									
								
								foo.reid
									
									
									
									
									
								
							
							
						
						
									
										469
									
								
								foo.reid
									
									
									
									
									
								
							| @ -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); |  | ||||||
| } |  | ||||||
| @ -95,6 +95,7 @@ impl ast::Module { | |||||||
|                         }, |                         }, | ||||||
|                         meta: (*range).as_meta(module_id), |                         meta: (*range).as_meta(module_id), | ||||||
|                         source_module: module_id, |                         source_module: module_id, | ||||||
|  |                         importer: None, | ||||||
|                     }; |                     }; | ||||||
|                     typedefs.push(def); |                     typedefs.push(def); | ||||||
|                 } |                 } | ||||||
|  | |||||||
| @ -75,7 +75,17 @@ impl Display for BinopDefinition { | |||||||
| 
 | 
 | ||||||
| impl Display for TypeDefinition { | impl Display for TypeDefinition { | ||||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |     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) |         Display::fmt(&self.kind, f) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -31,8 +31,8 @@ pub enum ErrorKind { | |||||||
|     ModuleNotFound(String), |     ModuleNotFound(String), | ||||||
|     #[error("Error while compiling module {0}: {1}")] |     #[error("Error while compiling module {0}: {1}")] | ||||||
|     ModuleCompilationError(String, String), |     ModuleCompilationError(String, String), | ||||||
|     #[error("No such function {0} found in module {1}")] |     #[error("No such value {0} found in module {1}")] | ||||||
|     NoSuchFunctionInModule(String, String), |     ImportDoesNotExist(String, String), | ||||||
|     #[error("Importing function {0}::{1} not possible: {2}")] |     #[error("Importing function {0}::{1} not possible: {2}")] | ||||||
|     FunctionImportIssue(String, String, EqualsIssue), |     FunctionImportIssue(String, String, EqualsIssue), | ||||||
|     #[error("Tried linking another main module: {0}")] |     #[error("Tried linking another main module: {0}")] | ||||||
| @ -111,10 +111,7 @@ impl<'map> Pass for LinkerPass<'map> { | |||||||
|             for import in importer_module.imports.clone() { |             for import in importer_module.imports.clone() { | ||||||
|                 let Import(path, _) = &import; |                 let Import(path, _) = &import; | ||||||
|                 if path.len() != 2 { |                 if path.len() != 2 { | ||||||
|                     state.ok::<_, Infallible>( |                     state.ok::<_, Infallible>(Err(ErrorKind::InnerModulesNotYetSupported(import.clone())), import.1); | ||||||
|                         Err(ErrorKind::InnerModulesNotYetSupported(import.clone())), |  | ||||||
|                         import.1, |  | ||||||
|                     ); |  | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 let module_name = unsafe { path.get_unchecked(0) }; |                 let module_name = unsafe { path.get_unchecked(0) }; | ||||||
| @ -123,38 +120,30 @@ impl<'map> Pass for LinkerPass<'map> { | |||||||
|                     modules.get(mod_id).unwrap() |                     modules.get(mod_id).unwrap() | ||||||
|                 } else if module_name == STD_NAME { |                 } else if module_name == STD_NAME { | ||||||
|                     let std = compile_std(&mut self.module_map)?; |                     let std = compile_std(&mut self.module_map)?; | ||||||
|                     modules.insert( |                     modules.insert(std.module_id, Rc::new(RefCell::new(compile_std(&mut self.module_map)?))); | ||||||
|                         std.module_id, |  | ||||||
|                         Rc::new(RefCell::new(compile_std(&mut self.module_map)?)), |  | ||||||
|                     ); |  | ||||||
|                     module_ids.insert(std.name, std.module_id); |                     module_ids.insert(std.name, std.module_id); | ||||||
|                     modules.get(&std.module_id).unwrap() |                     modules.get(&std.module_id).unwrap() | ||||||
|                 } else { |                 } else { | ||||||
|                     let file_path = |                     let file_path = PathBuf::from(&context.base.clone()).join(module_name.to_owned() + ".reid"); | ||||||
|                         PathBuf::from(&context.base.clone()).join(module_name.to_owned() + ".reid"); |  | ||||||
| 
 | 
 | ||||||
|                     let Ok(source) = fs::read_to_string(&file_path) else { |                     let Ok(source) = fs::read_to_string(&file_path) else { | ||||||
|                         state.ok::<_, Infallible>( |                         state.ok::<_, Infallible>(Err(ErrorKind::ModuleNotFound(module_name.clone())), import.1); | ||||||
|                             Err(ErrorKind::ModuleNotFound(module_name.clone())), |  | ||||||
|                             import.1, |  | ||||||
|                         ); |  | ||||||
|                         continue; |                         continue; | ||||||
|                     }; |                     }; | ||||||
| 
 | 
 | ||||||
|                     let (id, tokens) = |                     let (id, tokens) = match parse_module(&source, module_name.clone(), &mut self.module_map) { | ||||||
|                         match parse_module(&source, module_name.clone(), &mut self.module_map) { |                         Ok(val) => val, | ||||||
|                             Ok(val) => val, |                         Err(err) => { | ||||||
|                             Err(err) => { |                             state.ok::<_, Infallible>( | ||||||
|                                 state.ok::<_, Infallible>( |                                 Err(ErrorKind::ModuleCompilationError( | ||||||
|                                     Err(ErrorKind::ModuleCompilationError( |                                     module_name.clone(), | ||||||
|                                         module_name.clone(), |                                     format!("{}", err), | ||||||
|                                         format!("{}", err), |                                 )), | ||||||
|                                     )), |                                 import.1, | ||||||
|                                     import.1, |                             ); | ||||||
|                                 ); |                             continue; | ||||||
|                                 continue; |                         } | ||||||
|                             } |                     }; | ||||||
|                         }; |  | ||||||
| 
 | 
 | ||||||
|                     match compile_module(id, tokens, &mut self.module_map, Some(file_path), false) { |                     match compile_module(id, tokens, &mut self.module_map, Some(file_path), false) { | ||||||
|                         Ok(imported_module) => { |                         Ok(imported_module) => { | ||||||
| @ -166,8 +155,7 @@ impl<'map> Pass for LinkerPass<'map> { | |||||||
|                                 continue; |                                 continue; | ||||||
|                             } |                             } | ||||||
|                             let module_id = imported_module.module_id; |                             let module_id = imported_module.module_id; | ||||||
|                             module_ids |                             module_ids.insert(imported_module.name.clone(), imported_module.module_id); | ||||||
|                                 .insert(imported_module.name.clone(), imported_module.module_id); |  | ||||||
|                             modules.insert(module_id, Rc::new(RefCell::new(imported_module))); |                             modules.insert(module_id, Rc::new(RefCell::new(imported_module))); | ||||||
|                             let imported = modules.get_mut(&module_id).unwrap(); |                             let imported = modules.get_mut(&module_id).unwrap(); | ||||||
|                             modules_to_process.push(imported.clone()); |                             modules_to_process.push(imported.clone()); | ||||||
| @ -187,112 +175,74 @@ impl<'map> Pass for LinkerPass<'map> { | |||||||
|                 } |                 } | ||||||
|                 .borrow_mut(); |                 .borrow_mut(); | ||||||
| 
 | 
 | ||||||
|                 let func_name = unsafe { path.get_unchecked(1) }; |                 let import_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<CustomTypeKey> { |  | ||||||
|                     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 mut imported_types = Vec::new(); |                 let mut imported_types = Vec::new(); | ||||||
| 
 | 
 | ||||||
|                 let types = import_type(&func.return_type); |                 if let Some(func) = imported.functions.iter_mut().find(|f| f.name == *import_name) { | ||||||
|                 let return_type = func.return_type.clone(); |                     let func_name = func.name.clone(); | ||||||
|                 imported_types.extend(types); |  | ||||||
| 
 | 
 | ||||||
|                 let mut param_tys = Vec::new(); |                     if !func.is_pub { | ||||||
|                 for (param_name, param_ty) in &func.parameters { |                         state.ok::<_, Infallible>( | ||||||
|                     let types = import_type(¶m_ty); |                             Err(ErrorKind::FunctionIsPrivate(module_name.clone(), func_name.clone())), | ||||||
|                     imported_types.extend(types); |                             import.1, | ||||||
|                     param_tys.push((param_name.clone(), param_ty.clone())); |                         ); | ||||||
|                 } |                         continue; | ||||||
|  |                     } | ||||||
| 
 | 
 | ||||||
|                 fn find_inner_types( |                     func.is_imported = true; | ||||||
|                     typedef: &TypeDefinition, |  | ||||||
|                     mut seen: HashSet<CustomTypeKey>, |  | ||||||
|                     mod_id: SourceModuleId, |  | ||||||
|                 ) -> Vec<CustomTypeKey> { |  | ||||||
|                     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::<Vec<_>>(); |  | ||||||
| 
 | 
 | ||||||
|                             for typename in typenames { |                     if let Some(existing) = importer_module.functions.iter().find(|f| f.name == *func_name) { | ||||||
|                                 if seen.contains(&CustomTypeKey(typename.clone(), mod_id)) { |                         if let Err(e) = existing.equals_as_imported(func) { | ||||||
|                                     continue; |                             state.ok::<_, Infallible>( | ||||||
|                                 } |                                 Err(ErrorKind::FunctionImportIssue( | ||||||
|                                 let inner = find_inner_types(typedef, seen.clone(), mod_id); |                                     module_name.clone(), | ||||||
|                                 seen.insert(CustomTypeKey(typename, mod_id)); |                                     func_name.clone(), | ||||||
|                                 seen.extend(inner); |                                     e, | ||||||
|                             } |                                 )), | ||||||
| 
 |                                 import.1, | ||||||
|                             seen.into_iter().collect() |                             ); | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|  | 
 | ||||||
|  |                     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(); |                 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_id = imported.module_id; | ||||||
|                 let imported_mod_typedefs = &mut imported.typedefs; |                 let imported_mod_typedefs = &mut imported.typedefs; | ||||||
| @ -300,10 +250,10 @@ impl<'map> Pass for LinkerPass<'map> { | |||||||
|                 for typekey in imported_types.clone() { |                 for typekey in imported_types.clone() { | ||||||
|                     let typedef = imported_mod_typedefs |                     let typedef = imported_mod_typedefs | ||||||
|                         .iter() |                         .iter() | ||||||
|                         .find(|ty| CustomTypeKey(ty.name.clone(), imported_mod_id) == typekey) |                         .find(|ty| CustomTypeKey(ty.name.clone(), imported_mod_id) == typekey.0) | ||||||
|                         .unwrap(); |                         .unwrap(); | ||||||
|                     let inner = find_inner_types(typedef, seen.clone(), imported_mod_id); |                     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..
 |                 // 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()); |                 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() { |                 for typekey in seen.into_iter() { | ||||||
|                     let typedef = imported_mod_typedefs |                     dbg!(&typekey); | ||||||
|  |                     let mut typedef = imported_mod_typedefs | ||||||
|                         .iter() |                         .iter() | ||||||
|                         .find(|ty| CustomTypeKey(ty.name.clone(), imported_mod_id) == typekey) |                         .find(|ty| CustomTypeKey(ty.name.clone(), imported_mod_id) == typekey) | ||||||
|                         .unwrap() |                         .unwrap() | ||||||
|                         .clone(); |                         .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 { |                     importer_module.typedefs.push(typedef); | ||||||
|                     name: func_name, |                 } | ||||||
|                     is_pub: false, |                 dbg!(&importer_module.typedefs); | ||||||
|                     is_imported: false, |  | ||||||
|                     return_type, |  | ||||||
|                     parameters: param_tys, |  | ||||||
|                     kind: super::FunctionDefinitionKind::Extern(true), |  | ||||||
|                 }); |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -347,3 +310,48 @@ impl<'map> Pass for LinkerPass<'map> { | |||||||
|         Ok(()) |         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<CustomTypeKey>, | ||||||
|  |     mod_id: SourceModuleId, | ||||||
|  | ) -> Vec<CustomTypeKey> { | ||||||
|  |     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::<Vec<_>>(); | ||||||
|  | 
 | ||||||
|  |             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() | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | |||||||
| @ -354,6 +354,7 @@ pub struct TypeDefinition { | |||||||
|     pub kind: TypeDefinitionKind, |     pub kind: TypeDefinitionKind, | ||||||
|     pub meta: Metadata, |     pub meta: Metadata, | ||||||
|     pub source_module: SourceModuleId, |     pub source_module: SourceModuleId, | ||||||
|  |     pub importer: Option<SourceModuleId>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, Clone)] | #[derive(Debug, Clone)] | ||||||
|  | |||||||
| @ -34,12 +34,7 @@ impl<'t> Pass for TypeCheck<'t> { | |||||||
|     fn module(&mut self, module: &mut Module, mut state: TypecheckPassState) -> PassResult { |     fn module(&mut self, module: &mut Module, mut state: TypecheckPassState) -> PassResult { | ||||||
|         let mut defmap = HashMap::new(); |         let mut defmap = HashMap::new(); | ||||||
|         for typedef in &module.typedefs { |         for typedef in &module.typedefs { | ||||||
|             let TypeDefinition { |             let TypeDefinition { name, kind, meta, .. } = &typedef; | ||||||
|                 name, |  | ||||||
|                 kind, |  | ||||||
|                 meta, |  | ||||||
|                 source_module: _, |  | ||||||
|             } = &typedef; |  | ||||||
| 
 | 
 | ||||||
|             match kind { |             match kind { | ||||||
|                 TypeDefinitionKind::Struct(StructType(fields)) => { |                 TypeDefinitionKind::Struct(StructType(fields)) => { | ||||||
| @ -217,8 +212,6 @@ impl Block { | |||||||
|                         variable_reference.2, |                         variable_reference.2, | ||||||
|                     ); |                     ); | ||||||
| 
 | 
 | ||||||
|                     dbg!(&var_t_resolved); |  | ||||||
| 
 |  | ||||||
|                     // Typecheck (and coerce) expression with said type
 |                     // Typecheck (and coerce) expression with said type
 | ||||||
|                     let res = expression.typecheck(&mut state, &typerefs, HintKind::Coerce(var_t_resolved.clone())); |                     let res = expression.typecheck(&mut state, &typerefs, HintKind::Coerce(var_t_resolved.clone())); | ||||||
|                     // If expression resolution itself was erronous, resolve as
 |                     // If expression resolution itself was erronous, resolve as
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user