Skip to content

Commit

Permalink
Implement new precedence from #4075 (#4236)
Browse files Browse the repository at this point in the history
Co-authored-by: Josh L <[email protected]>
Co-authored-by: Geoff Romer <[email protected]>
  • Loading branch information
3 people authored Aug 22, 2024
1 parent 2174e50 commit 935715e
Show file tree
Hide file tree
Showing 9 changed files with 141 additions and 108 deletions.
7 changes: 3 additions & 4 deletions toolchain/parse/precedence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,22 +54,21 @@ struct OperatorPriorityTable {
MarkHigherThan({Highest}, {TermPrefix, LogicalPrefix});
MarkHigherThan({TermPrefix},
{NumericPrefix, BitwisePrefix, IncrementDecrement});
MarkHigherThan({NumericPrefix, BitwisePrefix},
MarkHigherThan({NumericPrefix, BitwisePrefix, TypePostfix},
{As, Multiplicative, Modulo, BitwiseAnd, BitwiseOr,
BitwiseXor, BitShift});
MarkHigherThan({Multiplicative}, {Additive});
MarkHigherThan(
{As, Additive, Modulo, BitwiseAnd, BitwiseOr, BitwiseXor, BitShift},
{Additive, Modulo, BitwiseAnd, BitwiseOr, BitwiseXor, BitShift},
{Relational});
MarkHigherThan({Relational, LogicalPrefix}, {LogicalAnd, LogicalOr});
MarkHigherThan({LogicalAnd, LogicalOr}, {If});
MarkHigherThan({As, LogicalAnd, LogicalOr}, {If});
MarkHigherThan({If}, {Assignment});
MarkHigherThan({Assignment, IncrementDecrement}, {Lowest});

// Types are mostly a separate precedence graph.
MarkHigherThan({Highest}, {TypePrefix});
MarkHigherThan({TypePrefix}, {TypePostfix});
MarkHigherThan({TypePostfix}, {As});

// Compute the transitive closure of the above relationships: if we parse
// `a $ b @ c` as `(a $ b) @ c` and parse `b @ c % d` as `(b @ c) % d`,
Expand Down
7 changes: 1 addition & 6 deletions toolchain/parse/precedence_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,12 @@ TEST(PrecedenceTest, InfixVsPostfix) {
EXPECT_FALSE(
PrecedenceGroup::ForTrailing(Lex::TokenKind::Star, false)->is_binary);

// Infix `*` can appear in `+` contexts; postfix `*` cannot.
// Infix `*` can appear in `+` contexts.
EXPECT_THAT(
PrecedenceGroup::GetPriority(
PrecedenceGroup::ForTrailing(Lex::TokenKind::Star, true)->level,
PrecedenceGroup::ForTrailing(Lex::TokenKind::Plus, true)->level),
Eq(OperatorPriority::LeftFirst));
EXPECT_THAT(
PrecedenceGroup::GetPriority(
PrecedenceGroup::ForTrailing(Lex::TokenKind::Star, false)->level,
PrecedenceGroup::ForTrailing(Lex::TokenKind::Plus, true)->level),
Eq(OperatorPriority::Ambiguous));
}

TEST(PrecedenceTest, Associativity) {
Expand Down
56 changes: 53 additions & 3 deletions toolchain/parse/testdata/operators/fail_precedence_as.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,40 @@ fn F(n: i32) {
// CHECK:STDERR:
not true as bool;

// No ordering between most binary operators and `as`.
// No ordering between mathematical binary operators and `as`.
// CHECK:STDERR: fail_precedence_as.carbon:[[@LINE+4]]:9: ERROR: Parentheses are required to disambiguate operator precedence.
// CHECK:STDERR: 1 + 1 as i32;
// CHECK:STDERR: ^~
// CHECK:STDERR:
1 + 1 as i32;
// CHECK:STDERR: fail_precedence_as.carbon:[[@LINE+3]]:9: ERROR: Parentheses are required to disambiguate operator precedence.
// CHECK:STDERR: fail_precedence_as.carbon:[[@LINE+4]]:9: ERROR: Parentheses are required to disambiguate operator precedence.
// CHECK:STDERR: 5 % 2 as i32;
// CHECK:STDERR: ^~
// CHECK:STDERR:
5 % 2 as i32;

// No ordering between logical binary operators and `as`.
// CHECK:STDERR: fail_precedence_as.carbon:[[@LINE+4]]:12: ERROR: Parentheses are required to disambiguate operator precedence.
// CHECK:STDERR: 3 as i32 and true;
// CHECK:STDERR: ^~~
// CHECK:STDERR:
3 as i32 and true;
// CHECK:STDERR: fail_precedence_as.carbon:[[@LINE+4]]:14: ERROR: Parentheses are required to disambiguate operator precedence.
// CHECK:STDERR: false or 4 as i32;
// CHECK:STDERR: ^~
// CHECK:STDERR:
false or 4 as i32;

// No ordering between relational binary operators and `as`.
// CHECK:STDERR: fail_precedence_as.carbon:[[@LINE+4]]:12: ERROR: Parentheses are required to disambiguate operator precedence.
// CHECK:STDERR: 6 as i32 == 7;
// CHECK:STDERR: ^~
// CHECK:STDERR:
6 as i32 == 7;
// CHECK:STDERR: fail_precedence_as.carbon:[[@LINE+3]]:10: ERROR: Parentheses are required to disambiguate operator precedence.
// CHECK:STDERR: 8 <= 9 as i32;
// CHECK:STDERR: ^~
8 <= 9 as i32;
}

// CHECK:STDOUT: - filename: fail_precedence_as.carbon
Expand Down Expand Up @@ -56,6 +80,32 @@ fn F(n: i32) {
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
// CHECK:STDOUT: {kind: 'InfixOperatorAs', text: 'as', has_error: yes, subtree_size: 5},
// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 6},
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 26},
// CHECK:STDOUT: {kind: 'IntLiteral', text: '3'},
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
// CHECK:STDOUT: {kind: 'InfixOperatorAs', text: 'as', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ShortCircuitOperandAnd', text: 'and', has_error: yes, subtree_size: 4},
// CHECK:STDOUT: {kind: 'BoolLiteralTrue', text: 'true'},
// CHECK:STDOUT: {kind: 'ShortCircuitOperatorAnd', text: 'and', has_error: yes, subtree_size: 6},
// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 7},
// CHECK:STDOUT: {kind: 'BoolLiteralFalse', text: 'false'},
// CHECK:STDOUT: {kind: 'ShortCircuitOperandOr', text: 'or', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IntLiteral', text: '4'},
// CHECK:STDOUT: {kind: 'ShortCircuitOperatorOr', text: 'or', subtree_size: 4},
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
// CHECK:STDOUT: {kind: 'InfixOperatorAs', text: 'as', has_error: yes, subtree_size: 6},
// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 7},
// CHECK:STDOUT: {kind: 'IntLiteral', text: '6'},
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
// CHECK:STDOUT: {kind: 'InfixOperatorAs', text: 'as', subtree_size: 3},
// CHECK:STDOUT: {kind: 'IntLiteral', text: '7'},
// CHECK:STDOUT: {kind: 'InfixOperatorEqualEqual', text: '==', has_error: yes, subtree_size: 5},
// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 6},
// CHECK:STDOUT: {kind: 'IntLiteral', text: '8'},
// CHECK:STDOUT: {kind: 'IntLiteral', text: '9'},
// CHECK:STDOUT: {kind: 'InfixOperatorLessEqual', text: '<=', subtree_size: 3},
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
// CHECK:STDOUT: {kind: 'InfixOperatorAs', text: 'as', has_error: yes, subtree_size: 5},
// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 6},
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 52},
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
// CHECK:STDOUT: ]
40 changes: 13 additions & 27 deletions toolchain/parse/testdata/operators/precedence_as.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@ fn F(n: i32) {
// Type operators and unary operators are higher precedence than `as`.
-n as const i32;
&n as i32*;

// `as` is higher precedence than relational comparisons and
// logical operators.
if (1 as i32 < 2 as i32 and true as bool and false as bool) {}
^n as i32;
*n as i32;
}

// CHECK:STDOUT: - filename: precedence_as.carbon
Expand All @@ -41,28 +39,16 @@ fn F(n: i32) {
// CHECK:STDOUT: {kind: 'PostfixOperatorStar', text: '*', subtree_size: 2},
// CHECK:STDOUT: {kind: 'InfixOperatorAs', text: 'as', subtree_size: 5},
// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 6},
// CHECK:STDOUT: {kind: 'IfConditionStart', text: '('},
// CHECK:STDOUT: {kind: 'IntLiteral', text: '1'},
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
// CHECK:STDOUT: {kind: 'InfixOperatorAs', text: 'as', subtree_size: 3},
// CHECK:STDOUT: {kind: 'IntLiteral', text: '2'},
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
// CHECK:STDOUT: {kind: 'InfixOperatorAs', text: 'as', subtree_size: 3},
// CHECK:STDOUT: {kind: 'InfixOperatorLess', text: '<', subtree_size: 7},
// CHECK:STDOUT: {kind: 'ShortCircuitOperandAnd', text: 'and', subtree_size: 8},
// CHECK:STDOUT: {kind: 'BoolLiteralTrue', text: 'true'},
// CHECK:STDOUT: {kind: 'BoolTypeLiteral', text: 'bool'},
// CHECK:STDOUT: {kind: 'InfixOperatorAs', text: 'as', subtree_size: 3},
// 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: 'InfixOperatorAs', text: 'as', subtree_size: 3},
// 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},
// CHECK:STDOUT: {kind: 'IfStatement', text: 'if', subtree_size: 22},
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 43},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'n'},
// CHECK:STDOUT: {kind: 'PrefixOperatorCaret', text: '^', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
// CHECK:STDOUT: {kind: 'InfixOperatorAs', text: 'as', subtree_size: 4},
// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 5},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'n'},
// CHECK:STDOUT: {kind: 'PrefixOperatorStar', text: '*', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
// CHECK:STDOUT: {kind: 'InfixOperatorAs', text: 'as', subtree_size: 4},
// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 5},
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 31},
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
// CHECK:STDOUT: ]
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,21 @@
//
// AUTOUPDATE
// TIP: To test this file alone, run:
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/parse/testdata/operators/fail_precedence_star_minus.carbon
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/parse/testdata/operators/recover_star_minus.carbon
// TIP: To dump output, run:
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/parse/testdata/operators/fail_precedence_star_minus.carbon
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/parse/testdata/operators/recover_star_minus.carbon

