You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-09 12:50:35 +00:00
Merge pull request #78837 from dalexeev/gds-const-array-and-dict-constructors
GDScript: Add constant `Array` and `Dictionary` constructors
This commit is contained in:
@@ -5208,24 +5208,29 @@ void GDScriptAnalyzer::reduce_unary_op(GDScriptParser::UnaryOpNode *p_unary_op)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Variant GDScriptAnalyzer::make_expression_reduced_value(GDScriptParser::ExpressionNode *p_expression, bool &is_reduced) {
|
Variant GDScriptAnalyzer::make_expression_reduced_value(GDScriptParser::ExpressionNode *p_expression, bool &is_reduced) {
|
||||||
Variant value;
|
|
||||||
|
|
||||||
if (p_expression == nullptr) {
|
if (p_expression == nullptr) {
|
||||||
return value;
|
return Variant();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_expression->is_constant) {
|
if (p_expression->is_constant) {
|
||||||
is_reduced = true;
|
is_reduced = true;
|
||||||
value = p_expression->reduced_value;
|
return p_expression->reduced_value;
|
||||||
} else if (p_expression->type == GDScriptParser::Node::ARRAY) {
|
|
||||||
value = make_array_reduced_value(static_cast<GDScriptParser::ArrayNode *>(p_expression), is_reduced);
|
|
||||||
} else if (p_expression->type == GDScriptParser::Node::DICTIONARY) {
|
|
||||||
value = make_dictionary_reduced_value(static_cast<GDScriptParser::DictionaryNode *>(p_expression), is_reduced);
|
|
||||||
} else if (p_expression->type == GDScriptParser::Node::SUBSCRIPT) {
|
|
||||||
value = make_subscript_reduced_value(static_cast<GDScriptParser::SubscriptNode *>(p_expression), is_reduced);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
switch (p_expression->type) {
|
||||||
|
case GDScriptParser::Node::ARRAY:
|
||||||
|
return make_array_reduced_value(static_cast<GDScriptParser::ArrayNode *>(p_expression), is_reduced);
|
||||||
|
case GDScriptParser::Node::DICTIONARY:
|
||||||
|
return make_dictionary_reduced_value(static_cast<GDScriptParser::DictionaryNode *>(p_expression), is_reduced);
|
||||||
|
case GDScriptParser::Node::SUBSCRIPT:
|
||||||
|
return make_subscript_reduced_value(static_cast<GDScriptParser::SubscriptNode *>(p_expression), is_reduced);
|
||||||
|
case GDScriptParser::Node::CALL:
|
||||||
|
return make_call_reduced_value(static_cast<GDScriptParser::CallNode *>(p_expression), is_reduced);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Variant();
|
||||||
}
|
}
|
||||||
|
|
||||||
Variant GDScriptAnalyzer::make_array_reduced_value(GDScriptParser::ArrayNode *p_array, bool &is_reduced) {
|
Variant GDScriptAnalyzer::make_array_reduced_value(GDScriptParser::ArrayNode *p_array, bool &is_reduced) {
|
||||||
@@ -5317,6 +5322,53 @@ Variant GDScriptAnalyzer::make_subscript_reduced_value(GDScriptParser::Subscript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Variant GDScriptAnalyzer::make_call_reduced_value(GDScriptParser::CallNode *p_call, bool &is_reduced) {
|
||||||
|
if (p_call->get_callee_type() == GDScriptParser::Node::IDENTIFIER) {
|
||||||
|
Variant::Type type = Variant::NIL;
|
||||||
|
if (p_call->function_name == SNAME("Array")) {
|
||||||
|
type = Variant::ARRAY;
|
||||||
|
} else if (p_call->function_name == SNAME("Dictionary")) {
|
||||||
|
type = Variant::DICTIONARY;
|
||||||
|
} else {
|
||||||
|
return Variant();
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector<Variant> args;
|
||||||
|
args.resize(p_call->arguments.size());
|
||||||
|
const Variant **argptrs = (const Variant **)alloca(sizeof(const Variant **) * args.size());
|
||||||
|
for (int i = 0; i < p_call->arguments.size(); i++) {
|
||||||
|
bool is_arg_value_reduced = false;
|
||||||
|
Variant arg_value = make_expression_reduced_value(p_call->arguments[i], is_arg_value_reduced);
|
||||||
|
if (!is_arg_value_reduced) {
|
||||||
|
return Variant();
|
||||||
|
}
|
||||||
|
args.write[i] = arg_value;
|
||||||
|
argptrs[i] = &args[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
Variant result;
|
||||||
|
Callable::CallError ce;
|
||||||
|
Variant::construct(type, result, argptrs, args.size(), ce);
|
||||||
|
if (ce.error) {
|
||||||
|
push_error(vformat(R"(Failed to construct "%s".)", Variant::get_type_name(type)), p_call);
|
||||||
|
return Variant();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == Variant::ARRAY) {
|
||||||
|
Array array = result;
|
||||||
|
array.make_read_only();
|
||||||
|
} else if (type == Variant::DICTIONARY) {
|
||||||
|
Dictionary dictionary = result;
|
||||||
|
dictionary.make_read_only();
|
||||||
|
}
|
||||||
|
|
||||||
|
is_reduced = true;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Variant();
|
||||||
|
}
|
||||||
|
|
||||||
Array GDScriptAnalyzer::make_array_from_element_datatype(const GDScriptParser::DataType &p_element_datatype, const GDScriptParser::Node *p_source_node) {
|
Array GDScriptAnalyzer::make_array_from_element_datatype(const GDScriptParser::DataType &p_element_datatype, const GDScriptParser::Node *p_source_node) {
|
||||||
Array array;
|
Array array;
|
||||||
|
|
||||||
|
|||||||
@@ -120,6 +120,7 @@ class GDScriptAnalyzer {
|
|||||||
Variant make_array_reduced_value(GDScriptParser::ArrayNode *p_array, bool &is_reduced);
|
Variant make_array_reduced_value(GDScriptParser::ArrayNode *p_array, bool &is_reduced);
|
||||||
Variant make_dictionary_reduced_value(GDScriptParser::DictionaryNode *p_dictionary, bool &is_reduced);
|
Variant make_dictionary_reduced_value(GDScriptParser::DictionaryNode *p_dictionary, bool &is_reduced);
|
||||||
Variant make_subscript_reduced_value(GDScriptParser::SubscriptNode *p_subscript, bool &is_reduced);
|
Variant make_subscript_reduced_value(GDScriptParser::SubscriptNode *p_subscript, bool &is_reduced);
|
||||||
|
Variant make_call_reduced_value(GDScriptParser::CallNode *p_call, bool &is_reduced);
|
||||||
|
|
||||||
// Helpers.
|
// Helpers.
|
||||||
Array make_array_from_element_datatype(const GDScriptParser::DataType &p_element_datatype, const GDScriptParser::Node *p_source_node = nullptr);
|
Array make_array_from_element_datatype(const GDScriptParser::DataType &p_element_datatype, const GDScriptParser::Node *p_source_node = nullptr);
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
const A1 = Array()
|
||||||
|
const A2 = Array(Array())
|
||||||
|
const A3 = Array([])
|
||||||
|
const A4 = [Array()]
|
||||||
|
const A5 = [[]]
|
||||||
|
const A6 = Array([1], TYPE_INT, &"", null)
|
||||||
|
|
||||||
|
const D1 = Dictionary()
|
||||||
|
const D2 = Dictionary(Dictionary())
|
||||||
|
const D3 = Dictionary({})
|
||||||
|
const D4 = { Dictionary(): Dictionary() }
|
||||||
|
const D5 = { {}: {} }
|
||||||
|
const D6 = Dictionary({ 1: 1 }, TYPE_INT, &"", null, TYPE_INT, &"", null)
|
||||||
|
|
||||||
|
var a1 = Array()
|
||||||
|
var a2 = Array(Array())
|
||||||
|
var a3 = Array([])
|
||||||
|
var a4 = [Array()]
|
||||||
|
var a5 = [[]]
|
||||||
|
var a6 = Array([1], TYPE_INT, &"", null)
|
||||||
|
|
||||||
|
var d1 = Dictionary()
|
||||||
|
var d2 = Dictionary(Dictionary())
|
||||||
|
var d3 = Dictionary({})
|
||||||
|
var d4 = { Dictionary(): Dictionary() }
|
||||||
|
var d5 = { {}: {} }
|
||||||
|
var d6 = Dictionary({ 1: 1 }, TYPE_INT, &"", null, TYPE_INT, &"", null)
|
||||||
|
|
||||||
|
func test_value(value: Variant) -> void:
|
||||||
|
@warning_ignore("unsafe_method_access")
|
||||||
|
prints(value.is_read_only(), var_to_str(value).replace("\n", " "))
|
||||||
|
|
||||||
|
func test():
|
||||||
|
print('---')
|
||||||
|
test_value(A1)
|
||||||
|
test_value(A2)
|
||||||
|
test_value(A3)
|
||||||
|
test_value(A4)
|
||||||
|
test_value(A5)
|
||||||
|
test_value(A6)
|
||||||
|
|
||||||
|
print('---')
|
||||||
|
test_value(D1)
|
||||||
|
test_value(D2)
|
||||||
|
test_value(D3)
|
||||||
|
test_value(D4)
|
||||||
|
test_value(D5)
|
||||||
|
test_value(D6)
|
||||||
|
|
||||||
|
print('---')
|
||||||
|
test_value(a1)
|
||||||
|
test_value(a2)
|
||||||
|
test_value(a3)
|
||||||
|
test_value(a4)
|
||||||
|
test_value(a5)
|
||||||
|
test_value(a6)
|
||||||
|
|
||||||
|
print('---')
|
||||||
|
test_value(d1)
|
||||||
|
test_value(d2)
|
||||||
|
test_value(d3)
|
||||||
|
test_value(d4)
|
||||||
|
test_value(d5)
|
||||||
|
test_value(d6)
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
GDTEST_OK
|
||||||
|
---
|
||||||
|
true []
|
||||||
|
true []
|
||||||
|
true []
|
||||||
|
true [[]]
|
||||||
|
true [[]]
|
||||||
|
true Array[int]([1])
|
||||||
|
---
|
||||||
|
true {}
|
||||||
|
true {}
|
||||||
|
true {}
|
||||||
|
true { {}: {} }
|
||||||
|
true { {}: {} }
|
||||||
|
true Dictionary[int, int]({ 1: 1 })
|
||||||
|
---
|
||||||
|
false []
|
||||||
|
false []
|
||||||
|
false []
|
||||||
|
false [[]]
|
||||||
|
false [[]]
|
||||||
|
false Array[int]([1])
|
||||||
|
---
|
||||||
|
false {}
|
||||||
|
false {}
|
||||||
|
false {}
|
||||||
|
false { {}: {} }
|
||||||
|
false { {}: {} }
|
||||||
|
false Dictionary[int, int]({ 1: 1 })
|
||||||
Reference in New Issue
Block a user