Merge pull request #78837 from dalexeev/gds-const-array-and-dict-constructors

GDScript: Add constant `Array` and `Dictionary` constructors
This commit is contained in:
Thaddeus Crews 2025-04-24 09:09:29 -05:00
commit 5d697c31c1
No known key found for this signature in database
GPG key ID: 8C6E5FEB5FC03CCC
4 changed files with 157 additions and 11 deletions

View file

@ -5208,24 +5208,29 @@ void GDScriptAnalyzer::reduce_unary_op(GDScriptParser::UnaryOpNode *p_unary_op)
}
Variant GDScriptAnalyzer::make_expression_reduced_value(GDScriptParser::ExpressionNode *p_expression, bool &is_reduced) {
Variant value;
if (p_expression == nullptr) {
return value;
return Variant();
}
if (p_expression->is_constant) {
is_reduced = true;
value = p_expression->reduced_value;
} else if (p_expression->type == GDScriptParser::Node::ARRAY) {
value = make_array_reduced_value(static_cast<GDScriptParser::ArrayNode *>(p_expression), is_reduced);
} else if (p_expression->type == GDScriptParser::Node::DICTIONARY) {
value = make_dictionary_reduced_value(static_cast<GDScriptParser::DictionaryNode *>(p_expression), is_reduced);
} else if (p_expression->type == GDScriptParser::Node::SUBSCRIPT) {
value = make_subscript_reduced_value(static_cast<GDScriptParser::SubscriptNode *>(p_expression), is_reduced);
return p_expression->reduced_value;
}
return value;
switch (p_expression->type) {
case GDScriptParser::Node::ARRAY:
return make_array_reduced_value(static_cast<GDScriptParser::ArrayNode *>(p_expression), is_reduced);
case GDScriptParser::Node::DICTIONARY:
return make_dictionary_reduced_value(static_cast<GDScriptParser::DictionaryNode *>(p_expression), is_reduced);
case GDScriptParser::Node::SUBSCRIPT:
return make_subscript_reduced_value(static_cast<GDScriptParser::SubscriptNode *>(p_expression), is_reduced);
case GDScriptParser::Node::CALL:
return make_call_reduced_value(static_cast<GDScriptParser::CallNode *>(p_expression), is_reduced);
default:
break;
}
return Variant();
}
Variant GDScriptAnalyzer::make_array_reduced_value(GDScriptParser::ArrayNode *p_array, bool &is_reduced) {
@ -5317,6 +5322,53 @@ Variant GDScriptAnalyzer::make_subscript_reduced_value(GDScriptParser::Subscript
}
}
Variant GDScriptAnalyzer::make_call_reduced_value(GDScriptParser::CallNode *p_call, bool &is_reduced) {
if (p_call->get_callee_type() == GDScriptParser::Node::IDENTIFIER) {
Variant::Type type = Variant::NIL;
if (p_call->function_name == SNAME("Array")) {
type = Variant::ARRAY;
} else if (p_call->function_name == SNAME("Dictionary")) {
type = Variant::DICTIONARY;
} else {
return Variant();
}
Vector<Variant> args;
args.resize(p_call->arguments.size());
const Variant **argptrs = (const Variant **)alloca(sizeof(const Variant **) * args.size());
for (int i = 0; i < p_call->arguments.size(); i++) {
bool is_arg_value_reduced = false;
Variant arg_value = make_expression_reduced_value(p_call->arguments[i], is_arg_value_reduced);
if (!is_arg_value_reduced) {
return Variant();
}
args.write[i] = arg_value;
argptrs[i] = &args[i];
}
Variant result;
Callable::CallError ce;
Variant::construct(type, result, argptrs, args.size(), ce);
if (ce.error) {
push_error(vformat(R"(Failed to construct "%s".)", Variant::get_type_name(type)), p_call);
return Variant();
}
if (type == Variant::ARRAY) {
Array array = result;
array.make_read_only();
} else if (type == Variant::DICTIONARY) {
Dictionary dictionary = result;
dictionary.make_read_only();
}
is_reduced = true;
return result;
}
return Variant();
}
Array GDScriptAnalyzer::make_array_from_element_datatype(const GDScriptParser::DataType &p_element_datatype, const GDScriptParser::Node *p_source_node) {
Array array;