mirror of
https://github.com/godotengine/godot
synced 2024-09-05 18:19:34 +00:00
Array/Dictinoary no more reduced to array/dictionary variant
Fix: #41377 Fix: #20436 Fix: #41953
This commit is contained in:
parent
3b25548e4c
commit
3886a2f9f6
|
@ -577,6 +577,12 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas
|
|||
|
||||
GDScriptParser::DataType datatype = member.constant->get_datatype();
|
||||
if (member.constant->initializer) {
|
||||
if (member.constant->initializer->type == GDScriptParser::Node::ARRAY) {
|
||||
const_fold_array(static_cast<GDScriptParser::ArrayNode *>(member.constant->initializer));
|
||||
} else if (member.constant->initializer->type == GDScriptParser::Node::DICTIONARY) {
|
||||
const_fold_dictionary(static_cast<GDScriptParser::DictionaryNode *>(member.constant->initializer));
|
||||
}
|
||||
|
||||
if (!member.constant->initializer->is_constant) {
|
||||
push_error(R"(Initializer for a constant must be a constant expression.)", member.constant->initializer);
|
||||
}
|
||||
|
@ -1113,6 +1119,11 @@ void GDScriptAnalyzer::resolve_constant(GDScriptParser::ConstantNode *p_constant
|
|||
GDScriptParser::DataType type;
|
||||
|
||||
reduce_expression(p_constant->initializer);
|
||||
if (p_constant->initializer->type == GDScriptParser::Node::ARRAY) {
|
||||
const_fold_array(static_cast<GDScriptParser::ArrayNode *>(p_constant->initializer));
|
||||
} else if (p_constant->initializer->type == GDScriptParser::Node::DICTIONARY) {
|
||||
const_fold_dictionary(static_cast<GDScriptParser::DictionaryNode *>(p_constant->initializer));
|
||||
}
|
||||
|
||||
if (!p_constant->initializer->is_constant) {
|
||||
push_error(vformat(R"(Assigned value for constant "%s" isn't a constant expression.)", p_constant->identifier->name), p_constant->initializer);
|
||||
|
@ -1422,22 +1433,9 @@ void GDScriptAnalyzer::reduce_expression(GDScriptParser::ExpressionNode *p_expre
|
|||
}
|
||||
|
||||
void GDScriptAnalyzer::reduce_array(GDScriptParser::ArrayNode *p_array) {
|
||||
bool all_is_constant = true;
|
||||
|
||||
for (int i = 0; i < p_array->elements.size(); i++) {
|
||||
GDScriptParser::ExpressionNode *element = p_array->elements[i];
|
||||
reduce_expression(element);
|
||||
all_is_constant = all_is_constant && element->is_constant;
|
||||
}
|
||||
|
||||
if (all_is_constant) {
|
||||
Array array;
|
||||
array.resize(p_array->elements.size());
|
||||
for (int i = 0; i < p_array->elements.size(); i++) {
|
||||
array[i] = p_array->elements[i]->reduced_value;
|
||||
}
|
||||
p_array->is_constant = true;
|
||||
p_array->reduced_value = array;
|
||||
}
|
||||
|
||||
// It's array in any case.
|
||||
|
@ -1984,8 +1982,6 @@ void GDScriptAnalyzer::reduce_cast(GDScriptParser::CastNode *p_cast) {
|
|||
}
|
||||
|
||||
void GDScriptAnalyzer::reduce_dictionary(GDScriptParser::DictionaryNode *p_dictionary) {
|
||||
bool all_is_constant = true;
|
||||
|
||||
HashMap<Variant, GDScriptParser::ExpressionNode *, VariantHasher, VariantComparator> elements;
|
||||
|
||||
for (int i = 0; i < p_dictionary->elements.size(); i++) {
|
||||
|
@ -1994,7 +1990,6 @@ void GDScriptAnalyzer::reduce_dictionary(GDScriptParser::DictionaryNode *p_dicti
|
|||
reduce_expression(element.key);
|
||||
}
|
||||
reduce_expression(element.value);
|
||||
all_is_constant = all_is_constant && element.key->is_constant && element.value->is_constant;
|
||||
|
||||
if (element.key->is_constant) {
|
||||
if (elements.has(element.key->reduced_value)) {
|
||||
|
@ -2005,16 +2000,6 @@ void GDScriptAnalyzer::reduce_dictionary(GDScriptParser::DictionaryNode *p_dicti
|
|||
}
|
||||
}
|
||||
|
||||
if (all_is_constant) {
|
||||
Dictionary dict;
|
||||
for (int i = 0; i < p_dictionary->elements.size(); i++) {
|
||||
const GDScriptParser::DictionaryNode::Pair &element = p_dictionary->elements[i];
|
||||
dict[element.key->reduced_value] = element.value->reduced_value;
|
||||
}
|
||||
p_dictionary->is_constant = true;
|
||||
p_dictionary->reduced_value = dict;
|
||||
}
|
||||
|
||||
// It's dictionary in any case.
|
||||
GDScriptParser::DataType dict_type;
|
||||
dict_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
|
||||
|
@ -2737,6 +2722,46 @@ void GDScriptAnalyzer::reduce_unary_op(GDScriptParser::UnaryOpNode *p_unary_op)
|
|||
p_unary_op->set_datatype(result);
|
||||
}
|
||||
|
||||
void GDScriptAnalyzer::const_fold_array(GDScriptParser::ArrayNode *p_array) {
|
||||
bool all_is_constant = true;
|
||||
|
||||
for (int i = 0; i < p_array->elements.size(); i++) {
|
||||
GDScriptParser::ExpressionNode *element = p_array->elements[i];
|
||||
all_is_constant = all_is_constant && element->is_constant;
|
||||
if (!all_is_constant) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Array array;
|
||||
array.resize(p_array->elements.size());
|
||||
for (int i = 0; i < p_array->elements.size(); i++) {
|
||||
array[i] = p_array->elements[i]->reduced_value;
|
||||
}
|
||||
p_array->is_constant = true;
|
||||
p_array->reduced_value = array;
|
||||
}
|
||||
|
||||
void GDScriptAnalyzer::const_fold_dictionary(GDScriptParser::DictionaryNode *p_dictionary) {
|
||||
bool all_is_constant = true;
|
||||
|
||||
for (int i = 0; i < p_dictionary->elements.size(); i++) {
|
||||
const GDScriptParser::DictionaryNode::Pair &element = p_dictionary->elements[i];
|
||||
all_is_constant = all_is_constant && element.key->is_constant && element.value->is_constant;
|
||||
if (!all_is_constant) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Dictionary dict;
|
||||
for (int i = 0; i < p_dictionary->elements.size(); i++) {
|
||||
const GDScriptParser::DictionaryNode::Pair &element = p_dictionary->elements[i];
|
||||
dict[element.key->reduced_value] = element.value->reduced_value;
|
||||
}
|
||||
p_dictionary->is_constant = true;
|
||||
p_dictionary->reduced_value = dict;
|
||||
}
|
||||
|
||||
GDScriptParser::DataType GDScriptAnalyzer::type_from_variant(const Variant &p_value, const GDScriptParser::Node *p_source) {
|
||||
GDScriptParser::DataType result;
|
||||
result.is_constant = true;
|
||||
|
|
|
@ -89,6 +89,9 @@ class GDScriptAnalyzer {
|
|||
void reduce_ternary_op(GDScriptParser::TernaryOpNode *p_ternary_op);
|
||||
void reduce_unary_op(GDScriptParser::UnaryOpNode *p_unary_op);
|
||||
|
||||
void const_fold_array(GDScriptParser::ArrayNode *p_array);
|
||||
void const_fold_dictionary(GDScriptParser::DictionaryNode *p_dictionary);
|
||||
|
||||
// Helpers.
|
||||
GDScriptParser::DataType type_from_variant(const Variant &p_value, const GDScriptParser::Node *p_source);
|
||||
GDScriptParser::DataType type_from_metatype(const GDScriptParser::DataType &p_meta_type) const;
|
||||
|
|
Loading…
Reference in a new issue