cgen: implement equality on arrays
parent
71190c27a9
commit
8f8f8c418e
|
@ -55,6 +55,7 @@ mut:
|
||||||
defer_ifdef string
|
defer_ifdef string
|
||||||
str_types []string // types that need automatic str() generation
|
str_types []string // types that need automatic str() generation
|
||||||
threaded_fns []string // for generating unique wrapper types and fns for `go xxx()`
|
threaded_fns []string // for generating unique wrapper types and fns for `go xxx()`
|
||||||
|
array_fn_definitions []string // array equality functions that have been defined
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -1300,7 +1301,6 @@ fn (g mut Gen) assign_expr(node ast.AssignExpr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (g mut Gen) infix_expr(node ast.InfixExpr) {
|
fn (g mut Gen) infix_expr(node ast.InfixExpr) {
|
||||||
left_sym := g.table.get_type_symbol(node.left_type)
|
|
||||||
// println('infix_expr() op="$node.op.str()" line_nr=$node.pos.line_nr')
|
// println('infix_expr() op="$node.op.str()" line_nr=$node.pos.line_nr')
|
||||||
// g.write('/*infix*/')
|
// g.write('/*infix*/')
|
||||||
// if it.left_type == table.string_type_idx {
|
// if it.left_type == table.string_type_idx {
|
||||||
|
@ -1308,6 +1308,8 @@ fn (g mut Gen) infix_expr(node ast.InfixExpr) {
|
||||||
// }
|
// }
|
||||||
// string + string, string == string etc
|
// string + string, string == string etc
|
||||||
// g.infix_op = node.op
|
// g.infix_op = node.op
|
||||||
|
left_sym := g.table.get_type_symbol(node.left_type)
|
||||||
|
right_sym := g.table.get_type_symbol(node.right_type)
|
||||||
if node.left_type == table.string_type_idx && node.op != .key_in {
|
if node.left_type == table.string_type_idx && node.op != .key_in {
|
||||||
fn_name := match node.op {
|
fn_name := match node.op {
|
||||||
.plus {
|
.plus {
|
||||||
|
@ -1340,8 +1342,23 @@ fn (g mut Gen) infix_expr(node ast.InfixExpr) {
|
||||||
g.write(', ')
|
g.write(', ')
|
||||||
g.expr(node.right)
|
g.expr(node.right)
|
||||||
g.write(')')
|
g.write(')')
|
||||||
|
} else if node.op in [.eq, .ne] && left_sym.kind == .array && right_sym.kind == .array {
|
||||||
|
styp := g.table.value_type(node.left_type)
|
||||||
|
ptr_typ := g.typ(node.left_type).split('_')[1]
|
||||||
|
if !(ptr_typ in g.array_fn_definitions) {
|
||||||
|
sym := g.table.get_type_symbol(left_sym.array_info().elem_type)
|
||||||
|
g.generate_array_equality_fn(ptr_typ, styp, sym)
|
||||||
|
}
|
||||||
|
if node.op == .eq {
|
||||||
|
g.write('${ptr_typ}_arr_eq(')
|
||||||
|
} else if node.op == .ne {
|
||||||
|
g.write('!${ptr_typ}_arr_eq(')
|
||||||
|
}
|
||||||
|
g.expr(node.left)
|
||||||
|
g.write(', ')
|
||||||
|
g.expr(node.right)
|
||||||
|
g.write(')')
|
||||||
} else if node.op == .key_in {
|
} else if node.op == .key_in {
|
||||||
right_sym := g.table.get_type_symbol(node.right_type)
|
|
||||||
if right_sym.kind == .array {
|
if right_sym.kind == .array {
|
||||||
match node.right {
|
match node.right {
|
||||||
ast.ArrayInit {
|
ast.ArrayInit {
|
||||||
|
@ -1379,7 +1396,6 @@ fn (g mut Gen) infix_expr(node ast.InfixExpr) {
|
||||||
tmp := g.new_tmp_var()
|
tmp := g.new_tmp_var()
|
||||||
sym := g.table.get_type_symbol(node.left_type)
|
sym := g.table.get_type_symbol(node.left_type)
|
||||||
info := sym.info as table.Array
|
info := sym.info as table.Array
|
||||||
right_sym := g.table.get_type_symbol(node.right_type)
|
|
||||||
if right_sym.kind == .array && info.elem_type != node.right_type {
|
if right_sym.kind == .array && info.elem_type != node.right_type {
|
||||||
// push an array => PUSH_MANY, but not if pushing an array to 2d array (`[][]int << []int`)
|
// push an array => PUSH_MANY, but not if pushing an array to 2d array (`[][]int << []int`)
|
||||||
g.write('_PUSH_MANY(&')
|
g.write('_PUSH_MANY(&')
|
||||||
|
@ -2038,6 +2054,27 @@ fn (g mut Gen) call_args(args []ast.CallArg, expected_types []table.Type) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (g mut Gen) generate_array_equality_fn(ptr_typ string, styp table.Type, sym &table.TypeSymbol) {
|
||||||
|
g.array_fn_definitions << ptr_typ
|
||||||
|
g.definitions.writeln('bool ${ptr_typ}_arr_eq(array_${ptr_typ} a, array_${ptr_typ} b) {')
|
||||||
|
g.definitions.writeln('\tif (a.len != b.len) {')
|
||||||
|
g.definitions.writeln('\t\treturn false;')
|
||||||
|
g.definitions.writeln('\t}')
|
||||||
|
g.definitions.writeln('\tfor (int i = 0; i < a.len; i++) {')
|
||||||
|
if styp == table.string_type_idx {
|
||||||
|
g.definitions.writeln('\t\tif (string_ne(*((${ptr_typ}*)(a.data+(i*a.element_size))), *((${ptr_typ}*)(b.data+(i*b.element_size))))) {')
|
||||||
|
} else if sym.kind == .struct_ {
|
||||||
|
g.definitions.writeln('\t\tif (memcmp((void*)(a.data+(i*a.element_size)), (void*)(b.data+(i*b.element_size)), a.element_size)) {')
|
||||||
|
} else {
|
||||||
|
g.definitions.writeln('\t\tif (*((${ptr_typ}*)(a.data+(i*a.element_size))) != *((${ptr_typ}*)(b.data+(i*b.element_size)))) {')
|
||||||
|
}
|
||||||
|
g.definitions.writeln('\t\t\treturn false;')
|
||||||
|
g.definitions.writeln('\t\t}')
|
||||||
|
g.definitions.writeln('\t}')
|
||||||
|
g.definitions.writeln('\treturn true;')
|
||||||
|
g.definitions.writeln('}')
|
||||||
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
fn (g mut Gen) ref_or_deref_arg(arg ast.CallArg, expected_type table.Type) {
|
fn (g mut Gen) ref_or_deref_arg(arg ast.CallArg, expected_type table.Type) {
|
||||||
arg_is_ptr := table.type_is_ptr(expected_type) || table.type_idx(expected_type) in table.pointer_type_idxs
|
arg_is_ptr := table.type_is_ptr(expected_type) || table.type_idx(expected_type) in table.pointer_type_idxs
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
struct Tester {
|
||||||
|
b bool
|
||||||
|
i int
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Color {
|
||||||
|
red green blue
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_array_equality() {
|
||||||
|
strs := ["a", "b", "c"]
|
||||||
|
assert strs == ["a", "b", "c"]
|
||||||
|
assert strs != ["a", "c", "b"]
|
||||||
|
assert strs != ["b", "c", "a"]
|
||||||
|
assert strs != ["b", "a", "c"]
|
||||||
|
assert strs != ["c", "b", "a"]
|
||||||
|
assert strs != ["c", "a", "b"]
|
||||||
|
bools := [true, true, false]
|
||||||
|
assert bools == [true, true, false]
|
||||||
|
assert bools != [true, false, false]
|
||||||
|
assert bools != [false, true, true]
|
||||||
|
assert bools != [false, false, true]
|
||||||
|
assert bools != [false, false, false]
|
||||||
|
assert bools != [false, true, false]
|
||||||
|
ints := [1, 2, 3]
|
||||||
|
assert ints == [1, 2, 3]
|
||||||
|
assert ints != [1, 3, 2]
|
||||||
|
assert ints != [2, 3, 1]
|
||||||
|
assert ints != [2, 1, 3]
|
||||||
|
assert ints != [3, 2, 1]
|
||||||
|
assert ints != [3, 1, 2]
|
||||||
|
a := Tester{true, 100}
|
||||||
|
b := Tester{false, 200}
|
||||||
|
testers := [a, b]
|
||||||
|
assert testers == [a, b]
|
||||||
|
assert testers != [a, a]
|
||||||
|
assert testers != [b, b]
|
||||||
|
assert testers != [b, a]
|
||||||
|
colors := [Color.red, Color.green, Color.blue]
|
||||||
|
assert colors == [Color.red, Color.green, Color.blue]
|
||||||
|
assert colors != [Color.red, Color.blue, Color.green]
|
||||||
|
assert colors != [Color.green, Color.blue, Color.red]
|
||||||
|
assert colors != [Color.green, Color.red, Color.blue]
|
||||||
|
assert colors != [Color.blue, Color.green, Color.red]
|
||||||
|
assert colors != [Color.blue, Color.red, Color.green]
|
||||||
|
}
|
Loading…
Reference in New Issue