v.gen.c: allow overriding of the == operator on C.Struct type aliases

pull/11427/head weekly.2021.36
Delyan Angelov 2021-09-07 11:30:33 +03:00
parent aec016bb14
commit 0b6d585b07
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
5 changed files with 84 additions and 12 deletions

View File

@ -58,24 +58,25 @@ fn (mut g Gen) gen_sumtype_equality_fn(left_type ast.Type) string {
fn (mut g Gen) gen_struct_equality_fn(left_type ast.Type) string {
left := g.unwrap(left_type)
ptr_styp := g.typ(left.typ.set_nr_muls(0))
if ptr_styp in g.struct_fn_definitions {
return ptr_styp
fn_name := ptr_styp.replace('struct ', '')
if fn_name in g.struct_fn_definitions {
return fn_name
}
g.struct_fn_definitions << ptr_styp
g.struct_fn_definitions << fn_name
info := left.sym.struct_info()
g.type_definitions.writeln('static bool ${ptr_styp}_struct_eq($ptr_styp a, $ptr_styp b); // auto')
g.type_definitions.writeln('static bool ${fn_name}_struct_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 bool ${ptr_styp}_struct_eq($ptr_styp a, $ptr_styp b) {')
fn_builder.writeln('static bool ${fn_name}_struct_eq($ptr_styp a, $ptr_styp b) {')
// overloaded
if left.sym.has_method('==') {
fn_builder.writeln('\treturn ${ptr_styp}__eq(a, b);')
fn_builder.writeln('\treturn ${fn_name}__eq(a, b);')
fn_builder.writeln('}')
return ptr_styp
return fn_name
}
fn_builder.write_string('\treturn ')
@ -117,7 +118,7 @@ fn (mut g Gen) gen_struct_equality_fn(left_type ast.Type) string {
}
fn_builder.writeln(';')
fn_builder.writeln('}')
return ptr_styp
return fn_name
}
fn (mut g Gen) gen_alias_equality_fn(left_type ast.Type) string {

View File

@ -81,10 +81,11 @@ fn (mut g Gen) infix_expr_arrow_op(node ast.InfixExpr) {
fn (mut g Gen) infix_expr_eq_op(node ast.InfixExpr) {
left := g.unwrap(node.left_type)
right := g.unwrap(node.right_type)
has_operator_overloading := g.table.type_has_method(left.sym, '==')
has_defined_eq_operator := g.table.type_has_method(left.sym, '==')
has_alias_eq_op_overload := left.sym.info is ast.Alias && left.sym.has_method('==')
if (left.typ.is_ptr() && right.typ.is_int()) || (right.typ.is_ptr() && left.typ.is_int()) {
g.gen_plain_infix_expr(node)
} else if (left.typ.idx() == ast.string_type_idx || (!has_operator_overloading
} else if (left.typ.idx() == ast.string_type_idx || (!has_defined_eq_operator
&& left.unaliased.idx() == ast.string_type_idx)) && node.right is ast.StringLiteral
&& (node.right as ast.StringLiteral).val == '' {
// `str == ''` -> `str.len == 0` optimization
@ -93,11 +94,15 @@ fn (mut g Gen) infix_expr_eq_op(node ast.InfixExpr) {
g.write(')')
arrow := if left.typ.is_ptr() { '->' } else { '.' }
g.write('${arrow}len $node.op 0')
} else if has_operator_overloading {
} else if has_defined_eq_operator {
if node.op == .ne {
g.write('!')
}
g.write(g.typ(left.unaliased.set_nr_muls(0)))
if has_alias_eq_op_overload {
g.write(g.typ(left.typ.set_nr_muls(0)))
} else {
g.write(g.typ(left.unaliased.set_nr_muls(0)))
}
g.write('__eq(')
g.write('*'.repeat(left.typ.nr_muls()))
g.expr(node.left)

View File

@ -0,0 +1,8 @@
struct __mpz_struct1 {
int x;
};
typedef struct __mpz_struct2 {
int x;
} __mpz_struct_typedef;

View File

@ -0,0 +1,58 @@
#include "@VMODROOT/cstructs.h"
struct C.__mpz_struct1 {
x int
}
[typedef]
struct C.__mpz_struct_typedef {
x int
}
type Bigint = C.__mpz_struct1
type BigintTypedef = C.__mpz_struct_typedef
pub fn (a Bigint) == (b Bigint) bool {
println('>>>> struct a.x: $a.x | == | b.x: $b.x => ${a.x == b.x:-5} <<<<')
return a.x == b.x
}
pub fn (a BigintTypedef) == (b BigintTypedef) bool {
println('>>>> typedef struct a.x: $a.x | == | b.x: $b.x => ${a.x == b.x:-5} <<<<')
return a.x == b.x
}
fn test_ordinary_c_struct_aliases_with_an_equal_op_overload() {
bi_1 := Bigint{
x: 12
}
bi_2 := Bigint{
x: 34
}
bi_3 := Bigint{
x: 12
}
println(bi_1)
println(bi_2)
assert bi_1 == bi_1
assert bi_1 == bi_3
assert bi_1 != bi_2
}
fn test_typedefed_c_struct_aliases_with_an_equal_op_overload() {
bit_1 := BigintTypedef{
x: 55
}
bit_2 := BigintTypedef{
x: 99
}
bit_3 := BigintTypedef{
x: 55
}
println(bit_1)
println(bit_2)
println(bit_3)
assert bit_1 == bit_1
assert bit_1 == bit_3
assert bit_1 != bit_2
}