Browse Source

Merge pull request #52914 from vnen/gdscript-assign-member-with-op

Rémi Verschelde 3 years ago
parent
commit
7fe0f4a426

+ 15 - 8
modules/gdscript/gdscript_compiler.cpp

@@ -1019,25 +1019,32 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
 				}
 			} else if (assignment->assignee->type == GDScriptParser::Node::IDENTIFIER && _is_class_member_property(codegen, static_cast<GDScriptParser::IdentifierNode *>(assignment->assignee)->name)) {
 				// Assignment to member property.
-				GDScriptCodeGenerator::Address assigned = _parse_expression(codegen, r_error, assignment->assigned_value);
+				GDScriptCodeGenerator::Address assigned_value = _parse_expression(codegen, r_error, assignment->assigned_value);
 				if (r_error) {
 					return GDScriptCodeGenerator::Address();
 				}
-				GDScriptCodeGenerator::Address assign_temp = assigned;
+
+				GDScriptCodeGenerator::Address to_assign = assigned_value;
+				bool has_operation = assignment->operation != GDScriptParser::AssignmentNode::OP_NONE;
 
 				StringName name = static_cast<GDScriptParser::IdentifierNode *>(assignment->assignee)->name;
 
-				if (assignment->operation != GDScriptParser::AssignmentNode::OP_NONE) {
+				if (has_operation) {
+					GDScriptCodeGenerator::Address op_result = codegen.add_temporary();
 					GDScriptCodeGenerator::Address member = codegen.add_temporary();
 					gen->write_get_member(member, name);
-					gen->write_binary_operator(assigned, assignment->variant_op, member, assigned);
-					gen->pop_temporary();
+					gen->write_binary_operator(op_result, assignment->variant_op, member, assigned_value);
+					gen->pop_temporary(); // Pop member temp.
+					to_assign = op_result;
 				}
 
-				gen->write_set_member(assigned, name);
+				gen->write_set_member(to_assign, name);
 
-				if (assign_temp.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
-					gen->pop_temporary();
+				if (to_assign.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
+					gen->pop_temporary(); // Pop the assigned expression or the temp result if it has operation.
+				}
+				if (has_operation && assigned_value.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
+					gen->pop_temporary(); // Pop the assigned expression if not done before.
 				}
 			} else {
 				// Regular assignment.

+ 13 - 0
modules/gdscript/tests/scripts/runtime/features/assign_member_with_operation.gd

@@ -0,0 +1,13 @@
+extends Node
+
+func test():
+	process_priority = 10
+	var change = 20
+
+	print(process_priority)
+	print(change)
+
+	process_priority += change
+
+	print(process_priority)
+	print(change)

+ 5 - 0
modules/gdscript/tests/scripts/runtime/features/assign_member_with_operation.out

@@ -0,0 +1,5 @@
+GDTEST_OK
+10
+20
+30
+20