From 32091dd90ec764454c34cca2b00307cc7338a026 Mon Sep 17 00:00:00 2001 From: yuyi Date: Tue, 29 Dec 2020 00:22:47 +0800 Subject: [PATCH] cgen: fix struct equality (#7649) --- vlib/v/gen/auto_eq_methods.v | 111 +++++++++++----------------- vlib/v/gen/cgen.v | 17 +++++ vlib/v/tests/struct_equality_test.v | 15 ++++ 3 files changed, 77 insertions(+), 66 deletions(-) create mode 100644 vlib/v/tests/struct_equality_test.v diff --git a/vlib/v/gen/auto_eq_methods.v b/vlib/v/gen/auto_eq_methods.v index 701f32e9ae..564bc24f3d 100644 --- a/vlib/v/gen/auto_eq_methods.v +++ b/vlib/v/gen/auto_eq_methods.v @@ -18,28 +18,21 @@ fn (mut g Gen) gen_struct_equality_fn(left table.Type) string { fn_builder.writeln('static bool ${ptr_typ}_struct_eq($ptr_typ a, $ptr_typ b) {') for field in info.fields { sym := g.table.get_type_symbol(field.typ) - match sym.kind { - .string { - fn_builder.writeln('\tif (string_ne(a.$field.name, b.$field.name)) {') - } - .struct_ { - eq_fn := g.gen_struct_equality_fn(field.typ) - fn_builder.writeln('\tif (!${eq_fn}_struct_eq(a.$field.name, b.$field.name)) {') - } - .array { - eq_fn := g.gen_array_equality_fn(field.typ) - fn_builder.writeln('\tif (!${eq_fn}_arr_eq(a.$field.name, b.$field.name)) {') - } - .map { - eq_fn := g.gen_map_equality_fn(field.typ) - fn_builder.writeln('\tif (!${eq_fn}_map_eq(a.$field.name, b.$field.name)) {') - } - .function { - fn_builder.writeln('\tif (*((voidptr*)(a.$field.name)) != *((voidptr*)(b.$field.name))) {') - } - else { - fn_builder.writeln('\tif (a.$field.name != b.$field.name) {') - } + if sym.kind == .string { + fn_builder.writeln('\tif (string_ne(a.$field.name, b.$field.name)) {') + } else if sym.kind == .struct_ && !field.typ.is_ptr() { + eq_fn := g.gen_struct_equality_fn(field.typ) + fn_builder.writeln('\tif (!${eq_fn}_struct_eq(a.$field.name, b.$field.name)) {') + } else if sym.kind == .array && !field.typ.is_ptr() { + eq_fn := g.gen_array_equality_fn(field.typ) + fn_builder.writeln('\tif (!${eq_fn}_arr_eq(a.$field.name, b.$field.name)) {') + } else if sym.kind == .map && !field.typ.is_ptr() { + eq_fn := g.gen_map_equality_fn(field.typ) + fn_builder.writeln('\tif (!${eq_fn}_map_eq(a.$field.name, b.$field.name)) {') + } else if sym.kind == .function { + fn_builder.writeln('\tif (*((voidptr*)(a.$field.name)) != *((voidptr*)(b.$field.name))) {') + } else { + fn_builder.writeln('\tif (a.$field.name != b.$field.name) {') } fn_builder.writeln('\t\treturn false;') fn_builder.writeln('\t}') @@ -68,28 +61,21 @@ fn (mut g Gen) gen_array_equality_fn(left table.Type) string { fn_builder.writeln('\t}') fn_builder.writeln('\tfor (int i = 0; i < a.len; ++i) {') // compare every pair of elements of the two arrays - match elem_sym.kind { - .string { - fn_builder.writeln('\t\tif (string_ne(*(($ptr_elem_typ*)((byte*)a.data+(i*a.element_size))), *(($ptr_elem_typ*)((byte*)b.data+(i*b.element_size))))) {') - } - .struct_ { - eq_fn := g.gen_struct_equality_fn(elem_typ) - fn_builder.writeln('\t\tif (!${eq_fn}_struct_eq((($ptr_elem_typ*)a.data)[i], (($ptr_elem_typ*)b.data)[i])) {') - } - .array { - eq_fn := g.gen_array_equality_fn(elem_typ) - fn_builder.writeln('\t\tif (!${eq_fn}_arr_eq((($ptr_elem_typ*)a.data)[i], (($ptr_elem_typ*)b.data)[i])) {') - } - .map { - eq_fn := g.gen_map_equality_fn(elem_typ) - fn_builder.writeln('\t\tif (!${eq_fn}_map_eq((($ptr_elem_typ*)a.data)[i], (($ptr_elem_typ*)b.data)[i])) {') - } - .function { - fn_builder.writeln('\t\tif (*((voidptr*)((byte*)a.data+(i*a.element_size))) != *((voidptr*)((byte*)b.data+(i*b.element_size)))) {') - } - else { - fn_builder.writeln('\t\tif (*(($ptr_elem_typ*)((byte*)a.data+(i*a.element_size))) != *(($ptr_elem_typ*)((byte*)b.data+(i*b.element_size)))) {') - } + if elem_sym.kind == .string { + fn_builder.writeln('\t\tif (string_ne(*(($ptr_elem_typ*)((byte*)a.data+(i*a.element_size))), *(($ptr_elem_typ*)((byte*)b.data+(i*b.element_size))))) {') + } else if elem_sym.kind == .struct_ && !elem_typ.is_ptr() { + eq_fn := g.gen_struct_equality_fn(elem_typ) + fn_builder.writeln('\t\tif (!${eq_fn}_struct_eq((($ptr_elem_typ*)a.data)[i], (($ptr_elem_typ*)b.data)[i])) {') + } else if elem_sym.kind == .array && !elem_typ.is_ptr() { + eq_fn := g.gen_array_equality_fn(elem_typ) + fn_builder.writeln('\t\tif (!${eq_fn}_arr_eq((($ptr_elem_typ*)a.data)[i], (($ptr_elem_typ*)b.data)[i])) {') + } else if elem_sym.kind == .map && !elem_typ.is_ptr() { + eq_fn := g.gen_map_equality_fn(elem_typ) + fn_builder.writeln('\t\tif (!${eq_fn}_map_eq((($ptr_elem_typ*)a.data)[i], (($ptr_elem_typ*)b.data)[i])) {') + } else if elem_sym.kind == .function { + fn_builder.writeln('\t\tif (*((voidptr*)((byte*)a.data+(i*a.element_size))) != *((voidptr*)((byte*)b.data+(i*b.element_size)))) {') + } else { + fn_builder.writeln('\t\tif (*(($ptr_elem_typ*)((byte*)a.data+(i*a.element_size))) != *(($ptr_elem_typ*)((byte*)b.data+(i*b.element_size)))) {') } fn_builder.writeln('\t\t\treturn false;') fn_builder.writeln('\t\t}') @@ -135,28 +121,21 @@ fn (mut g Gen) gen_map_equality_fn(left table.Type) string { } else { fn_builder.writeln('\t\t$ptr_value_typ v = (*($ptr_value_typ*)map_get_1(&a, &k, &($ptr_value_typ[]){ 0 }));') } - match value_sym.kind { - .string { - fn_builder.writeln('\t\tif (!map_exists_1(&b, &k) || string_ne((*(string*)map_get_1(&b, &k, &(string[]){_SLIT("")})), v)) {') - } - .struct_ { - eq_fn := g.gen_struct_equality_fn(value_typ) - fn_builder.writeln('\t\tif (!map_exists_1(&b, &k) || !${eq_fn}_struct_eq(*($ptr_value_typ*)map_get_1(&b, &k, &($ptr_value_typ[]){ 0 }), v)) {') - } - .array { - eq_fn := g.gen_array_equality_fn(value_typ) - fn_builder.writeln('\t\tif (!map_exists_1(&b, &k) || !${eq_fn}_arr_eq(*($ptr_value_typ*)map_get_1(&b, &k, &($ptr_value_typ[]){ 0 }), v)) {') - } - .map { - eq_fn := g.gen_map_equality_fn(value_typ) - fn_builder.writeln('\t\tif (!map_exists_1(&b, &k) || !${eq_fn}_map_eq(*($ptr_value_typ*)map_get_1(&b, &k, &($ptr_value_typ[]){ 0 }), v)) {') - } - .function { - fn_builder.writeln('\t\tif (!map_exists_1(&b, &k) || (*(voidptr*)map_get_1(&b, &k, &(voidptr[]){ 0 })) != v) {') - } - else { - fn_builder.writeln('\t\tif (!map_exists_1(&b, &k) || (*($ptr_value_typ*)map_get_1(&b, &k, &($ptr_value_typ[]){ 0 })) != v) {') - } + if value_sym.kind == .string { + fn_builder.writeln('\t\tif (!map_exists_1(&b, &k) || string_ne((*(string*)map_get_1(&b, &k, &(string[]){_SLIT("")})), v)) {') + } else if value_sym.kind == .struct_ && !value_typ.is_ptr() { + eq_fn := g.gen_struct_equality_fn(value_typ) + fn_builder.writeln('\t\tif (!map_exists_1(&b, &k) || !${eq_fn}_struct_eq(*($ptr_value_typ*)map_get_1(&b, &k, &($ptr_value_typ[]){ 0 }), v)) {') + } else if value_sym.kind == .array && !value_typ.is_ptr() { + eq_fn := g.gen_array_equality_fn(value_typ) + fn_builder.writeln('\t\tif (!map_exists_1(&b, &k) || !${eq_fn}_arr_eq(*($ptr_value_typ*)map_get_1(&b, &k, &($ptr_value_typ[]){ 0 }), v)) {') + } else if value_sym.kind == .map && !value_typ.is_ptr() { + eq_fn := g.gen_map_equality_fn(value_typ) + fn_builder.writeln('\t\tif (!map_exists_1(&b, &k) || !${eq_fn}_map_eq(*($ptr_value_typ*)map_get_1(&b, &k, &($ptr_value_typ[]){ 0 }), v)) {') + } else if value_sym.kind == .function { + fn_builder.writeln('\t\tif (!map_exists_1(&b, &k) || (*(voidptr*)map_get_1(&b, &k, &(voidptr[]){ 0 })) != v) {') + } else { + fn_builder.writeln('\t\tif (!map_exists_1(&b, &k) || (*($ptr_value_typ*)map_get_1(&b, &k, &($ptr_value_typ[]){ 0 })) != v) {') } fn_builder.writeln('\t\t\treturn false;') fn_builder.writeln('\t\t}') diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 4ae1da4196..eb2b99cce6 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -3036,6 +3036,23 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) { } g.expr(node.right) g.write(')') + } else if node.op in [.eq, .ne] && left_sym.kind == .struct_ && right_sym.kind == .struct_ { + ptr_typ := g.gen_struct_equality_fn(left_type) + if node.op == .eq { + g.write('${ptr_typ}_struct_eq(') + } else if node.op == .ne { + g.write('!${ptr_typ}_struct_eq(') + } + if node.left_type.is_ptr() { + g.write('*') + } + g.expr(node.left) + g.write(', ') + if node.right_type.is_ptr() { + g.write('*') + } + g.expr(node.right) + g.write(')') } else if node.op in [.key_in, .not_in] { if node.op == .not_in { g.write('!') diff --git a/vlib/v/tests/struct_equality_test.v b/vlib/v/tests/struct_equality_test.v new file mode 100644 index 0000000000..bc2229d832 --- /dev/null +++ b/vlib/v/tests/struct_equality_test.v @@ -0,0 +1,15 @@ +struct User { + name string + age int +} + +fn test_struct_equality() { + mut usr1 := User{'sanath', 28} + mut usr2 := User{'sanath', 28} + if usr1 == usr2 { + println('Same User') + } else { + println('Not same User') + } + assert usr1 == usr2 +}