diff --git a/vlib/builtin/map.v b/vlib/builtin/map.v index 42a6ec152c..22651e70fd 100644 --- a/vlib/builtin/map.v +++ b/vlib/builtin/map.v @@ -458,7 +458,7 @@ fn (m map) get(key string, zero voidptr) voidptr { // If `key` matches the key of an element in the container, // the method returns a reference to its mapped value. // If not, a zero/default value is returned. -fn (m map) get_1(key voidptr, zero voidptr) voidptr { +fn (m &map) get_1(key voidptr, zero voidptr) voidptr { mut index, mut meta := m.key_to_index(key) for { if meta == unsafe {m.metas[index]} { @@ -482,7 +482,7 @@ fn (m map) exists(key string) bool { } // Checks whether a particular key exists in the map. -fn (m map) exists_1(key voidptr) bool { +fn (m &map) exists_1(key voidptr) bool { mut index, mut meta := m.key_to_index(key) for { if meta == unsafe {m.metas[index]} { diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 1ccd05b2ef..222af09c97 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -1714,16 +1714,20 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { left_type := assign_stmt.left_types[i] left_sym := g.table.get_type_symbol(left_type) g.write_fn_ptr_decl(left_sym.info as table.FnType, '_var_$left.pos.pos') - g.write(' = *(voidptr*)map_get(') + g.write(' = *(voidptr*)map_get_1(') } else { - g.write('$styp _var_$left.pos.pos = *($styp*)map_get(') + g.write('$styp _var_$left.pos.pos = *($styp*)map_get_1(') } - if left.left_type.is_ptr() { - g.write('*') + if !left.left_type.is_ptr() { + g.write('ADDR(map, ') + g.expr(left.left) + g.write(')') + } else { + g.expr(left.left) } - g.expr(left.left) - g.write(', ') + g.write(', &(string[]){') g.expr(left.index) + g.write('}') if val_typ.kind == .function { g.writeln(', &(voidptr[]){ $zero });') } else { @@ -3843,9 +3847,9 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) { if g.is_assign_lhs && !g.is_array_set && !get_and_set_types { if g.assign_op == .assign || info.value_type == table.string_type { g.is_array_set = true - g.write('map_set(') + g.write('map_set_1(') } else { - g.write('*(($elem_type_str*)map_get_and_set(') + g.write('*(($elem_type_str*)map_get_and_set_1(') } if !left_is_ptr || node.left_type.has_flag(.shared_f) { g.write('&') @@ -3858,8 +3862,9 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) { g.write('.val') } } - g.write(', ') + g.write(', &(string[]){') g.expr(node.index) + g.write('}') if elem_typ.kind == .function { g.write(', &(voidptr[]) { ') } else { @@ -3872,31 +3877,34 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) { } else if (g.inside_map_postfix || g.inside_map_infix) || (g.is_assign_lhs && !g.is_array_set && get_and_set_types) { zero := g.type_default(info.value_type) - g.write('(*($elem_type_str*)map_get_and_set(') + g.write('(*($elem_type_str*)map_get_and_set_1(') if !left_is_ptr { g.write('&') } g.expr(node.left) - g.write(', ') + g.write(', &(string[]){') g.expr(node.index) - g.write(', &($elem_type_str[]){ $zero }))') + g.write('}, &($elem_type_str[]){ $zero }))') } else { zero := g.type_default(info.value_type) if g.is_fn_index_call { if elem_typ.info is table.FnType { g.write('((') g.write_fn_ptr_decl(&elem_typ.info, '') - g.write(')(*(voidptr*)map_get(') + g.write(')(*(voidptr*)map_get_1(') } } else if elem_typ.kind == .function { - g.write('(*(voidptr*)map_get(') + g.write('(*(voidptr*)map_get_1(') } else { - g.write('(*($elem_type_str*)map_get(') + g.write('(*($elem_type_str*)map_get_1(') } - if node.left_type.is_ptr() && !node.left_type.has_flag(.shared_f) { - g.write('*') + if !left_is_ptr || node.left_type.has_flag(.shared_f) { + g.write('ADDR(map, ') + g.expr(node.left) + } else { + g.write('(') + g.expr(node.left) } - g.expr(node.left) if node.left_type.has_flag(.shared_f) { if left_is_ptr { g.write('->val') @@ -3904,8 +3912,9 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) { g.write('.val') } } - g.write(', ') + g.write('), &(string[]){') g.expr(node.index) + g.write('}') if g.is_fn_index_call { g.write(', &(voidptr[]){ $zero })))') } else if elem_typ.kind == .function { @@ -4546,14 +4555,14 @@ fn (mut g Gen) gen_map_equality_fn(left table.Type) string { g.definitions.write(', ') } } - g.definitions.writeln(') = (*(voidptr*)map_get(a, k, &(voidptr[]){ 0 }));') + g.definitions.writeln(') = (*(voidptr*)map_get_1(&a, &k, &(voidptr[]){ 0 }));') } else { - g.definitions.writeln('\t\t$value_typ v = (*($value_typ*)map_get(a, k, &($value_typ[]){ 0 }));') + g.definitions.writeln('\t\t$value_typ v = (*($value_typ*)map_get_1(&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[]){_SLIT("")})), 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) {') } + .string { g.definitions.writeln('\t\tif (!map_exists(b, k) || string_ne((*(string*)map_get_1(&b, &k, &(string[]){_SLIT("")})), v)) {') } + .function { g.definitions.writeln('\t\tif (!map_exists(b, k) || (*(voidptr*)map_get_1(&b, &k, &(voidptr[]){ 0 })) != v) {') } + else { g.definitions.writeln('\t\tif (!map_exists(b, k) || (*($value_typ*)map_get_1(&b, &k, &($value_typ[]){ 0 })) != v) {') } } g.definitions.writeln('\t\t\treturn false;') g.definitions.writeln('\t\t}') diff --git a/vlib/v/gen/cheaders.v b/vlib/v/gen/cheaders.v index b3a4b17459..cb01218ac5 100644 --- a/vlib/v/gen/cheaders.v +++ b/vlib/v/gen/cheaders.v @@ -269,6 +269,8 @@ static void* g_live_info = NULL; //#define tos4(s, slen) ((string){.str=(s), .len=(slen)}) // `"" s` is used to enforce a string literal argument #define _SLIT(s) ((string){.str=(byteptr)("" s), .len=(sizeof(s)-1), .is_lit=1}) +// take the address of an rvalue +#define ADDR(type, expr) (&((type[]){expr}[0])) #define _PUSH_MANY(arr, val, tmp, tmp_typ) {tmp_typ tmp = (val); array_push_many(arr, tmp.data, tmp.len);} #define _IN(typ, val, arr) array_##typ##_contains(arr, val) #define _IN_MAP(val, m) map_exists(m, val) diff --git a/vlib/v/gen/json.v b/vlib/v/gen/json.v index 7ed319fe6d..11b4c98134 100644 --- a/vlib/v/gen/json.v +++ b/vlib/v/gen/json.v @@ -263,7 +263,8 @@ fn (mut g Gen) decode_map(key_type table.Type, value_type table.Type) string { cJSON_ArrayForEach(jsval, root) { $s - map_set(&res, tos2( (byteptr) jsval->string ) , &val ); + string key = tos2( (byteptr) jsval->string ); + map_set_1(&res, &key, &val); } ' } @@ -286,7 +287,7 @@ fn (mut g Gen) encode_map(key_type table.Type, value_type table.Type) string { array_$styp $keys_tmp = map_keys(&val); for (int i = 0; i < ${keys_tmp}.len; ++i) { $key - cJSON_AddItemToObject(o, (char*) key.str, $fn_name_v ( *($styp_v*) map_get(val, key, &($styp_v[]) { $zero } ) ) ); + cJSON_AddItemToObject(o, (char*) key.str, $fn_name_v ( *($styp_v*) map_get_1(&val, &key, &($styp_v[]) { $zero } ) ) ); } array_free(&$keys_tmp); ' diff --git a/vlib/v/tests/maps_equal_test.v b/vlib/v/tests/maps_equal_test.v new file mode 100644 index 0000000000..adcb14e8ec --- /dev/null +++ b/vlib/v/tests/maps_equal_test.v @@ -0,0 +1,9 @@ +fn test_string_int() { + mut m := {'hi':4} + m2:= {'hi':5} + assert m != m2 + m['hi']++ + assert m == m2 + m.delete('hi') + assert m != m2 +}