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

cgen: fix array and map with fns (#5938)

This commit is contained in:
Ruofan XU 2020-07-26 20:22:02 +08:00 committed by GitHub
parent dfa01d8877
commit 7027b2354b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 63 additions and 33 deletions

View File

@ -1166,8 +1166,8 @@ fn (mut g Gen) write_fn_ptr_decl(func &table.FnType, ptr_name string) {
g.write('$ret_styp (*$ptr_name) (') g.write('$ret_styp (*$ptr_name) (')
arg_len := func.func.args.len arg_len := func.func.args.len
for i, arg in func.func.args { for i, arg in func.func.args {
arg_typ := g.table.get_type_symbol(arg.typ) arg_styp := g.typ(arg.typ)
g.write('$arg_typ.str() $arg.name') g.write('$arg_styp $arg.name')
if i < arg_len - 1 { if i < arg_len - 1 {
g.write(', ') g.write(', ')
} }
@ -2165,13 +2165,17 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
} else { } else {
// push a single element // push a single element
elem_type_str := g.typ(info.elem_type) elem_type_str := g.typ(info.elem_type)
elem_sym := g.table.get_type_symbol(info.elem_type)
g.write('array_push(') g.write('array_push(')
if !left_type.is_ptr() { if !left_type.is_ptr() {
g.write('&') g.write('&')
} }
g.expr(node.left) g.expr(node.left)
if elem_sym.kind == .function {
g.write(', _MOV((voidptr[]){ ')
} else {
g.write(', _MOV(($elem_type_str[]){ ') g.write(', _MOV(($elem_type_str[]){ ')
elem_sym := g.table.get_type_symbol(info.elem_type) }
if elem_sym.kind == .interface_ && node.right_type != info.elem_type { if elem_sym.kind == .interface_ && node.right_type != info.elem_type {
g.interface_call(node.right_type, info.elem_type) g.interface_call(node.right_type, info.elem_type)
} }
@ -3226,14 +3230,13 @@ fn (mut g Gen) gen_array_equality_fn(left table.Type) string {
g.definitions.writeln('\t\treturn false;') g.definitions.writeln('\t\treturn false;')
g.definitions.writeln('\t}') g.definitions.writeln('\t}')
g.definitions.writeln('\tfor (int i = 0; i < a.len; ++i) {') g.definitions.writeln('\tfor (int i = 0; i < a.len; ++i) {')
if elem_sym.kind == .string { // compare every pair of elements of the two arrays
g.definitions.writeln('\t\tif (string_ne(*(($ptr_typ*)((byte*)a.data+(i*a.element_size))), *(($ptr_typ*)((byte*)b.data+(i*b.element_size))))) {') match elem_sym.kind {
} else if elem_sym.kind == .struct_ { .string { g.definitions.writeln('\t\tif (string_ne(*(($ptr_typ*)((byte*)a.data+(i*a.element_size))), *(($ptr_typ*)((byte*)b.data+(i*b.element_size))))) {') }
g.definitions.writeln('\t\tif (memcmp((byte*)a.data+(i*a.element_size), (byte*)b.data+(i*b.element_size), a.element_size)) {') .struct_ { g.definitions.writeln('\t\tif (memcmp((byte*)a.data+(i*a.element_size), (byte*)b.data+(i*b.element_size), a.element_size)) {') }
} else if elem_sym.kind == .array { .array { g.definitions.writeln('\t\tif (!${ptr_elem_typ}_arr_eq((($elem_typ*)a.data)[i], (($elem_typ*)b.data)[i])) {') }
g.definitions.writeln('\t\tif (!${ptr_elem_typ}_arr_eq((($elem_typ*)a.data)[i], (($elem_typ*)b.data)[i])) {') .function { g.definitions.writeln('\t\tif (*((voidptr*)((byte*)a.data+(i*a.element_size))) != *((voidptr*)((byte*)b.data+(i*b.element_size)))) {') }
} else { else { g.definitions.writeln('\t\tif (*(($ptr_typ*)((byte*)a.data+(i*a.element_size))) != *(($ptr_typ*)((byte*)b.data+(i*b.element_size)))) {') }
g.definitions.writeln('\t\tif (*(($ptr_typ*)((byte*)a.data+(i*a.element_size))) != *(($ptr_typ*)((byte*)b.data+(i*b.element_size)))) {')
} }
g.definitions.writeln('\t\t\treturn false;') g.definitions.writeln('\t\t\treturn false;')
g.definitions.writeln('\t\t}') g.definitions.writeln('\t\t}')
@ -3264,11 +3267,26 @@ fn (mut g Gen) gen_map_equality_fn(left table.Type) string {
g.definitions.writeln('\tarray_string _keys = map_keys(&a);') g.definitions.writeln('\tarray_string _keys = map_keys(&a);')
g.definitions.writeln('\tfor (int i = 0; i < _keys.len; ++i) {') g.definitions.writeln('\tfor (int i = 0; i < _keys.len; ++i) {')
g.definitions.writeln('\t\tstring k = string_clone( ((string*)_keys.data)[i]);') g.definitions.writeln('\t\tstring k = string_clone( ((string*)_keys.data)[i]);')
g.definitions.writeln('\t\t$value_typ v = (*($value_typ*)map_get(a, k, &($value_typ[]){ 0 }));') if value_sym.kind == .function {
if value_sym.kind == .string { func := value_sym.info as table.FnType
g.definitions.writeln('\t\tif (!map_exists(b, k) || string_ne((*($value_typ*)map_get(b, k, &($value_typ[]){tos_lit("")})), v)) {') ret_styp := g.typ(func.func.return_type)
g.definitions.write('\t\t$ret_styp (*v) (')
arg_len := func.func.args.len
for i, arg in func.func.args {
arg_styp := g.typ(arg.typ)
g.definitions.write('$arg_styp $arg.name')
if i < arg_len - 1 {
g.definitions.write(', ')
}
}
g.definitions.writeln(') = (*(voidptr*)map_get(a, k, &(voidptr[]){ 0 }));')
} else { } else {
g.definitions.writeln('\t\tif (!map_exists(b, k) || (*($value_typ*)map_get(b, k, &($value_typ[]){ 0 })) != v) {') g.definitions.writeln('\t\t$value_typ v = (*($value_typ*)map_get(a, k, &($value_typ[]){ 0 }));')
}
match value_sym.kind {
.string { g.definitions.writeln('\t\tif (!map_exists(b, k) || string_ne((*($value_typ*)map_get(b, k, &($value_typ[]){tos_lit("")})), v)) {') }
.function { g.definitions.writeln('\t\tif (!map_exists(b, k) || (*(voidptr*)map_get(b, k, &(voidptr[]){ 0 })) != v) {') }
else { g.definitions.writeln('\t\tif (!map_exists(b, k) || (*($value_typ*)map_get(b, k, &($value_typ[]){ 0 })) != v) {') }
} }
g.definitions.writeln('\t\t\treturn false;') g.definitions.writeln('\t\t\treturn false;')
g.definitions.writeln('\t\t}') g.definitions.writeln('\t\t}')
@ -4877,7 +4895,11 @@ fn (mut g Gen) array_init(it ast.ArrayInit) {
} else { } else {
g.write('0, ') g.write('0, ')
} }
if elem_sym.kind == .function {
g.write('sizeof(voidptr), ')
} else {
g.write('sizeof($elem_type_str), ') g.write('sizeof($elem_type_str), ')
}
if is_default_array { if is_default_array {
g.write('($elem_type_str[]){') g.write('($elem_type_str[]){')
g.expr(it.default_expr) g.expr(it.default_expr)

View File

@ -1,51 +1,59 @@
fn foo(a string) int { fn foo(a, b string) int {
return 10 + a.len return 10 + a.len + b.len
} }
fn foo2(a string) int { fn foo2(a, b string) int {
return 20 + a.len return 20 + a.len + b.len
} }
fn test_array_with_fns() { fn test_array_with_fns() {
mut a := [foo, foo2] mut a := [foo, foo2]
assert a.len == 2 assert a.len == 2
assert (a != [foo, foo2]) == false
assert (foo in a) == true assert (foo in a) == true
f0 := a[0] f0 := a[0]
assert f0('xx') == 12 assert f0('xx', '') == 12
f1 := a[1] f1 := a[1]
assert f1('yyy') == 23 assert f1('yyy', '') == 23
a[0], a[1] = a[1], a[0] a[0], a[1] = a[1], a[0]
f2 := a[0] f2 := a[0]
assert f2('zzzz') == 24 assert f2('zzzz', '') == 24
f3 := a[1] f3 := a[1]
assert f3('aaaaa') == 15 assert f3('aaaaa', '') == 15
mut b := [foo] mut b := [foo]
assert (foo2 !in b) == true assert (foo2 !in b) == true
b[0] = a[0] b[0] = a[0]
f4 := b[0] f4 := b[0]
assert f4('bbbbbb') == 26 assert f4('bbbbbb', '') == 26
for func in b { for func in b {
assert func('ccccccc') == 27 assert func('ccccccc', '') == 27
} }
b = []
b << foo
b << [foo2]
assert (b == [foo, foo2]) == true
f5 := b[0]
assert f5('dddddddd', '') == 18
} }
fn test_map_with_fns() { fn test_map_with_fns() {
mut a := {'one':foo, 'two':foo2} mut a := {'one':foo, 'two':foo2}
assert a.len == 2 assert a.len == 2
assert (a == {'one':foo, 'two':foo2}) == true
f0 := a['one'] f0 := a['one']
assert f0('xx') == 12 assert f0('xx', '') == 12
f1 := a['two'] f1 := a['two']
assert f1('yyy') == 23 assert f1('yyy', '') == 23
a['one'], a['two'] = a['two'], a['one'] a['one'], a['two'] = a['two'], a['one']
f2 := a['one'] f2 := a['one']
assert f2('zzzz') == 24 assert f2('zzzz', '') == 24
f3 := a['two'] f3 := a['two']
assert f3('aaaaa') == 15 assert f3('aaaaa', '') == 15
mut b := {'one':foo} mut b := {'one':foo}
b['one'] = a['one'] b['one'] = a['one']
f4 := b['one'] f4 := b['one']
assert f4('bbbbbb') == 26 assert f4('bbbbbb', '') == 26
for _, func in b { for _, func in b {
assert func('ccccccc') == 27 assert func('ccccccc', '') == 27
} }
} }