cgen: fix array and map with fns (#5938)
							parent
							
								
									dfa01d8877
								
							
						
					
					
						commit
						7027b2354b
					
				| 
						 | 
					@ -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)
 | 
				
			||||||
			g.write(', _MOV(($elem_type_str[]){ ')
 | 
								if elem_sym.kind == .function {
 | 
				
			||||||
			elem_sym := g.table.get_type_symbol(info.elem_type)
 | 
									g.write(', _MOV((voidptr[]){ ')
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									g.write(', _MOV(($elem_type_str[]){ ')
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			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, ')
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		g.write('sizeof($elem_type_str), ')
 | 
							if elem_sym.kind == .function {
 | 
				
			||||||
 | 
								g.write('sizeof(voidptr), ')
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								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)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue