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