From 81e82dc5b2646f8a26fa297ff93779397fe76efa Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Fri, 18 Dec 2020 11:57:43 +0000 Subject: [PATCH 1/6] map: use reference for receiver --- vlib/builtin/map.v | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vlib/builtin/map.v b/vlib/builtin/map.v index 42a6ec152c419f..22651e70fd0e93 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]} { From 9c68947dc7145d303a89e75ed7b30fcef78c6f09 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Fri, 18 Dec 2020 11:58:12 +0000 Subject: [PATCH 2/6] cgen: Use map_get_1, map_set_1, map_get_and_set_1 --- vlib/v/gen/cgen.v | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 1ccd05b2ef9568..64dad235336cb9 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -1714,16 +1714,17 @@ 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('&') } 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 +3844,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 +3859,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,29 +3874,29 @@ 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 !node.left_type.is_ptr() && !node.left_type.has_flag(.shared_f) { + g.write('&') } g.expr(node.left) if node.left_type.has_flag(.shared_f) { @@ -3904,8 +3906,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 { From 08cd4332dbb662f23d4b6f7e0d28b2a8e139286d Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Fri, 18 Dec 2020 12:34:05 +0000 Subject: [PATCH 3/6] json decode_map encode_map --- vlib/v/gen/json.v | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/vlib/v/gen/json.v b/vlib/v/gen/json.v index 7ed319fe6d6ab5..11b4c98134f007 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); ' From 48c8c44443085f64a0798ba372d9b95b256470dd Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Fri, 18 Dec 2020 12:41:12 +0000 Subject: [PATCH 4/6] gen_map_equality_fn, add test --- vlib/v/gen/cgen.v | 10 +++++----- vlib/v/tests/maps_equal_test.v | 9 +++++++++ 2 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 vlib/v/tests/maps_equal_test.v diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 64dad235336cb9..c23e8193d378b9 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -4549,14 +4549,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/tests/maps_equal_test.v b/vlib/v/tests/maps_equal_test.v new file mode 100644 index 00000000000000..adcb14e8ec989e --- /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 +} From 0f513a378f80ade16698d8c81c61305ea6b3832e Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Fri, 18 Dec 2020 13:15:11 +0000 Subject: [PATCH 5/6] Fix shared_map_test --- vlib/v/gen/cgen.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index c23e8193d378b9..a669f9e2cb6707 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -3895,7 +3895,7 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) { } else { g.write('(*($elem_type_str*)map_get_1(') } - if !node.left_type.is_ptr() && !node.left_type.has_flag(.shared_f) { + if !left_is_ptr || node.left_type.has_flag(.shared_f) { g.write('&') } g.expr(node.left) From ba0d314e6dc3370015210b9a8617a84885402344 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Fri, 18 Dec 2020 15:52:27 +0000 Subject: [PATCH 6/6] Fix indexing a map rvalue Also add a cgen macro ADDR. --- vlib/v/gen/cgen.v | 16 +++++++++++----- vlib/v/gen/cheaders.v | 2 ++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index a669f9e2cb6707..222af09c9742ab 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -1719,9 +1719,12 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { g.write('$styp _var_$left.pos.pos = *($styp*)map_get_1(') } if !left.left_type.is_ptr() { - g.write('&') + g.write('ADDR(map, ') + g.expr(left.left) + g.write(')') + } else { + g.expr(left.left) } - g.expr(left.left) g.write(', &(string[]){') g.expr(left.index) g.write('}') @@ -3896,9 +3899,12 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) { g.write('(*($elem_type_str*)map_get_1(') } if !left_is_ptr || node.left_type.has_flag(.shared_f) { - g.write('&') + 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') @@ -3906,7 +3912,7 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) { g.write('.val') } } - g.write(', &(string[]){') + g.write('), &(string[]){') g.expr(node.index) g.write('}') if g.is_fn_index_call { diff --git a/vlib/v/gen/cheaders.v b/vlib/v/gen/cheaders.v index b3a4b1745993eb..cb01218ac5f496 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)