cgen: auto eq method for sumtype (#9408)
parent
e5a698395a
commit
0258482caf
|
@ -741,6 +741,7 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
eq_ne := infix_expr.op in [.eq, .ne]
|
||||||
// Single side check
|
// Single side check
|
||||||
// Place these branches according to ops' usage frequency to accelerate.
|
// Place these branches according to ops' usage frequency to accelerate.
|
||||||
// TODO: First branch includes ops where single side check is not needed, or needed but hasn't been implemented.
|
// TODO: First branch includes ops where single side check is not needed, or needed but hasn't been implemented.
|
||||||
|
@ -748,8 +749,8 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
|
||||||
match infix_expr.op {
|
match infix_expr.op {
|
||||||
// .eq, .ne, .gt, .lt, .ge, .le, .and, .logical_or, .dot, .key_as, .right_shift {}
|
// .eq, .ne, .gt, .lt, .ge, .le, .and, .logical_or, .dot, .key_as, .right_shift {}
|
||||||
.eq, .ne {
|
.eq, .ne {
|
||||||
is_mismatch := (left.kind == .alias && right.kind in [.struct_, .array])
|
is_mismatch := (left.kind == .alias && right.kind in [.struct_, .array, .sum_type])
|
||||||
|| (right.kind == .alias && left.kind in [.struct_, .array])
|
|| (right.kind == .alias && left.kind in [.struct_, .array, .sum_type])
|
||||||
if is_mismatch {
|
if is_mismatch {
|
||||||
c.error('possible type mismatch of compared values of `$infix_expr.op` operation',
|
c.error('possible type mismatch of compared values of `$infix_expr.op` operation',
|
||||||
left_right_pos)
|
left_right_pos)
|
||||||
|
@ -996,7 +997,7 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
|
||||||
// TODO broken !in
|
// TODO broken !in
|
||||||
c.error('string types only have the following operators defined: `==`, `!=`, `<`, `>`, `<=`, `>=`, and `+`',
|
c.error('string types only have the following operators defined: `==`, `!=`, `<`, `>`, `<=`, `>=`, and `+`',
|
||||||
infix_expr.pos)
|
infix_expr.pos)
|
||||||
} else if left.kind == .enum_ && right.kind == .enum_ && infix_expr.op !in [.ne, .eq] {
|
} else if left.kind == .enum_ && right.kind == .enum_ && !eq_ne {
|
||||||
left_enum := left.info as table.Enum
|
left_enum := left.info as table.Enum
|
||||||
right_enum := right.info as table.Enum
|
right_enum := right.info as table.Enum
|
||||||
if left_enum.is_flag && right_enum.is_flag {
|
if left_enum.is_flag && right_enum.is_flag {
|
||||||
|
@ -1011,10 +1012,11 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
|
||||||
infix_expr.pos)
|
infix_expr.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// sum types can't have any infix operation except of "is", is is checked before and doesn't reach this
|
// sum types can't have any infix operation except of `is`, `eq`, `ne`.
|
||||||
if c.table.type_kind(left_type) == .sum_type {
|
// `is` is checked before and doesn't reach this.
|
||||||
|
if c.table.type_kind(left_type) == .sum_type && !eq_ne {
|
||||||
c.error('cannot use operator `$infix_expr.op` with `$left.name`', infix_expr.pos)
|
c.error('cannot use operator `$infix_expr.op` with `$left.name`', infix_expr.pos)
|
||||||
} else if c.table.type_kind(right_type) == .sum_type {
|
} else if c.table.type_kind(right_type) == .sum_type && !eq_ne {
|
||||||
c.error('cannot use operator `$infix_expr.op` with `$right.name`', infix_expr.pos)
|
c.error('cannot use operator `$infix_expr.op` with `$right.name`', infix_expr.pos)
|
||||||
}
|
}
|
||||||
// TODO move this to symmetric_check? Right now it would break `return 0` for `fn()?int `
|
// TODO move this to symmetric_check? Right now it would break `return 0` for `fn()?int `
|
||||||
|
|
|
@ -1,84 +1,139 @@
|
||||||
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:10:10: error: infix expr: cannot use `int literal` (right expression) as `Aaa`
|
|
||||||
8 |
|
|
||||||
9 | fn main() {
|
|
||||||
10 | println(Aaa{} == 10)
|
|
||||||
| ~~~~~~~~~~~
|
|
||||||
11 | println(10 == Aaa{})
|
|
||||||
12 | println(Aaa{} != 10)
|
|
||||||
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:11:10: error: infix expr: cannot use `Aaa` (right expression) as `int literal`
|
|
||||||
9 | fn main() {
|
|
||||||
10 | println(Aaa{} == 10)
|
|
||||||
11 | println(10 == Aaa{})
|
|
||||||
| ~~~~~~~~~~~
|
|
||||||
12 | println(Aaa{} != 10)
|
|
||||||
13 | println(10 != Aaa{})
|
|
||||||
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:12:10: error: infix expr: cannot use `int literal` (right expression) as `Aaa`
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:12:10: error: infix expr: cannot use `int literal` (right expression) as `Aaa`
|
||||||
10 | println(Aaa{} == 10)
|
10 |
|
||||||
11 | println(10 == Aaa{})
|
11 | fn main() {
|
||||||
12 | println(Aaa{} != 10)
|
12 | println(Aaa{} == 10)
|
||||||
| ~~~~~~~~~~~
|
| ~~~~~~~~~~~
|
||||||
13 | println(10 != Aaa{})
|
13 | println(10 == Aaa{})
|
||||||
14 |
|
14 | println(Aaa{} != 10)
|
||||||
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:13:10: error: infix expr: cannot use `Aaa` (right expression) as `int literal`
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:13:10: error: infix expr: cannot use `Aaa` (right expression) as `int literal`
|
||||||
11 | println(10 == Aaa{})
|
11 | fn main() {
|
||||||
12 | println(Aaa{} != 10)
|
12 | println(Aaa{} == 10)
|
||||||
13 | println(10 != Aaa{})
|
13 | println(10 == Aaa{})
|
||||||
| ~~~~~~~~~~~
|
| ~~~~~~~~~~~
|
||||||
14 |
|
14 | println(Aaa{} != 10)
|
||||||
15 | println(Aaa{0} == AAaa{0})
|
15 | println(10 != Aaa{})
|
||||||
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:15:10: error: possible type mismatch of compared values of `==` operation
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:14:10: error: infix expr: cannot use `int literal` (right expression) as `Aaa`
|
||||||
13 | println(10 != Aaa{})
|
12 | println(Aaa{} == 10)
|
||||||
14 |
|
13 | println(10 == Aaa{})
|
||||||
15 | println(Aaa{0} == AAaa{0})
|
14 | println(Aaa{} != 10)
|
||||||
|
| ~~~~~~~~~~~
|
||||||
|
15 | println(10 != Aaa{})
|
||||||
|
16 |
|
||||||
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:15:10: error: infix expr: cannot use `Aaa` (right expression) as `int literal`
|
||||||
|
13 | println(10 == Aaa{})
|
||||||
|
14 | println(Aaa{} != 10)
|
||||||
|
15 | println(10 != Aaa{})
|
||||||
|
| ~~~~~~~~~~~
|
||||||
|
16 |
|
||||||
|
17 | println(Aaa{0} == AAaa{0})
|
||||||
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:17:10: error: possible type mismatch of compared values of `==` operation
|
||||||
|
15 | println(10 != Aaa{})
|
||||||
|
16 |
|
||||||
|
17 | println(Aaa{0} == AAaa{0})
|
||||||
| ~~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~~
|
||||||
16 | println(AAaa{0} == Aaa{0})
|
18 | println(AAaa{0} == Aaa{0})
|
||||||
17 | println(AAaa{1} != Aaa{1})
|
19 | println(AAaa{1} != Aaa{1})
|
||||||
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:16:10: error: possible type mismatch of compared values of `==` operation
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:18:10: error: possible type mismatch of compared values of `==` operation
|
||||||
14 |
|
16 |
|
||||||
15 | println(Aaa{0} == AAaa{0})
|
17 | println(Aaa{0} == AAaa{0})
|
||||||
16 | println(AAaa{0} == Aaa{0})
|
18 | println(AAaa{0} == Aaa{0})
|
||||||
| ~~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~~
|
||||||
17 | println(AAaa{1} != Aaa{1})
|
19 | println(AAaa{1} != Aaa{1})
|
||||||
18 | println(Aaa{1} != AAaa{1})
|
20 | println(Aaa{1} != AAaa{1})
|
||||||
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:17:10: error: possible type mismatch of compared values of `!=` operation
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:19:10: error: possible type mismatch of compared values of `!=` operation
|
||||||
15 | println(Aaa{0} == AAaa{0})
|
17 | println(Aaa{0} == AAaa{0})
|
||||||
16 | println(AAaa{0} == Aaa{0})
|
18 | println(AAaa{0} == Aaa{0})
|
||||||
17 | println(AAaa{1} != Aaa{1})
|
19 | println(AAaa{1} != Aaa{1})
|
||||||
| ~~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~~
|
||||||
18 | println(Aaa{1} != AAaa{1})
|
20 | println(Aaa{1} != AAaa{1})
|
||||||
19 |
|
21 |
|
||||||
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:18:10: error: possible type mismatch of compared values of `!=` operation
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:20:10: error: possible type mismatch of compared values of `!=` operation
|
||||||
16 | println(AAaa{0} == Aaa{0})
|
18 | println(AAaa{0} == Aaa{0})
|
||||||
17 | println(AAaa{1} != Aaa{1})
|
19 | println(AAaa{1} != Aaa{1})
|
||||||
18 | println(Aaa{1} != AAaa{1})
|
20 | println(Aaa{1} != AAaa{1})
|
||||||
| ~~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~~
|
||||||
19 |
|
21 |
|
||||||
20 | arr := Arr([0])
|
22 | arr := Arr([0])
|
||||||
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:21:10: error: possible type mismatch of compared values of `==` operation
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:23:10: error: possible type mismatch of compared values of `==` operation
|
||||||
19 |
|
21 |
|
||||||
20 | arr := Arr([0])
|
22 | arr := Arr([0])
|
||||||
21 | println(arr == [0])
|
23 | println(arr == [0])
|
||||||
| ~~~~~~~~~~
|
| ~~~~~~~~~~
|
||||||
22 | println([1] == arr)
|
24 | println([1] == arr)
|
||||||
23 | println(arr != [0])
|
25 | println(arr != [0])
|
||||||
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:22:10: error: possible type mismatch of compared values of `==` operation
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:24:10: error: possible type mismatch of compared values of `==` operation
|
||||||
20 | arr := Arr([0])
|
22 | arr := Arr([0])
|
||||||
21 | println(arr == [0])
|
23 | println(arr == [0])
|
||||||
22 | println([1] == arr)
|
24 | println([1] == arr)
|
||||||
| ~~~~~~~~~~
|
| ~~~~~~~~~~
|
||||||
23 | println(arr != [0])
|
25 | println(arr != [0])
|
||||||
24 | println([1] != arr)
|
26 | println([1] != arr)
|
||||||
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:23:10: error: possible type mismatch of compared values of `!=` operation
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:25:10: error: possible type mismatch of compared values of `!=` operation
|
||||||
21 | println(arr == [0])
|
23 | println(arr == [0])
|
||||||
22 | println([1] == arr)
|
24 | println([1] == arr)
|
||||||
23 | println(arr != [0])
|
25 | println(arr != [0])
|
||||||
| ~~~~~~~~~~
|
| ~~~~~~~~~~
|
||||||
24 | println([1] != arr)
|
26 | println([1] != arr)
|
||||||
25 | }
|
27 |
|
||||||
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:24:10: error: possible type mismatch of compared values of `!=` operation
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:26:10: error: possible type mismatch of compared values of `!=` operation
|
||||||
22 | println([1] == arr)
|
24 | println([1] == arr)
|
||||||
23 | println(arr != [0])
|
25 | println(arr != [0])
|
||||||
24 | println([1] != arr)
|
26 | println([1] != arr)
|
||||||
| ~~~~~~~~~~
|
| ~~~~~~~~~~
|
||||||
25 | }
|
27 |
|
||||||
|
28 | arr_aaa := ArrAaa(arr)
|
||||||
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:29:10: error: possible type mismatch of compared values of `==` operation
|
||||||
|
27 |
|
||||||
|
28 | arr_aaa := ArrAaa(arr)
|
||||||
|
29 | println(arr_aaa == arr)
|
||||||
|
| ~~~~~~~~~~~~~~
|
||||||
|
30 | println(arr == arr_aaa)
|
||||||
|
31 | println(arr_aaa != arr)
|
||||||
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:30:10: error: possible type mismatch of compared values of `==` operation
|
||||||
|
28 | arr_aaa := ArrAaa(arr)
|
||||||
|
29 | println(arr_aaa == arr)
|
||||||
|
30 | println(arr == arr_aaa)
|
||||||
|
| ~~~~~~~~~~~~~~
|
||||||
|
31 | println(arr_aaa != arr)
|
||||||
|
32 | println(arr != arr_aaa)
|
||||||
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:31:10: error: possible type mismatch of compared values of `!=` operation
|
||||||
|
29 | println(arr_aaa == arr)
|
||||||
|
30 | println(arr == arr_aaa)
|
||||||
|
31 | println(arr_aaa != arr)
|
||||||
|
| ~~~~~~~~~~~~~~
|
||||||
|
32 | println(arr != arr_aaa)
|
||||||
|
33 |
|
||||||
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:32:10: error: possible type mismatch of compared values of `!=` operation
|
||||||
|
30 | println(arr == arr_aaa)
|
||||||
|
31 | println(arr_aaa != arr)
|
||||||
|
32 | println(arr != arr_aaa)
|
||||||
|
| ~~~~~~~~~~~~~~
|
||||||
|
33 |
|
||||||
|
34 | println(arr_aaa == [0])
|
||||||
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:34:10: error: infix expr: cannot use `[]int` (right expression) as `ArrAaa`
|
||||||
|
32 | println(arr != arr_aaa)
|
||||||
|
33 |
|
||||||
|
34 | println(arr_aaa == [0])
|
||||||
|
| ~~~~~~~~~~~~~~
|
||||||
|
35 | println([1] == arr_aaa)
|
||||||
|
36 | println(arr_aaa != [0])
|
||||||
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:35:10: error: infix expr: cannot use `ArrAaa` (right expression) as `[]int`
|
||||||
|
33 |
|
||||||
|
34 | println(arr_aaa == [0])
|
||||||
|
35 | println([1] == arr_aaa)
|
||||||
|
| ~~~~~~~~~~~~~~
|
||||||
|
36 | println(arr_aaa != [0])
|
||||||
|
37 | println([1] != arr_aaa)
|
||||||
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:36:10: error: infix expr: cannot use `[]int` (right expression) as `ArrAaa`
|
||||||
|
34 | println(arr_aaa == [0])
|
||||||
|
35 | println([1] == arr_aaa)
|
||||||
|
36 | println(arr_aaa != [0])
|
||||||
|
| ~~~~~~~~~~~~~~
|
||||||
|
37 | println([1] != arr_aaa)
|
||||||
|
38 | }
|
||||||
|
vlib/v/checker/tests/eq_ne_op_wrong_type_err.vv:37:10: error: infix expr: cannot use `ArrAaa` (right expression) as `[]int`
|
||||||
|
35 | println([1] == arr_aaa)
|
||||||
|
36 | println(arr_aaa != [0])
|
||||||
|
37 | println([1] != arr_aaa)
|
||||||
|
| ~~~~~~~~~~~~~~
|
||||||
|
38 | }
|
||||||
|
|
|
@ -6,6 +6,8 @@ type AAaa = Aaa
|
||||||
|
|
||||||
type Arr = []int
|
type Arr = []int
|
||||||
|
|
||||||
|
type ArrAaa = Aaa | Arr
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println(Aaa{} == 10)
|
println(Aaa{} == 10)
|
||||||
println(10 == Aaa{})
|
println(10 == Aaa{})
|
||||||
|
@ -22,4 +24,15 @@ fn main() {
|
||||||
println([1] == arr)
|
println([1] == arr)
|
||||||
println(arr != [0])
|
println(arr != [0])
|
||||||
println([1] != arr)
|
println([1] != arr)
|
||||||
|
|
||||||
|
arr_aaa := ArrAaa(arr)
|
||||||
|
println(arr_aaa == arr)
|
||||||
|
println(arr == arr_aaa)
|
||||||
|
println(arr_aaa != arr)
|
||||||
|
println(arr != arr_aaa)
|
||||||
|
|
||||||
|
println(arr_aaa == [0])
|
||||||
|
println([1] == arr_aaa)
|
||||||
|
println(arr_aaa != [0])
|
||||||
|
println([1] != arr_aaa)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,59 @@ module c
|
||||||
import strings
|
import strings
|
||||||
import v.table
|
import v.table
|
||||||
|
|
||||||
|
fn (mut g Gen) gen_sumtype_equality_fn(left table.Type) string {
|
||||||
|
ptr_typ := g.typ(left).trim('*')
|
||||||
|
if ptr_typ in g.sumtype_fn_definitions {
|
||||||
|
return ptr_typ
|
||||||
|
}
|
||||||
|
g.sumtype_fn_definitions << ptr_typ
|
||||||
|
left_sym := g.table.get_type_symbol(left)
|
||||||
|
info := left_sym.sumtype_info()
|
||||||
|
g.type_definitions.writeln('static bool ${ptr_typ}_sumtype_eq($ptr_typ a, $ptr_typ b); // auto')
|
||||||
|
mut fn_builder := strings.new_builder(512)
|
||||||
|
fn_builder.writeln('static bool ${ptr_typ}_sumtype_eq($ptr_typ a, $ptr_typ b) {')
|
||||||
|
|
||||||
|
fn_builder.writeln('\tif (a._typ != b._typ) { return false; } ')
|
||||||
|
for typ in info.variants {
|
||||||
|
sym := g.table.get_type_symbol(typ)
|
||||||
|
fn_builder.writeln('\tif (a._typ == $typ) {')
|
||||||
|
name := '_$sym.cname'
|
||||||
|
if sym.kind == .string {
|
||||||
|
fn_builder.writeln('\t\tif (string_ne(*a.$name, *b.$name)) {')
|
||||||
|
} else if sym.kind == .sum_type && !typ.is_ptr() {
|
||||||
|
eq_fn := g.gen_sumtype_equality_fn(typ)
|
||||||
|
fn_builder.writeln('\t\tif (!${eq_fn}_sumtype_eq(*a.$name, *b.$name)) {')
|
||||||
|
} else if sym.kind == .struct_ && !typ.is_ptr() {
|
||||||
|
eq_fn := g.gen_struct_equality_fn(typ)
|
||||||
|
fn_builder.writeln('\t\tif (!${eq_fn}_struct_eq(*a.$name, *b.$name)) {')
|
||||||
|
} else if sym.kind == .array && !typ.is_ptr() {
|
||||||
|
eq_fn := g.gen_array_equality_fn(typ)
|
||||||
|
fn_builder.writeln('\t\tif (!${eq_fn}_arr_eq(*a.$name, *b.$name)) {')
|
||||||
|
} else if sym.kind == .array_fixed && !typ.is_ptr() {
|
||||||
|
eq_fn := g.gen_fixed_array_equality_fn(typ)
|
||||||
|
fn_builder.writeln('\t\tif (!${eq_fn}_arr_eq(*a.$name, *b.$name)) {')
|
||||||
|
} else if sym.kind == .map && !typ.is_ptr() {
|
||||||
|
eq_fn := g.gen_map_equality_fn(typ)
|
||||||
|
fn_builder.writeln('\t\tif (!${eq_fn}_map_eq(*a.$name, *b.$name)) {')
|
||||||
|
} else if sym.kind == .alias && !typ.is_ptr() {
|
||||||
|
eq_fn := g.gen_alias_equality_fn(typ)
|
||||||
|
fn_builder.writeln('\t\tif (!${eq_fn}_alias_eq(*a.$name, *b.$name)) {')
|
||||||
|
} else if sym.kind == .function {
|
||||||
|
fn_builder.writeln('\t\tif (*((voidptr*)(*a.$name)) != *((voidptr*)(*b.$name))) {')
|
||||||
|
} else {
|
||||||
|
fn_builder.writeln('\t\tif (*a.$name != *b.$name) {')
|
||||||
|
}
|
||||||
|
fn_builder.writeln('\t\t\treturn false;')
|
||||||
|
fn_builder.writeln('\t\t}')
|
||||||
|
fn_builder.writeln('\t\treturn true;')
|
||||||
|
fn_builder.writeln('\t}')
|
||||||
|
}
|
||||||
|
fn_builder.writeln('\treturn false;')
|
||||||
|
fn_builder.writeln('}')
|
||||||
|
g.auto_fn_definitions << fn_builder.str()
|
||||||
|
return ptr_typ
|
||||||
|
}
|
||||||
|
|
||||||
fn (mut g Gen) gen_struct_equality_fn(left table.Type) string {
|
fn (mut g Gen) gen_struct_equality_fn(left table.Type) string {
|
||||||
ptr_typ := g.typ(left).trim('*')
|
ptr_typ := g.typ(left).trim('*')
|
||||||
if ptr_typ in g.struct_fn_definitions {
|
if ptr_typ in g.struct_fn_definitions {
|
||||||
|
@ -20,6 +73,9 @@ fn (mut g Gen) gen_struct_equality_fn(left table.Type) string {
|
||||||
sym := g.table.get_type_symbol(field.typ)
|
sym := g.table.get_type_symbol(field.typ)
|
||||||
if sym.kind == .string {
|
if sym.kind == .string {
|
||||||
fn_builder.writeln('\tif (string_ne(a.$field.name, b.$field.name)) {')
|
fn_builder.writeln('\tif (string_ne(a.$field.name, b.$field.name)) {')
|
||||||
|
} else if sym.kind == .sum_type && !field.typ.is_ptr() {
|
||||||
|
eq_fn := g.gen_sumtype_equality_fn(field.typ)
|
||||||
|
fn_builder.writeln('\tif (!${eq_fn}_sumtype_eq(a.$field.name, b.$field.name)) {')
|
||||||
} else if sym.kind == .struct_ && !field.typ.is_ptr() {
|
} else if sym.kind == .struct_ && !field.typ.is_ptr() {
|
||||||
eq_fn := g.gen_struct_equality_fn(field.typ)
|
eq_fn := g.gen_struct_equality_fn(field.typ)
|
||||||
fn_builder.writeln('\tif (!${eq_fn}_struct_eq(a.$field.name, b.$field.name)) {')
|
fn_builder.writeln('\tif (!${eq_fn}_struct_eq(a.$field.name, b.$field.name)) {')
|
||||||
|
@ -63,6 +119,9 @@ fn (mut g Gen) gen_alias_equality_fn(left table.Type) string {
|
||||||
sym := g.table.get_type_symbol(info.parent_type)
|
sym := g.table.get_type_symbol(info.parent_type)
|
||||||
if sym.kind == .string {
|
if sym.kind == .string {
|
||||||
fn_builder.writeln('\tif (string_ne(a, b)) {')
|
fn_builder.writeln('\tif (string_ne(a, b)) {')
|
||||||
|
} else if sym.kind == .sum_type && !left.is_ptr() {
|
||||||
|
eq_fn := g.gen_sumtype_equality_fn(info.parent_type)
|
||||||
|
fn_builder.writeln('\tif (!${eq_fn}_sumtype_eq(a, b)) {')
|
||||||
} else if sym.kind == .struct_ && !left.is_ptr() {
|
} else if sym.kind == .struct_ && !left.is_ptr() {
|
||||||
eq_fn := g.gen_struct_equality_fn(info.parent_type)
|
eq_fn := g.gen_struct_equality_fn(info.parent_type)
|
||||||
fn_builder.writeln('\tif (!${eq_fn}_struct_eq(a, b)) {')
|
fn_builder.writeln('\tif (!${eq_fn}_struct_eq(a, b)) {')
|
||||||
|
@ -108,6 +167,9 @@ fn (mut g Gen) gen_array_equality_fn(left table.Type) string {
|
||||||
// compare every pair of elements of the two arrays
|
// compare every pair of elements of the two arrays
|
||||||
if elem_sym.kind == .string {
|
if elem_sym.kind == .string {
|
||||||
fn_builder.writeln('\t\tif (string_ne(*(($ptr_elem_typ*)((byte*)a.data+(i*a.element_size))), *(($ptr_elem_typ*)((byte*)b.data+(i*b.element_size))))) {')
|
fn_builder.writeln('\t\tif (string_ne(*(($ptr_elem_typ*)((byte*)a.data+(i*a.element_size))), *(($ptr_elem_typ*)((byte*)b.data+(i*b.element_size))))) {')
|
||||||
|
} else if elem_sym.kind == .sum_type && !elem_typ.is_ptr() {
|
||||||
|
eq_fn := g.gen_sumtype_equality_fn(elem_typ)
|
||||||
|
fn_builder.writeln('\t\tif (!${eq_fn}_sumtype_eq((($ptr_elem_typ*)a.data)[i], (($ptr_elem_typ*)b.data)[i])) {')
|
||||||
} else if elem_sym.kind == .struct_ && !elem_typ.is_ptr() {
|
} else if elem_sym.kind == .struct_ && !elem_typ.is_ptr() {
|
||||||
eq_fn := g.gen_struct_equality_fn(elem_typ)
|
eq_fn := g.gen_struct_equality_fn(elem_typ)
|
||||||
fn_builder.writeln('\t\tif (!${eq_fn}_struct_eq((($ptr_elem_typ*)a.data)[i], (($ptr_elem_typ*)b.data)[i])) {')
|
fn_builder.writeln('\t\tif (!${eq_fn}_struct_eq((($ptr_elem_typ*)a.data)[i], (($ptr_elem_typ*)b.data)[i])) {')
|
||||||
|
@ -155,6 +217,9 @@ fn (mut g Gen) gen_fixed_array_equality_fn(left table.Type) string {
|
||||||
// compare every pair of elements of the two fixed arrays
|
// compare every pair of elements of the two fixed arrays
|
||||||
if elem_sym.kind == .string {
|
if elem_sym.kind == .string {
|
||||||
fn_builder.writeln('\t\tif (string_ne(a[i], b[i])) {')
|
fn_builder.writeln('\t\tif (string_ne(a[i], b[i])) {')
|
||||||
|
} else if elem_sym.kind == .sum_type && !elem_typ.is_ptr() {
|
||||||
|
eq_fn := g.gen_sumtype_equality_fn(elem_typ)
|
||||||
|
fn_builder.writeln('\t\tif (!${eq_fn}_sumtype_eq(a[i], b[i])) {')
|
||||||
} else if elem_sym.kind == .struct_ && !elem_typ.is_ptr() {
|
} else if elem_sym.kind == .struct_ && !elem_typ.is_ptr() {
|
||||||
eq_fn := g.gen_struct_equality_fn(elem_typ)
|
eq_fn := g.gen_struct_equality_fn(elem_typ)
|
||||||
fn_builder.writeln('\t\tif (!${eq_fn}_struct_eq(a[i], b[i])) {')
|
fn_builder.writeln('\t\tif (!${eq_fn}_struct_eq(a[i], b[i])) {')
|
||||||
|
@ -225,6 +290,10 @@ fn (mut g Gen) gen_map_equality_fn(left table.Type) string {
|
||||||
.string {
|
.string {
|
||||||
fn_builder.writeln('\t\tif (!fast_string_eq(*(string*)map_get_1(&b, k, &(string[]){_SLIT("")}), v)) {')
|
fn_builder.writeln('\t\tif (!fast_string_eq(*(string*)map_get_1(&b, k, &(string[]){_SLIT("")}), v)) {')
|
||||||
}
|
}
|
||||||
|
.sum_type {
|
||||||
|
eq_fn := g.gen_sumtype_equality_fn(value_typ)
|
||||||
|
fn_builder.writeln('\t\tif (!${eq_fn}_sumtype_eq(*($ptr_value_typ*)map_get_1(&b, k, &($ptr_value_typ[]){ 0 }), v)) {')
|
||||||
|
}
|
||||||
.struct_ {
|
.struct_ {
|
||||||
eq_fn := g.gen_struct_equality_fn(value_typ)
|
eq_fn := g.gen_struct_equality_fn(value_typ)
|
||||||
fn_builder.writeln('\t\tif (!${eq_fn}_struct_eq(*($ptr_value_typ*)map_get_1(&b, k, &($ptr_value_typ[]){ 0 }), v)) {')
|
fn_builder.writeln('\t\tif (!${eq_fn}_struct_eq(*($ptr_value_typ*)map_get_1(&b, k, &($ptr_value_typ[]){ 0 }), v)) {')
|
||||||
|
@ -249,6 +318,7 @@ fn (mut g Gen) gen_map_equality_fn(left table.Type) string {
|
||||||
fn_builder.writeln('\t\tif (*(voidptr*)map_get_1(&b, k, &(voidptr[]){ 0 }) != v) {')
|
fn_builder.writeln('\t\tif (*(voidptr*)map_get_1(&b, k, &(voidptr[]){ 0 }) != v) {')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
println(kind)
|
||||||
fn_builder.writeln('\t\tif (*($ptr_value_typ*)map_get_1(&b, k, &($ptr_value_typ[]){ 0 }) != v) {')
|
fn_builder.writeln('\t\tif (*($ptr_value_typ*)map_get_1(&b, k, &($ptr_value_typ[]){ 0 }) != v) {')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,6 +102,7 @@ mut:
|
||||||
array_fn_definitions []string // array equality functions that have been defined
|
array_fn_definitions []string // array equality functions that have been defined
|
||||||
map_fn_definitions []string // map equality functions that have been defined
|
map_fn_definitions []string // map equality functions that have been defined
|
||||||
struct_fn_definitions []string // struct equality functions that have been defined
|
struct_fn_definitions []string // struct equality functions that have been defined
|
||||||
|
sumtype_fn_definitions []string // sumtype equality functions that have been defined
|
||||||
alias_fn_definitions []string // alias equality functions that have been defined
|
alias_fn_definitions []string // alias equality functions that have been defined
|
||||||
auto_fn_definitions []string // auto generated functions defination list
|
auto_fn_definitions []string // auto generated functions defination list
|
||||||
anon_fn_definitions []string // anon generated functions defination list
|
anon_fn_definitions []string // anon generated functions defination list
|
||||||
|
@ -3518,6 +3519,23 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
||||||
}
|
}
|
||||||
g.expr(node.right)
|
g.expr(node.right)
|
||||||
g.write(')')
|
g.write(')')
|
||||||
|
} else if op_is_eq_or_ne && left_sym.kind == .sum_type && right_sym.kind == .sum_type {
|
||||||
|
ptr_typ := g.gen_sumtype_equality_fn(left_type)
|
||||||
|
if node.op == .eq {
|
||||||
|
g.write('${ptr_typ}_sumtype_eq(')
|
||||||
|
} else if node.op == .ne {
|
||||||
|
g.write('!${ptr_typ}_sumtype_eq(')
|
||||||
|
}
|
||||||
|
if node.left_type.is_ptr() {
|
||||||
|
g.write('*')
|
||||||
|
}
|
||||||
|
g.expr(node.left)
|
||||||
|
g.write(', ')
|
||||||
|
if node.right_type.is_ptr() {
|
||||||
|
g.write('*')
|
||||||
|
}
|
||||||
|
g.expr(node.right)
|
||||||
|
g.write(')')
|
||||||
} else if op_is_key_in_or_not_in {
|
} else if op_is_key_in_or_not_in {
|
||||||
if node.op == .not_in {
|
if node.op == .not_in {
|
||||||
g.write('!')
|
g.write('!')
|
||||||
|
|
|
@ -525,6 +525,14 @@ pub fn (t &TypeSymbol) struct_info() Struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
pub fn (t &TypeSymbol) sumtype_info() SumType {
|
||||||
|
match mut t.info {
|
||||||
|
SumType { return t.info }
|
||||||
|
else { panic('TypeSymbol.sumtype_info(): no sumtype info for type: $t.name') }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
pub fn (t TypeSymbol) str() string {
|
pub fn (t TypeSymbol) str() string {
|
||||||
return t.name
|
return t.name
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
type Str = string | ustring
|
||||||
|
|
||||||
|
struct Foo {
|
||||||
|
v int
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Bar {
|
||||||
|
v int
|
||||||
|
}
|
||||||
|
|
||||||
|
type FooBar = Foo | Bar
|
||||||
|
|
||||||
|
fn test_sumtype_equality() {
|
||||||
|
s1 := Str('s')
|
||||||
|
s2 := Str('s2')
|
||||||
|
u1 := Str('s1'.ustring())
|
||||||
|
u2 := Str('s2'.ustring())
|
||||||
|
assert s1 == s1
|
||||||
|
assert u1 == u1
|
||||||
|
assert s1 != s2
|
||||||
|
assert u1 != u2
|
||||||
|
assert u1 != s1
|
||||||
|
|
||||||
|
// Same value, defferent type
|
||||||
|
foo := FooBar(Foo{v: 0})
|
||||||
|
bar := FooBar(Bar{v: 0})
|
||||||
|
assert foo.v == bar.v
|
||||||
|
assert foo != bar
|
||||||
|
}
|
Loading…
Reference in New Issue