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 {
|
fn (mut g Gen) gen_struct_equality_fn(left_type ast.Type) string {
|
||||||
left := g.unwrap(left_type)
|
left := g.unwrap(left_type)
|
||||||
ptr_styp := g.typ(left.typ.set_nr_muls(0))
|
ptr_styp := g.typ(left.typ.set_nr_muls(0))
|
||||||
if ptr_styp in g.struct_fn_definitions {
|
fn_name := ptr_styp.replace('struct ', '')
|
||||||
return ptr_styp
|
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()
|
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)
|
mut fn_builder := strings.new_builder(512)
|
||||||
defer {
|
defer {
|
||||||
g.auto_fn_definitions << fn_builder.str()
|
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
|
// overloaded
|
||||||
if left.sym.has_method('==') {
|
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('}')
|
fn_builder.writeln('}')
|
||||||
return ptr_styp
|
return fn_name
|
||||||
}
|
}
|
||||||
|
|
||||||
fn_builder.write_string('\treturn ')
|
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(';')
|
||||||
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 {
|
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) {
|
fn (mut g Gen) infix_expr_eq_op(node ast.InfixExpr) {
|
||||||
left := g.unwrap(node.left_type)
|
left := g.unwrap(node.left_type)
|
||||||
right := g.unwrap(node.right_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()) {
|
if (left.typ.is_ptr() && right.typ.is_int()) || (right.typ.is_ptr() && left.typ.is_int()) {
|
||||||
g.gen_plain_infix_expr(node)
|
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
|
&& left.unaliased.idx() == ast.string_type_idx)) && node.right is ast.StringLiteral
|
||||||
&& (node.right as ast.StringLiteral).val == '' {
|
&& (node.right as ast.StringLiteral).val == '' {
|
||||||
// `str == ''` -> `str.len == 0` optimization
|
// `str == ''` -> `str.len == 0` optimization
|
||||||
|
@ -93,11 +94,15 @@ fn (mut g Gen) infix_expr_eq_op(node ast.InfixExpr) {
|
||||||
g.write(')')
|
g.write(')')
|
||||||
arrow := if left.typ.is_ptr() { '->' } else { '.' }
|
arrow := if left.typ.is_ptr() { '->' } else { '.' }
|
||||||
g.write('${arrow}len $node.op 0')
|
g.write('${arrow}len $node.op 0')
|
||||||
} else if has_operator_overloading {
|
} else if has_defined_eq_operator {
|
||||||
if node.op == .ne {
|
if node.op == .ne {
|
||||||
g.write('!')
|
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('__eq(')
|
||||||
g.write('*'.repeat(left.typ.nr_muls()))
|
g.write('*'.repeat(left.typ.nr_muls()))
|
||||||
g.expr(node.left)
|
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