// CHECK:STDERR: fail_precedence_star_minus.carbon:[[@LINE+3]]:16: ERROR: Parentheses are required to disambiguate operator precedence.
// TODO: There are two possible fixes that would make this expression legal:
// `n * -n` and `n* - n`. The parser doesn't realize that the first fix is
// available because it has already accepted that first part of the expression,
// so it is recovering by using the second option, but the diagnostic should
// ideally offer (or consider) both fixes as alternatives.
// CHECK:STDERR: recover_star_minus.carbon:[[@LINE+3]]:16: ERROR: Whitespace missing after binary operator.
// CHECK:STDERR: var n: i8 = n* -n;
// CHECK:STDERR: ^
var n: i8 = n* -n;

// CHECK:STDOUT: - filename: fail_precedence_star_minus.carbon
// CHECK:STDOUT: - filename: recover_star_minus.carbon
// CHECK:STDOUT: parse_tree: [
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
// CHECK:STDOUT: {kind: 'VariableIntroducer', text: 'var'},
Expand All @@ -24,7 +29,7 @@ var n: i8 = n* -n;
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'n'},
// CHECK:STDOUT: {kind: 'PostfixOperatorStar', text: '*', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'n'},
// CHECK:STDOUT: {kind: 'InfixOperatorMinus', text: '-', has_error: yes, subtree_size: 4},
// CHECK:STDOUT: {kind: 'InfixOperatorMinus', text: '-', subtree_size: 4},
// CHECK:STDOUT: {kind: 'VariableDecl', text: ';', subtree_size: 10},
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
// CHECK:STDOUT: ]
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@
//
// AUTOUPDATE
// TIP: To test this file alone, run:
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/parse/testdata/operators/fail_precedence_star_star.carbon
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/parse/testdata/operators/recover_star_star.carbon
// TIP: To dump output, run:
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/parse/testdata/operators/fail_precedence_star_star.carbon
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/parse/testdata/operators/recover_star_star.carbon

