v.gen.c: allow overriding of the == operator on C.Struct type aliases
parent
aec016bb14
commit
0b6d585b07
|
@ -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 {
|
||||
|
|
|
@ -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('!')
|
||||
}
|
||||
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)
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
struct __mpz_struct1 {
|
||||
int x;
|
||||
};
|
||||
|
||||
typedef struct __mpz_struct2 {
|
||||
int x;
|
||||
} __mpz_struct_typedef;
|
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue