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

This commit is contained in:
Rémi Verschelde 2021-09-29 16:39:21 +02:00 committed by GitHub
commit bd573f8aba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 40 additions and 15 deletions

View File

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

View File

@ -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)

View File

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