// CHECK:STDERR: fail_precedence_star_star.carbon:[[@LINE+3]]:16: ERROR: Parentheses are required to disambiguate operator precedence.
// CHECK:STDERR: recover_star_star.carbon:[[@LINE+3]]:16: ERROR: Whitespace missing after binary operator.
// CHECK:STDERR: var n: i8 = n* *p;
// CHECK:STDERR: ^
var n: i8 = n* *p;

// CHECK:STDOUT: - filename: fail_precedence_star_star.carbon
// CHECK:STDOUT: - filename: recover_star_star.carbon
// CHECK:STDOUT: parse_tree: [
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
// CHECK:STDOUT: {kind: 'VariableIntroducer', text: 'var'},
Expand All @@ -24,7 +24,7 @@ var n: i8 = n* *p;
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'n'},
// CHECK:STDOUT: {kind: 'PostfixOperatorStar', text: '*', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'p'},
// CHECK:STDOUT: {kind: 'InfixOperatorStar', text: '*', has_error: yes, subtree_size: 4},
// CHECK:STDOUT: {kind: 'InfixOperatorStar', text: '*', subtree_size: 4},
// CHECK:STDOUT: {kind: 'VariableDecl', text: ';', subtree_size: 10},
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
// CHECK:STDOUT: ]
32 changes: 32 additions & 0 deletions toolchain/parse/testdata/operators/three_stars.carbon
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// TIP: To test this file alone, run:
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/parse/testdata/operators/three_stars.carbon
// TIP: To dump output, run:
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/parse/testdata/operators/three_stars.carbon

