From 4248fc55c5ea2ce609d98a1c2bcf54b6c8122651 Mon Sep 17 00:00:00 2001 From: yuyi Date: Wed, 25 Sep 2024 16:49:27 +0800 Subject: [PATCH] cgen: fix operation overload for type aliases of fixed arrays (fix #22297) (#22304) --- vlib/v/gen/c/assign.v | 28 +++++-- .../array_fixed_op_overload_test.v | 78 +++++++++++++++++++ 2 files changed, 100 insertions(+), 6 deletions(-) create mode 100644 vlib/v/tests/builtin_arrays/array_fixed_op_overload_test.v diff --git a/vlib/v/gen/c/assign.v b/vlib/v/gen/c/assign.v index 3bcba1668eb3bd..07be32d1365d4b 100644 --- a/vlib/v/gen/c/assign.v +++ b/vlib/v/gen/c/assign.v @@ -525,6 +525,7 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) { .mult_assign { '*' } else { 'unknown op' } } + pos := g.out.len g.expr(left) if left_sym.info is ast.Struct && left_sym.info.generic_types.len > 0 { concrete_types := left_sym.info.concrete_types @@ -548,7 +549,15 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) { } return } else { - g.write(' = ${styp}_${util.replace_op(extracted_op)}(') + if g.table.final_sym(g.unwrap_generic(var_type)).kind == .array_fixed { + g.go_back_to(pos) + g.empty_line = true + g.write('memcpy(') + g.expr(left) + g.write(', ${styp}_${util.replace_op(extracted_op)}(') + } else { + g.write(' = ${styp}_${util.replace_op(extracted_op)}(') + } method := g.table.find_method(left_sym, extracted_op) or { // the checker will most likely have found this, already... g.error('assignment operator `${extracted_op}=` used but no `${extracted_op}` method defined', @@ -750,11 +759,18 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) { g.write(' = ') g.expr(val) } else { - g.write('memcpy(${final_typ_str}') - g.expr(left) - g.write(', ${final_ref_str}') - g.expr(val) - g.write(', sizeof(${typ_str})) /*assign*/') + if op_overloaded { + g.expr(left) + g.write(', ') + g.expr(val) + g.write(').ret_arr, sizeof(${typ_str})') + } else { + g.write('memcpy(${final_typ_str}') + g.expr(left) + g.write(', ${final_ref_str}') + g.expr(val) + g.write(', sizeof(${typ_str})) /*assign*/') + } } } else if is_decl { g.is_shared = var_type.has_flag(.shared_f) diff --git a/vlib/v/tests/builtin_arrays/array_fixed_op_overload_test.v b/vlib/v/tests/builtin_arrays/array_fixed_op_overload_test.v new file mode 100644 index 00000000000000..283802c1ceb398 --- /dev/null +++ b/vlib/v/tests/builtin_arrays/array_fixed_op_overload_test.v @@ -0,0 +1,78 @@ +import math +import math.vec + +type Vector3 = vec.Vec3[f32] + +fn vector3(x f32, y f32, z f32) Vector3 { + return Vector3{x, y, z} +} + +pub type Matrix4 = [16]f32 + +pub fn matrix4(x0 f32, x1 f32, x2 f32, x3 f32, x4 f32, x5 f32, x6 f32, x7 f32, x8 f32, x9 f32, x10 f32, x11 f32, x12 f32, x13 f32, x14 f32, x15 f32) Matrix4 { + return [ + x0, + x1, + x2, + x3, + x4, + x5, + x6, + x7, + x8, + x9, + x10, + x11, + x12, + x13, + x14, + x15, + ]! +} + +pub fn (x Matrix4) str() string { + return '|${x[0]:-6.3},${x[1]:-6.3},${x[2]:-6.3},${x[3]:-6.3}|\n' + + '|${x[4]:-6.3},${x[5]:-6.3},${x[6]:-6.3},${x[7]:-6.3}|\n' + + '|${x[8]:-6.3},${x[9]:-6.3},${x[10]:-6.3},${x[11]:-6.3}|\n' + + '|${x[12]:-6.3},${x[13]:-6.3},${x[14]:-6.3},${x[15]:-6.3}|' +} + +pub fn matrix4_unit() Matrix4 { + return matrix4(f32(1), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1) +} + +pub fn (a Matrix4) * (b Matrix4) Matrix4 { + mut res := Matrix4{} + for i := 0; i < 4; i++ { + for j := 0; j < 4; j++ { + res[j * 4 + i] = 0 + for k := 0; k < 4; k++ { + res[j * 4 + i] += a[k * 4 + i] * b[j * 4 + k] + } + } + } + return res +} + +pub fn rotate(angle f32, w Vector3) Matrix4 { + cs := f32(math.cos(angle)) + sn := f32(math.sin(angle)) + cv := f32(1.0) - cs + axis := w.normalize() + + ax := axis.x + ay := axis.y + az := axis.z + + return matrix4((ax * ax * cv) + cs, (ax * ay * cv) + az * sn, (ax * az * cv) - ay * sn, + 0, (ay * ax * cv) - az * sn, (ay * ay * cv) + cs, (ay * az * cv) + ax * sn, 0, + (az * ax * cv) + ay * sn, (az * ay * cv) - ax * sn, (az * az * cv) + cs, 0, 0, + 0, 0, 1) +} + +fn test_array_fixed_op_overload() { + mut rot := matrix4_unit() + rot *= rotate(0.5, vector3(0.5, 0.5, 0.5)) + println(rot) + assert true +}