Skip to content

Commit 7dde76e

Browse files
committed
Desugar target call node with safe navigation
1 parent 89e9171 commit 7dde76e

File tree

4 files changed

+84
-850
lines changed

4 files changed

+84
-850
lines changed

parser/prism/Translator.cc

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -575,34 +575,49 @@ ast::ExpressionPtr Translator::desugarMlhs(core::LocOffsets loc, PrismNode *lhs,
575575
auto callTargetNode = down_cast<pm_call_target_node>(c);
576576
auto receiverNode = callTargetNode->receiver;
577577

578+
auto methodName = translateConstantName(callTargetNode->name);
579+
auto methodNameLoc = translateLoc(callTargetNode->message_loc);
580+
578581
if (PM_NODE_FLAG_P(callTargetNode, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) {
579-
categoryCounterInc("Prism fallback", "PM_CALL_TARGET_NODE with PM_CALL_NODE_FLAGS_SAFE_NAVIGATION");
580-
throw PrismFallback{};
581-
}
582+
auto body = [&val](ast::ExpressionPtr receiverTempLocal, core::LocOffsets parentLoc,
583+
core::NameRef methodName, core::LocOffsets methodNameLoc) {
584+
ast::Send::ARGS_store arguments;
585+
arguments.emplace_back(move(val));
582586

583-
ast::ExpressionPtr receiver;
584-
if (receiverNode == nullptr) { // Convert `foo()` to `self.foo()`
585-
receiver = MK::Self(zcloc);
586-
} else {
587-
receiver = desugar(receiverNode);
588-
}
587+
return MK::Send(parentLoc, move(receiverTempLocal), methodName, methodNameLoc, 1, move(arguments));
588+
};
589589

590-
// Unsupported nodes are desugared to an empty tree.
591-
// Treat them as if they were `self` to match `Desugar.cc`.
592-
// TODO: Clean up after direct desugaring is complete.
593-
// https://github.com/Shopify/sorbet/issues/671
594-
ast::Send::Flags flags;
595-
if (ast::isa_tree<ast::EmptyTree>(receiver)) {
596-
receiver = MK::Self(zcloc);
597-
flags.isPrivateOk = true;
590+
auto recvLoc = translateLoc(receiverNode->location);
591+
auto csendRecvExpr = desugar(receiverNode);
592+
auto expr = desugarConditionalSend(cloc, move(csendRecvExpr), recvLoc,
593+
callTargetNode->name, callTargetNode->message_loc, body);
594+
stats.emplace_back(move(expr));
598595
} else {
599-
flags.isPrivateOk = PM_NODE_FLAG_P(callTargetNode, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY);
600-
}
596+
ast::ExpressionPtr receiver;
597+
if (receiverNode == nullptr) { // Convert `foo()` to `self.foo()`
598+
receiver = MK::Self(zcloc);
599+
} else {
600+
receiver = desugar(receiverNode);
601+
}
601602

602-
auto methodName = translateConstantName(callTargetNode->name);
603-
auto methodNameLoc = translateLoc(callTargetNode->message_loc);
604-
ast::Send::ARGS_store emptyArgs;
605-
stats.emplace_back(MK::Send(cloc, move(receiver), methodName, methodNameLoc, 0, move(emptyArgs), flags));
603+
// Unsupported nodes are desugared to an empty tree.
604+
// Treat them as if they were `self` to match `Desugar.cc`.
605+
// TODO: Clean up after direct desugaring is complete.
606+
// https://github.com/Shopify/sorbet/issues/671
607+
ast::Send::Flags flags;
608+
if (ast::isa_tree<ast::EmptyTree>(receiver)) {
609+
receiver = MK::Self(zcloc);
610+
flags.isPrivateOk = true;
611+
} else {
612+
flags.isPrivateOk = PM_NODE_FLAG_P(callTargetNode, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY);
613+
}
614+
615+
ast::Send::ARGS_store arguments;
616+
arguments.emplace_back(move(val));
617+
618+
stats.emplace_back(
619+
MK::Send(cloc, move(receiver), methodName, methodNameLoc, 1, move(arguments), flags));
620+
}
606621
} else {
607622
ast::ExpressionPtr lh = desugar(c);
608623
if (auto restParam = ast::cast_tree<ast::RestParam>(lh)) {
Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
11
# typed: false
22

3-
# Regular assignment
4-
self.m = 1
3+
# # Regular assignment
4+
# self.m = 1
55

6-
# Compound assignment operators
7-
self.m &= 2
8-
self.m |= 3
9-
self.m ^= 4
10-
self.m >>= 5
11-
self.m <<= 6
12-
self.m += 7
13-
self.m -= 8
14-
self.m %= 9
15-
self.m /= 10
16-
self.m *= 11
17-
self.m **= 12
6+
# # Compound assignment operators
7+
# self.m &= 2
8+
# self.m |= 3
9+
# self.m ^= 4
10+
# self.m >>= 5
11+
# self.m <<= 6
12+
# self.m += 7
13+
# self.m -= 8
14+
# self.m %= 9
15+
# self.m /= 10
16+
# self.m *= 11
17+
# self.m **= 12
1818

19-
# Special cases
20-
self.m &&= 13
21-
self.m ||= 14
19+
# # Special cases
20+
# self.m &&= 13
21+
# self.m ||= 14
2222

23-
# Multi-target assignment
24-
self.target1, self.target2 = 15, 16
25-
# self&.target1, self&.target2 = 17, 18 # Not valid Ruby, but the parser needs to support it for the diagnostics to work
23+
# # Multi-target assignment
24+
# self.target1, self.target2 = 15, 16
25+
self&.target1, self&.target2 = 17, 18 # Not valid Ruby, but the parser needs to support it for the diagnostics to work
2626

27-
FOO.target1, FOO.target2 = 19, 20 # `isPrivateOk` should be false
27+
# FOO.target1, FOO.target2 = 19, 20 # `isPrivateOk` should be false

0 commit comments

Comments
 (0)