diff options
author | Rémi Verschelde <rverschelde@gmail.com> | 2023-02-24 13:29:49 +0100 |
---|---|---|
committer | Rémi Verschelde <rverschelde@gmail.com> | 2023-02-24 13:29:49 +0100 |
commit | 49e5e0ed79d5280629a835749c5b9f6ce053f6f4 (patch) | |
tree | 9ddc63d290154a24b4f9eae36ef14a1a29df6f31 /modules | |
parent | 6c65ff82f2695c38af5d25397da7314a8b5de1f8 (diff) | |
parent | 55c5774be948752665059ba205336e1571b2f057 (diff) |
Merge pull request #73841 from vonagam/fix-range-regression
GDScript: Fix range regression
Diffstat (limited to 'modules')
3 files changed, 32 insertions, 12 deletions
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index 1161403c0c..e058187860 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -1857,29 +1857,40 @@ void GDScriptAnalyzer::resolve_for(GDScriptParser::ForNode *p_for) { push_error(vformat(R"*(Invalid call for "range()" function. Expected at most 3 arguments, %d given.)*", call->arguments.size()), call->callee); } else { // Now we can optimize it. - bool all_is_constant = true; + bool can_reduce = true; Vector<Variant> args; args.resize(call->arguments.size()); for (int i = 0; i < call->arguments.size(); i++) { GDScriptParser::ExpressionNode *argument = call->arguments[i]; reduce_expression(argument); - if (!argument->is_constant) { - all_is_constant = false; - break; - } - if (argument->reduced_value.get_type() != Variant::INT && argument->reduced_value.get_type() != Variant::FLOAT) { - push_error(vformat(R"*(Invalid argument for "range()" call. Argument %d should be int or float but "%s" was given.)*", i + 1, Variant::get_type_name(argument->reduced_value.get_type())), argument); - all_is_constant = false; - break; + if (argument->is_constant) { + if (argument->reduced_value.get_type() != Variant::INT && argument->reduced_value.get_type() != Variant::FLOAT) { + can_reduce = false; + push_error(vformat(R"*(Invalid argument for "range()" call. Argument %d should be int or float but "%s" was given.)*", i + 1, Variant::get_type_name(argument->reduced_value.get_type())), argument); + } + if (can_reduce) { + args.write[i] = argument->reduced_value; + } + } else { + can_reduce = false; + GDScriptParser::DataType argument_type = argument->get_datatype(); + if (argument_type.is_variant() || !argument_type.is_hard_type()) { + mark_node_unsafe(argument); + } + if (!argument_type.is_variant() && (argument_type.builtin_type != Variant::INT && argument_type.builtin_type != Variant::FLOAT)) { + if (!argument_type.is_hard_type()) { + downgrade_node_type_source(argument); + } else { + push_error(vformat(R"*(Invalid argument for "range()" call. Argument %d should be int or float but "%s" was given.)*", i + 1, argument_type.to_string()), argument); + } + } } - - args.write[i] = argument->reduced_value; } Variant reduced; - if (all_is_constant) { + if (can_reduce) { switch (args.size()) { case 1: reduced = (int32_t)args[0]; diff --git a/modules/gdscript/tests/scripts/analyzer/features/for_range_usage.gd b/modules/gdscript/tests/scripts/analyzer/features/for_range_usage.gd new file mode 100644 index 0000000000..4a7f10f1ee --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/for_range_usage.gd @@ -0,0 +1,7 @@ +func test(): + var array := [3, 6, 9] + var result := '' + for i in range(array.size(), 0, -1): + result += str(array[i - 1]) + assert(result == '963') + print('ok') diff --git a/modules/gdscript/tests/scripts/analyzer/features/for_range_usage.out b/modules/gdscript/tests/scripts/analyzer/features/for_range_usage.out new file mode 100644 index 0000000000..1b47ed10dc --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/for_range_usage.out @@ -0,0 +1,2 @@ +GDTEST_OK +ok |