cgen: implement eq operator for interfaces (#12047)
parent
f282e64fe3
commit
129c81f34d
|
@ -39,6 +39,9 @@ fn (mut g Gen) gen_equality_fns() {
|
|||
.alias {
|
||||
g.gen_alias_equality_fn(needed_typ)
|
||||
}
|
||||
.interface_ {
|
||||
g.gen_interface_equality_fn(needed_typ)
|
||||
}
|
||||
else {
|
||||
verror('could not generate equality function for type $sym.kind')
|
||||
}
|
||||
|
@ -386,3 +389,69 @@ fn (mut g Gen) gen_map_equality_fn(left_type ast.Type) string {
|
|||
g.auto_fn_definitions << fn_builder.str()
|
||||
return ptr_styp
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_interface_equality_fn(left_type ast.Type) string {
|
||||
left := g.unwrap(left_type)
|
||||
ptr_styp := g.typ(left.typ.set_nr_muls(0))
|
||||
fn_name := ptr_styp.replace('interface ', '')
|
||||
if left_type in g.generated_eq_fns {
|
||||
return fn_name
|
||||
}
|
||||
g.generated_eq_fns << left_type
|
||||
info := left.sym.info
|
||||
g.type_definitions.writeln('static bool ${ptr_styp}_interface_eq($ptr_styp a, $ptr_styp b); // auto')
|
||||
|
||||
mut fn_builder := strings.new_builder(512)
|
||||
defer {
|
||||
g.auto_fn_definitions << fn_builder.str()
|
||||
}
|
||||
fn_builder.writeln('static int v_typeof_interface_idx_${ptr_styp}(int sidx); // for auto eq method')
|
||||
fn_builder.writeln('static bool ${fn_name}_interface_eq($ptr_styp a, $ptr_styp b) {')
|
||||
fn_builder.writeln('\tif (a._typ == b._typ) {')
|
||||
fn_builder.writeln('\t\tint idx = v_typeof_interface_idx_${ptr_styp}(a._typ);')
|
||||
if info is ast.Interface {
|
||||
for typ in info.types {
|
||||
fn_builder.writeln('\t\tif (idx == $typ) {')
|
||||
fn_builder.write_string('\t\t\treturn ')
|
||||
match g.table.type_kind(typ) {
|
||||
.struct_ {
|
||||
eq_fn := g.gen_struct_equality_fn(typ)
|
||||
fn_builder.write_string('${eq_fn}_struct_eq(*(a._$eq_fn), *(b._$eq_fn))')
|
||||
}
|
||||
.string {
|
||||
fn_builder.write_string('string__eq(*(a._string), *(b._string))')
|
||||
}
|
||||
.sum_type {
|
||||
eq_fn := g.gen_sumtype_equality_fn(typ)
|
||||
fn_builder.write_string('${eq_fn}_sumtype_eq(*(a._$eq_fn), *(b._$eq_fn))')
|
||||
}
|
||||
.array {
|
||||
eq_fn := g.gen_array_equality_fn(typ)
|
||||
fn_builder.write_string('${eq_fn}_arr_eq(*(a._$eq_fn), *(b._$eq_fn))')
|
||||
}
|
||||
.array_fixed {
|
||||
eq_fn := g.gen_fixed_array_equality_fn(typ)
|
||||
fn_builder.write_string('${eq_fn}_arr_eq(*(a._$eq_fn), *(b._$eq_fn))')
|
||||
}
|
||||
.map {
|
||||
eq_fn := g.gen_map_equality_fn(typ)
|
||||
fn_builder.write_string('${eq_fn}_map_eq(*(a._$eq_fn), *(b._$eq_fn))')
|
||||
}
|
||||
.alias {
|
||||
eq_fn := g.gen_alias_equality_fn(typ)
|
||||
fn_builder.write_string('${eq_fn}_alias_eq(*(a._$eq_fn), *(b._$eq_fn))')
|
||||
}
|
||||
else {
|
||||
fn_builder.write_string('false')
|
||||
}
|
||||
}
|
||||
fn_builder.writeln(';')
|
||||
fn_builder.writeln('\t\t}')
|
||||
}
|
||||
}
|
||||
fn_builder.writeln('\t}')
|
||||
fn_builder.writeln('\treturn false;')
|
||||
fn_builder.writeln('}')
|
||||
|
||||
return fn_name
|
||||
}
|
||||
|
|
|
@ -111,7 +111,7 @@ fn (mut g Gen) infix_expr_eq_op(node ast.InfixExpr) {
|
|||
g.expr(node.right)
|
||||
g.write(')')
|
||||
} else if left.typ.idx() == right.typ.idx()
|
||||
&& left.sym.kind in [.array, .array_fixed, .alias, .map, .struct_, .sum_type] {
|
||||
&& left.sym.kind in [.array, .array_fixed, .alias, .map, .struct_, .sum_type, .interface_] {
|
||||
match left.sym.kind {
|
||||
.alias {
|
||||
ptr_typ := g.equality_fn(left.typ)
|
||||
|
@ -226,6 +226,23 @@ fn (mut g Gen) infix_expr_eq_op(node ast.InfixExpr) {
|
|||
g.expr(node.right)
|
||||
g.write(')')
|
||||
}
|
||||
.interface_ {
|
||||
ptr_typ := g.equality_fn(left.unaliased)
|
||||
if node.op == .ne {
|
||||
g.write('!')
|
||||
}
|
||||
g.write('${ptr_typ}_interface_eq(')
|
||||
if left.typ.is_ptr() {
|
||||
g.write('*')
|
||||
}
|
||||
g.expr(node.left)
|
||||
g.write(', ')
|
||||
if right.typ.is_ptr() {
|
||||
g.write('*')
|
||||
}
|
||||
g.expr(node.right)
|
||||
g.write(')')
|
||||
}
|
||||
else {}
|
||||
}
|
||||
} else if left.unaliased.idx() in [ast.u32_type_idx, ast.u64_type_idx]
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
interface IExample {}
|
||||
|
||||
struct Example {
|
||||
id string
|
||||
}
|
||||
|
||||
struct Example2 {
|
||||
n int
|
||||
}
|
||||
|
||||
fn equals(a IExample, b IExample) bool {
|
||||
return a == b
|
||||
}
|
||||
|
||||
fn test_equality() {
|
||||
assert !equals(Example{ id: 'a' }, 'abc')
|
||||
assert !equals(Example{ id: 'a' }, Example{
|
||||
id: 'b'
|
||||
})
|
||||
assert equals(Example{ id: 'a' }, Example{
|
||||
id: 'a'
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue