mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
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).
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -471,8 +471,8 @@ CARBON_PARSE_STATE(ExprInPostfixLoop)
|
||||
|
||||
// Handles processing of an expression.
|
||||
//
|
||||
// expr <binary operator> ...
|
||||
// ^~~~~~~~~~~~~~~~~
|
||||
// expr <infix operator> ...
|
||||
// ^~~~~~~~~~~~~~~~
|
||||
// 1. Expr
|
||||
// 2. ExprLoopForBinary
|
||||
//
|
||||
@@ -480,6 +480,11 @@ CARBON_PARSE_STATE(ExprInPostfixLoop)
|
||||
// ^~~~~~~~~~~~~~~~~~
|
||||
// 1. ExprLoop
|
||||
//
|
||||
// expr <short circuit operator> ...
|
||||
// ^~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// 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 <binary operator> expr ...
|
||||
// ^
|
||||
// expr <infix operator> 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 <short circuit operator> 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 ...
|
||||
|
||||
+6
-6
@@ -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},
|
||||
|
||||
+4
-4
@@ -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: ''},
|
||||
|
||||
@@ -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: ''},
|
||||
|
||||
@@ -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: ''},
|
||||
|
||||
+4
-4
@@ -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},
|
||||
|
||||
@@ -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: ''},
|
||||
|
||||
@@ -388,14 +388,12 @@ class InstNamer {
|
||||
name = "if.done";
|
||||
break;
|
||||
|
||||
case Parse::NodeKind::ShortCircuitOperand: {
|
||||
bool is_rhs = inst.Is<BranchIf>();
|
||||
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<BranchIf>() ? "and.rhs" : "and.result";
|
||||
break;
|
||||
case Parse::NodeKind::ShortCircuitOperandOr:
|
||||
name = inst.Is<BranchIf>() ? "or.rhs" : "or.result";
|
||||
break;
|
||||
}
|
||||
|
||||
case Parse::NodeKind::WhileConditionStart:
|
||||
name = "while.cond";
|
||||
|
||||
Reference in New Issue
Block a user