Skip to content

Commit

Permalink
Fix various issues when function argument's default value is array/di…
Browse files Browse the repository at this point in the history
…ctionary
  • Loading branch information
Xwdit committed Nov 26, 2022
1 parent e29b982 commit 94d6456
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 11 deletions.
77 changes: 68 additions & 9 deletions modules/gdscript/gdscript_analyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1160,7 +1160,11 @@ void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode *
if (p_function->parameters[i]->default_value) {
default_value_count++;

if (p_function->parameters[i]->default_value->is_constant) {
if (p_function->parameters[i]->default_value->type == GDScriptParser::Node::ARRAY || p_function->parameters[i]->default_value->type == GDScriptParser::Node::DICTIONARY) {
if (p_function->parameters[i]->default_value->reduced_value.get_type() != Variant::NIL) {
p_function->default_arg_values.push_back(p_function->parameters[i]->default_value->reduced_value);
}
} else if (p_function->parameters[i]->default_value->is_constant) {
p_function->default_arg_values.push_back(p_function->parameters[i]->default_value->reduced_value);
}
}
Expand Down Expand Up @@ -1725,6 +1729,13 @@ void GDScriptAnalyzer::resolve_parameter(GDScriptParser::ParameterNode *p_parame
} else {
result.type_source = GDScriptParser::DataType::INFERRED;
}
result.is_constant = false;

if (p_parameter->default_value->type == GDScriptParser::Node::ARRAY) {
parameter_fold_array(static_cast<GDScriptParser::ArrayNode *>(p_parameter->default_value));
} else if (p_parameter->default_value->type == GDScriptParser::Node::DICTIONARY) {
parameter_fold_dictionary(static_cast<GDScriptParser::DictionaryNode *>(p_parameter->default_value));
}
}

if (p_parameter->datatype_specifier != nullptr) {
Expand Down Expand Up @@ -3653,8 +3664,6 @@ void GDScriptAnalyzer::reduce_unary_op(GDScriptParser::UnaryOpNode *p_unary_op)
}

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

Expand All @@ -3664,8 +3673,7 @@ void GDScriptAnalyzer::const_fold_array(GDScriptParser::ArrayNode *p_array) {
const_fold_dictionary(static_cast<GDScriptParser::DictionaryNode *>(element));
}

all_is_constant = all_is_constant && element->is_constant;
if (!all_is_constant) {
if (!element->is_constant) {
return;
}
}
Expand All @@ -3680,8 +3688,6 @@ void GDScriptAnalyzer::const_fold_array(GDScriptParser::ArrayNode *p_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];

Expand All @@ -3691,8 +3697,7 @@ void GDScriptAnalyzer::const_fold_dictionary(GDScriptParser::DictionaryNode *p_d
const_fold_dictionary(static_cast<GDScriptParser::DictionaryNode *>(element.value));
}

all_is_constant = all_is_constant && element.key->is_constant && element.value->is_constant;
if (!all_is_constant) {
if (!element.key->is_constant || !element.value->is_constant) {
return;
}
}
Expand All @@ -3706,6 +3711,60 @@ void GDScriptAnalyzer::const_fold_dictionary(GDScriptParser::DictionaryNode *p_d
p_dictionary->reduced_value = dict;
}

void GDScriptAnalyzer::parameter_fold_array(GDScriptParser::ArrayNode *p_array) {
for (int i = 0; i < p_array->elements.size(); i++) {
GDScriptParser::ExpressionNode *element = p_array->elements[i];

if (element->type == GDScriptParser::Node::ARRAY) {
parameter_fold_array(static_cast<GDScriptParser::ArrayNode *>(element));
if (element->reduced_value.get_type() == Variant::NIL) {
return;
}
} else if (element->type == GDScriptParser::Node::DICTIONARY) {
parameter_fold_dictionary(static_cast<GDScriptParser::DictionaryNode *>(element));
if (element->reduced_value.get_type() == Variant::NIL) {
return;
}
} else if (!element->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->reduced_value = array;
}

void GDScriptAnalyzer::parameter_fold_dictionary(GDScriptParser::DictionaryNode *p_dictionary) {
for (int i = 0; i < p_dictionary->elements.size(); i++) {
const GDScriptParser::DictionaryNode::Pair &element = p_dictionary->elements[i];

if (element.value->type == GDScriptParser::Node::ARRAY) {
parameter_fold_array(static_cast<GDScriptParser::ArrayNode *>(element.value));
if (element.value->reduced_value.get_type() == Variant::NIL) {
return;
}
} else if (element.value->type == GDScriptParser::Node::DICTIONARY) {
parameter_fold_dictionary(static_cast<GDScriptParser::DictionaryNode *>(element.value));
if (element.value->reduced_value.get_type() == Variant::NIL) {
return;
}
} else if (!element.key->is_constant || !element.value->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->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 @@ -100,6 +100,9 @@ class GDScriptAnalyzer {
void const_fold_array(GDScriptParser::ArrayNode *p_array);
void const_fold_dictionary(GDScriptParser::DictionaryNode *p_dictionary);

void parameter_fold_array(GDScriptParser::ArrayNode *p_array);
void parameter_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
4 changes: 2 additions & 2 deletions modules/gdscript/gdscript_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -702,13 +702,13 @@ static String _make_arguments_hint(const GDScriptParser::FunctionNode *p_functio
} break;
case GDScriptParser::Node::ARRAY: {
const GDScriptParser::ArrayNode *arr = static_cast<const GDScriptParser::ArrayNode *>(par->default_value);
if (arr->is_constant && arr->reduced) {
if (arr->reduced_value.get_type() != Variant::NIL && arr->reduced) {
def_val = arr->reduced_value.operator String();
}
} break;
case GDScriptParser::Node::DICTIONARY: {
const GDScriptParser::DictionaryNode *dict = static_cast<const GDScriptParser::DictionaryNode *>(par->default_value);
if (dict->is_constant && dict->reduced) {
if (dict->reduced_value.get_type() != Variant::NIL && dict->reduced) {
def_val = dict->reduced_value.operator String();
}
} break;
Expand Down

0 comments on commit 94d6456

Please sign in to comment.