diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 3fe3fe010e..ed9cce30fa 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -3300,6 +3300,206 @@ fn (mut g Gen) enum_expr(node ast.Expr) { } } +fn (mut g Gen) infix_gen_equality(node ast.InfixExpr, left_type table.Type, left_sym table.TypeSymbol, right_sym table.TypeSymbol) { + has_eq_overloaded := left_sym.has_method('==') + if left_sym.kind != right_sym.kind { + return + } + match left_sym.kind { + .array { + ptr_typ := g.gen_array_equality_fn(left_type.clear_flag(.shared_f)) + if node.op == .ne { + g.write('!') + } + g.write('${ptr_typ}_arr_eq(') + if node.left_type.is_ptr() && !node.left_type.has_flag(.shared_f) { + g.write('*') + } + g.expr(node.left) + if node.left_type.has_flag(.shared_f) { + if node.left_type.is_ptr() { + g.write('->val') + } else { + g.write('.val') + } + } + g.write(', ') + if node.right_type.is_ptr() && !node.right_type.has_flag(.shared_f) { + g.write('*') + } + g.expr(node.right) + if node.right_type.has_flag(.shared_f) { + if node.right_type.is_ptr() { + g.write('->val') + } else { + g.write('.val') + } + } + g.write(')') + } + .array_fixed { + ptr_typ := g.gen_fixed_array_equality_fn(left_type) + if node.op == .ne { + g.write('!') + } + g.write('${ptr_typ}_arr_eq(') + if node.left_type.is_ptr() { + g.write('*') + } + if node.left is ast.ArrayInit { + s := g.typ(left_type) + g.write('($s)') + } + g.expr(node.left) + g.write(', ') + if node.right is ast.ArrayInit { + s := g.typ(left_type) + g.write('($s)') + } + g.expr(node.right) + g.write(')') + } + .alias { + ptr_typ := g.gen_alias_equality_fn(left_type) + if node.op == .eq { + g.write('${ptr_typ}_alias_eq(') + } else if node.op == .ne { + g.write('!${ptr_typ}_alias_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(')') + } + .map { + ptr_typ := g.gen_map_equality_fn(left_type) + if node.op == .eq { + g.write('${ptr_typ}_map_eq(') + } else if node.op == .ne { + g.write('!${ptr_typ}_map_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(')') + } + .struct_ { + if has_eq_overloaded { + // Define `==` as negation of Autogenerated `!=` + styp := g.typ(left_type) + if node.op == .ne { + g.write('!${styp}__eq(') + } else if node.op == .eq { + g.write('${styp}__eq(') + } + } else { + // Auto generate both `==` and `!=` + ptr_typ := g.gen_struct_equality_fn(left_type) + if node.op == .eq { + g.write('${ptr_typ}_struct_eq(') + } else if node.op == .ne { + g.write('!${ptr_typ}_struct_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(')') + } + .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 {} + } +} + +fn (mut g Gen) infix_in_or_not_in(node ast.InfixExpr, left_sym table.TypeSymbol, right_sym table.TypeSymbol) { + if node.op == .not_in { + g.write('!') + } + if right_sym.kind == .array { + if mut node.right is ast.ArrayInit { + if node.right.exprs.len > 0 { + // `a in [1,2,3]` optimization => `a == 1 || a == 2 || a == 3` + // avoids an allocation + // g.write('/*in opt*/') + g.write('(') + g.in_optimization(node.left, node.right) + g.write(')') + return + } + } + fn_name := g.gen_array_contains_method(node.right_type) + g.write('(${fn_name}(') + if node.right_type.is_ptr() { + g.write('*') + } + g.expr(node.right) + g.write(', ') + g.expr(node.left) + g.write('))') + return + } else if right_sym.kind == .map { + g.write('_IN_MAP(') + if !node.left_type.is_ptr() { + left_type_str := g.table.type_to_str(node.left_type) + g.write('ADDR($left_type_str, ') + g.expr(node.left) + g.write(')') + } else { + g.expr(node.left) + } + g.write(', ') + if !node.right_type.is_ptr() { + g.write('ADDR(map, ') + g.expr(node.right) + g.write(')') + } else { + g.expr(node.right) + } + g.write(')') + } else if right_sym.kind == .string { + g.write('string_contains(') + g.expr(node.right) + g.write(', ') + g.expr(node.left) + g.write(')') + } +} + fn (mut g Gen) infix_expr(node ast.InfixExpr) { if node.auto_locked != '' { g.writeln('sync__RwMutex_lock(&$node.auto_locked->mtx);') @@ -3321,7 +3521,6 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) { op_is_eq_or_ne := node.op in [.eq, .ne] right_sym := g.table.get_type_symbol(node.right_type) right_final_sym := g.table.get_final_type_symbol(node.right_type) - has_eq_overloaded := !left_sym.has_method('==') unaliased_right := if right_sym.info is table.Alias { right_sym.info.parent_type } else { @@ -3403,189 +3602,11 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) { g.expr(node.right) g.write(')') } - } else if op_is_eq_or_ne && left_sym.kind == .array && right_sym.kind == .array { - ptr_typ := g.gen_array_equality_fn(left_type.clear_flag(.shared_f)) - if node.op == .ne { - g.write('!') - } - g.write('${ptr_typ}_arr_eq(') - if node.left_type.is_ptr() && !node.left_type.has_flag(.shared_f) { - g.write('*') - } - g.expr(node.left) - if node.left_type.has_flag(.shared_f) { - if node.left_type.is_ptr() { - g.write('->val') - } else { - g.write('.val') - } - } - g.write(', ') - if node.right_type.is_ptr() && !node.right_type.has_flag(.shared_f) { - g.write('*') - } - g.expr(node.right) - if node.right_type.has_flag(.shared_f) { - if node.right_type.is_ptr() { - g.write('->val') - } else { - g.write('.val') - } - } - g.write(')') - } else if op_is_eq_or_ne && left_sym.kind == .array_fixed && right_sym.kind == .array_fixed { - ptr_typ := g.gen_fixed_array_equality_fn(left_type) - if node.op == .ne { - g.write('!') - } - g.write('${ptr_typ}_arr_eq(') - if node.left_type.is_ptr() { - g.write('*') - } - if node.left is ast.ArrayInit { - s := g.typ(left_type) - g.write('($s)') - } - g.expr(node.left) - g.write(', ') - if node.right is ast.ArrayInit { - s := g.typ(left_type) - g.write('($s)') - } - g.expr(node.right) - g.write(')') - } else if op_is_eq_or_ne && left_sym.kind == .alias && right_sym.kind == .alias { - ptr_typ := g.gen_alias_equality_fn(left_type) - if node.op == .eq { - g.write('${ptr_typ}_alias_eq(') - } else if node.op == .ne { - g.write('!${ptr_typ}_alias_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_eq_or_ne && left_sym.kind == .map && right_sym.kind == .map { - ptr_typ := g.gen_map_equality_fn(left_type) - if node.op == .eq { - g.write('${ptr_typ}_map_eq(') - } else if node.op == .ne { - g.write('!${ptr_typ}_map_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_eq_or_ne && left_sym.kind == .struct_ && right_sym.kind == .struct_ { - if !has_eq_overloaded { - // Define `==` as negation of Autogenerated `!=` - styp := g.typ(left_type) - if node.op == .ne { - g.write('!${styp}__eq(') - } else if node.op == .eq { - g.write('${styp}__eq(') - } - } - if has_eq_overloaded { - // Auto generate both `==` and `!=` - ptr_typ := g.gen_struct_equality_fn(left_type) - if node.op == .eq { - g.write('${ptr_typ}_struct_eq(') - } else if node.op == .ne { - g.write('!${ptr_typ}_struct_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_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_eq_or_ne && left_sym.kind == right_sym.kind + && left_sym.kind in [.array, .array_fixed, .alias, .map, .struct_, .sum_type] { + g.infix_gen_equality(node, left_type, left_sym, right_sym) } else if op_is_key_in_or_not_in { - if node.op == .not_in { - g.write('!') - } - if right_sym.kind == .array { - if mut node.right is ast.ArrayInit { - if node.right.exprs.len > 0 { - // `a in [1,2,3]` optimization => `a == 1 || a == 2 || a == 3` - // avoids an allocation - // g.write('/*in opt*/') - g.write('(') - g.in_optimization(node.left, node.right) - g.write(')') - return - } - } - fn_name := g.gen_array_contains_method(node.right_type) - g.write('(${fn_name}(') - if node.right_type.is_ptr() { - g.write('*') - } - g.expr(node.right) - g.write(', ') - g.expr(node.left) - g.write('))') - return - } else if right_sym.kind == .map { - g.write('_IN_MAP(') - if !node.left_type.is_ptr() { - left_type_str := g.table.type_to_str(node.left_type) - g.write('ADDR($left_type_str, ') - g.expr(node.left) - g.write(')') - } else { - g.expr(node.left) - } - g.write(', ') - if !node.right_type.is_ptr() { - g.write('ADDR(map, ') - g.expr(node.right) - g.write(')') - } else { - g.expr(node.right) - } - g.write(')') - } else if right_sym.kind == .string { - g.write('string_contains(') - g.expr(node.right) - g.write(', ') - g.expr(node.left) - g.write(')') - } + g.infix_in_or_not_in(node, left_sym, right_sym) } else if node.op == .left_shift && left_final_sym.kind == .array { // arr << val tmp := g.new_tmp_var()