Skip to content

Commit

Permalink
Merge pull request #310 from Shopify/translate-pattern-matching-opera…
Browse files Browse the repository at this point in the history
…tors

Translate pattern matching operators
  • Loading branch information
amomchilov authored Oct 28, 2024
2 parents bc8caf7 + 69fba23 commit f1e5aea
Show file tree
Hide file tree
Showing 3 changed files with 310 additions and 2 deletions.
18 changes: 16 additions & 2 deletions parser/prism/Translator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,22 @@ unique_ptr<parser::Node> Translator::translate(pm_node_t *node) {

return make_unique<parser::MatchCurLine>(location, move(regex));
}
case PM_MATCH_REQUIRED_NODE: {
auto matchRequiredNode = down_cast<pm_match_required_node>(node);

auto value = patternTranslate(matchRequiredNode->value);
auto pattern = patternTranslate(matchRequiredNode->pattern);

return make_unique<parser::MatchPattern>(location, move(value), move(pattern));
}
case PM_MATCH_PREDICATE_NODE: {
auto matchPredicateNode = down_cast<pm_match_predicate_node>(node);

auto value = patternTranslate(matchPredicateNode->value);
auto pattern = patternTranslate(matchPredicateNode->pattern);

return make_unique<parser::MatchPatternP>(location, move(value), move(pattern));
}
case PM_MATCH_WRITE_NODE: { // A regex match that assigns to a local variable, like `a =~ /wat/`
auto matchWriteNode = down_cast<pm_match_write_node>(node);

Expand Down Expand Up @@ -1186,8 +1202,6 @@ unique_ptr<parser::Node> Translator::translate(pm_node_t *node) {
unreachable("Prism's parser never produces `PM_SCOPE_NODE` nodes.");

case PM_IMPLICIT_NODE:
case PM_MATCH_PREDICATE_NODE:
case PM_MATCH_REQUIRED_NODE:
case PM_MISSING_NODE:
auto type_id = PM_NODE_TYPE(node);
auto type_name = pm_node_type_to_str(type_id);
Expand Down
266 changes: 266 additions & 0 deletions test/prism_regression/pattern_matching_operators.parse-tree.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
Begin {
stmts = [
MatchPatternP {
lhs = Send {
receiver = NULL
method = <U match>
args = [
]
}
rhs = Integer {
val = "1"
}
}
MatchPatternP {
lhs = Send {
receiver = NULL
method = <U no_match>
args = [
]
}
rhs = ArrayPattern {
elts = [
Integer {
val = "1"
}
Integer {
val = "2"
}
]
}
}
MatchPatternP {
lhs = Array {
elts = [
Send {
receiver = NULL
method = <U match_1>
args = [
]
}
Send {
receiver = NULL
method = <U match_2>
args = [
]
}
]
}
rhs = ArrayPattern {
elts = [
Integer {
val = "1"
}
Integer {
val = "2"
}
]
}
}
MatchPatternP {
lhs = Integer {
val = "1"
}
rhs = MatchVar {
name = <U var>
}
}
MatchPatternP {
lhs = Array {
elts = [
Integer {
val = "1"
}
Integer {
val = "2"
}
]
}
rhs = ArrayPattern {
elts = [
MatchVar {
name = <U var_a>
}
MatchVar {
name = <U var_b>
}
]
}
}
If {
condition = Send {
receiver = LVar {
name = <U d>
}
method = <U ==>
args = [
Send {
receiver = LVar {
name = <U c>
}
method = <U *>
args = [
Integer {
val = "2"
}
]
}
]
}
then_ = MatchPatternP {
lhs = Array {
elts = [
Integer {
val = "3"
}
Integer {
val = "4"
}
]
}
rhs = ArrayPattern {
elts = [
MatchVar {
name = <U c>
}
MatchVar {
name = <U d>
}
]
}
}
else_ = NULL
}
MatchPattern {
lhs = Send {
receiver = NULL
method = <U match>
args = [
]
}
rhs = Integer {
val = "10"
}
}
MatchPattern {
lhs = Send {
receiver = NULL
method = <U no_match>
args = [
]
}
rhs = ArrayPattern {
elts = [
Integer {
val = "10"
}
Integer {
val = "20"
}
]
}
}
MatchPattern {
lhs = Array {
elts = [
Send {
receiver = NULL
method = <U match_1>
args = [
]
}
Send {
receiver = NULL
method = <U match_2>
args = [
]
}
]
}
rhs = ArrayPattern {
elts = [
Integer {
val = "10"
}
Integer {
val = "20"
}
]
}
}
MatchPattern {
lhs = Integer {
val = "10"
}
rhs = MatchVar {
name = <U var_c>
}
}
MatchPattern {
lhs = Array {
elts = [
Integer {
val = "10"
}
Integer {
val = "20"
}
]
}
rhs = ArrayPattern {
elts = [
MatchVar {
name = <U var_c>
}
MatchVar {
name = <U var_d>
}
]
}
}
If {
condition = Send {
receiver = LVar {
name = <U var_d>
}
method = <U ==>
args = [
Send {
receiver = LVar {
name = <U var_c>
}
method = <U *>
args = [
Integer {
val = "2"
}
]
}
]
}
then_ = MatchPattern {
lhs = Array {
elts = [
Integer {
val = "30"
}
Integer {
val = "40"
}
]
}
rhs = ArrayPattern {
elts = [
MatchVar {
name = <U var_c>
}
MatchVar {
name = <U var_d>
}
]
}
}
else_ = NULL
}
]
}
28 changes: 28 additions & 0 deletions test/prism_regression/pattern_matching_operators.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# typed: false

# matching expressions to patterns
match in 1
no_match in 1, 2
[match_1, match_2] in 1, 2

# assigning expressions to patterns
1 in var
[1, 2] in var_a, var_b

# guards don't work outside of case-based pattern matching
# so this should be normal conditional assignment
[3, 4] in c, d if d == c*2


# matching expressions to patterns
match => 10
no_match => 10, 20
[match_1, match_2] => 10, 20

# assigning expressions to patterns
10 => var_c
[10, 20] => var_c, var_d

# guards don't work outside of case-based pattern matching
# so this should be normal conditional assignment
[30, 40] => var_c, var_d if var_d == var_c*2

0 comments on commit f1e5aea

Please sign in to comment.