summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Marques <george@gmarqu.es>2023-01-28 19:49:14 -0300
committerGeorge Marques <george@gmarqu.es>2023-01-28 19:53:27 -0300
commitc68b2358d58c9acd09dc9618bb7ba89246d759f7 (patch)
treea3010b6d61d1b582d013a60dd8bdddbd012be719
parent218bef90af2091afde3b1be816c87286c194a2a8 (diff)
GDScript: Allow variables in match patterns
To restore an ability available in 3.x and reduce compatibility changes.
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp19
-rw-r--r--modules/gdscript/gdscript_parser.cpp14
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/match_with_subscript.gd5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/match_with_subscript.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/match_with_variable_expression.gd5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/errors/match_with_variable_expression.out2
-rw-r--r--modules/gdscript/tests/scripts/parser/features/match_with_variables.gd22
-rw-r--r--modules/gdscript/tests/scripts/parser/features/match_with_variables.out5
8 files changed, 59 insertions, 15 deletions
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index 8c3521c530..8660dbdd42 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -1901,11 +1901,22 @@ void GDScriptAnalyzer::resolve_match_pattern(GDScriptParser::PatternNode *p_matc
break;
case GDScriptParser::PatternNode::PT_EXPRESSION:
if (p_match_pattern->expression) {
- reduce_expression(p_match_pattern->expression);
- if (!p_match_pattern->expression->is_constant) {
- push_error(R"(Expression in match pattern must be a constant.)", p_match_pattern->expression);
+ GDScriptParser::ExpressionNode *expr = p_match_pattern->expression;
+ reduce_expression(expr);
+ result = expr->get_datatype();
+ if (!expr->is_constant) {
+ while (expr && expr->type == GDScriptParser::Node::SUBSCRIPT) {
+ GDScriptParser::SubscriptNode *sub = static_cast<GDScriptParser::SubscriptNode *>(expr);
+ if (!sub->is_attribute) {
+ expr = nullptr;
+ } else {
+ expr = sub->base;
+ }
+ }
+ if (!expr || expr->type != GDScriptParser::Node::IDENTIFIER) {
+ push_error(R"(Expression in match pattern must be a constant expression, an identifier, or an attribute access ("A.B").)", expr);
+ }
}
- result = p_match_pattern->expression->get_datatype();
}
break;
case GDScriptParser::PatternNode::PT_BIND:
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 1a744d59ba..74d7f94d7c 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -1904,7 +1904,6 @@ GDScriptParser::MatchNode *GDScriptParser::parse_match() {
#ifdef DEBUG_ENABLED
bool all_have_return = true;
bool have_wildcard = false;
- bool have_wildcard_without_continue = false;
#endif
while (!check(GDScriptTokenizer::Token::DEDENT) && !is_at_end()) {
@@ -1915,19 +1914,12 @@ GDScriptParser::MatchNode *GDScriptParser::parse_match() {
}
#ifdef DEBUG_ENABLED
- if (have_wildcard_without_continue && !branch->patterns.is_empty()) {
+ if (have_wildcard && !branch->patterns.is_empty()) {
push_warning(branch->patterns[0], GDScriptWarning::UNREACHABLE_PATTERN);
}
- if (branch->has_wildcard) {
- have_wildcard = true;
- if (!branch->block->has_continue) {
- have_wildcard_without_continue = true;
- }
- }
- if (!branch->block->has_return) {
- all_have_return = false;
- }
+ have_wildcard = have_wildcard || branch->has_wildcard;
+ all_have_return = all_have_return && branch->block->has_return;
#endif
match->branches.push_back(branch);
}
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/match_with_subscript.gd b/modules/gdscript/tests/scripts/analyzer/errors/match_with_subscript.gd
new file mode 100644
index 0000000000..6d92db34c1
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/match_with_subscript.gd
@@ -0,0 +1,5 @@
+func test():
+ var dict = { a = 1 }
+ match 2:
+ dict["a"]:
+ print("not allowed")
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/match_with_subscript.out b/modules/gdscript/tests/scripts/analyzer/errors/match_with_subscript.out
new file mode 100644
index 0000000000..b7385a50d5
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/match_with_subscript.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Expression in match pattern must be a constant expression, an identifier, or an attribute access ("A.B").
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/match_with_variable_expression.gd b/modules/gdscript/tests/scripts/analyzer/errors/match_with_variable_expression.gd
new file mode 100644
index 0000000000..4df44d9ea2
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/match_with_variable_expression.gd
@@ -0,0 +1,5 @@
+func test():
+ var a = 1
+ match 2:
+ a + 2:
+ print("not allowed")
diff --git a/modules/gdscript/tests/scripts/analyzer/errors/match_with_variable_expression.out b/modules/gdscript/tests/scripts/analyzer/errors/match_with_variable_expression.out
new file mode 100644
index 0000000000..b7385a50d5
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/errors/match_with_variable_expression.out
@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Expression in match pattern must be a constant expression, an identifier, or an attribute access ("A.B").
diff --git a/modules/gdscript/tests/scripts/parser/features/match_with_variables.gd b/modules/gdscript/tests/scripts/parser/features/match_with_variables.gd
new file mode 100644
index 0000000000..aa38c3bf41
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/match_with_variables.gd
@@ -0,0 +1,22 @@
+func test():
+ var a = 1
+ match 1:
+ a:
+ print("reach 1")
+
+ var dict = { b = 2 }
+ match 2:
+ dict.b:
+ print("reach 2")
+
+ var nested_dict = {
+ sub = { c = 3 }
+ }
+ match 3:
+ nested_dict.sub.c:
+ print("reach 3")
+
+ var sub_pattern = { d = 4 }
+ match [4]:
+ [sub_pattern.d]:
+ print("reach 4")
diff --git a/modules/gdscript/tests/scripts/parser/features/match_with_variables.out b/modules/gdscript/tests/scripts/parser/features/match_with_variables.out
new file mode 100644
index 0000000000..de1dcb0d40
--- /dev/null
+++ b/modules/gdscript/tests/scripts/parser/features/match_with_variables.out
@@ -0,0 +1,5 @@
+GDTEST_OK
+reach 1
+reach 2
+reach 3
+reach 4