cgen: fix gen_array_equality_fn() (#7633)

pull/7649/head
yuyi 2020-12-28 18:26:50 +08:00 committed by GitHub
parent 164dd3000b
commit 07459a77e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 42 additions and 25 deletions

View File

@ -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',
]

View File

@ -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]]
}

View File

@ -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

View File

@ -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}')