cgen: add gen_fixed_array_equality_fn (#8006)
parent
55e3e50b9b
commit
1559e72d0d
|
@ -10,3 +10,37 @@ fn test_eq() {
|
|||
assert [{'bob': 22}, {'tom': 33}] == [{'bob': 22}, {'tom': 33}]
|
||||
assert [[1, 2, 3], [4]] == [[1, 2, 3], [4]]
|
||||
}
|
||||
|
||||
fn test_fixed_array_eq() {
|
||||
a1 := [1, 2, 3]!!
|
||||
assert a1 == [1, 2, 3]!!
|
||||
assert a1 != [2, 3, 4]!!
|
||||
|
||||
a2 := [[1, 2]!!, [3, 4]!!]!!
|
||||
assert a2 == [[1, 2]!!, [3, 4]!!]!!
|
||||
assert a2 != [[3, 4]!!, [1, 2]!!]!!
|
||||
|
||||
a3 := [[1, 2], [3, 4]]!!
|
||||
assert a3 == [[1, 2], [3, 4]]!!
|
||||
assert a3 != [[1, 1], [2, 2]]!!
|
||||
|
||||
a4 := [[`a`, `b`], [`c`, `d`]]!!
|
||||
assert a4 == [[`a`, `b`], [`c`, `d`]]!!
|
||||
assert a4 != [[`c`, `a`], [`a`, `b`]]!!
|
||||
|
||||
a5 := [['aaa', 'bbb'], ['ccc', 'ddd']]!!
|
||||
assert a5 == [['aaa', 'bbb'], ['ccc', 'ddd']]!!
|
||||
assert a5 != [['abc', 'def'], ['ccc', 'ddd']]!!
|
||||
|
||||
a6 := [['aaa', 'bbb']!!, ['ccc', 'ddd']!!]!!
|
||||
assert a6 == [['aaa', 'bbb']!!, ['ccc', 'ddd']!!]!!
|
||||
assert a6 != [['aaa', 'bbb']!!, ['aaa', 'ddd']!!]!!
|
||||
|
||||
a7 := [[1, 2]!!, [3, 4]!!]
|
||||
assert a7 == [[1, 2]!!, [3, 4]!!]
|
||||
assert a7 != [[2, 3]!!, [1, 2]!!]
|
||||
|
||||
a8 := [['aaa', 'bbb']!!, ['ccc', 'ddd']!!]
|
||||
assert a8 == [['aaa', 'bbb']!!, ['ccc', 'ddd']!!]
|
||||
assert a8 != [['bbb', 'aaa']!!, ['cccc', 'dddd']!!]
|
||||
}
|
||||
|
|
|
@ -26,6 +26,9 @@ fn (mut g Gen) gen_struct_equality_fn(left table.Type) string {
|
|||
} 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 == .array_fixed && !field.typ.is_ptr() {
|
||||
eq_fn := g.gen_fixed_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)) {')
|
||||
|
@ -69,6 +72,9 @@ fn (mut g Gen) gen_array_equality_fn(left table.Type) string {
|
|||
} 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 == .array_fixed && !elem_typ.is_ptr() {
|
||||
eq_fn := g.gen_fixed_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])) {')
|
||||
|
@ -86,6 +92,50 @@ fn (mut g Gen) gen_array_equality_fn(left table.Type) string {
|
|||
return ptr_typ
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_fixed_array_equality_fn(left table.Type) string {
|
||||
ptr_typ := g.typ(left).trim('*')
|
||||
if ptr_typ in g.array_fn_definitions {
|
||||
return ptr_typ
|
||||
}
|
||||
g.array_fn_definitions << ptr_typ
|
||||
left_sym := g.table.get_type_symbol(left)
|
||||
elem_info := left_sym.array_fixed_info()
|
||||
elem_typ := elem_info.elem_type
|
||||
size := elem_info.size
|
||||
elem_sym := g.table.get_type_symbol(elem_typ)
|
||||
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($ptr_typ a, $ptr_typ b) {')
|
||||
fn_builder.writeln('\tfor (int i = 0; i < $size; ++i) {')
|
||||
// compare every pair of elements of the two fixed arrays
|
||||
if elem_sym.kind == .string {
|
||||
fn_builder.writeln('\t\tif (string_ne(a[i], b[i])) {')
|
||||
} 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(a[i], b[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(a[i], b[i])) {')
|
||||
} else if elem_sym.kind == .array_fixed && !elem_typ.is_ptr() {
|
||||
eq_fn := g.gen_fixed_array_equality_fn(elem_typ)
|
||||
fn_builder.writeln('\t\tif (!${eq_fn}_arr_eq(a[i], b[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(a[i], b[i])) {')
|
||||
} else if elem_sym.kind == .function {
|
||||
fn_builder.writeln('\t\tif (a[i] != b[i]) {')
|
||||
} else {
|
||||
fn_builder.writeln('\t\tif (a[i] != b[i]) {')
|
||||
}
|
||||
fn_builder.writeln('\t\t\treturn false;')
|
||||
fn_builder.writeln('\t\t}')
|
||||
fn_builder.writeln('\t}')
|
||||
fn_builder.writeln('\treturn true;')
|
||||
fn_builder.writeln('}')
|
||||
g.auto_fn_definitions << fn_builder.str()
|
||||
return ptr_typ
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_map_equality_fn(left table.Type) string {
|
||||
ptr_typ := g.typ(left).trim('*')
|
||||
if ptr_typ in g.map_fn_definitions {
|
||||
|
@ -135,6 +185,10 @@ fn (mut g Gen) gen_map_equality_fn(left table.Type) string {
|
|||
eq_fn := g.gen_array_equality_fn(value_typ)
|
||||
fn_builder.writeln('\t\tif (!${eq_fn}_arr_eq(*($ptr_value_typ*)map_get_1(&b, k, &($ptr_value_typ[]){ 0 }), v)) {')
|
||||
}
|
||||
.array_fixed {
|
||||
eq_fn := g.gen_fixed_array_equality_fn(value_typ)
|
||||
fn_builder.writeln('\t\tif (!${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 (!${eq_fn}_map_eq(*($ptr_value_typ*)map_get_1(&b, k, &($ptr_value_typ[]){ 0 }), v)) {')
|
||||
|
|
|
@ -204,7 +204,12 @@ fn (mut g Gen) gen_str_for_array(info table.Array, styp string, str_fn_name stri
|
|||
if sym.kind == .function {
|
||||
g.auto_str_funcs.writeln('\t\tstring x = ${elem_str_fn_name}();')
|
||||
} else {
|
||||
g.auto_str_funcs.writeln('\t\t$field_styp it = (*($field_styp*)array_get(a, i));')
|
||||
if sym.kind == .array_fixed {
|
||||
g.auto_str_funcs.writeln('\t\t$field_styp it;')
|
||||
g.auto_str_funcs.writeln('\t\tmemcpy(*($field_styp*)it, (byte*)array_get(a, i), sizeof($field_styp));')
|
||||
} else {
|
||||
g.auto_str_funcs.writeln('\t\t$field_styp it = *($field_styp*)array_get(a, i);')
|
||||
}
|
||||
if sym.kind == .struct_ && !sym_has_str_method {
|
||||
if is_elem_ptr {
|
||||
g.auto_str_funcs.writeln('\t\tstring x = indent_${elem_str_fn_name}(*it, indent_count);')
|
||||
|
|
|
@ -3011,11 +3011,10 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
|||
}
|
||||
} else if node.op in [.eq, .ne] && left_sym.kind == .array && right_sym.kind == .array {
|
||||
ptr_typ := g.gen_array_equality_fn(left_type)
|
||||
if node.op == .eq {
|
||||
g.write('${ptr_typ}_arr_eq(')
|
||||
} else if node.op == .ne {
|
||||
g.write('!${ptr_typ}_arr_eq(')
|
||||
if node.op == .ne {
|
||||
g.write('!')
|
||||
}
|
||||
g.write('${ptr_typ}_arr_eq(')
|
||||
if node.left_type.is_ptr() {
|
||||
g.write('*')
|
||||
}
|
||||
|
@ -3028,12 +3027,14 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
|||
g.write(')')
|
||||
} else if node.op in [.eq, .ne] &&
|
||||
left_sym.kind == .array_fixed && right_sym.kind == .array_fixed {
|
||||
info := left_sym.info as table.ArrayFixed
|
||||
et := info.elem_type
|
||||
if !et.is_ptr() && !et.is_pointer() && !et.is_number() && et.idx() !in [table.bool_type_idx, table.char_type_idx] {
|
||||
verror('`==` on fixed array only supported with POD element types ATM')
|
||||
ptr_typ := g.gen_fixed_array_equality_fn(left_type)
|
||||
if node.op == .ne {
|
||||
g.write('!')
|
||||
}
|
||||
g.write('${ptr_typ}_arr_eq(')
|
||||
if node.left_type.is_ptr() {
|
||||
g.write('*')
|
||||
}
|
||||
g.write('(memcmp(')
|
||||
g.expr(node.left)
|
||||
g.write(', ')
|
||||
if node.right is ast.ArrayInit {
|
||||
|
@ -3041,13 +3042,6 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
|||
g.write('($s)')
|
||||
}
|
||||
g.expr(node.right)
|
||||
g.write(', sizeof(')
|
||||
g.expr(node.left)
|
||||
if node.op == .eq {
|
||||
g.write(')) == 0')
|
||||
} else if node.op == .ne {
|
||||
g.write(')) != 0')
|
||||
}
|
||||
g.write(')')
|
||||
} else if node.op in [.eq, .ne] && left_sym.kind == .map && right_sym.kind == .map {
|
||||
ptr_typ := g.gen_map_equality_fn(left_type)
|
||||
|
|
Loading…
Reference in New Issue