Skip to content

Commit e062974

Browse files
add helper for very common pattern in Direct Prism Desugar (sorbet#9684)
1 parent adb4ca9 commit e062974

File tree

1 file changed

+40
-48
lines changed

1 file changed

+40
-48
lines changed

parser/prism/Translator.cc

Lines changed: 40 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,22 @@ template <typename... Tail> bool hasExpr(const std::unique_ptr<parser::Node> &he
3333
return hasExpr(head) && hasExpr(tail...);
3434
}
3535

36+
// Helper to extract desugared expression or return EmptyTree if node is null.
37+
ExpressionPtr takeDesugaredExprOrEmptyTree(const std::unique_ptr<parser::Node> &node) {
38+
if (node == nullptr) {
39+
return MK::EmptyTree();
40+
}
41+
ENFORCE(node->hasDesugaredExpr(), "Node has no desugared expression");
42+
return node->takeDesugaredExpr();
43+
}
44+
3645
// Helper template to convert nodes to any store type with takeDesugaredExpr or EmptyTree for nulls.
3746
// This is used to convert a NodeVec to the store type argument for nodes including `Send`, `InsSeq`.
3847
template <typename StoreType> StoreType nodeVecToStore(const sorbet::parser::NodeVec &nodes) {
3948
StoreType store;
4049
store.reserve(nodes.size());
4150
for (const auto &node : nodes) {
42-
store.emplace_back(node ? node->takeDesugaredExpr() : sorbet::ast::MK::EmptyTree());
51+
store.emplace_back(takeDesugaredExprOrEmptyTree(node));
4352
}
4453
return store;
4554
}
@@ -1110,7 +1119,7 @@ unique_ptr<parser::Node> Translator::translate(pm_node_t *node, bool preserveCon
11101119
ExpressionPtr breakArgs;
11111120
if (arguments.size() == 1) {
11121121
auto &first = arguments[0];
1113-
breakArgs = first == nullptr ? MK::EmptyTree() : first->takeDesugaredExpr();
1122+
breakArgs = takeDesugaredExprOrEmptyTree(first);
11141123
} else {
11151124
auto args = nodeVecToStore<ast::Array::ENTRY_store>(arguments);
11161125
auto arrayLocation = parser.translateLocation(breakNode->arguments->base.location);
@@ -1630,8 +1639,7 @@ unique_ptr<parser::Node> Translator::translate(pm_node_t *node, bool preserveCon
16301639
blockExpr = desugarSymbolProc(symbol);
16311640
} else {
16321641
auto blockLoc = translateLoc(prismBlock->location);
1633-
auto blockBodyExpr =
1634-
blockBody == nullptr ? MK::EmptyTree() : blockBody->takeDesugaredExpr();
1642+
auto blockBodyExpr = takeDesugaredExprOrEmptyTree(blockBody);
16351643
blockExpr = MK::Block(blockLoc, move(blockBodyExpr), move(blockParamsStore));
16361644
}
16371645

@@ -1748,7 +1756,7 @@ unique_ptr<parser::Node> Translator::translate(pm_node_t *node, bool preserveCon
17481756
blockExpr = desugarSymbolProc(symbol);
17491757
} else {
17501758
auto blockLoc = translateLoc(prismBlock->location);
1751-
auto blockBodyExpr = blockBody == nullptr ? MK::EmptyTree() : blockBody->takeDesugaredExpr();
1759+
auto blockBodyExpr = takeDesugaredExprOrEmptyTree(blockBody);
17521760
blockExpr = MK::Block(blockLoc, move(blockBodyExpr), move(blockParamsStore));
17531761
}
17541762

@@ -1829,7 +1837,7 @@ unique_ptr<parser::Node> Translator::translate(pm_node_t *node, bool preserveCon
18291837
}
18301838

18311839
// Start with the else clause as the final else
1832-
ExpressionPtr resultExpr = elseClause == nullptr ? MK::EmptyTree() : elseClause->takeDesugaredExpr();
1840+
ExpressionPtr resultExpr = takeDesugaredExprOrEmptyTree(elseClause);
18331841

18341842
// Build the if ladder backwards from the last "in" to the first
18351843
for (auto it = inNodes.rbegin(); it != inNodes.rend(); ++it) {
@@ -1841,7 +1849,7 @@ unique_ptr<parser::Node> Translator::translate(pm_node_t *node, bool preserveCon
18411849
auto matchExpr = MK::RaiseUnimplemented(patternLoc);
18421850

18431851
// The body is the statements from the "in" clause
1844-
auto thenExpr = inPattern->body != nullptr ? inPattern->body->takeDesugaredExpr() : MK::EmptyTree();
1852+
auto thenExpr = takeDesugaredExprOrEmptyTree(inPattern->body);
18451853

18461854
// Collect pattern variable assignments from the pattern
18471855
ast::InsSeq::STATS_store vars;
@@ -1910,7 +1918,7 @@ unique_ptr<parser::Node> Translator::translate(pm_node_t *node, bool preserveCon
19101918

19111919
ast::Send::ARGS_store args;
19121920
args.reserve(2 + whenNodes.size() + totalPatterns); // +2 is for the predicate and the patterns count
1913-
args.emplace_back(predicate == nullptr ? MK::EmptyTree() : predicate->takeDesugaredExpr());
1921+
args.emplace_back(takeDesugaredExprOrEmptyTree(predicate));
19141922
args.emplace_back(MK::Int(locZeroLen, totalPatterns));
19151923

19161924
for (auto &whenNodePtr : whenNodes) {
@@ -1919,20 +1927,18 @@ unique_ptr<parser::Node> Translator::translate(pm_node_t *node, bool preserveCon
19191927
// Each pattern node already has a desugared expression (populated by translateMulti +
19201928
// NodeWithExpr). Consume them now; the wrapper's placeholder expression is intentionally ignored.
19211929
for (auto &patternNode : whenNodeWrapped->patterns) {
1922-
args.emplace_back(patternNode == nullptr ? MK::EmptyTree() : patternNode->takeDesugaredExpr());
1930+
args.emplace_back(takeDesugaredExprOrEmptyTree(patternNode));
19231931
}
19241932
}
19251933

19261934
for (auto &whenNodePtr : whenNodes) {
19271935
auto whenNodeWrapped = parser::NodeWithExpr::cast_node<parser::When>(whenNodePtr.get());
19281936
ENFORCE(whenNodeWrapped != nullptr, "case without a when?");
19291937
// The body node also carries a real expression once translateStatements has run.
1930-
auto bodyExpr =
1931-
whenNodeWrapped->body == nullptr ? MK::EmptyTree() : whenNodeWrapped->body->takeDesugaredExpr();
1932-
args.emplace_back(move(bodyExpr));
1938+
args.emplace_back(takeDesugaredExprOrEmptyTree(whenNodeWrapped->body));
19331939
}
19341940

1935-
args.emplace_back(elseClause == nullptr ? MK::EmptyTree() : elseClause->takeDesugaredExpr());
1941+
args.emplace_back(takeDesugaredExprOrEmptyTree(elseClause));
19361942

19371943
// Desugar to `::Magic.caseWhen(predicate, num_patterns, patterns..., bodies..., else)`
19381944
auto expr = MK::Send(location, MK::Magic(locZeroLen), core::Names::caseWhen(), locZeroLen, args.size(),
@@ -1955,15 +1961,15 @@ unique_ptr<parser::Node> Translator::translate(pm_node_t *node, bool preserveCon
19551961

19561962
// The if/else ladder for the entire case statement, starting with the else clause as the final `else` when
19571963
// building backwards
1958-
ExpressionPtr resultExpr = elseClause == nullptr ? MK::EmptyTree() : elseClause->takeDesugaredExpr();
1964+
ExpressionPtr resultExpr = takeDesugaredExprOrEmptyTree(elseClause);
19591965

19601966
for (auto it = whenNodes.rbegin(); it != whenNodes.rend(); ++it) {
19611967
auto whenNodeWrapped = parser::NodeWithExpr::cast_node<parser::When>(it->get());
19621968
ENFORCE(whenNodeWrapped != nullptr, "case without a when?");
19631969

19641970
ExpressionPtr patternsResult; // the if/else ladder for this when clause's patterns
19651971
for (auto &patternNode : whenNodeWrapped->patterns) {
1966-
auto patternExpr = patternNode == nullptr ? MK::EmptyTree() : patternNode->takeDesugaredExpr();
1972+
auto patternExpr = takeDesugaredExprOrEmptyTree(patternNode);
19671973
auto patternLoc = patternExpr.loc();
19681974

19691975
ExpressionPtr testExpr;
@@ -1998,8 +2004,7 @@ unique_ptr<parser::Node> Translator::translate(pm_node_t *node, bool preserveCon
19982004
}
19992005
}
20002006

2001-
auto thenExpr =
2002-
whenNodeWrapped->body != nullptr ? whenNodeWrapped->body->takeDesugaredExpr() : MK::EmptyTree();
2007+
auto thenExpr = takeDesugaredExprOrEmptyTree(whenNodeWrapped->body);
20032008
resultExpr = MK::If(whenNodeWrapped->loc, move(patternsResult), move(thenExpr), move(resultExpr));
20042009
}
20052010

@@ -2232,7 +2237,7 @@ unique_ptr<parser::Node> Translator::translate(pm_node_t *node, bool preserveCon
22322237
}
22332238
}
22342239

2235-
auto methodBody = body == nullptr ? MK::EmptyTree() : body->takeDesugaredExpr();
2240+
auto methodBody = takeDesugaredExprOrEmptyTree(body);
22362241

22372242
auto methodExpr = MK::Method(location, declLoc, name, move(paramsStore), move(methodBody));
22382243

@@ -2413,7 +2418,7 @@ unique_ptr<parser::Node> Translator::translate(pm_node_t *node, bool preserveCon
24132418
canProvideNiceDesugar = parser::NodeWithExpr::isa_node<parser::LVarLhs>(variable.get());
24142419
}
24152420

2416-
auto bodyExpr = body ? body->takeDesugaredExpr() : MK::EmptyTree();
2421+
auto bodyExpr = takeDesugaredExprOrEmptyTree(body);
24172422
auto collectionExpr = collection->takeDesugaredExpr();
24182423
auto locZeroLen = location.copyWithZeroLength();
24192424
ast::MethodDef::PARAMS_store params;
@@ -2988,7 +2993,7 @@ unique_ptr<parser::Node> Translator::translate(pm_node_t *node, bool preserveCon
29882993
ExpressionPtr nextArgs;
29892994
if (arguments.size() == 1) {
29902995
auto &first = arguments[0];
2991-
nextArgs = first == nullptr ? MK::EmptyTree() : first->takeDesugaredExpr();
2996+
nextArgs = takeDesugaredExprOrEmptyTree(first);
29922997
} else {
29932998
auto args = nodeVecToStore<ast::Array::ENTRY_store>(arguments);
29942999
auto arrayLocation = parser.translateLocation(nextNode->arguments->base.location);
@@ -3148,8 +3153,8 @@ unique_ptr<parser::Node> Translator::translate(pm_node_t *node, bool preserveCon
31483153
auto recv = MK::Magic(location);
31493154
auto locZeroLen = core::LocOffsets{location.beginPos(), location.beginPos()};
31503155

3151-
auto fromExpr = left ? left->takeDesugaredExpr() : MK::EmptyTree();
3152-
auto toExpr = right ? right->takeDesugaredExpr() : MK::EmptyTree();
3156+
auto fromExpr = takeDesugaredExprOrEmptyTree(left);
3157+
auto toExpr = takeDesugaredExprOrEmptyTree(right);
31533158

31543159
auto excludeEndExpr = isExclusive ? MK::True(location) : MK::False(location);
31553160

@@ -3280,7 +3285,7 @@ unique_ptr<parser::Node> Translator::translate(pm_node_t *node, bool preserveCon
32803285
ExpressionPtr returnArgs;
32813286
if (returnValues.size() == 1) {
32823287
auto &first = returnValues[0];
3283-
returnArgs = first == nullptr ? MK::EmptyTree() : first->takeDesugaredExpr();
3288+
returnArgs = takeDesugaredExprOrEmptyTree(first);
32843289
} else {
32853290
auto args = nodeVecToStore<ast::Array::ENTRY_store>(std::move(returnValues));
32863291
auto arrayLocation = parser.translateLocation(returnNode->arguments->base.location);
@@ -3487,7 +3492,7 @@ unique_ptr<parser::Node> Translator::translate(pm_node_t *node, bool preserveCon
34873492
}
34883493
} else {
34893494
auto cond = predicate->takeDesugaredExpr();
3490-
auto body = statements ? statements->takeDesugaredExpr() : MK::EmptyTree();
3495+
auto body = takeDesugaredExprOrEmptyTree(statements);
34913496
if (beginModifier) {
34923497
auto breaker =
34933498
MK::If(location, std::move(cond), MK::Break(location, MK::EmptyTree()), MK::EmptyTree());
@@ -3529,7 +3534,7 @@ unique_ptr<parser::Node> Translator::translate(pm_node_t *node, bool preserveCon
35293534
}
35303535
} else {
35313536
auto cond = predicate->takeDesugaredExpr();
3532-
auto body = statements ? statements->takeDesugaredExpr() : MK::EmptyTree();
3537+
auto body = takeDesugaredExprOrEmptyTree(statements);
35333538
if (beginModifier) {
35343539
// TODO using bang (aka !) is not semantically correct because it can be overridden by the user.
35353540
auto negatedCond =
@@ -4926,11 +4931,7 @@ unique_ptr<parser::Node> Translator::translateRescue(pm_begin_node *parentBeginN
49264931
// Regular local variable
49274932
varExpr = var->takeDesugaredExpr();
49284933

4929-
if (rescueBody != nullptr) {
4930-
rescueBodyExpr = rescueBody->takeDesugaredExpr();
4931-
} else {
4932-
rescueBodyExpr = ast::MK::EmptyTree();
4933-
}
4934+
rescueBodyExpr = takeDesugaredExprOrEmptyTree(rescueBody);
49344935
} else if (isReference) {
49354936
// Non-local reference (lvalue exception variables like @ex, @@ex, $ex)
49364937
// Create a temp variable and wrap the body
@@ -4945,7 +4946,7 @@ unique_ptr<parser::Node> Translator::translateRescue(pm_begin_node *parentBeginN
49454946
ast::InsSeq::STATS_store stats;
49464947
stats.emplace_back(move(assignExpr));
49474948

4948-
auto bodyExpr = rescueBody != nullptr ? rescueBody->takeDesugaredExpr() : ast::MK::EmptyTree();
4949+
auto bodyExpr = takeDesugaredExprOrEmptyTree(rescueBody);
49494950
rescueBodyExpr = ast::MK::InsSeq(varLoc, move(stats), move(bodyExpr));
49504951
} else {
49514952
// For bare rescue clauses with no variable, create a <rescueTemp> variable
@@ -4957,7 +4958,7 @@ unique_ptr<parser::Node> Translator::translateRescue(pm_begin_node *parentBeginN
49574958
: rescueKeywordLoc;
49584959
varExpr = ast::MK::Local(syntheticVarLoc, rescueTemp);
49594960

4960-
rescueBodyExpr = rescueBody != nullptr ? rescueBody->takeDesugaredExpr() : ast::MK::EmptyTree();
4961+
rescueBodyExpr = takeDesugaredExprOrEmptyTree(rescueBody);
49614962
}
49624963

49634964
auto rescueCaseExpr = ast::make_expression<ast::RescueCase>(resbodyLoc, move(astExceptions), move(varExpr),
@@ -5028,12 +5029,7 @@ unique_ptr<parser::Node> Translator::translateRescue(pm_begin_node *parentBeginN
50285029
}
50295030

50305031
// Build the ast::Rescue expression
5031-
ast::ExpressionPtr bodyExpr;
5032-
if (bodyNode != nullptr) {
5033-
bodyExpr = bodyNode->takeDesugaredExpr();
5034-
} else {
5035-
bodyExpr = ast::MK::EmptyTree();
5036-
}
5032+
auto bodyExpr = takeDesugaredExprOrEmptyTree(bodyNode);
50375033

50385034
// Extract RescueCase expressions from each Resbody node
50395035
ast::Rescue::RESCUE_CASE_store rescueCases;
@@ -5047,8 +5043,7 @@ unique_ptr<parser::Node> Translator::translateRescue(pm_begin_node *parentBeginN
50475043
}
50485044

50495045
// Extract the else expression
5050-
ast::ExpressionPtr elseExpr;
5051-
elseExpr = (elseNode != nullptr) ? elseNode->takeDesugaredExpr() : ast::MK::EmptyTree();
5046+
auto elseExpr = takeDesugaredExprOrEmptyTree(elseNode);
50525047

50535048
// Build the ast::Rescue expression (ensure is EmptyTree since this is translateRescue, not translateEnsure)
50545049
auto rescueExpr = ast::make_expression<ast::Rescue>(rescueLoc, move(bodyExpr), move(rescueCases), move(elseExpr),
@@ -5127,7 +5122,7 @@ NodeVec Translator::translateEnsure(pm_begin_node *beginNode) {
51275122
auto rescue = ast::cast_tree<ast::Rescue>(bodyExpr);
51285123
ENFORCE(rescue != nullptr, "translatedRescue should be a Rescue node");
51295124

5130-
rescue->ensure = ensureBody != nullptr ? ensureBody->takeDesugaredExpr() : ast::MK::EmptyTree();
5125+
rescue->ensure = takeDesugaredExprOrEmptyTree(ensureBody);
51315126

51325127
translatedEnsure =
51335128
make_node_with_expr<parser::Ensure>(move(bodyExpr), loc, move(translatedRescue), move(ensureBody));
@@ -5158,11 +5153,8 @@ NodeVec Translator::translateEnsure(pm_begin_node *beginNode) {
51585153
} else {
51595154
// Build ast::Rescue expression with ensure field set
51605155
// When there's no rescue clause, create a new Rescue with empty rescue cases
5161-
ast::ExpressionPtr bodyExpr;
5162-
bodyExpr = (bodyNode != nullptr) ? bodyNode->takeDesugaredExpr() : ast::MK::EmptyTree();
5163-
5164-
ast::ExpressionPtr ensureExpr =
5165-
(ensureBody != nullptr) ? ensureBody->takeDesugaredExpr() : ast::MK::EmptyTree();
5156+
auto bodyExpr = takeDesugaredExprOrEmptyTree(bodyNode);
5157+
auto ensureExpr = takeDesugaredExprOrEmptyTree(ensureBody);
51665158

51675159
// Create ast::Rescue with empty rescue cases
51685160
ast::Rescue::RESCUE_CASE_store emptyCases;
@@ -5250,8 +5242,8 @@ unique_ptr<parser::Node> Translator::translateIfNode(core::LocOffsets location,
52505242
}
52515243

52525244
auto condExpr = predicate->takeDesugaredExpr();
5253-
auto thenExpr = ifTrue ? ifTrue->takeDesugaredExpr() : MK::EmptyTree();
5254-
auto elseExpr = ifFalse ? ifFalse->takeDesugaredExpr() : MK::EmptyTree();
5245+
auto thenExpr = takeDesugaredExprOrEmptyTree(ifTrue);
5246+
auto elseExpr = takeDesugaredExprOrEmptyTree(ifFalse);
52555247
auto ifNode = MK::If(location, move(condExpr), move(thenExpr), move(elseExpr));
52565248
return make_node_with_expr<parser::If>(move(ifNode), location, move(predicate), move(ifTrue), move(ifFalse));
52575249
}

0 commit comments

Comments
 (0)