From c4864aa2ff4580fe0fb16019e9d706ac2c9b3641 Mon Sep 17 00:00:00 2001 From: Jon Ross-Perkins Date: Fri, 8 Dec 2023 17:03:32 -0800 Subject: [PATCH] Split out and/or operator handling from infix. (#3480) This is also doing the parse node split, allowing lower reliance in formatter on the tokenized buffer (something that I may be touching more due to import handling). --- toolchain/check/handle_operator.cpp | 103 ++++++++++-------- toolchain/check/node_stack.h | 5 +- toolchain/parse/handle_expr.cpp | 49 ++++++--- toolchain/parse/node_kind.def | 14 +-- toolchain/parse/state.def | 21 +++- .../parse/testdata/if_expr/precedence.carbon | 12 +- .../testdata/operators/associative.carbon | 8 +- .../operators/fail_precedence_and_or.carbon | 8 +- .../operators/fail_precedence_or_and.carbon | 8 +- .../testdata/operators/precedence_as.carbon | 8 +- .../testdata/operators/precedence_not.carbon | 8 +- toolchain/sem_ir/formatter.cpp | 12 +- 12 files changed, 151 insertions(+), 105 deletions(-) diff --git a/toolchain/check/handle_operator.cpp b/toolchain/check/handle_operator.cpp index 46d9e045e9df..cd0b4f2c9265 100644 --- a/toolchain/check/handle_operator.cpp +++ b/toolchain/check/handle_operator.cpp @@ -14,28 +14,6 @@ auto HandleInfixOperator(Context& context, Parse::NodeId parse_node) -> bool { // Figure out the operator for the token. auto token = context.parse_tree().node_token(parse_node); switch (auto token_kind = context.tokens().GetKind(token)) { - case Lex::TokenKind::And: - case Lex::TokenKind::Or: { - // The first operand is wrapped in a ShortCircuitOperand, which we - // already handled by creating a RHS block and a resumption block, which - // are the current block and its enclosing block. - rhs_id = ConvertToBoolValue(context, parse_node, rhs_id); - - // When the second operand is evaluated, the result of `and` and `or` is - // its value. - auto resume_block_id = context.inst_block_stack().PeekOrAdd(/*depth=*/1); - context.AddInst( - SemIR::BranchWithArg{parse_node, resume_block_id, rhs_id}); - context.inst_block_stack().Pop(); - context.AddCurrentCodeBlockToFunction(); - - // Collect the result from either the first or second operand. - context.AddInstAndPush( - parse_node, - SemIR::BlockArg{parse_node, context.insts().Get(rhs_id).type_id(), - resume_block_id}); - return true; - } case Lex::TokenKind::As: { auto rhs_type_id = ExprAsType(context, rhs_node, rhs_id); context.node_stack().Push( @@ -181,7 +159,9 @@ auto HandlePrefixOperator(Context& context, Parse::NodeId parse_node) -> bool { } } -auto HandleShortCircuitOperand(Context& context, Parse::NodeId parse_node) +// Adds the branch for a short circuit operand. +static auto HandleShortCircuitOperand(Context& context, + Parse::NodeId parse_node, bool is_or) -> bool { // Convert the condition to `bool`. auto cond_value_id = context.node_stack().PopExpr(); @@ -189,26 +169,13 @@ auto HandleShortCircuitOperand(Context& context, Parse::NodeId parse_node) auto bool_type_id = context.insts().Get(cond_value_id).type_id(); // Compute the branch value: the condition for `and`, inverted for `or`. - auto token = context.parse_tree().node_token(parse_node); - SemIR::InstId branch_value_id = SemIR::InstId::Invalid; - auto short_circuit_result_id = SemIR::InstId::Invalid; - switch (auto token_kind = context.tokens().GetKind(token)) { - case Lex::TokenKind::And: - branch_value_id = cond_value_id; - short_circuit_result_id = context.AddInst(SemIR::BoolLiteral{ - parse_node, bool_type_id, SemIR::BoolValue::False}); - break; - - case Lex::TokenKind::Or: - branch_value_id = context.AddInst( - SemIR::UnaryOperatorNot{parse_node, bool_type_id, cond_value_id}); - short_circuit_result_id = context.AddInst( - SemIR::BoolLiteral{parse_node, bool_type_id, SemIR::BoolValue::True}); - break; - - default: - CARBON_FATAL() << "Unexpected short-circuiting operator " << token_kind; - } + SemIR::InstId branch_value_id = + is_or ? context.AddInst(SemIR::UnaryOperatorNot{parse_node, bool_type_id, + cond_value_id}) + : cond_value_id; + auto short_circuit_result_id = context.AddInst(SemIR::BoolLiteral{ + parse_node, bool_type_id, + is_or ? SemIR::BoolValue::True : SemIR::BoolValue::False}); // Create a block for the right-hand side and for the continuation. auto rhs_block_id = @@ -223,9 +190,55 @@ auto HandleShortCircuitOperand(Context& context, Parse::NodeId parse_node) context.inst_block_stack().Push(rhs_block_id); context.AddCurrentCodeBlockToFunction(); - // Put the condition back on the stack for HandleInfixOperator. - context.node_stack().Push(parse_node, cond_value_id); + // HandleShortCircuitOperator will follow, and doesn't need the operand on the + // node stack. return true; } +auto HandleShortCircuitOperandAnd(Context& context, Parse::NodeId parse_node) + -> bool { + return HandleShortCircuitOperand(context, parse_node, /*is_or=*/false); +} + +auto HandleShortCircuitOperandOr(Context& context, Parse::NodeId parse_node) + -> bool { + return HandleShortCircuitOperand(context, parse_node, /*is_or=*/true); +} + +// Short circuit operator handling is uniform because the branching logic +// occurs during operand handling. +static auto HandleShortCircuitOperator(Context& context, + Parse::NodeId parse_node) -> bool { + auto [rhs_node, rhs_id] = context.node_stack().PopExprWithParseNode(); + + // The first operand is wrapped in a ShortCircuitOperand, which we + // already handled by creating a RHS block and a resumption block, which + // are the current block and its enclosing block. + rhs_id = ConvertToBoolValue(context, parse_node, rhs_id); + + // When the second operand is evaluated, the result of `and` and `or` is + // its value. + auto resume_block_id = context.inst_block_stack().PeekOrAdd(/*depth=*/1); + context.AddInst(SemIR::BranchWithArg{parse_node, resume_block_id, rhs_id}); + context.inst_block_stack().Pop(); + context.AddCurrentCodeBlockToFunction(); + + // Collect the result from either the first or second operand. + context.AddInstAndPush( + parse_node, + SemIR::BlockArg{parse_node, context.insts().Get(rhs_id).type_id(), + resume_block_id}); + return true; +} + +auto HandleShortCircuitOperatorAnd(Context& context, Parse::NodeId parse_node) + -> bool { + return HandleShortCircuitOperator(context, parse_node); +} + +auto HandleShortCircuitOperatorOr(Context& context, Parse::NodeId parse_node) + -> bool { + return HandleShortCircuitOperator(context, parse_node); +} + } // namespace Carbon::Check diff --git a/toolchain/check/node_stack.h b/toolchain/check/node_stack.h index 387ae1bb6e3d..7be0faeb801e 100644 --- a/toolchain/check/node_stack.h +++ b/toolchain/check/node_stack.h @@ -339,7 +339,10 @@ class NodeStack { case Parse::NodeKind::ReturnType: case Parse::NodeKind::SelfTypeNameExpr: case Parse::NodeKind::SelfValueNameExpr: - case Parse::NodeKind::ShortCircuitOperand: + case Parse::NodeKind::ShortCircuitOperandAnd: + case Parse::NodeKind::ShortCircuitOperandOr: + case Parse::NodeKind::ShortCircuitOperatorAnd: + case Parse::NodeKind::ShortCircuitOperatorOr: case Parse::NodeKind::StructFieldValue: case Parse::NodeKind::StructLiteral: case Parse::NodeKind::StructFieldType: diff --git a/toolchain/parse/handle_expr.cpp b/toolchain/parse/handle_expr.cpp index 4c99b4b09469..8ba86cc127fb 100644 --- a/toolchain/parse/handle_expr.cpp +++ b/toolchain/parse/handle_expr.cpp @@ -264,15 +264,26 @@ auto HandleExprLoop(Context& context) -> void { state.lhs_precedence = operator_precedence; if (is_binary) { - if (operator_kind == Lex::TokenKind::And || - operator_kind == Lex::TokenKind::Or) { + switch (operator_kind) { // For `and` and `or`, wrap the first operand in a virtual parse tree - // node so that semantics can insert control flow here. - context.AddNode(NodeKind::ShortCircuitOperand, state.token, - state.subtree_start, state.has_error); + // node so that checking can insert control flow here. + case Lex::TokenKind::And: + context.AddNode(NodeKind::ShortCircuitOperandAnd, state.token, + state.subtree_start, state.has_error); + state.state = State::ExprLoopForShortCircuitOperatorAsAnd; + break; + case Lex::TokenKind::Or: + context.AddNode(NodeKind::ShortCircuitOperandOr, state.token, + state.subtree_start, state.has_error); + state.state = State::ExprLoopForShortCircuitOperatorAsOr; + break; + + default: + state.state = State::ExprLoopForBinary; + break; } - context.PushState(state, State::ExprLoopForBinary); + context.PushState(state); context.PushStateForExpr(operator_precedence); } else { context.AddNode(NodeKind::PostfixOperator, state.token, state.subtree_start, @@ -282,22 +293,30 @@ auto HandleExprLoop(Context& context) -> void { } } -auto HandleExprLoopForBinary(Context& context) -> void { +// Adds the operator node and returns the the main expression loop. +static auto HandleExprLoopForOperator(Context& context, NodeKind node_kind) + -> void { auto state = context.PopState(); - context.AddNode(NodeKind::InfixOperator, state.token, state.subtree_start, - state.has_error); + context.AddNode(node_kind, state.token, state.subtree_start, state.has_error); state.has_error = false; context.PushState(state, State::ExprLoop); } -auto HandleExprLoopForPrefix(Context& context) -> void { - auto state = context.PopState(); +auto HandleExprLoopForBinary(Context& context) -> void { + HandleExprLoopForOperator(context, NodeKind::InfixOperator); +} - context.AddNode(NodeKind::PrefixOperator, state.token, state.subtree_start, - state.has_error); - state.has_error = false; - context.PushState(state, State::ExprLoop); +auto HandleExprLoopForPrefix(Context& context) -> void { + HandleExprLoopForOperator(context, NodeKind::PrefixOperator); +} + +auto HandleExprLoopForShortCircuitOperatorAsAnd(Context& context) -> void { + HandleExprLoopForOperator(context, NodeKind::ShortCircuitOperatorAnd); +} + +auto HandleExprLoopForShortCircuitOperatorAsOr(Context& context) -> void { + HandleExprLoopForOperator(context, NodeKind::ShortCircuitOperatorOr); } auto HandleIfExprFinishCondition(Context& context) -> void { diff --git a/toolchain/parse/node_kind.def b/toolchain/parse/node_kind.def index 66c42ea52f86..c578dfb07a94 100644 --- a/toolchain/parse/node_kind.def +++ b/toolchain/parse/node_kind.def @@ -530,7 +530,6 @@ CARBON_PARSE_NODE_KIND_CHILD_COUNT(PrefixOperator, 1, CARBON_PARSE_NODE_KIND_CHILD_COUNT(InfixOperator, 2, CARBON_TOKEN(Amp) CARBON_TOKEN(AmpEqual) - CARBON_TOKEN(And) CARBON_TOKEN(As) CARBON_TOKEN(Caret) CARBON_TOKEN(CaretEqual) @@ -547,7 +546,6 @@ CARBON_PARSE_NODE_KIND_CHILD_COUNT(InfixOperator, 2, CARBON_TOKEN(LessLessEqual) CARBON_TOKEN(Minus) CARBON_TOKEN(MinusEqual) - CARBON_TOKEN(Or) CARBON_TOKEN(Percent) CARBON_TOKEN(PercentEqual) CARBON_TOKEN(Pipe) @@ -561,13 +559,15 @@ CARBON_PARSE_NODE_KIND_CHILD_COUNT(InfixOperator, 2, // clang-format on -// The first operand of a short-circuiting infix operator: +// A short-circuiting infix operator: // _external_: expression -// ShortCircuitOperand +// ShortCircuitOperand(And|Or) // _external_: expression -// _external_: InfixOperator -CARBON_PARSE_NODE_KIND_CHILD_COUNT(ShortCircuitOperand, 1, - CARBON_TOKEN(And) CARBON_TOKEN(Or)) +// ShortCircuitOperand(And|Or) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(ShortCircuitOperandAnd, 1, CARBON_TOKEN(And)) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(ShortCircuitOperandOr, 1, CARBON_TOKEN(Or)) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(ShortCircuitOperatorAnd, 2, CARBON_TOKEN(And)) +CARBON_PARSE_NODE_KIND_CHILD_COUNT(ShortCircuitOperatorOr, 2, CARBON_TOKEN(Or)) // A postfix operator: // _external_: expression diff --git a/toolchain/parse/state.def b/toolchain/parse/state.def index 3339c84b5c35..59abca5f0ffe 100644 --- a/toolchain/parse/state.def +++ b/toolchain/parse/state.def @@ -471,8 +471,8 @@ CARBON_PARSE_STATE(ExprInPostfixLoop) // Handles processing of an expression. // -// expr ... -// ^~~~~~~~~~~~~~~~~ +// expr ... +// ^~~~~~~~~~~~~~~~ // 1. Expr // 2. ExprLoopForBinary // @@ -480,6 +480,11 @@ CARBON_PARSE_STATE(ExprInPostfixLoop) // ^~~~~~~~~~~~~~~~~~ // 1. ExprLoop // +// expr ... +// ^~~~~~~~~~~~~~~~~~~~~~~~ +// 1. Expr +// 2. ExprLoopForShortCircuitOperator +// // expr ... // ^ // (state done) @@ -488,8 +493,8 @@ CARBON_PARSE_STATE(ExprLoop) // Completes an ExprLoop pass by adding an infix operator, then goes back // to ExprLoop. // -// expr expr ... -// ^ +// expr expr ... +// ^ // 1. ExprLoop CARBON_PARSE_STATE(ExprLoopForBinary) @@ -501,6 +506,14 @@ CARBON_PARSE_STATE(ExprLoopForBinary) // 1. ExprLoop CARBON_PARSE_STATE(ExprLoopForPrefix) +// Completes an ExprLoop pass by adding a short circuit operator, then goes back +// to ExprLoop. +// +// expr expr ... +// ^ +// 1. ExprLoop +CARBON_PARSE_STATE_VARIANTS2(ExprLoopForShortCircuitOperator, And, Or) + // Completes the condition of an `if` expression and handles the `then` token. // // if expr then ... diff --git a/toolchain/parse/testdata/if_expr/precedence.carbon b/toolchain/parse/testdata/if_expr/precedence.carbon index 791db05d199b..46acdca3fd21 100644 --- a/toolchain/parse/testdata/if_expr/precedence.carbon +++ b/toolchain/parse/testdata/if_expr/precedence.carbon @@ -23,19 +23,19 @@ fn F(b: bool) -> bool { // CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 10}, // CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'}, // CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'b'}, -// CHECK:STDOUT: {kind: 'ShortCircuitOperand', text: 'and', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'ShortCircuitOperandAnd', text: 'and', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'b'}, -// CHECK:STDOUT: {kind: 'InfixOperator', text: 'and', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'ShortCircuitOperatorAnd', text: 'and', subtree_size: 4}, // CHECK:STDOUT: {kind: 'IfExprIf', text: 'if', subtree_size: 5}, // CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'b'}, -// CHECK:STDOUT: {kind: 'ShortCircuitOperand', text: 'and', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'ShortCircuitOperandAnd', text: 'and', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'b'}, -// CHECK:STDOUT: {kind: 'InfixOperator', text: 'and', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'ShortCircuitOperatorAnd', text: 'and', subtree_size: 4}, // CHECK:STDOUT: {kind: 'IfExprThen', text: 'then', subtree_size: 5}, // CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'b'}, -// CHECK:STDOUT: {kind: 'ShortCircuitOperand', text: 'or', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'ShortCircuitOperandOr', text: 'or', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'b'}, -// CHECK:STDOUT: {kind: 'InfixOperator', text: 'or', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'ShortCircuitOperatorOr', text: 'or', subtree_size: 4}, // CHECK:STDOUT: {kind: 'IfExprElse', text: 'else', subtree_size: 15}, // CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 17}, // CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 28}, diff --git a/toolchain/parse/testdata/operators/associative.carbon b/toolchain/parse/testdata/operators/associative.carbon index ff20053f814b..dc4c22c72a07 100644 --- a/toolchain/parse/testdata/operators/associative.carbon +++ b/toolchain/parse/testdata/operators/associative.carbon @@ -17,12 +17,12 @@ fn F() { // CHECK:STDOUT: {kind: 'TuplePattern', text: ')', subtree_size: 2}, // CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5}, // CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'a'}, -// CHECK:STDOUT: {kind: 'ShortCircuitOperand', text: 'and', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'ShortCircuitOperandAnd', text: 'and', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'b'}, -// CHECK:STDOUT: {kind: 'InfixOperator', text: 'and', subtree_size: 4}, -// CHECK:STDOUT: {kind: 'ShortCircuitOperand', text: 'and', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'ShortCircuitOperatorAnd', text: 'and', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'ShortCircuitOperandAnd', text: 'and', subtree_size: 5}, // CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'c'}, -// CHECK:STDOUT: {kind: 'InfixOperator', text: 'and', subtree_size: 7}, +// CHECK:STDOUT: {kind: 'ShortCircuitOperatorAnd', text: 'and', subtree_size: 7}, // CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 8}, // CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 14}, // CHECK:STDOUT: {kind: 'FileEnd', text: ''}, diff --git a/toolchain/parse/testdata/operators/fail_precedence_and_or.carbon b/toolchain/parse/testdata/operators/fail_precedence_and_or.carbon index 75bb638d8f6e..b3d583679c51 100644 --- a/toolchain/parse/testdata/operators/fail_precedence_and_or.carbon +++ b/toolchain/parse/testdata/operators/fail_precedence_and_or.carbon @@ -20,12 +20,12 @@ fn F() { // CHECK:STDOUT: {kind: 'TuplePattern', text: ')', subtree_size: 2}, // CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5}, // CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'a'}, -// CHECK:STDOUT: {kind: 'ShortCircuitOperand', text: 'and', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'ShortCircuitOperandAnd', text: 'and', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'b'}, -// CHECK:STDOUT: {kind: 'InfixOperator', text: 'and', subtree_size: 4}, -// CHECK:STDOUT: {kind: 'ShortCircuitOperand', text: 'or', has_error: yes, subtree_size: 5}, +// CHECK:STDOUT: {kind: 'ShortCircuitOperatorAnd', text: 'and', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'ShortCircuitOperandOr', text: 'or', has_error: yes, subtree_size: 5}, // CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'c'}, -// CHECK:STDOUT: {kind: 'InfixOperator', text: 'or', has_error: yes, subtree_size: 7}, +// CHECK:STDOUT: {kind: 'ShortCircuitOperatorOr', text: 'or', has_error: yes, subtree_size: 7}, // CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 8}, // CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 14}, // CHECK:STDOUT: {kind: 'FileEnd', text: ''}, diff --git a/toolchain/parse/testdata/operators/fail_precedence_or_and.carbon b/toolchain/parse/testdata/operators/fail_precedence_or_and.carbon index 01fae506da3c..bd0fd935adba 100644 --- a/toolchain/parse/testdata/operators/fail_precedence_or_and.carbon +++ b/toolchain/parse/testdata/operators/fail_precedence_or_and.carbon @@ -20,12 +20,12 @@ fn F() { // CHECK:STDOUT: {kind: 'TuplePattern', text: ')', subtree_size: 2}, // CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5}, // CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'a'}, -// CHECK:STDOUT: {kind: 'ShortCircuitOperand', text: 'or', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'ShortCircuitOperandOr', text: 'or', subtree_size: 2}, // CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'b'}, -// CHECK:STDOUT: {kind: 'InfixOperator', text: 'or', subtree_size: 4}, -// CHECK:STDOUT: {kind: 'ShortCircuitOperand', text: 'and', has_error: yes, subtree_size: 5}, +// CHECK:STDOUT: {kind: 'ShortCircuitOperatorOr', text: 'or', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'ShortCircuitOperandAnd', text: 'and', has_error: yes, subtree_size: 5}, // CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'c'}, -// CHECK:STDOUT: {kind: 'InfixOperator', text: 'and', has_error: yes, subtree_size: 7}, +// CHECK:STDOUT: {kind: 'ShortCircuitOperatorAnd', text: 'and', has_error: yes, subtree_size: 7}, // CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 8}, // CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 14}, // CHECK:STDOUT: {kind: 'FileEnd', text: ''}, diff --git a/toolchain/parse/testdata/operators/precedence_as.carbon b/toolchain/parse/testdata/operators/precedence_as.carbon index a2166a7da34c..52779be973e0 100644 --- a/toolchain/parse/testdata/operators/precedence_as.carbon +++ b/toolchain/parse/testdata/operators/precedence_as.carbon @@ -45,16 +45,16 @@ fn F(n: i32) { // CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, // CHECK:STDOUT: {kind: 'InfixOperator', text: 'as', subtree_size: 3}, // CHECK:STDOUT: {kind: 'InfixOperator', text: '<', subtree_size: 7}, -// CHECK:STDOUT: {kind: 'ShortCircuitOperand', text: 'and', subtree_size: 8}, +// CHECK:STDOUT: {kind: 'ShortCircuitOperandAnd', text: 'and', subtree_size: 8}, // CHECK:STDOUT: {kind: 'BoolLiteralTrue', text: 'true'}, // CHECK:STDOUT: {kind: 'BoolTypeLiteral', text: 'bool'}, // CHECK:STDOUT: {kind: 'InfixOperator', text: 'as', subtree_size: 3}, -// CHECK:STDOUT: {kind: 'InfixOperator', text: 'and', subtree_size: 12}, -// CHECK:STDOUT: {kind: 'ShortCircuitOperand', text: 'and', subtree_size: 13}, +// CHECK:STDOUT: {kind: 'ShortCircuitOperatorAnd', text: 'and', subtree_size: 12}, +// CHECK:STDOUT: {kind: 'ShortCircuitOperandAnd', text: 'and', subtree_size: 13}, // CHECK:STDOUT: {kind: 'BoolLiteralFalse', text: 'false'}, // CHECK:STDOUT: {kind: 'BoolTypeLiteral', text: 'bool'}, // CHECK:STDOUT: {kind: 'InfixOperator', text: 'as', subtree_size: 3}, -// CHECK:STDOUT: {kind: 'InfixOperator', text: 'and', subtree_size: 17}, +// CHECK:STDOUT: {kind: 'ShortCircuitOperatorAnd', text: 'and', subtree_size: 17}, // CHECK:STDOUT: {kind: 'IfCondition', text: ')', subtree_size: 19}, // CHECK:STDOUT: {kind: 'CodeBlockStart', text: '{'}, // CHECK:STDOUT: {kind: 'CodeBlock', text: '}', subtree_size: 2}, diff --git a/toolchain/parse/testdata/operators/precedence_not.carbon b/toolchain/parse/testdata/operators/precedence_not.carbon index 99682d47c4a1..4ded7e5d02ac 100644 --- a/toolchain/parse/testdata/operators/precedence_not.carbon +++ b/toolchain/parse/testdata/operators/precedence_not.carbon @@ -18,14 +18,14 @@ fn F() { // CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5}, // CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'a'}, // CHECK:STDOUT: {kind: 'PrefixOperator', text: 'not', subtree_size: 2}, -// CHECK:STDOUT: {kind: 'ShortCircuitOperand', text: 'and', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'ShortCircuitOperandAnd', text: 'and', subtree_size: 3}, // CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'b'}, // CHECK:STDOUT: {kind: 'PrefixOperator', text: 'not', subtree_size: 2}, -// CHECK:STDOUT: {kind: 'InfixOperator', text: 'and', subtree_size: 6}, -// CHECK:STDOUT: {kind: 'ShortCircuitOperand', text: 'and', subtree_size: 7}, +// CHECK:STDOUT: {kind: 'ShortCircuitOperatorAnd', text: 'and', subtree_size: 6}, +// CHECK:STDOUT: {kind: 'ShortCircuitOperandAnd', text: 'and', subtree_size: 7}, // CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'c'}, // CHECK:STDOUT: {kind: 'PrefixOperator', text: 'not', subtree_size: 2}, -// CHECK:STDOUT: {kind: 'InfixOperator', text: 'and', subtree_size: 10}, +// CHECK:STDOUT: {kind: 'ShortCircuitOperatorAnd', text: 'and', subtree_size: 10}, // CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 11}, // CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 17}, // CHECK:STDOUT: {kind: 'FileEnd', text: ''}, diff --git a/toolchain/sem_ir/formatter.cpp b/toolchain/sem_ir/formatter.cpp index b315d1df1a36..696e8b7b829f 100644 --- a/toolchain/sem_ir/formatter.cpp +++ b/toolchain/sem_ir/formatter.cpp @@ -388,14 +388,12 @@ class InstNamer { name = "if.done"; break; - case Parse::NodeKind::ShortCircuitOperand: { - bool is_rhs = inst.Is(); - bool is_and = tokenized_buffer_.GetKind(parse_tree_.node_token( - inst.parse_node())) == Lex::TokenKind::And; - name = is_and ? (is_rhs ? "and.rhs" : "and.result") - : (is_rhs ? "or.rhs" : "or.result"); + case Parse::NodeKind::ShortCircuitOperandAnd: + name = inst.Is() ? "and.rhs" : "and.result"; + break; + case Parse::NodeKind::ShortCircuitOperandOr: + name = inst.Is() ? "or.rhs" : "or.result"; break; - } case Parse::NodeKind::WhileConditionStart: name = "while.cond";