cgen: implement equality on arrays
							parent
							
								
									71190c27a9
								
							
						
					
					
						commit
						8f8f8c418e
					
				|  | @ -55,6 +55,7 @@ mut: | |||
| 	defer_ifdef    string | ||||
| 	str_types      []string // types that need automatic str() generation
 | ||||
| 	threaded_fns   []string // for generating unique wrapper types and fns for `go xxx()`
 | ||||
| 	array_fn_definitions []string // array equality functions that have been defined
 | ||||
| } | ||||
| 
 | ||||
| const ( | ||||
|  | @ -1300,7 +1301,6 @@ fn (g mut Gen) assign_expr(node ast.AssignExpr) { | |||
| } | ||||
| 
 | ||||
| fn (g mut Gen) infix_expr(node ast.InfixExpr) { | ||||
| 	left_sym := g.table.get_type_symbol(node.left_type) | ||||
| 	// println('infix_expr() op="$node.op.str()" line_nr=$node.pos.line_nr')
 | ||||
| 	// g.write('/*infix*/')
 | ||||
| 	// if it.left_type == table.string_type_idx {
 | ||||
|  | @ -1308,6 +1308,8 @@ fn (g mut Gen) infix_expr(node ast.InfixExpr) { | |||
| 	// }
 | ||||
| 	// string + string, string == string etc
 | ||||
| 	// g.infix_op = node.op
 | ||||
| 	left_sym := g.table.get_type_symbol(node.left_type) | ||||
| 	right_sym := g.table.get_type_symbol(node.right_type) | ||||
| 	if node.left_type == table.string_type_idx && node.op != .key_in { | ||||
| 		fn_name := match node.op { | ||||
| 			.plus { | ||||
|  | @ -1340,8 +1342,23 @@ fn (g mut Gen) infix_expr(node ast.InfixExpr) { | |||
| 		g.write(', ') | ||||
| 		g.expr(node.right) | ||||
| 		g.write(')') | ||||
| 	} else if node.op in [.eq, .ne] && left_sym.kind == .array && right_sym.kind == .array { | ||||
| 		styp := g.table.value_type(node.left_type) | ||||
| 		ptr_typ := g.typ(node.left_type).split('_')[1] | ||||
| 		if !(ptr_typ in g.array_fn_definitions) { | ||||
| 			sym := g.table.get_type_symbol(left_sym.array_info().elem_type) | ||||
| 			g.generate_array_equality_fn(ptr_typ, styp, sym) | ||||
| 		} | ||||
| 		if node.op == .eq { | ||||
| 			g.write('${ptr_typ}_arr_eq(') | ||||
| 		} else if node.op == .ne { | ||||
| 			g.write('!${ptr_typ}_arr_eq(') | ||||
| 		} | ||||
| 		g.expr(node.left) | ||||
| 		g.write(', ') | ||||
| 		g.expr(node.right) | ||||
| 		g.write(')') | ||||
| 	} else if node.op == .key_in { | ||||
| 		right_sym := g.table.get_type_symbol(node.right_type) | ||||
| 		if right_sym.kind == .array { | ||||
| 			match node.right { | ||||
| 				ast.ArrayInit { | ||||
|  | @ -1379,7 +1396,6 @@ fn (g mut Gen) infix_expr(node ast.InfixExpr) { | |||
| 		tmp := g.new_tmp_var() | ||||
| 		sym := g.table.get_type_symbol(node.left_type) | ||||
| 		info := sym.info as table.Array | ||||
| 		right_sym := g.table.get_type_symbol(node.right_type) | ||||
| 		if right_sym.kind == .array && info.elem_type != node.right_type { | ||||
| 			// push an array => PUSH_MANY, but not if pushing an array to 2d array (`[][]int << []int`)
 | ||||
| 			g.write('_PUSH_MANY(&') | ||||
|  | @ -2038,6 +2054,27 @@ fn (g mut Gen) call_args(args []ast.CallArg, expected_types []table.Type) { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| fn (g mut Gen) generate_array_equality_fn(ptr_typ string, styp table.Type, sym &table.TypeSymbol) { | ||||
| 	g.array_fn_definitions << ptr_typ | ||||
| 	g.definitions.writeln('bool ${ptr_typ}_arr_eq(array_${ptr_typ} a, array_${ptr_typ} b) {') | ||||
| 	g.definitions.writeln('\tif (a.len != b.len) {') | ||||
| 	g.definitions.writeln('\t\treturn false;') | ||||
| 	g.definitions.writeln('\t}') | ||||
| 	g.definitions.writeln('\tfor (int i = 0; i < a.len; i++) {') | ||||
| 	if styp == table.string_type_idx { | ||||
| 		g.definitions.writeln('\t\tif (string_ne(*((${ptr_typ}*)(a.data+(i*a.element_size))), *((${ptr_typ}*)(b.data+(i*b.element_size))))) {') | ||||
| 	} else if sym.kind == .struct_ { | ||||
| 		g.definitions.writeln('\t\tif (memcmp((void*)(a.data+(i*a.element_size)), (void*)(b.data+(i*b.element_size)), a.element_size)) {') | ||||
| 	} else { | ||||
| 		g.definitions.writeln('\t\tif (*((${ptr_typ}*)(a.data+(i*a.element_size))) != *((${ptr_typ}*)(b.data+(i*b.element_size)))) {') | ||||
| 	} | ||||
| 	g.definitions.writeln('\t\t\treturn false;') | ||||
| 	g.definitions.writeln('\t\t}') | ||||
| 	g.definitions.writeln('\t}') | ||||
| 	g.definitions.writeln('\treturn true;') | ||||
| 	g.definitions.writeln('}') | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| fn (g mut Gen) ref_or_deref_arg(arg ast.CallArg, expected_type table.Type) { | ||||
| 	arg_is_ptr := table.type_is_ptr(expected_type) || table.type_idx(expected_type) in table.pointer_type_idxs | ||||
|  |  | |||
|  | @ -0,0 +1,46 @@ | |||
| struct Tester { | ||||
| 	b bool | ||||
| 	i int | ||||
| } | ||||
| 
 | ||||
| enum Color { | ||||
| 	red green blue | ||||
| } | ||||
| 
 | ||||
| fn test_array_equality() { | ||||
| 	strs := ["a", "b", "c"] | ||||
| 	assert strs == ["a", "b", "c"] | ||||
| 	assert strs != ["a", "c", "b"] | ||||
| 	assert strs != ["b", "c", "a"] | ||||
| 	assert strs != ["b", "a", "c"] | ||||
| 	assert strs != ["c", "b", "a"] | ||||
| 	assert strs != ["c", "a", "b"] | ||||
| 	bools := [true, true, false] | ||||
| 	assert bools == [true, true, false] | ||||
| 	assert bools != [true, false, false] | ||||
| 	assert bools != [false, true, true] | ||||
| 	assert bools != [false, false, true] | ||||
| 	assert bools != [false, false, false] | ||||
| 	assert bools != [false, true, false] | ||||
| 	ints := [1, 2, 3] | ||||
| 	assert ints == [1, 2, 3] | ||||
| 	assert ints != [1, 3, 2] | ||||
| 	assert ints != [2, 3, 1] | ||||
| 	assert ints != [2, 1, 3] | ||||
| 	assert ints != [3, 2, 1] | ||||
| 	assert ints != [3, 1, 2] | ||||
| 	a := Tester{true, 100} | ||||
| 	b := Tester{false, 200} | ||||
| 	testers := [a, b] | ||||
| 	assert testers == [a, b] | ||||
| 	assert testers != [a, a] | ||||
| 	assert testers != [b, b] | ||||
| 	assert testers != [b, a] | ||||
| 	colors := [Color.red, Color.green, Color.blue] | ||||
| 	assert colors == [Color.red, Color.green, Color.blue] | ||||
| 	assert colors != [Color.red, Color.blue, Color.green] | ||||
| 	assert colors != [Color.green, Color.blue, Color.red] | ||||
| 	assert colors != [Color.green, Color.red, Color.blue] | ||||
| 	assert colors != [Color.blue, Color.green, Color.red] | ||||
| 	assert colors != [Color.blue, Color.red, Color.green] | ||||
| } | ||||
		Loading…
	
		Reference in New Issue