Skip to content

Commit

Permalink
Merge pull request #72285 from vnen/gdscript-variable-match
Browse files Browse the repository at this point in the history
GDScript: Allow variables in match patterns
  • Loading branch information
akien-mga authored Jan 29, 2023
2 parents d866d6c + c68b235 commit a3dae9e
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 15 deletions.
19 changes: 15 additions & 4 deletions modules/gdscript/gdscript_analyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1891,11 +1891,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:
Expand Down
14 changes: 3 additions & 11 deletions modules/gdscript/gdscript_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand All @@ -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);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
func test():
var dict = { a = 1 }
match 2:
dict["a"]:
print("not allowed")
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Expression in match pattern must be a constant expression, an identifier, or an attribute access ("A.B").
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
func test():
var a = 1
match 2:
a + 2:
print("not allowed")
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Expression in match pattern must be a constant expression, an identifier, or an attribute access ("A.B").
Original file line number Diff line number Diff line change
@@ -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")
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
GDTEST_OK
reach 1
reach 2
reach 3
reach 4

0 comments on commit a3dae9e

Please sign in to comment.