|
@@ -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;
|