From 07459a77e3e7875ca195f31a8a348e40700487fe Mon Sep 17 00:00:00 2001 From: yuyi Date: Mon, 28 Dec 2020 18:26:50 +0800 Subject: [PATCH] cgen: fix gen_array_equality_fn() (#7633) --- cmd/tools/vtest-fmt.v | 2 ++ vlib/builtin/array_eq_test.v | 12 ++++++++++ vlib/builtin/array_test.v | 7 ------ vlib/v/gen/auto_eq_methods.v | 46 ++++++++++++++++++++++-------------- 4 files changed, 42 insertions(+), 25 deletions(-) create mode 100644 vlib/builtin/array_eq_test.v diff --git a/cmd/tools/vtest-fmt.v b/cmd/tools/vtest-fmt.v index 303433ee08..e2b6ae7f5b 100644 --- a/cmd/tools/vtest-fmt.v +++ b/cmd/tools/vtest-fmt.v @@ -17,6 +17,8 @@ const ( 'vlib/builtin/js/jsfns_browser.js.v', /* error: expr(): bad token `asm`, on `asm {}` */ 'vlib/builtin/bare/linuxsys_bare.v', + /* total chaos (duplicated code several times) in array_eq_test.v */ + 'vlib/builtin/array_eq_test.v', /* the fn args are removed, then `cb fn (picohttpparser.Request, mut picohttpparser.Response)` can not be reparsed */ 'vlib/picoev/picoev.v', ] diff --git a/vlib/builtin/array_eq_test.v b/vlib/builtin/array_eq_test.v new file mode 100644 index 0000000000..b53f00fbc9 --- /dev/null +++ b/vlib/builtin/array_eq_test.v @@ -0,0 +1,12 @@ +struct User { + age int + name string +} + +fn test_eq() { + assert [5, 6, 7] != [6, 7] + assert [`a`, `b`] == [`a`, `b`] + assert [User{age: 22, name: 'bob'}] == [User{age: 22, name: 'bob'}] + assert [{'bob': 22}, {'tom': 33}] == [{'bob': 22}, {'tom': 33}] + assert [[1, 2, 3], [4]] == [[1, 2, 3], [4]] +} diff --git a/vlib/builtin/array_test.v b/vlib/builtin/array_test.v index 3a2b70d22d..b55626f95a 100644 --- a/vlib/builtin/array_test.v +++ b/vlib/builtin/array_test.v @@ -691,13 +691,6 @@ fn test_array_str() { // assert numbers2.str() == '[[1, 2, 3], [4, 5, 6]]' } -fn test_eq() { - /* - assert [5, 6, 7].eq([6, 7]) == false - assert [`a`, `b`].eq([`a`, `b`]) == true - */ -} - struct User { age int name string diff --git a/vlib/v/gen/auto_eq_methods.v b/vlib/v/gen/auto_eq_methods.v index 3898ddd6b8..56324fee99 100644 --- a/vlib/v/gen/auto_eq_methods.v +++ b/vlib/v/gen/auto_eq_methods.v @@ -45,34 +45,44 @@ fn (mut g Gen) gen_struct_equality_fn(left table.Type) string { fn (mut g Gen) gen_array_equality_fn(left table.Type) string { left_sym := g.table.get_type_symbol(left) - typ_name := g.typ(left) - ptr_typ := typ_name[typ_name.index_after('_', 0) + 1..].trim('*') - elem_sym := g.table.get_type_symbol(left_sym.array_info().elem_type) - elem_typ := g.typ(left_sym.array_info().elem_type) - ptr_elem_typ := elem_typ[elem_typ.index_after('_', 0) + 1..] - if elem_sym.kind == .array { - // Recursively generate array element comparison function code if array element is array type - g.gen_array_equality_fn(left_sym.array_info().elem_type) - } + ptr_typ := g.typ(left).trim('*') + elem_typ := left_sym.array_info().elem_type + ptr_elem_typ := g.typ(elem_typ) + elem_sym := g.table.get_type_symbol(elem_typ) if ptr_typ in g.array_fn_definitions { return ptr_typ } g.array_fn_definitions << ptr_typ - g.type_definitions.writeln('static bool ${ptr_typ}_arr_eq(array_$ptr_typ a, array_$ptr_typ b); // auto') + g.type_definitions.writeln('static bool ${ptr_typ}_arr_eq($ptr_typ a, $ptr_typ b); // auto') mut fn_builder := strings.new_builder(512) - fn_builder.writeln('static bool ${ptr_typ}_arr_eq(array_$ptr_typ a, array_$ptr_typ b) {') + fn_builder.writeln('static bool ${ptr_typ}_arr_eq($ptr_typ a, $ptr_typ b) {') fn_builder.writeln('\tif (a.len != b.len) {') fn_builder.writeln('\t\treturn false;') fn_builder.writeln('\t}') - i := g.new_tmp_var() - fn_builder.writeln('\tfor (int $i = 0; $i < a.len; ++$i) {') + 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_typ*)((byte*)a.data+($i*a.element_size))), *(($ptr_typ*)((byte*)b.data+($i*b.element_size))))) {') } - .struct_ { fn_builder.writeln('\t\tif (memcmp((byte*)a.data+($i*a.element_size), (byte*)b.data+($i*b.element_size), a.element_size)) {') } - .array { fn_builder.writeln('\t\tif (!${ptr_elem_typ}_arr_eq((($elem_typ*)a.data)[$i], (($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_typ*)((byte*)a.data+($i*a.element_size))) != *(($ptr_typ*)((byte*)b.data+($i*b.element_size)))) {') } + .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)))) {') + } } fn_builder.writeln('\t\t\treturn false;') fn_builder.writeln('\t\t}')