1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

cgen: add gen_alias_equlity_fn (#8514)

This commit is contained in:
yuyi 2021-02-03 01:37:57 +08:00 committed by GitHub
parent c818ad97eb
commit 7875164d91
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 84 additions and 0 deletions

View File

@ -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) {')
}

View File

@ -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 {

View File

@ -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')])
}