Skip to content

Commit 5d697c3

Browse files
committed
Merge pull request #78837 from dalexeev/gds-const-array-and-dict-constructors
GDScript: Add constant `Array` and `Dictionary` constructors
2 parents e8240fd + 7721e13 commit 5d697c3

File tree

4 files changed

+157
-11
lines changed

4 files changed

+157
-11
lines changed

modules/gdscript/gdscript_analyzer.cpp

Lines changed: 63 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5208,24 +5208,29 @@ void GDScriptAnalyzer::reduce_unary_op(GDScriptParser::UnaryOpNode *p_unary_op)
52085208
}
52095209

52105210
Variant GDScriptAnalyzer::make_expression_reduced_value(GDScriptParser::ExpressionNode *p_expression, bool &is_reduced) {
5211-
Variant value;
5212-
52135211
if (p_expression == nullptr) {
5214-
return value;
5212+
return Variant();
52155213
}
52165214

52175215
if (p_expression->is_constant) {
52185216
is_reduced = true;
5219-
value = p_expression->reduced_value;
5220-
} else if (p_expression->type == GDScriptParser::Node::ARRAY) {
5221-
value = make_array_reduced_value(static_cast<GDScriptParser::ArrayNode *>(p_expression), is_reduced);
5222-
} else if (p_expression->type == GDScriptParser::Node::DICTIONARY) {
5223-
value = make_dictionary_reduced_value(static_cast<GDScriptParser::DictionaryNode *>(p_expression), is_reduced);
5224-
} else if (p_expression->type == GDScriptParser::Node::SUBSCRIPT) {
5225-
value = make_subscript_reduced_value(static_cast<GDScriptParser::SubscriptNode *>(p_expression), is_reduced);
5217+
return p_expression->reduced_value;
52265218
}
52275219

5228-
return value;
5220+
switch (p_expression->type) {
5221+
case GDScriptParser::Node::ARRAY:
5222+
return make_array_reduced_value(static_cast<GDScriptParser::ArrayNode *>(p_expression), is_reduced);
5223+
case GDScriptParser::Node::DICTIONARY:
5224+
return make_dictionary_reduced_value(static_cast<GDScriptParser::DictionaryNode *>(p_expression), is_reduced);
5225+
case GDScriptParser::Node::SUBSCRIPT:
5226+
return make_subscript_reduced_value(static_cast<GDScriptParser::SubscriptNode *>(p_expression), is_reduced);
5227+
case GDScriptParser::Node::CALL:
5228+
return make_call_reduced_value(static_cast<GDScriptParser::CallNode *>(p_expression), is_reduced);
5229+
default:
5230+
break;
5231+
}
5232+
5233+
return Variant();
52295234
}
52305235

52315236
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
53175322
}
53185323
}
53195324

