Browse Source

Array/Dictinoary no more reduced to array/dictionary variant

Fix: #41377
Fix: #20436
Fix: #41953
Thakee Nathees 4 years ago
parent
commit
3886a2f9f6
2 changed files with 54 additions and 26 deletions
  1. 51 26
      modules/gdscript/gdscript_analyzer.cpp
  2. 3 0
      modules/gdscript/gdscript_analyzer.h

+ 51 - 26
modules/gdscript/gdscript_analyzer.cpp

@@ -577,6 +577,12 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas
 
 
 				GDScriptParser::DataType datatype = member.constant->get_datatype();
 				GDScriptParser::DataType datatype = member.constant->get_datatype();
 				if (member.constant->initializer) {
 				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) {
 					if (!member.constant->initializer->is_constant) {
 						push_error(R"(Initializer for a constant must be a constant expression.)", member.constant->initializer);
 						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;
 	GDScriptParser::DataType type;
 
 
 	reduce_expression(p_constant->initializer);
 	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) {
 	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);
 		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) {
 void GDScriptAnalyzer::reduce_array(GDScriptParser::ArrayNode *p_array) {
-	bool all_is_constant = true;
-
 	for (int i = 0; i < p_array->elements.size(); i++) {
 	for (int i = 0; i < p_array->elements.size(); i++) {
 		GDScriptParser::ExpressionNode *element = p_array->elements[i];
 		GDScriptParser::ExpressionNode *element = p_array->elements[i];
 		reduce_expression(element);
 		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.
 	// 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) {
 void GDScriptAnalyzer::reduce_dictionary(GDScriptParser::DictionaryNode *p_dictionary) {
-	bool all_is_constant = true;
-
 	HashMap<Variant, GDScriptParser::ExpressionNode *, VariantHasher, VariantComparator> elements;
 	HashMap<Variant, GDScriptParser::ExpressionNode *, VariantHasher, VariantComparator> elements;
 
 
 	for (int i = 0; i < p_dictionary->elements.size(); i++) {
 	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.key);
 		}
 		}
 		reduce_expression(element.value);
 		reduce_expression(element.value);
-		all_is_constant = all_is_constant && element.key->is_constant && element.value->is_constant;
 
 
 		if (element.key->is_constant) {
 		if (element.key->is_constant) {
 			if (elements.has(element.key->reduced_value)) {
 			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.
 	// It's dictionary in any case.
 	GDScriptParser::DataType dict_type;
 	GDScriptParser::DataType dict_type;
 	dict_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
 	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);
 	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 GDScriptAnalyzer::type_from_variant(const Variant &p_value, const GDScriptParser::Node *p_source) {
 	GDScriptParser::DataType result;
 	GDScriptParser::DataType result;
 	result.is_constant = true;
 	result.is_constant = true;

+ 3 - 0
modules/gdscript/gdscript_analyzer.h

@@ -89,6 +89,9 @@ class GDScriptAnalyzer {
 	void reduce_ternary_op(GDScriptParser::TernaryOpNode *p_ternary_op);
 	void reduce_ternary_op(GDScriptParser::TernaryOpNode *p_ternary_op);
 	void reduce_unary_op(GDScriptParser::UnaryOpNode *p_unary_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.
 	// Helpers.
 	GDScriptParser::DataType type_from_variant(const Variant &p_value, const GDScriptParser::Node *p_source);
 	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;
 	GDScriptParser::DataType type_from_metatype(const GDScriptParser::DataType &p_meta_type) const;