Skip to content

Commit

Permalink
Array/Dictinoary no more reduced to array/dictionary variant
Browse files Browse the repository at this point in the history
Fix: #41377
Fix: #20436
Fix: #41953
  • Loading branch information
ThakeeNathees committed Sep 11, 2020
1 parent 3b25548 commit 3886a2f
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 26 deletions.
77 changes: 51 additions & 26 deletions modules/gdscript/gdscript_analyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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++) {
Expand All @@ -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)) {
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions modules/gdscript/gdscript_analyzer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 3886a2f

Please sign in to comment.