mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-06 07:54:41 +01:00
Implement parsing observe declarations (#6674)
This implements parsing of the [`observe`](https://docs.carbon-lang.dev/docs/design/generics/details.html#observing-a-type-implements-an-interface) declarations. - Added states and node kinds. - Added node categories. - Added a diagnostic for invalid keywords/operators. - Implemented parser state handlers. - Added structs to `typed_nodes.h`. - Added parser tests.
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
// 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
|
||||
|
||||
#include "toolchain/check/context.h"
|
||||
#include "toolchain/check/handle.h"
|
||||
#include "toolchain/parse/node_ids.h"
|
||||
|
||||
namespace Carbon::Check {
|
||||
|
||||
auto HandleParseNode(Context& context, Parse::ObserveIntroducerId node_id)
|
||||
-> bool {
|
||||
return context.TODO(node_id, "ObserveIntroducerId");
|
||||
}
|
||||
|
||||
auto HandleParseNode(Context& context, Parse::ObserveEqualEqualId node_id)
|
||||
-> bool {
|
||||
return context.TODO(node_id, "ObserveEqualEqualId");
|
||||
}
|
||||
|
||||
auto HandleParseNode(Context& context, Parse::ObserveImplsId node_id) -> bool {
|
||||
return context.TODO(node_id, "ObserveImplsId");
|
||||
}
|
||||
|
||||
auto HandleParseNode(Context& context, Parse::ObserveDeclId node_id) -> bool {
|
||||
return context.TODO(node_id, "ObserveDeclId");
|
||||
}
|
||||
|
||||
} // namespace Carbon::Check
|
||||
@@ -467,6 +467,7 @@ class NodeStack {
|
||||
case Parse::NodeKind::LetInitializer:
|
||||
case Parse::NodeKind::LetIntroducer:
|
||||
case Parse::NodeKind::NamedConstraintIntroducer:
|
||||
case Parse::NodeKind::ObserveIntroducer:
|
||||
case Parse::NodeKind::RefBindingName:
|
||||
case Parse::NodeKind::ReturnStatementStart:
|
||||
case Parse::NodeKind::StructLiteralStart:
|
||||
@@ -527,6 +528,8 @@ class NodeStack {
|
||||
case Parse::NodeKind::MatchIntroducer:
|
||||
case Parse::NodeKind::MatchStatementStart:
|
||||
case Parse::NodeKind::NamespaceStart:
|
||||
case Parse::NodeKind::ObserveEqualEqual:
|
||||
case Parse::NodeKind::ObserveImpls:
|
||||
case Parse::NodeKind::PackageIntroducer:
|
||||
case Parse::NodeKind::ParenExprStart:
|
||||
case Parse::NodeKind::PatternListComma:
|
||||
|
||||
@@ -115,6 +115,7 @@ CARBON_DIAGNOSTIC_KIND(ExpectedStructLiteralField)
|
||||
CARBON_DIAGNOSTIC_KIND(ExpectedVarAfterReturned)
|
||||
CARBON_DIAGNOSTIC_KIND(ExpectedChoiceDefinition)
|
||||
CARBON_DIAGNOSTIC_KIND(ExpectedChoiceAlternativeName)
|
||||
CARBON_DIAGNOSTIC_KIND(ExpectedObserveOperator)
|
||||
CARBON_DIAGNOSTIC_KIND(NestedVar)
|
||||
CARBON_DIAGNOSTIC_KIND(NestedUnused)
|
||||
CARBON_DIAGNOSTIC_KIND(OperatorRequiresParentheses)
|
||||
|
||||
@@ -103,6 +103,7 @@ cc_library(
|
||||
":context",
|
||||
":dump",
|
||||
":node_kind",
|
||||
":precedence",
|
||||
":state",
|
||||
":tree",
|
||||
"//common:check",
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "toolchain/parse/context.h"
|
||||
#include "toolchain/parse/handle.h"
|
||||
#include "toolchain/parse/node_kind.h"
|
||||
#include "toolchain/parse/state.h"
|
||||
|
||||
namespace Carbon::Parse {
|
||||
|
||||
@@ -130,6 +131,8 @@ static constexpr auto DeclIntroducers = [] {
|
||||
StateKind::TypeAfterIntroducerAsInterface);
|
||||
set(Lex::TokenKind::Namespace, NodeKind::NamespaceStart,
|
||||
StateKind::Namespace);
|
||||
set(Lex::TokenKind::Observe, NodeKind::ObserveIntroducer,
|
||||
StateKind::ObserveAfterIntroducer);
|
||||
set(Lex::TokenKind::Require, NodeKind::RequireIntroducer,
|
||||
StateKind::RequireAfterIntroducer);
|
||||
set_contextual(Lex::TokenKind::Let, RegularContext, NodeKind::LetIntroducer,
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
// 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
|
||||
|
||||
#include "toolchain/lex/token_kind.h"
|
||||
#include "toolchain/parse/context.h"
|
||||
#include "toolchain/parse/handle.h"
|
||||
#include "toolchain/parse/node_kind.h"
|
||||
#include "toolchain/parse/precedence.h"
|
||||
#include "toolchain/parse/state.h"
|
||||
#include "toolchain/parse/typed_nodes.h"
|
||||
|
||||
namespace Carbon::Parse {
|
||||
auto HandleObserveAfterIntroducer(Context& context) -> void {
|
||||
auto state = context.PopState();
|
||||
|
||||
context.PushState(state, StateKind::ObserveOperator);
|
||||
context.PushStateForExpr(PrecedenceGroup::ForRequirements());
|
||||
}
|
||||
|
||||
auto HandleObserveOperator(Context& context) -> void {
|
||||
auto state = context.PopState();
|
||||
|
||||
switch (context.PositionKind()) {
|
||||
case Lex::TokenKind::EqualEqual: {
|
||||
state.token = context.Consume();
|
||||
context.PushState(state, StateKind::ObserveFinishOperator);
|
||||
context.PushStateForExpr(PrecedenceGroup::ForRequirements());
|
||||
return;
|
||||
}
|
||||
case Lex::TokenKind::Impls: {
|
||||
state.token = context.Consume();
|
||||
context.PushState(state, StateKind::ObserveFinishOperator);
|
||||
context.PushState(StateKind::Expr);
|
||||
return;
|
||||
}
|
||||
default: {
|
||||
if (!state.has_error) {
|
||||
CARBON_DIAGNOSTIC(ExpectedObserveOperator, Error,
|
||||
"observe should use `==` or `impls` operator");
|
||||
context.emitter().Emit(*context.position(), ExpectedObserveOperator);
|
||||
}
|
||||
context.RecoverFromDeclError(state, NodeKind::ObserveDecl,
|
||||
/*skip_past_likely_end=*/true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto HandleObserveFinishOperator(Context& context) -> void {
|
||||
auto state = context.PopState();
|
||||
auto token_kind = context.tokens().GetKind(state.token);
|
||||
|
||||
if (token_kind == Lex::TokenKind::EqualEqual) {
|
||||
context.AddNode(NodeKind::ObserveEqualEqual, state.token, state.has_error);
|
||||
} else {
|
||||
context.AddNode(NodeKind::ObserveImpls, state.token, state.has_error);
|
||||
}
|
||||
if (context.PositionIs(Lex::TokenKind::Semi)) {
|
||||
context.PushState(state, StateKind::ObserveDecl);
|
||||
} else {
|
||||
context.PushState(state, StateKind::ObserveOperator);
|
||||
}
|
||||
}
|
||||
|
||||
auto HandleObserveDecl(Context& context) -> void {
|
||||
auto state = context.PopState();
|
||||
context.AddNodeExpectingDeclSemi(state, NodeKind::ObserveDecl,
|
||||
Lex::TokenKind::Observe,
|
||||
/*is_def_allowed=*/false);
|
||||
}
|
||||
} // namespace Carbon::Parse
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "toolchain/lex/token_kind.h"
|
||||
#include "toolchain/parse/context.h"
|
||||
#include "toolchain/parse/handle.h"
|
||||
|
||||
@@ -64,6 +65,7 @@ auto HandleStatement(Context& context) -> void {
|
||||
case Lex::TokenKind::Let:
|
||||
case Lex::TokenKind::Library:
|
||||
case Lex::TokenKind::Namespace:
|
||||
case Lex::TokenKind::Observe:
|
||||
// We intentionally don't handle Package here, because `package.` can be
|
||||
// used at the start of an expression, and it's not worth disambiguating it.
|
||||
case Lex::TokenKind::Var: {
|
||||
|
||||
@@ -15,21 +15,23 @@ namespace Carbon::Parse {
|
||||
// #define CARBON_NODE_CATEGORY_FOR_XYZ(Name) ...
|
||||
// CARBON_NODE_CATEGORY(CARBON_NODE_CATEGORY_FOR_XYZ)
|
||||
// #undef CARBON_NODE_CATEGORY_FOR_XYZ
|
||||
#define CARBON_NODE_CATEGORY(X) \
|
||||
X(Decl) \
|
||||
X(Expr) \
|
||||
/* `impl <type> as` or just `impl as` */ \
|
||||
X(ImplAs) \
|
||||
X(IntConst) \
|
||||
X(MemberExpr) \
|
||||
X(MemberName) \
|
||||
X(Modifier) \
|
||||
X(NonExprName) \
|
||||
X(PackageName) \
|
||||
X(Pattern) \
|
||||
/* `require <type> impls` or just `require impls` */ \
|
||||
X(RequireImpls) \
|
||||
X(Requirement) \
|
||||
#define CARBON_NODE_CATEGORY(X) \
|
||||
X(Decl) \
|
||||
X(Expr) \
|
||||
/* `impl <type> as` or just `impl as` */ \
|
||||
X(ImplAs) \
|
||||
X(IntConst) \
|
||||
X(MemberExpr) \
|
||||
X(MemberName) \
|
||||
X(Modifier) \
|
||||
X(NonExprName) \
|
||||
/* `observe <type> == <type>` or `observe <type> impls` */ \
|
||||
X(ObserveOperator) \
|
||||
X(PackageName) \
|
||||
X(Pattern) \
|
||||
/* `require <type> impls` or just `require impls` */ \
|
||||
X(RequireImpls) \
|
||||
X(Requirement) \
|
||||
X(Statement)
|
||||
|
||||
// We expect this to grow, so are using a bigger size than needed.
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "toolchain/base/index_base.h"
|
||||
#include "toolchain/lex/token_index.h"
|
||||
#include "toolchain/parse/node_category.h"
|
||||
#include "toolchain/parse/node_kind.h"
|
||||
|
||||
namespace Carbon::Parse {
|
||||
@@ -110,6 +111,9 @@ using AnyStatementId =
|
||||
NodeIdInCategory<NodeCategory::Statement | NodeCategory::Decl>;
|
||||
using AnyRequireImplsId = NodeIdInCategory<NodeCategory::RequireImpls>;
|
||||
using AnyRequirementId = NodeIdInCategory<NodeCategory::Requirement>;
|
||||
using AnyObserveOperatorId = NodeIdInCategory<NodeCategory::ObserveOperator>;
|
||||
using AnyObserveOperandId =
|
||||
NodeIdInCategory<NodeCategory::Expr | NodeCategory::ObserveOperator>;
|
||||
using AnyNonExprNameId = NodeIdInCategory<NodeCategory::NonExprName>;
|
||||
using AnyPackageNameId = NodeIdInCategory<NodeCategory::PackageName>;
|
||||
|
||||
|
||||
@@ -393,6 +393,11 @@ CARBON_PARSE_NODE_KIND(RequireTypeImpls)
|
||||
CARBON_PARSE_NODE_KIND(RequireDefaultSelfImpls)
|
||||
CARBON_PARSE_NODE_KIND(RequireDecl)
|
||||
|
||||
CARBON_PARSE_NODE_KIND(ObserveIntroducer)
|
||||
CARBON_PARSE_NODE_KIND(ObserveEqualEqual)
|
||||
CARBON_PARSE_NODE_KIND(ObserveImpls)
|
||||
CARBON_PARSE_NODE_KIND(ObserveDecl)
|
||||
|
||||
CARBON_PARSE_NODE_KIND(NamedConstraintIntroducer)
|
||||
CARBON_PARSE_NODE_KIND(NamedConstraintDefinitionStart)
|
||||
CARBON_PARSE_NODE_KIND(NamedConstraintDefinition)
|
||||
|
||||
@@ -63,7 +63,7 @@ class PrecedenceGroup {
|
||||
static auto ForRequireImpls() -> PrecedenceGroup;
|
||||
|
||||
// Get the precedence level at which to parse expressions in requirements
|
||||
// after `where` or `require`.
|
||||
// after `where`, `require`, or `observe`.
|
||||
static auto ForRequirements() -> PrecedenceGroup;
|
||||
|
||||
// Look up the operator information of the given prefix operator token, or
|
||||
|
||||
@@ -396,6 +396,10 @@ CARBON_PARSE_STATE(DeclNameAndParamsAfterParams)
|
||||
// ^~~~~~~
|
||||
// 1. RequireAfterIntroducer
|
||||
//
|
||||
// observe ...
|
||||
// ^~~~~~~
|
||||
// 1. ObserveAfterIntroducer
|
||||
//
|
||||
// var ... (variant is Regular)
|
||||
// ^~~
|
||||
// 1. VarAsRegular
|
||||
@@ -1549,6 +1553,43 @@ CARBON_PARSE_STATE(RequireBeforeImpls)
|
||||
// (state done)
|
||||
CARBON_PARSE_STATE(RequireDecl)
|
||||
|
||||
// Handles processing of an `observe` declaration after the introducer.
|
||||
//
|
||||
// observe TypeExpression ...
|
||||
// ^
|
||||
// 1. Expr
|
||||
// 2. ObserveOperator
|
||||
CARBON_PARSE_STATE(ObserveAfterIntroducer)
|
||||
|
||||
// Handles processing of an operator in an `observe` declaration.
|
||||
//
|
||||
// observe TypeExpression == TypeExpression ...
|
||||
// ^~
|
||||
// 1. Expr
|
||||
// 2. ObserveFinishOperator
|
||||
// observe TypeExpression impls ...
|
||||
// ^~~~~
|
||||
// 1. Expr
|
||||
// 2. ObserveFinishOperator
|
||||
CARBON_PARSE_STATE(ObserveOperator)
|
||||
|
||||
// Finishes an operator in an `observe` declaration.
|
||||
//
|
||||
// observe TypeExpression == TypeExpression ...
|
||||
// ^
|
||||
// 1. ObserveOperator
|
||||
// observe TypeExpression == TypeExpression ;
|
||||
// ^
|
||||
// 1. ObserveDecl
|
||||
CARBON_PARSE_STATE(ObserveFinishOperator)
|
||||
|
||||
// Handles processing of a completed `observe` declaration.
|
||||
//
|
||||
// observe ... ;
|
||||
// ^
|
||||
// (state done)
|
||||
CARBON_PARSE_STATE(ObserveDecl)
|
||||
|
||||
// Handles the start of a `var` or `returned var` in a non-class context.
|
||||
//
|
||||
// var ... (variant is Regular)
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
// 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/observe/fail_invalid_operator.carbon
|
||||
// TIP: To dump output, run:
|
||||
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/parse/testdata/observe/fail_invalid_operator.carbon
|
||||
|
||||
// CHECK:STDERR: fail_invalid_operator.carbon:[[@LINE+4]]:11: error: observe should use `==` or `impls` operator [ExpectedObserveOperator]
|
||||
// CHECK:STDERR: observe T = U impls I;
|
||||
// CHECK:STDERR: ^
|
||||
// CHECK:STDERR:
|
||||
observe T = U impls I;
|
||||
|
||||
// CHECK:STDOUT: - filename: fail_invalid_operator.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'ObserveIntroducer', text: 'observe'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'T'},
|
||||
// CHECK:STDOUT: {kind: 'ObserveDecl', text: ';', has_error: yes, subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
@@ -0,0 +1,62 @@
|
||||
// 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/observe/fail_missing_expr.carbon
|
||||
// TIP: To dump output, run:
|
||||
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/parse/testdata/observe/fail_missing_expr.carbon
|
||||
|
||||
// --- fail_missing_expr_after_observe.carbon
|
||||
|
||||
// CHECK:STDERR: fail_missing_expr_after_observe.carbon:[[@LINE+4]]:9: error: expected expression [ExpectedExpr]
|
||||
// CHECK:STDERR: observe impls I;
|
||||
// CHECK:STDERR: ^~~~~
|
||||
// CHECK:STDERR:
|
||||
observe impls I;
|
||||
|
||||
// --- fail_missing_expr_after_impls.carbon
|
||||
|
||||
// CHECK:STDERR: fail_missing_expr_after_impls.carbon:[[@LINE+4]]:17: error: expected expression [ExpectedExpr]
|
||||
// CHECK:STDERR: observe T impls ;
|
||||
// CHECK:STDERR: ^
|
||||
// CHECK:STDERR:
|
||||
observe T impls ;
|
||||
|
||||
// --- fail_missing_impls.carbon
|
||||
|
||||
// CHECK:STDERR: fail_missing_impls.carbon:[[@LINE+4]]:11: error: observe should use `==` or `impls` operator [ExpectedObserveOperator]
|
||||
// CHECK:STDERR: observe T ;
|
||||
// CHECK:STDERR: ^
|
||||
// CHECK:STDERR:
|
||||
observe T ;
|
||||
|
||||
// CHECK:STDOUT: - filename: fail_missing_expr_after_observe.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'ObserveIntroducer', text: 'observe'},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: 'impls', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'I'},
|
||||
// CHECK:STDOUT: {kind: 'ObserveImpls', text: 'impls', has_error: yes, subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'ObserveDecl', text: ';', has_error: yes, subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: - filename: fail_missing_expr_after_impls.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'ObserveIntroducer', text: 'observe'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'T'},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: ';', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'ObserveImpls', text: 'impls', has_error: yes, subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'ObserveDecl', text: ';', has_error: yes, subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: - filename: fail_missing_impls.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'ObserveIntroducer', text: 'observe'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'T'},
|
||||
// CHECK:STDOUT: {kind: 'ObserveDecl', text: ';', has_error: yes, subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
// 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/observe/observe.carbon
|
||||
// TIP: To dump output, run:
|
||||
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/parse/testdata/observe/observe.carbon
|
||||
|
||||
// --- base.carbon
|
||||
|
||||
observe A == B == C;
|
||||
|
||||
// --- impls.carbon
|
||||
|
||||
observe T impls I;
|
||||
|
||||
// --- equal_equal_impls.carbon
|
||||
|
||||
observe T == U impls I;
|
||||
observe A == B == C == D impls I;
|
||||
|
||||
// --- statement.carbon
|
||||
|
||||
fn F() {
|
||||
observe A == B;
|
||||
}
|
||||
|
||||
interface I {
|
||||
observe A == B;
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: - filename: base.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'ObserveIntroducer', text: 'observe'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'A'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'B'},
|
||||
// CHECK:STDOUT: {kind: 'ObserveEqualEqual', text: '==', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'C'},
|
||||
// CHECK:STDOUT: {kind: 'ObserveEqualEqual', text: '==', subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'ObserveDecl', text: ';', subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: - filename: impls.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'ObserveIntroducer', text: 'observe'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'T'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'I'},
|
||||
// CHECK:STDOUT: {kind: 'ObserveImpls', text: 'impls', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'ObserveDecl', text: ';', subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: - filename: equal_equal_impls.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'ObserveIntroducer', text: 'observe'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'T'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'U'},
|
||||
// CHECK:STDOUT: {kind: 'ObserveEqualEqual', text: '==', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'I'},
|
||||
// CHECK:STDOUT: {kind: 'ObserveImpls', text: 'impls', subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'ObserveDecl', text: ';', subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'ObserveIntroducer', text: 'observe'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'A'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'B'},
|
||||
// CHECK:STDOUT: {kind: 'ObserveEqualEqual', text: '==', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'C'},
|
||||
// CHECK:STDOUT: {kind: 'ObserveEqualEqual', text: '==', subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'D'},
|
||||
// CHECK:STDOUT: {kind: 'ObserveEqualEqual', text: '==', subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'I'},
|
||||
// CHECK:STDOUT: {kind: 'ObserveImpls', text: 'impls', subtree_size: 9},
|
||||
// CHECK:STDOUT: {kind: 'ObserveDecl', text: ';', subtree_size: 11},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: - filename: statement.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameMaybeBeforeSignature', text: 'F'},
|
||||
// CHECK:STDOUT: {kind: 'ExplicitParamListStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'ExplicitParamList', text: ')', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'ObserveIntroducer', text: 'observe'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'A'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'B'},
|
||||
// CHECK:STDOUT: {kind: 'ObserveEqualEqual', text: '==', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'ObserveDecl', text: ';', subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 11},
|
||||
// CHECK:STDOUT: {kind: 'InterfaceIntroducer', text: 'interface'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeSignature', text: 'I'},
|
||||
// CHECK:STDOUT: {kind: 'InterfaceDefinitionStart', text: '{', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'ObserveIntroducer', text: 'observe'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'A'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'B'},
|
||||
// CHECK:STDOUT: {kind: 'ObserveEqualEqual', text: '==', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'ObserveDecl', text: ';', subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'InterfaceDefinition', text: '}', subtree_size: 9},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
@@ -1589,6 +1589,45 @@ struct RequireDecl {
|
||||
Lex::SemiTokenIndex token;
|
||||
};
|
||||
|
||||
// `observe` declarations
|
||||
// --------------------------------
|
||||
|
||||
// `observe`
|
||||
using ObserveIntroducer =
|
||||
LeafNode<NodeKind::ObserveIntroducer, Lex::ObserveTokenIndex>;
|
||||
|
||||
// `==`
|
||||
struct ObserveEqualEqual {
|
||||
static constexpr auto Kind = NodeKind::ObserveEqualEqual.Define(
|
||||
{.category = NodeCategory::ObserveOperator, .child_count = 2});
|
||||
|
||||
AnyObserveOperandId lhs;
|
||||
Lex::EqualEqualTokenIndex token;
|
||||
AnyExprId rhs;
|
||||
};
|
||||
|
||||
// `impls`
|
||||
struct ObserveImpls {
|
||||
static constexpr auto Kind = NodeKind::ObserveImpls.Define(
|
||||
{.category = NodeCategory::ObserveOperator, .child_count = 2});
|
||||
|
||||
AnyObserveOperandId lhs;
|
||||
Lex::ImplsTokenIndex token;
|
||||
AnyExprId rhs;
|
||||
};
|
||||
|
||||
// `observe T == U impls I`
|
||||
struct ObserveDecl {
|
||||
static constexpr auto Kind =
|
||||
NodeKind::ObserveDecl.Define({.category = NodeCategory::Decl,
|
||||
.bracketed_by = ObserveIntroducer::Kind});
|
||||
|
||||
ObserveIntroducerId introducer;
|
||||
llvm::SmallVector<AnyModifierId> modifiers;
|
||||
AnyObserveOperatorId op;
|
||||
Lex::SemiTokenIndex token;
|
||||
};
|
||||
|
||||
// `impl`...`as` declarations and definitions
|
||||
// ------------------------------------------
|
||||
|
||||
|
||||
Reference in New Issue
Block a user