From d146ec69fd9d7e94e5d25e04c5a9584dbca5ed0e Mon Sep 17 00:00:00 2001 From: lisyarus Date: Thu, 7 May 2026 13:47:15 +0300 Subject: [PATCH] Allow mutable function arguments --- examples/raytracer.psl | 49 +++++++++++++++++++------------------- libs/parser/rules/pslang.y | 1 + 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/examples/raytracer.psl b/examples/raytracer.psl index 4d80d0c..ca53a4c 100644 --- a/examples/raytracer.psl +++ b/examples/raytracer.psl @@ -19,12 +19,11 @@ func print_byte(c: u8): foreign func putchar(c: i32) -> i32 putchar(c as i32) -func print_str(str: u8*): +func print_str(mut str: u8*): // Don't use puts() because it adds a newline - mut p = str - while *p != 0ub: - print_byte(*p) - p += 1 + while *str != 0ub: + print_byte(*str) + str += 1 func print_i32(x: i32): if x < 0: @@ -35,7 +34,7 @@ func print_i32(x: i32): print_i32(x / 10) print_byte('0' + (x % 10 as u8)) -func print_f32(x: f32): +func print_f32(mut x: f32): if x < 0.0: print_byte('-') print_f32(-x) @@ -44,14 +43,14 @@ func print_f32(x: f32): let xfloor = floor(x) print_i32(xfloor) print_byte('.') - mut y = x - (xfloor as f32) + x -= (xfloor as f32) // Print fractional part mut i = 0 while i < 3: - y = y * 10.0 - let yfloor = floor(y) - print_byte('0' + (yfloor as u8)) - y = y - (yfloor as f32) + x = x * 10.0 + let xfloor = floor(x) + print_byte('0' + (xfloor as u8)) + x -= (xfloor as f32) i = i + 1 func print_vec3(v: vec3): @@ -108,8 +107,8 @@ struct file: func open(path: u8*, mode: u8) -> file*: foreign func fopen(path: u8*, mode: u8*) -> file* // A hack to turn a single u8 into a zero-terminated array - let mode_wide = mode as u32 - return fopen(path, &mode as u8*) + let mode_wide = [mode, 0ub] + return fopen(path, &mode_wide as u8*) func close(file: file*): foreign func fclose(file: file*) -> i32 @@ -527,7 +526,7 @@ func intersect_box(ray: ray, object: object*) -> intersection: normal = vec3(0.0, 0.0, -1.0) else: normal = vec3(0.0, 0.0, 1.0) - + if inside: normal = mults(normal, -1.0) @@ -548,7 +547,7 @@ func intersect_scene(scene: scene*, ray: ray) -> intersection: if current_intersection.intersected && current_intersection.distance < intersection.distance: intersection = current_intersection - + i += 1ul return intersection @@ -568,7 +567,7 @@ func raytrace(scene: scene*, camera_ray: ray, rng: rng mut*) -> vec3: // Uncomment to debug normals // return mults(add(intersection.normal, vec3(1.0, 1.0, 1.0)), 0.5) - + let cosine = - dot(intersection.normal, current_ray.direction) let inside = cosine < 0.0 @@ -577,7 +576,7 @@ func raytrace(scene: scene*, camera_ray: ray, rng: rng mut*) -> vec3: // Russian roulette ray termination if next_f32(rng) < termination_probability: break - + mut new_direction = vec3(0.0, 0.0, 0.0) if intersection.material.type == diffuse_tag: @@ -604,7 +603,7 @@ func raytrace(scene: scene*, camera_ray: ray, rng: rng mut*) -> vec3: mut ior = intersection.material.ior if inside: ior = 1.0 / ior - + // Schlick's approximation for Fresnel term let r0 = sqr((1.0 - ior) / (1.0 + ior)) let reflectance = r0 + (1.0 - r0) * pow(max(0.0, 1.0 - abs(cosine)), 5.0) @@ -687,7 +686,7 @@ func make_default_scene() -> scene: // dictated by arm64 limitations (add immediate is bound by 12 bits => 4Kb) // The reasonable solution: fix the compiler! // The temporary solution: split into several separate functions! - + func fill_walls(objects: object mut*): // Floor objects[0].position = vec3(0.0, -5.0, 0.0) @@ -756,7 +755,7 @@ func make_default_scene() -> scene: objects[7].material.type = metallic_tag objects[7].material.roughness = 0.5 set_sphere(&mut objects[7], sphere(2.0)) - + fill_walls(objects) fill_objects(objects) @@ -788,7 +787,7 @@ func main(): // const samples_per_pixel = 256ul // const samples_per_pixel = 16ul // const samples_per_pixel = 1ul - + struct thread_data: scene: scene* image: image @@ -797,7 +796,7 @@ func main(): ystep: u64 done_mutex: mutex mut* done: u64 - + func thread_func(data_raw: unit mut*): let data = data_raw as thread_data mut* mut y = data.ystart @@ -864,7 +863,7 @@ func main(): continue done = 0ul - + mut th = 0ul while th < thread_count: lock_mutex(threads_data[th].done_mutex) @@ -907,7 +906,7 @@ func main(): let total_time = time_delta(get_time(), start_time) let total_samples = image.width * image.height * samples_per_pixel - + let str1 = ['R', 'e', 'n', 'd', 'e', 'r', ' ', 't', 'o', 'o', 'k', ' ', '\0'] let str2 = [' ', 'p', 'e', 'r', ' ', 's', 'a', 'm', 'p', 'l', 'e', '\0'] clear_line(50u) @@ -925,4 +924,4 @@ func main(): deallocate(scene.objects.data as unit*) -main() \ No newline at end of file +main() diff --git a/libs/parser/rules/pslang.y b/libs/parser/rules/pslang.y index b913f5b..b839456 100644 --- a/libs/parser/rules/pslang.y +++ b/libs/parser/rules/pslang.y @@ -275,6 +275,7 @@ nonempty_function_declaration_argument_list function_declaration_single_argument : name colon type_expression { $$ = ast::function_declaration::argument{ast::value_category::constant, $1, std::make_unique($3), @$}; } +| mut name colon type_expression { $$ = ast::function_declaration::argument{ast::value_category::_mutable, $2, std::make_unique($4), @$}; } ; function_return_type