Allow mutable function arguments

This commit is contained in:
Nikita Lisitsa 2026-05-07 13:47:15 +03:00
parent 79838a1bb3
commit d146ec69fd
2 changed files with 25 additions and 25 deletions

View file

@ -19,12 +19,11 @@ func print_byte(c: u8):
foreign func putchar(c: i32) -> i32 foreign func putchar(c: i32) -> i32
putchar(c as 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 // Don't use puts() because it adds a newline
mut p = str while *str != 0ub:
while *p != 0ub: print_byte(*str)
print_byte(*p) str += 1
p += 1
func print_i32(x: i32): func print_i32(x: i32):
if x < 0: if x < 0:
@ -35,7 +34,7 @@ func print_i32(x: i32):
print_i32(x / 10) print_i32(x / 10)
print_byte('0' + (x % 10 as u8)) print_byte('0' + (x % 10 as u8))
func print_f32(x: f32): func print_f32(mut x: f32):
if x < 0.0: if x < 0.0:
print_byte('-') print_byte('-')
print_f32(-x) print_f32(-x)
@ -44,14 +43,14 @@ func print_f32(x: f32):
let xfloor = floor(x) let xfloor = floor(x)
print_i32(xfloor) print_i32(xfloor)
print_byte('.') print_byte('.')
mut y = x - (xfloor as f32) x -= (xfloor as f32)
// Print fractional part // Print fractional part
mut i = 0 mut i = 0
while i < 3: while i < 3:
y = y * 10.0 x = x * 10.0
let yfloor = floor(y) let xfloor = floor(x)
print_byte('0' + (yfloor as u8)) print_byte('0' + (xfloor as u8))
y = y - (yfloor as f32) x -= (xfloor as f32)
i = i + 1 i = i + 1
func print_vec3(v: vec3): func print_vec3(v: vec3):
@ -108,8 +107,8 @@ struct file:
func open(path: u8*, mode: u8) -> file*: func open(path: u8*, mode: u8) -> file*:
foreign func fopen(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 // A hack to turn a single u8 into a zero-terminated array
let mode_wide = mode as u32 let mode_wide = [mode, 0ub]
return fopen(path, &mode as u8*) return fopen(path, &mode_wide as u8*)
func close(file: file*): func close(file: file*):
foreign func fclose(file: file*) -> i32 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) normal = vec3(0.0, 0.0, -1.0)
else: else:
normal = vec3(0.0, 0.0, 1.0) normal = vec3(0.0, 0.0, 1.0)
if inside: if inside:
normal = mults(normal, -1.0) 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: if current_intersection.intersected && current_intersection.distance < intersection.distance:
intersection = current_intersection intersection = current_intersection
i += 1ul i += 1ul
return intersection return intersection
@ -568,7 +567,7 @@ func raytrace(scene: scene*, camera_ray: ray, rng: rng mut*) -> vec3:
// Uncomment to debug normals // Uncomment to debug normals
// return mults(add(intersection.normal, vec3(1.0, 1.0, 1.0)), 0.5) // return mults(add(intersection.normal, vec3(1.0, 1.0, 1.0)), 0.5)
let cosine = - dot(intersection.normal, current_ray.direction) let cosine = - dot(intersection.normal, current_ray.direction)
let inside = cosine < 0.0 let inside = cosine < 0.0
@ -577,7 +576,7 @@ func raytrace(scene: scene*, camera_ray: ray, rng: rng mut*) -> vec3:
// Russian roulette ray termination // Russian roulette ray termination
if next_f32(rng) < termination_probability: if next_f32(rng) < termination_probability:
break break
mut new_direction = vec3(0.0, 0.0, 0.0) mut new_direction = vec3(0.0, 0.0, 0.0)
if intersection.material.type == diffuse_tag: 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 mut ior = intersection.material.ior
if inside: if inside:
ior = 1.0 / ior ior = 1.0 / ior
// Schlick's approximation for Fresnel term // Schlick's approximation for Fresnel term
let r0 = sqr((1.0 - ior) / (1.0 + ior)) 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) 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) // dictated by arm64 limitations (add immediate is bound by 12 bits => 4Kb)
// The reasonable solution: fix the compiler! // The reasonable solution: fix the compiler!
// The temporary solution: split into several separate functions! // The temporary solution: split into several separate functions!
func fill_walls(objects: object mut*): func fill_walls(objects: object mut*):
// Floor // Floor
objects[0].position = vec3(0.0, -5.0, 0.0) 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.type = metallic_tag
objects[7].material.roughness = 0.5 objects[7].material.roughness = 0.5
set_sphere(&mut objects[7], sphere(2.0)) set_sphere(&mut objects[7], sphere(2.0))
fill_walls(objects) fill_walls(objects)
fill_objects(objects) fill_objects(objects)
@ -788,7 +787,7 @@ func main():
// const samples_per_pixel = 256ul // const samples_per_pixel = 256ul
// const samples_per_pixel = 16ul // const samples_per_pixel = 16ul
// const samples_per_pixel = 1ul // const samples_per_pixel = 1ul
struct thread_data: struct thread_data:
scene: scene* scene: scene*
image: image image: image
@ -797,7 +796,7 @@ func main():
ystep: u64 ystep: u64
done_mutex: mutex mut* done_mutex: mutex mut*
done: u64 done: u64
func thread_func(data_raw: unit mut*): func thread_func(data_raw: unit mut*):
let data = data_raw as thread_data mut* let data = data_raw as thread_data mut*
mut y = data.ystart mut y = data.ystart
@ -864,7 +863,7 @@ func main():
continue continue
done = 0ul done = 0ul
mut th = 0ul mut th = 0ul
while th < thread_count: while th < thread_count:
lock_mutex(threads_data[th].done_mutex) lock_mutex(threads_data[th].done_mutex)
@ -907,7 +906,7 @@ func main():
let total_time = time_delta(get_time(), start_time) let total_time = time_delta(get_time(), start_time)
let total_samples = image.width * image.height * samples_per_pixel let total_samples = image.width * image.height * samples_per_pixel
let str1 = ['R', 'e', 'n', 'd', 'e', 'r', ' ', 't', 'o', 'o', 'k', ' ', '\0'] 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'] let str2 = [' ', 'p', 'e', 'r', ' ', 's', 'a', 'm', 'p', 'l', 'e', '\0']
clear_line(50u) clear_line(50u)
@ -925,4 +924,4 @@ func main():
deallocate(scene.objects.data as unit*) deallocate(scene.objects.data as unit*)
main() main()

View file

@ -275,6 +275,7 @@ nonempty_function_declaration_argument_list
function_declaration_single_argument function_declaration_single_argument
: name colon type_expression { $$ = ast::function_declaration::argument{ast::value_category::constant, $1, std::make_unique<ast::type>($3), @$}; } : name colon type_expression { $$ = ast::function_declaration::argument{ast::value_category::constant, $1, std::make_unique<ast::type>($3), @$}; }
| mut name colon type_expression { $$ = ast::function_declaration::argument{ast::value_category::_mutable, $2, std::make_unique<ast::type>($4), @$}; }
; ;
function_return_type function_return_type