From 7875164d91f6025c8895bf55383100ccc2e1d8bb Mon Sep 17 00:00:00 2001 From: yuyi Date: Wed, 3 Feb 2021 01:37:57 +0800 Subject: [PATCH] cgen: add gen_alias_equlity_fn (#8514) --- vlib/v/gen/c/auto_eq_methods.v | 52 ++++++++++++++++++++++++++++++ vlib/v/gen/c/cgen.v | 18 +++++++++++ vlib/v/tests/array_equality_test.v | 14 ++++++++ 3 files changed, 84 insertions(+) diff --git a/vlib/v/gen/c/auto_eq_methods.v b/vlib/v/gen/c/auto_eq_methods.v index 301ff1fcc1..954cc3667a 100644 --- a/vlib/v/gen/c/auto_eq_methods.v +++ b/vlib/v/gen/c/auto_eq_methods.v @@ -32,6 +32,9 @@ fn (mut g Gen) gen_struct_equality_fn(left table.Type) string { } else if sym.kind == .map && !field.typ.is_ptr() { eq_fn := g.gen_map_equality_fn(field.typ) fn_builder.writeln('\tif (!${eq_fn}_map_eq(a.$field.name, b.$field.name)) {') + } else if sym.kind == .alias && !field.typ.is_ptr() { + eq_fn := g.gen_alias_equality_fn(field.typ) + fn_builder.writeln('\tif (!${eq_fn}_alias_eq(a.$field.name, b.$field.name)) {') } else if sym.kind == .function { fn_builder.writeln('\tif (*((voidptr*)(a.$field.name)) != *((voidptr*)(b.$field.name))) {') } else { @@ -46,6 +49,45 @@ fn (mut g Gen) gen_struct_equality_fn(left table.Type) string { return ptr_typ } +fn (mut g Gen) gen_alias_equality_fn(left table.Type) string { + ptr_typ := g.typ(left).trim('*') + if ptr_typ in g.alias_fn_definitions { + return ptr_typ + } + g.alias_fn_definitions << ptr_typ + left_sym := g.table.get_type_symbol(left) + info := left_sym.info as table.Alias + g.type_definitions.writeln('static bool ${ptr_typ}_alias_eq($ptr_typ a, $ptr_typ b); // auto') + mut fn_builder := strings.new_builder(512) + fn_builder.writeln('static bool ${ptr_typ}_alias_eq($ptr_typ a, $ptr_typ b) {') + sym := g.table.get_type_symbol(info.parent_type) + if sym.kind == .string { + fn_builder.writeln('\tif (string_ne(a, b)) {') + } else if sym.kind == .struct_ && !left.is_ptr() { + eq_fn := g.gen_struct_equality_fn(info.parent_type) + fn_builder.writeln('\tif (!${eq_fn}_struct_eq(a, b)) {') + } else if sym.kind == .array && !left.is_ptr() { + eq_fn := g.gen_array_equality_fn(info.parent_type) + fn_builder.writeln('\tif (!${eq_fn}_arr_eq(a, b)) {') + } else if sym.kind == .array_fixed && !left.is_ptr() { + eq_fn := g.gen_fixed_array_equality_fn(info.parent_type) + fn_builder.writeln('\tif (!${eq_fn}_arr_eq(a, b)) {') + } else if sym.kind == .map && !left.is_ptr() { + eq_fn := g.gen_map_equality_fn(info.parent_type) + fn_builder.writeln('\tif (!${eq_fn}_map_eq(a, b)) {') + } else if sym.kind == .function { + fn_builder.writeln('\tif (*((voidptr*)(a)) != *((voidptr*)(b))) {') + } else { + fn_builder.writeln('\tif (a != b) {') + } + fn_builder.writeln('\t\treturn false;') + fn_builder.writeln('\t}') + fn_builder.writeln('\treturn true;') + fn_builder.writeln('}') + g.auto_fn_definitions << fn_builder.str() + return ptr_typ +} + fn (mut g Gen) gen_array_equality_fn(left table.Type) string { ptr_typ := g.typ(left).trim('*') if ptr_typ in g.array_fn_definitions { @@ -78,6 +120,9 @@ fn (mut g Gen) gen_array_equality_fn(left table.Type) string { } else if elem_sym.kind == .map && !elem_typ.is_ptr() { eq_fn := g.gen_map_equality_fn(elem_typ) fn_builder.writeln('\t\tif (!${eq_fn}_map_eq((($ptr_elem_typ*)a.data)[i], (($ptr_elem_typ*)b.data)[i])) {') + } else if elem_sym.kind == .alias && !elem_typ.is_ptr() { + eq_fn := g.gen_alias_equality_fn(elem_typ) + fn_builder.writeln('\t\tif (!${eq_fn}_alias_eq((($ptr_elem_typ*)a.data)[i], (($ptr_elem_typ*)b.data)[i])) {') } else if elem_sym.kind == .function { fn_builder.writeln('\t\tif (*((voidptr*)((byte*)a.data+(i*a.element_size))) != *((voidptr*)((byte*)b.data+(i*b.element_size)))) {') } else { @@ -122,6 +167,9 @@ fn (mut g Gen) gen_fixed_array_equality_fn(left table.Type) string { } else if elem_sym.kind == .map && !elem_typ.is_ptr() { eq_fn := g.gen_map_equality_fn(elem_typ) fn_builder.writeln('\t\tif (!${eq_fn}_map_eq(a[i], b[i])) {') + } else if elem_sym.kind == .alias && !elem_typ.is_ptr() { + eq_fn := g.gen_alias_equality_fn(elem_typ) + fn_builder.writeln('\t\tif (!${eq_fn}_alias_eq(a[i], b[i])) {') } else if elem_sym.kind == .function { fn_builder.writeln('\t\tif (a[i] != b[i]) {') } else { @@ -193,6 +241,10 @@ fn (mut g Gen) gen_map_equality_fn(left table.Type) string { eq_fn := g.gen_map_equality_fn(value_typ) fn_builder.writeln('\t\tif (!${eq_fn}_map_eq(*($ptr_value_typ*)map_get_1(&b, k, &($ptr_value_typ[]){ 0 }), v)) {') } + .alias { + eq_fn := g.gen_alias_equality_fn(value_typ) + fn_builder.writeln('\t\tif (!${eq_fn}_alias_eq(*($ptr_value_typ*)map_get_1(&b, k, &($ptr_value_typ[]){ 0 }), v)) {') + } .function { fn_builder.writeln('\t\tif (*(voidptr*)map_get_1(&b, k, &(voidptr[]){ 0 }) != v) {') } diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 152335dfc5..9fd0e14e76 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -98,6 +98,7 @@ mut: array_fn_definitions []string // array 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 + alias_fn_definitions []string // alias equality functions that have been defined auto_fn_definitions []string // auto generated functions defination list anon_fn_definitions []string // anon generated functions defination list is_json_fn bool // inside json.encode() @@ -3138,6 +3139,23 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) { } g.expr(node.right) g.write(')') + } else if node.op in [.eq, .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 node.op in [.eq, .ne] && left_sym.kind == .map && right_sym.kind == .map { ptr_typ := g.gen_map_equality_fn(left_type) if node.op == .eq { diff --git a/vlib/v/tests/array_equality_test.v b/vlib/v/tests/array_equality_test.v index aabfce4815..caf77fc000 100644 --- a/vlib/v/tests/array_equality_test.v +++ b/vlib/v/tests/array_equality_test.v @@ -74,3 +74,17 @@ fn test_nested_array_equality() { assert a9 == [[[u16(22), 11]]] assert a9 != [[[u16(20), 10]]] } + +type Literal = string +type Literals = []Literal + +fn (l1 Literal) concat(l2 Literal) Literals { + return Literals([l1, l2]) +} + +fn test_array_of_alias_equality() { + mut literals := Literals([]Literal{}) + literals = Literal('hello').concat(Literal('World')) + println(literals) + assert literals == Literals([Literal('hello'), Literal('World')]) +}