5325+
Variant GDScriptAnalyzer::make_call_reduced_value(GDScriptParser::CallNode *p_call, bool &is_reduced) {
5326+
if (p_call->get_callee_type() == GDScriptParser::Node::IDENTIFIER) {
5327+
Variant::Type type = Variant::NIL;
5328+
if (p_call->function_name == SNAME("Array")) {
5329+
type = Variant::ARRAY;
5330+
} else if (p_call->function_name == SNAME("Dictionary")) {
5331+
type = Variant::DICTIONARY;
5332+
} else {
5333+
return Variant();
5334+
}
5335+
5336+
Vector<Variant> args;
5337+
args.resize(p_call->arguments.size());
5338+
const Variant **argptrs = (const Variant **)alloca(sizeof(const Variant **) * args.size());
5339+
for (int i = 0; i < p_call->arguments.size(); i++) {
5340+
bool is_arg_value_reduced = false;
5341+
Variant arg_value = make_expression_reduced_value(p_call->arguments[i], is_arg_value_reduced);
5342+
if (!is_arg_value_reduced) {
5343+
return Variant();
5344+
}
5345+
args.write[i] = arg_value;
5346+
argptrs[i] = &args[i];
5347+
}
5348+
5349+
Variant result;
5350+
Callable::CallError ce;
5351+
Variant::construct(type, result, argptrs, args.size(), ce);
5352+
if (ce.error) {
5353+
push_error(vformat(R"(Failed to construct "%s".)", Variant::get_type_name(type)), p_call);
5354+
return Variant();
5355+
}
5356+
5357+
if (type == Variant::ARRAY) {
5358+
Array array = result;
5359+
array.make_read_only();
5360+
} else if (type == Variant::DICTIONARY) {
5361+
Dictionary dictionary = result;
5362+
dictionary.make_read_only();
5363+
}
5364+
5365+
is_reduced = true;
5366+
return result;
5367+
}
5368+
5369+
return Variant();
5370+
}
5371+
53205372
Array GDScriptAnalyzer::make_array_from_element_datatype(const GDScriptParser::DataType &p_element_datatype, const GDScriptParser::Node *p_source_node) {
53215373
Array array;
53225374

modules/gdscript/gdscript_analyzer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ class GDScriptAnalyzer {
120120
Variant make_array_reduced_value(GDScriptParser::ArrayNode *p_array, bool &is_reduced);
121121
Variant make_dictionary_reduced_value(GDScriptParser::DictionaryNode *p_dictionary, bool &is_reduced);
122122
Variant make_subscript_reduced_value(GDScriptParser::SubscriptNode *p_subscript, bool &is_reduced);
123+
Variant make_call_reduced_value(GDScriptParser::CallNode *p_call, bool &is_reduced);
123124

124125
// Helpers.
125126
Array make_array_from_element_datatype(const GDScriptParser::DataType &p_element_datatype, const GDScriptParser::Node *p_source_node = nullptr);
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
const A1 = Array()
2+
const A2 = Array(Array())
3+
const A3 = Array([])
4+
const A4 = [Array()]
5+
const A5 = [[]]
6+
const A6 = Array([1], TYPE_INT, &"", null)
7+
8+
const D1 = Dictionary()
9+
const D2 = Dictionary(Dictionary())
10+
const D3 = Dictionary({})
11+
const D4 = { Dictionary(): Dictionary() }
12+
const D5 = { {}: {} }
13+
const D6 = Dictionary({ 1: 1 }, TYPE_INT, &"", null, TYPE_INT, &"", null)
14+
15+
var a1 = Array()
16+
var a2 = Array(Array())
17+
var a3 = Array([])
18+
var a4 = [Array()]
19+
var a5 = [[]]
20+
var a6 = Array([1], TYPE_INT, &"", null)
21+
22+
var d1 = Dictionary()
23+
var d2 = Dictionary(Dictionary())
24+
var d3 = Dictionary({})
25+
var d4 = { Dictionary(): Dictionary() }
26+
var d5 = { {}: {} }
27+
var d6 = Dictionary({ 1: 1 }, TYPE_INT, &"", null, TYPE_INT, &"", null)
28+
29+
func test_value(value: Variant) -> void:
30+
@warning_ignore("unsafe_method_access")
31+
prints(value.is_read_only(), var_to_str(value).replace("\n", " "))
32+
33+
func test():
34+
print('---')
35+
test_value(A1)
36+
test_value(A2)
37+
test_value(A3)
38+
test_value(A4)
39+
test_value(A5)
40+
test_value(A6)
41+
42+
print('---')
43+
test_value(D1)
44+
test_value(D2)
45+
test_value(D3)
46+
test_value(D4)
47+
test_value(D5)
48+
test_value(D6)
49+
50+
print('---')
51+
test_value(a1)
52+
test_value(a2)
53+
test_value(a3)
54+
test_value(a4)
55+
test_value(a5)
56+
test_value(a6)
57+
58+
print('---')
59+
test_value(d1)
60+
test_value(d2)
61+
test_value(d3)
62+
test_value(d4)
63+
test_value(d5)
64+
test_value(d6)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
GDTEST_OK
2+
---
3+
true []
4+
true []
5+
true []
6+
true [[]]
7+
true [[]]
8+
true Array[int]([1])
9+
---
10+
true {}
11+
true {}
12+
true {}
13+
true { {}: {} }
14+
true { {}: {} }
15+
true Dictionary[int, int]({ 1: 1 })
16+
---
17+
false []
18+
false []
19+
false []
20+
false [[]]
21+
false [[]]
22+
false Array[int]([1])
23+
---
24+
false {}
25+
false {}
26+
false {}
27+
false { {}: {} }
28+
false { {}: {} }
29+
false Dictionary[int, int]({ 1: 1 })

0 commit comments

Comments
 (0)