diff --git a/vlib/builtin/map_test.v b/vlib/builtin/map_test.v index aa4c0bf377..1d426046f0 100644 --- a/vlib/builtin/map_test.v +++ b/vlib/builtin/map_test.v @@ -353,3 +353,11 @@ fn test_map_str_after_delete() { assert osm == "{'first': 1, 'second': 2, 'third': 3}" assert nsm == "{'first': 1, 'third': 3}" } + +fn test_modify_map_value() { + mut m1 := {'foo': 3, 'bar': -7} + m1['foo'] += 5 + m1['bar'] *= -2 + assert m1['foo'] == 8 + assert m1['bar'] == 14 +} diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 2f1238d560..310b23fed4 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -3779,6 +3779,43 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) { } else { g.write(', &($elem_type_str[]) { ') } + if g.assign_op != .assign && + g.assign_op in token.assign_tokens && info.value_type != table.string_type { + g.write('(*(int*)map_get(') + if left_is_ptr && !node.left_type.has_flag(.shared_f) { + g.write('*') + } + g.expr(node.left) + if node.left_type.has_flag(.shared_f) { + if left_is_ptr { + g.write('->val') + } else { + g.write('.val') + } + } + g.write(', ') + g.expr(node.index) + zero := g.type_default(info.value_type) + if elem_typ.kind == .function { + g.write(', &(voidptr[]){ $zero }))') + } else { + g.write(', &($elem_type_str[]){ $zero }))') + } + op := match g.assign_op { + .mult_assign { '*' } + .plus_assign { '+' } + .minus_assign { '-' } + .div_assign { '/' } + .xor_assign { '^' } + .mod_assign { '%' } + .or_assign { '|' } + .and_assign { '&' } + .left_shift_assign { '<<' } + .right_shift_assign { '>>' } + else { '' } + } + g.write(' $op ') + } } 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) diff --git a/vlib/v/tests/shared_map_test.v b/vlib/v/tests/shared_map_test.v index accd15a514..d339e2a798 100644 --- a/vlib/v/tests/shared_map_test.v +++ b/vlib/v/tests/shared_map_test.v @@ -10,7 +10,12 @@ fn incr(shared foo map[string]int, key string, sem sync.Semaphore) { } fn test_shared_array() { - shared foo := &{'p': 10, 'q': 20} + shared foo := &{'p': 10, 'q': 0} + lock foo { + unsafe { + foo['q'] = 20 + } + } sem := sync.new_semaphore() go incr(shared foo, 'p', sem) go incr(shared foo, 'q', sem) @@ -19,8 +24,8 @@ fn test_shared_array() { for _ in 0 .. 50000 { lock foo { unsafe { - foo['p'] = foo['p'] - 2 - foo['q'] = foo['q'] + 3 + foo['p'] -= 2 + foo['q'] += 3 } } }