Support ref tags on arguments to ref params (#6312)

The issue of whether/how to include `ref` tags in the textual and
in-memory SemIR (see discussion
[here](https://discord.com/channels/655572317891461132/655578254970716160/1431316355742961805))
is left as future work.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
This commit is contained in:
Geoff Romer
2025-11-11 20:30:19 +00:00
committed by GitHub
co-authored by Richard Smith
parent b36f85c2a5
commit 43ffd721a4
39 changed files with 798 additions and 337 deletions
+54 -5
View File
@@ -43,6 +43,34 @@ auto HandleOnlyParenExprFinish(Context& context) -> void {
FinishParenExpr(context, state);
}
static auto HandleRefTagFinish(Context& context, StateKind state_kind) -> void {
auto state = context.PopState();
if (state_kind == StateKind::RefTagFinishAsAfterOpenParen &&
!context.PositionIs(Lex::TokenKind::Comma)) {
CARBON_DIAGNOSTIC(UnexpectedRef, Error,
"found `ref` in unexpected position");
context.emitter().Emit(state.token, UnexpectedRef);
}
context.AddNode(NodeKind::RefTag, state.token, state.has_error);
}
auto HandleRefTagFinishAsRegular(Context& context) -> void {
HandleRefTagFinish(context, StateKind::RefTagFinishAsRegular);
}
auto HandleRefTagFinishAsAfterOpenParen(Context& context) -> void {
HandleRefTagFinish(context, StateKind::RefTagFinishAsAfterOpenParen);
}
static auto StartTupleLiteralElement(Context& context) -> void {
context.PushState(StateKind::TupleLiteralElementFinish);
if (context.PositionIs(Lex::TokenKind::Ref)) {
context.PushState(StateKind::RefTagFinishAsRegular);
context.ConsumeChecked(Lex::TokenKind::Ref);
}
context.PushState(StateKind::Expr);
}
auto HandleParenExpr(Context& context) -> void {
auto state = context.PopState();
@@ -56,6 +84,10 @@ auto HandleParenExpr(Context& context) -> void {
} else {
context.PushState(state, StateKind::ParenExprFinish);
context.PushState(StateKind::ExprAfterOpenParenFinish);
if (context.PositionIs(Lex::TokenKind::Ref)) {
context.PushState(StateKind::RefTagFinishAsAfterOpenParen);
context.ConsumeChecked(Lex::TokenKind::Ref);
}
context.PushState(StateKind::Expr);
}
}
@@ -78,25 +110,26 @@ auto HandleExprAfterOpenParenFinish(Context& context) -> void {
// If the comma is not immediately followed by a close paren, push handlers
// for the next tuple element.
if (list_token_kind != Context::ListTokenKind::CommaClose) {
context.PushState(state, StateKind::TupleLiteralElementFinish);
context.PushState(StateKind::Expr);
StartTupleLiteralElement(context);
}
}
auto HandleTupleLiteralElementFinish(Context& context) -> void {
auto state = context.PopState();
if (state.has_error) {
context.ReturnErrorOnState();
}
if (context.ConsumeListToken(NodeKind::TupleLiteralComma,
Lex::TokenKind::CloseParen, state.has_error) ==
Context::ListTokenKind::Comma) {
context.PushState(state);
context.PushState(StateKind::Expr);
StartTupleLiteralElement(context);
}
}
auto HandleParenExprFinish(Context& context) -> void {
auto state = context.PopState();
context.ReplacePlaceholderNode(state.subtree_start, NodeKind::ParenExprStart,
state.token);
FinishParenExpr(context, state);
@@ -110,4 +143,20 @@ auto HandleTupleLiteralFinish(Context& context) -> void {
context.AddNode(NodeKind::TupleLiteral, context.Consume(), state.has_error);
}
auto HandleCallExpr(Context& context) -> void {
auto state = context.PopState();
context.PushState(state, StateKind::CallExprFinish);
context.AddNode(NodeKind::CallExprStart, context.Consume(), state.has_error);
if (!context.PositionIs(Lex::TokenKind::CloseParen)) {
StartTupleLiteralElement(context);
}
}
auto HandleCallExprFinish(Context& context) -> void {
auto state = context.PopState();
context.AddNode(NodeKind::CallExpr, context.Consume(), state.has_error);
}
} // namespace Carbon::Parse