cgen: implement eq operator for interfaces (#12047)
parent
f282e64fe3
commit
129c81f34d
|
@ -39,6 +39,9 @@ fn (mut g Gen) gen_equality_fns() {
|
||||||
.alias {
|
.alias {
|
||||||
g.gen_alias_equality_fn(needed_typ)
|
g.gen_alias_equality_fn(needed_typ)
|
||||||
}
|
}
|
||||||
|
.interface_ {
|
||||||
|
g.gen_interface_equality_fn(needed_typ)
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
verror('could not generate equality function for type $sym.kind')
|
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()
|
g.auto_fn_definitions << fn_builder.str()
|
||||||
return ptr_styp
|
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.expr(node.right)
|
||||||
g.write(')')
|
g.write(')')
|
||||||
} else if left.typ.idx() == right.typ.idx()
|
} 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 {
|
match left.sym.kind {
|
||||||
.alias {
|
.alias {
|
||||||
ptr_typ := g.equality_fn(left.typ)
|
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.expr(node.right)
|
||||||
g.write(')')
|
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 {}
|
||||||
}
|
}
|
||||||
} else if left.unaliased.idx() in [ast.u32_type_idx, ast.u64_type_idx]
|
} 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