Explorar el Código

Merge pull request #53215 from vnen/gdscript-property-assignment-op

Rémi Verschelde hace 3 años
padre
commit
bd573f8aba

+ 21 - 15
modules/gdscript/gdscript_compiler.cpp

@@ -1071,19 +1071,25 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
 					}
 				}
 
-				GDScriptCodeGenerator::Address assigned = _parse_expression(codegen, r_error, assignment->assigned_value);
-				GDScriptCodeGenerator::Address op_result;
+				GDScriptCodeGenerator::Address assigned_value = _parse_expression(codegen, r_error, assignment->assigned_value);
 				if (r_error) {
 					return GDScriptCodeGenerator::Address();
 				}
 
-				if (assignment->operation != GDScriptParser::AssignmentNode::OP_NONE) {
+				GDScriptCodeGenerator::Address to_assign;
+				bool has_operation = assignment->operation != GDScriptParser::AssignmentNode::OP_NONE;
+				if (has_operation) {
 					// Perform operation.
-					op_result = codegen.add_temporary();
-					gen->write_binary_operator(op_result, assignment->variant_op, target, assigned);
+					GDScriptCodeGenerator::Address op_result = codegen.add_temporary();
+					GDScriptCodeGenerator::Address og_value = _parse_expression(codegen, r_error, assignment->assignee);
+					gen->write_binary_operator(op_result, assignment->variant_op, og_value, assigned_value);
+					to_assign = op_result;
+
+					if (og_value.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
+						gen->pop_temporary();
+					}
 				} else {
-					op_result = assigned;
-					assigned = GDScriptCodeGenerator::Address();
+					to_assign = assigned_value;
 				}
 
 				GDScriptDataType assign_type = _gdtype_from_datatype(assignment->assignee->get_datatype());
@@ -1091,25 +1097,25 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
 				if (has_setter && !is_in_setter) {
 					// Call setter.
 					Vector<GDScriptCodeGenerator::Address> args;
-					args.push_back(op_result);
+					args.push_back(to_assign);
 					gen->write_call(GDScriptCodeGenerator::Address(), GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::SELF), setter_function, args);
 				} else {
 					// Just assign.
 					if (assignment->use_conversion_assign) {
-						gen->write_assign_with_conversion(target, op_result);
+						gen->write_assign_with_conversion(target, to_assign);
 					} else {
-						gen->write_assign(target, op_result);
+						gen->write_assign(target, to_assign);
 					}
 				}
 
-				if (op_result.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
-					gen->pop_temporary();
+				if (to_assign.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
+					gen->pop_temporary(); // Pop assigned value or temp operation result.
 				}
-				if (assigned.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
-					gen->pop_temporary();
+				if (has_operation && assigned_value.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
+					gen->pop_temporary(); // Pop assigned value if not done before.
 				}
 				if (target.mode == GDScriptCodeGenerator::Address::TEMPORARY) {
-					gen->pop_temporary();
+					gen->pop_temporary(); // Pop the target to assignment.
 				}
 			}
 			return GDScriptCodeGenerator::Address(); // Assignment does not return a value.

+ 11 - 0
modules/gdscript/tests/scripts/runtime/features/property_with_operator_assignment.gd

@@ -0,0 +1,11 @@
+#GDTEST_OK
+var prop : int = 0:
+	get:
+		return prop
+	set(value):
+		prop = value % 7
+
+func test():
+	for i in 7:
+		prop += 1
+		print(prop)

+ 8 - 0
modules/gdscript/tests/scripts/runtime/features/property_with_operator_assignment.out

@@ -0,0 +1,8 @@
+GDTEST_OK
+1
+2
+3
+4
+5
+6
+0