Fixed pre/post increment/decrement in assignment operations.

Previously, the compound assignment operations did not create temporary
index for increments/decrements in the generator. The result was that
the increment/decrement changed the value immediately in place, which
led to incorrect calculations.

The fix is to use a separate temporary index for increments/decrements in
assignment operations.

This closes #271 issue on GitHub.
diff --git a/src/njs_generator.c b/src/njs_generator.c
index 5174a08..3119271 100644
--- a/src/njs_generator.c
+++ b/src/njs_generator.c
@@ -1799,7 +1799,7 @@
     njs_parser_node_t *node)
 {
     njs_int_t              ret;
-    njs_index_t            index;
+    njs_index_t            index, src;
     njs_parser_node_t      *lvalue, *expr, *object, *property;
     njs_vmcode_move_t      *move;
     njs_vmcode_3addr_t     *code;
@@ -1876,6 +1876,34 @@
         return ret;
     }
 
+    if (njs_slow_path(njs_parser_has_side_effect(node->right))) {
+        /*
+         * Preserve object and property values stored in variables in a case
+         * if the variables can be changed by side effects in expression.
+         */
+        if (object->token_type == NJS_TOKEN_NAME) {
+            src = object->index;
+
+            index = njs_generate_node_temp_index_get(vm, generator, object);
+            if (njs_slow_path(index == NJS_INDEX_ERROR)) {
+                return NJS_ERROR;
+            }
+
+            njs_generate_code_move(generator, move, index, src, object);
+        }
+
+        if (property->token_type == NJS_TOKEN_NAME) {
+            src = property->index;
+
+            index = njs_generate_node_temp_index_get(vm, generator, property);
+            if (njs_slow_path(index == NJS_INDEX_ERROR)) {
+                return NJS_ERROR;
+            }
+
+            njs_generate_code_move(generator, move, index, src, property);
+        }
+    }
+
     index = njs_generate_node_temp_index_get(vm, generator, node);
     if (njs_slow_path(index == NJS_INDEX_ERROR)) {
         return NJS_ERROR;
diff --git a/src/njs_lexer.h b/src/njs_lexer.h
index 6689ded..9afc83c 100644
--- a/src/njs_lexer.h
+++ b/src/njs_lexer.h
@@ -51,7 +51,12 @@
     NJS_TOKEN_BITWISE_XOR_ASSIGNMENT,
     NJS_TOKEN_BITWISE_AND_ASSIGNMENT,
 
-#define NJS_TOKEN_LAST_ASSIGNMENT   NJS_TOKEN_BITWISE_AND_ASSIGNMENT
+    NJS_TOKEN_INCREMENT,
+    NJS_TOKEN_DECREMENT,
+    NJS_TOKEN_POST_INCREMENT,
+    NJS_TOKEN_POST_DECREMENT,
+
+#define NJS_TOKEN_LAST_ASSIGNMENT   NJS_TOKEN_POST_DECREMENT
 
     NJS_TOKEN_EQUAL,
     NJS_TOKEN_STRICT_EQUAL,
@@ -60,13 +65,9 @@
 
     NJS_TOKEN_ADDITION,
     NJS_TOKEN_UNARY_PLUS,
-    NJS_TOKEN_INCREMENT,
-    NJS_TOKEN_POST_INCREMENT,
 
     NJS_TOKEN_SUBSTRACTION,
     NJS_TOKEN_UNARY_NEGATION,
-    NJS_TOKEN_DECREMENT,
-    NJS_TOKEN_POST_DECREMENT,
 
     NJS_TOKEN_MULTIPLICATION,
 
diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c
index 16864ef..30618bd 100644
--- a/src/test/njs_unit_test.c
+++ b/src/test/njs_unit_test.c
@@ -2183,6 +2183,20 @@
                  "var b = ++a; a +' '+ b"),
       njs_str("NaN NaN") },
 
+    { njs_str("var a = 0; a = a + ++a; a"),
+      njs_str("1") },
+
+    { njs_str("var a = 0; a += a + ++a; a"),
+      njs_str("1") },
+
+    { njs_str("var i = 0, arr = ['a', 'b'];"
+              "arr[i] = arr[i] + arr[++i]; arr"),
+      njs_str("ab,b") },
+
+    { njs_str("var i = 0, arr = ['a', 'b'];"
+              "arr[i] += arr[i] + arr[++i]; arr"),
+      njs_str("aab,b") },
+
     /* Post increment. */
 
     { njs_str("var a = 1;   a++"),
@@ -2265,6 +2279,20 @@
                  "var b = a++; a +' '+ b"),
       njs_str("NaN NaN") },
 
+    { njs_str("var a = 0; a = a + a++; a"),
+      njs_str("0") },
+
+    { njs_str("var a = 0; a += a + a++; a"),
+      njs_str("0") },
+
+    { njs_str("var i = 1, arr = ['a', 'b'];"
+              "arr[i] = arr[i] + arr[i++]; arr"),
+      njs_str("a,bb") },
+
+    { njs_str("var i = 1, arr = ['a', 'b'];"
+              "arr[i] += arr[i] + arr[i++]; arr"),
+      njs_str("a,bbb") },
+
     /* Decrement. */
 
     { njs_str("var a = 1;   --a"),
@@ -2347,6 +2375,20 @@
                  "var b = --a; a +' '+ b"),
       njs_str("NaN NaN") },
 
+    { njs_str("var a = 0; a = a + --a; a"),
+      njs_str("-1") },
+
+    { njs_str("var a = 0; a -= a + --a; a"),
+      njs_str("1") },
+
+    { njs_str("var i = 1, arr = ['a', 'b'];"
+              "arr[i] = arr[i] + arr[--i]; arr"),
+      njs_str("a,ba") },
+
+    { njs_str("var i = 1, arr = ['a', 'b'];"
+              "arr[i] += arr[i] + arr[--i]; arr"),
+      njs_str("a,bba") },
+
     /* Post decrement. */
 
     { njs_str("var a = 1;   a--"),
@@ -2429,6 +2471,20 @@
                  "var b = a--; a +' '+ b"),
       njs_str("NaN NaN") },
 
+    { njs_str("var a = 0; a = a + a--; a"),
+      njs_str("0") },
+
+    { njs_str("var a = 0; a += a + a--; a"),
+      njs_str("0") },
+
+    { njs_str("var i = 1, arr = ['a', 'b'];"
+              "arr[i] = arr[i] + arr[i--]; arr"),
+      njs_str("a,bb") },
+
+    { njs_str("var i = 1, arr = ['a', 'b'];"
+              "arr[i] += arr[i] + arr[i--]; arr"),
+      njs_str("a,bbb") },
+
     /**/
 
     { njs_str("var a, b; a = 2; b = ++a + ++a; a + ' ' + b"),