Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Prism -> Sorbet translation for variable binding in patterns #275

Merged
merged 5 commits into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions parser/prism/Translator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1105,6 +1105,14 @@ unique_ptr<parser::Node> Translator::patternTranslate(pm_node_t *node) {

return make_unique<parser::MatchAlt>(location, move(left), move(right));
}
case PM_ASSOC_NODE: { // A key-value pair in a Hash pattern, e.g. the `k: v` in `h in { k: v }
auto assocNode = reinterpret_cast<pm_assoc_node *>(node);

auto key = patternTranslate(assocNode->key);
auto value = patternTranslate(assocNode->value);

return make_unique<parser::Pair>(location, move(key), move(value));
}
case PM_ARRAY_PATTERN_NODE: { // An array pattern such as the `[head, *tail]` in the `a in [head, *tail]`
auto arrayPatternNode = reinterpret_cast<pm_array_pattern_node *>(node);

Expand Down Expand Up @@ -1196,6 +1204,13 @@ unique_ptr<parser::Node> Translator::patternTranslate(pm_node_t *node) {

return make_unique<parser::InPattern>(location, move(sorbetPattern), nullptr, move(statements));
}
case PM_LOCAL_VARIABLE_TARGET_NODE: { // A variable binding in a pattern, like the `head` in `[head, *tail]`
auto localVarTargetNode = reinterpret_cast<pm_local_variable_target_node *>(node);

auto name = parser.resolveConstant(localVarTargetNode->name);

return make_unique<MatchVar>(location, gs.enterNameUTF8(name));
}
default: {
return translate(node);
}
Expand Down
246 changes: 246 additions & 0 deletions test/prism_regression/case_match_variable_binding.parse-tree.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
CaseMatch {
expr = Send {
receiver = NULL
method = <U foo>
args = [
]
}
inBodies = [
InPattern {
pattern = ArrayPattern {
elts = [
MatchVar {
name = <U x>
}
]
}
guard = NULL
body = DString {
nodes = [
String {
val = <U An Array-like thing that only contains >
}
Begin {
stmts = [
LVar {
name = <U x>
}
]
}
]
}
}
InPattern {
pattern = HashPattern {
pairs = [
Pair {
key = Symbol {
val = <U k>
}
value = MatchVar {
name = <U x>
}
}
]
}
guard = NULL
body = DString {
nodes = [
String {
val = <U A Hash-like whose key `:k` has value >
}
Begin {
stmts = [
LVar {
name = <U x>
}
]
}
]
}
}
InPattern {
pattern = ArrayPattern {
elts = [
ArrayPattern {
elts = [
MatchVar {
name = <U value>
}
]
}
MatchRest {
var = MatchVar {
name = <U tail>
}
}
]
}
guard = NULL
body = DString {
nodes = [
String {
val = <U An array-like thing that starts with a one-element Array containing >
}
Begin {
stmts = [
LVar {
name = <U value>
}
]
}
String {
val = <U , and ends with >
}
Begin {
stmts = [
LVar {
name = <U tail>
}
]
}
]
}
}
InPattern {
pattern = HashPattern {
pairs = [
Pair {
key = Symbol {
val = <U k>
}
value = ArrayPattern {
elts = [
MatchVar {
name = <U value>
}
]
}
}
]
}
guard = NULL
body = DString {
nodes = [
String {
val = <U A hash-like whose key `:k` has a one-element Array value containing >
}
Begin {
stmts = [
LVar {
name = <U value>
}
]
}
]
}
}
InPattern {
pattern = ArrayPattern {
elts = [
HashPattern {
pairs = [
Pair {
key = Symbol {
val = <U k>
}
value = MatchVar {
name = <U value>
}
}
]
}
MatchRest {
var = MatchVar {
name = <U tail>
}
}
]
}
guard = NULL
body = DString {
nodes = [
String {
val = <U An array-like thing that starts with a one-element Hash containing >
}
Begin {
stmts = [
LVar {
name = <U value>
}
]
}
String {
val = <U , and ends with >
}
Begin {
stmts = [
LVar {
name = <U tail>
}
]
}
]
}
}
InPattern {
pattern = HashPattern {
pairs = [
Pair {
key = Symbol {
val = <U k>
}
value = HashPattern {
pairs = [
Pair {
key = Symbol {
val = <U k2>
}
value = MatchVar {
name = <U value>
}
}
]
}
}
]
}
guard = NULL
body = DString {
nodes = [
String {
val = <U A hash-like whose key `:k` has a one-element Hash value containing k2: >
}
Begin {
stmts = [
LVar {
name = <U value>
}
]
}
]
}
}
InPattern {
pattern = MatchVar {
name = <U x>
}
guard = NULL
body = DString {
nodes = [
String {
val = <U Some other value: >
}
Begin {
stmts = [
LVar {
name = <U x>
}
]
}
]
}
}
]
elseBody = NULL
}
21 changes: 21 additions & 0 deletions test/prism_regression/case_match_variable_binding.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# typed: false

case foo
in [x] # Variable binding nested in an Array pattern
"An Array-like thing that only contains #{x}"
in { k: x } # Variable binding nested in a Hash pattern
"A Hash-like whose key `:k` has value #{x}"

in [[value], *tail] # Array pattern inside an Array pattern
"An array-like thing that starts with a one-element Array containing #{value}, and ends with #{tail}"
in { k: [value] } # Array pattern inside a Hash pattern
"A hash-like whose key `:k` has a one-element Array value containing #{value}"

in [{ k: value }, *tail] # A Hash pattern inside an Array pattern
"An array-like thing that starts with a one-element Hash containing #{value}, and ends with #{tail}"
in { k: { k2: value } } # A Hash pattern inside a Hash pattern
"A hash-like whose key `:k` has a one-element Hash value containing k2: #{value}"

in x
"Some other value: #{x}"
end
Loading