fn F() {
const T* * *p;
}

// CHECK:STDOUT: - filename: three_stars.carbon
// CHECK:STDOUT: parse_tree: [
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'F'},
// CHECK:STDOUT: {kind: 'TuplePatternStart', text: '('},
// CHECK:STDOUT: {kind: 'TuplePattern', text: ')', subtree_size: 2},
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'T'},
// CHECK:STDOUT: {kind: 'PrefixOperatorConst', text: 'const', subtree_size: 2},
// CHECK:STDOUT: {kind: 'PostfixOperatorStar', text: '*', subtree_size: 3},
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'p'},
// CHECK:STDOUT: {kind: 'PrefixOperatorStar', text: '*', subtree_size: 2},
// CHECK:STDOUT: {kind: 'InfixOperatorStar', text: '*', subtree_size: 6},
// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 7},
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 13},
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
// CHECK:STDOUT: ]
54 changes: 0 additions & 54 deletions toolchain/parse/testdata/pointer/fail_pointer_type_in_expr.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,6 @@
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/parse/testdata/pointer/fail_pointer_type_in_expr.carbon

fn F() -> i32 {
// TODO: Indicate the locations of both operators involved in the precedence
// error, so that it's clear what ambiguity we're referring to.
// TODO: Improve error recovery so that we recover as `3 * (i32*) * 4`, not
// as `(3 * i32)* * 4`, to suppress the second error here.
// CHECK:STDERR: fail_pointer_type_in_expr.carbon:[[@LINE+8]]:17: ERROR: Parentheses are required to disambiguate operator precedence.
// CHECK:STDERR: return 3 * i32* * 4;
// CHECK:STDERR: ^
// CHECK:STDERR:
// CHECK:STDERR: fail_pointer_type_in_expr.carbon:[[@LINE+4]]:19: ERROR: Parentheses are required to disambiguate operator precedence.
// CHECK:STDERR: return 3 * i32* * 4;
// CHECK:STDERR: ^
// CHECK:STDERR:
return 3 * i32* * 4;
}

fn G() -> i32 {
// CHECK:STDERR: fail_pointer_type_in_expr.carbon:[[@LINE+4]]:15: ERROR: Parentheses are required to disambiguate operator precedence.
// CHECK:STDERR: return i32* + 4;
// CHECK:STDERR: ^
// CHECK:STDERR:
return i32* + 4;
}

fn H() -> i32 {
// CHECK:STDERR: fail_pointer_type_in_expr.carbon:[[@LINE+3]]:14: ERROR: Parentheses are required to disambiguate operator precedence.
// CHECK:STDERR: return *i32*;
// CHECK:STDERR: ^
Expand All @@ -50,36 +26,6 @@ fn H() -> i32 {
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 7},
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
// CHECK:STDOUT: {kind: 'IntLiteral', text: '3'},
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
// CHECK:STDOUT: {kind: 'InfixOperatorStar', text: '*', subtree_size: 3},
// CHECK:STDOUT: {kind: 'PostfixOperatorStar', text: '*', has_error: yes, subtree_size: 4},
// CHECK:STDOUT: {kind: 'IntLiteral', text: '4'},
// CHECK:STDOUT: {kind: 'InfixOperatorStar', text: '*', has_error: yes, subtree_size: 6},
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 8},
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 16},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'G'},
// CHECK:STDOUT: {kind: 'TuplePatternStart', text: '('},
// CHECK:STDOUT: {kind: 'TuplePattern', text: ')', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 7},
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
// CHECK:STDOUT: {kind: 'PostfixOperatorStar', text: '*', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IntLiteral', text: '4'},
// CHECK:STDOUT: {kind: 'InfixOperatorPlus', text: '+', has_error: yes, subtree_size: 4},
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 6},
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 14},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'IdentifierName', text: 'H'},
// CHECK:STDOUT: {kind: 'TuplePatternStart', text: '('},
// CHECK:STDOUT: {kind: 'TuplePattern', text: ')', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 7},
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'},
// CHECK:STDOUT: {kind: 'PrefixOperatorStar', text: '*', subtree_size: 2},
// CHECK:STDOUT: {kind: 'PostfixOperatorStar', text: '*', has_error: yes, subtree_size: 3},
Expand Down
Loading

0 comments on commit 935715e

Please sign in to comment.