mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[Syntax] Implement return-statement and integer-literal-expr
A return statement needs something to return, so implement
integer-literal-expression too. This necessarily also forced
UnknownExprSyntax, UnknownStmtSyntax, and UnknownDeclSyntax,
which are stand-in token buckets for when we don't know
how to transform/migrate an AST.
This commit also contains the core function for caching
SyntaxData children. This is highly tricky code, with some
detailed comments in SyntaxData.{h,cpp}. The gist is that
we have to atomically swap in a SyntaxData pointer into the
child field, so we can maintain pointer identity of SyntaxData
nodes, while still being able to cache them internally.
To prove that this works, there is a multithreaded test that
checks that two threads can ask for a child that hasn't been
cached yet without crashing or violating pointer identity.
https://bugs.swift.org/browse/SR-4010
This commit is contained in:
@@ -21,14 +21,58 @@ using llvm::None;
|
||||
using namespace swift;
|
||||
using namespace swift::syntax;
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-parameter Data
|
||||
#pragma mark - conformance-requirement Data
|
||||
|
||||
ConformanceRequirementSyntaxData::
|
||||
ConformanceRequirementSyntaxData(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent)
|
||||
: SyntaxData(Raw, Parent, IndexInParent) {
|
||||
assert(Raw->Kind == SyntaxKind::ConformanceRequirement);
|
||||
syntax_assert_child_kind(Raw,
|
||||
ConformanceRequirementSyntax::Cursor::LeftTypeIdentifier,
|
||||
SyntaxKind::TypeIdentifier);
|
||||
syntax_assert_child_token_text(Raw,
|
||||
ConformanceRequirementSyntax::Cursor::Colon,
|
||||
tok::colon, ":");
|
||||
syntax_assert_child_kind(Raw,
|
||||
ConformanceRequirementSyntax::Cursor::RightTypeIdentifier,
|
||||
SyntaxKind::TypeIdentifier);
|
||||
}
|
||||
|
||||
RC<ConformanceRequirementSyntaxData>
|
||||
ConformanceRequirementSyntaxData::make(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent) {
|
||||
return RC<ConformanceRequirementSyntaxData> {
|
||||
new ConformanceRequirementSyntaxData {
|
||||
Raw, Parent, IndexInParent
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
RC<ConformanceRequirementSyntaxData>
|
||||
ConformanceRequirementSyntaxData::makeBlank() {
|
||||
auto Raw = RawSyntax::make(SyntaxKind::ConformanceRequirement,
|
||||
{
|
||||
RawSyntax::missing(SyntaxKind::TypeIdentifier),
|
||||
TokenSyntax::missingToken(tok::colon, ":"),
|
||||
RawSyntax::missing(SyntaxKind::TypeIdentifier),
|
||||
},
|
||||
SourcePresence::Present);
|
||||
return make(Raw);
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - generic-parameter Data
|
||||
|
||||
GenericParameterSyntaxData::
|
||||
GenericParameterSyntaxData(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent)
|
||||
: SyntaxData(Raw, Parent, IndexInParent) {}
|
||||
: SyntaxData(Raw, Parent, IndexInParent) {
|
||||
assert(Raw->Kind == SyntaxKind::GenericParameter);
|
||||
}
|
||||
|
||||
RC<GenericParameterSyntaxData>
|
||||
GenericParameterSyntaxData::make(RC<RawSyntax> Raw,
|
||||
@@ -49,14 +93,40 @@ RC<GenericParameterSyntaxData> GenericParameterSyntaxData::makeBlank() {
|
||||
SourcePresence::Present));
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-parameter API
|
||||
#pragma mark - generic-parameter API
|
||||
|
||||
GenericParameterSyntax::
|
||||
GenericParameterSyntax(RC<SyntaxData> Root,
|
||||
const GenericParameterSyntaxData *Data)
|
||||
: Syntax(Root, Data) {}
|
||||
|
||||
#pragma mark - generic-parameter-list Data
|
||||
|
||||
GenericParameterListSyntaxData::
|
||||
GenericParameterListSyntaxData(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent)
|
||||
: SyntaxData(Raw, Parent, IndexInParent) {
|
||||
assert(Raw->Kind == SyntaxKind::GenericParameterList);
|
||||
}
|
||||
|
||||
RC<GenericParameterListSyntaxData>
|
||||
GenericParameterListSyntaxData::make(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent) {
|
||||
return RC<GenericParameterListSyntaxData> {
|
||||
new GenericParameterListSyntaxData {
|
||||
Raw, Parent, IndexInParent
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
RC<GenericParameterListSyntaxData> GenericParameterListSyntaxData::makeBlank() {
|
||||
auto Raw = RawSyntax::make(SyntaxKind::GenericParameterList,
|
||||
{}, SourcePresence::Present);
|
||||
return make(Raw);
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-parameter-clause Data
|
||||
|
||||
@@ -65,7 +135,17 @@ GenericParameterClauseSyntaxData(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent)
|
||||
: SyntaxData(Raw, Parent, IndexInParent) {
|
||||
// TODO: Kind assertions
|
||||
syntax_assert_child_token_text(Raw,
|
||||
GenericParameterClauseSyntax::Cursor::LeftAngleBracketToken,
|
||||
tok::l_angle, "<");
|
||||
|
||||
syntax_assert_child_kind(Raw,
|
||||
GenericParameterClauseSyntax::Cursor::GenericParameterList,
|
||||
SyntaxKind::GenericParameterList);
|
||||
|
||||
syntax_assert_child_token_text(Raw,
|
||||
GenericParameterClauseSyntax::Cursor::RightAngleBracketToken,
|
||||
tok::r_angle, ">");
|
||||
}
|
||||
|
||||
RC<GenericParameterClauseSyntaxData>
|
||||
@@ -90,16 +170,14 @@ GenericParameterClauseSyntaxData::makeBlank() {
|
||||
SourcePresence::Present));
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-parameter-clause API
|
||||
#pragma mark - generic-parameter-clause API
|
||||
|
||||
GenericParameterClauseSyntax::
|
||||
GenericParameterClauseSyntax(RC<SyntaxData> Root,
|
||||
const GenericParameterClauseSyntaxData *Data)
|
||||
: Syntax(Root, Data) {}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-parameter-clause Builder
|
||||
#pragma mark - generic-parameter-clause Builder
|
||||
|
||||
GenericParameterClauseBuilder::GenericParameterClauseBuilder()
|
||||
: LeftAngleToken(TokenSyntax::missingToken(tok::l_angle, "<")),
|
||||
@@ -148,14 +226,46 @@ GenericParameterClauseSyntax GenericParameterClauseBuilder::build() const {
|
||||
return { Data, Data.get() };
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-where-clause Data
|
||||
#pragma mark - generic-requirement-list Data
|
||||
|
||||
GenericRequirementListSyntaxData::
|
||||
GenericRequirementListSyntaxData(RC<RawSyntax> Raw, const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent)
|
||||
: SyntaxData(Raw, Parent, IndexInParent) {
|
||||
assert(Raw->Kind == SyntaxKind::GenericRequirementList);
|
||||
}
|
||||
|
||||
RC<GenericRequirementListSyntaxData>
|
||||
GenericRequirementListSyntaxData::make(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent) {
|
||||
return RC<GenericRequirementListSyntaxData> {
|
||||
new GenericRequirementListSyntaxData {
|
||||
Raw, Parent, IndexInParent
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
RC<GenericRequirementListSyntaxData>
|
||||
GenericRequirementListSyntaxData::makeBlank() {
|
||||
auto Raw = RawSyntax::make(SyntaxKind::GenericRequirementList,
|
||||
{},
|
||||
SourcePresence::Present);
|
||||
return make(Raw);
|
||||
}
|
||||
|
||||
#pragma mark - generic-where-clause Data
|
||||
|
||||
GenericWhereClauseSyntaxData::
|
||||
GenericWhereClauseSyntaxData(RC<RawSyntax> Raw, const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent)
|
||||
: SyntaxData(Raw, Parent, IndexInParent) {
|
||||
// TODO: Kind Assertions
|
||||
assert(Raw->Kind == SyntaxKind::GenericWhereClause);
|
||||
syntax_assert_child_token_text(Raw,
|
||||
GenericWhereClauseSyntax::Cursor::WhereToken, tok::kw_where, "where");
|
||||
syntax_assert_child_kind(Raw,
|
||||
GenericWhereClauseSyntax::Cursor::RequirementList,
|
||||
SyntaxKind::GenericRequirementList);
|
||||
}
|
||||
|
||||
RC<GenericWhereClauseSyntaxData>
|
||||
@@ -169,31 +279,35 @@ GenericWhereClauseSyntaxData::make(RC<RawSyntax> Raw,
|
||||
|
||||
RC<GenericWhereClauseSyntaxData> GenericWhereClauseSyntaxData::makeBlank() {
|
||||
return make(RawSyntax::make(SyntaxKind::GenericWhereClause,
|
||||
{
|
||||
RawSyntax::missing(SyntaxKind::TypeIdentifier),
|
||||
TokenSyntax::missingToken(tok::equal, "="),
|
||||
RawSyntax::missing(SyntaxKind::MissingType),
|
||||
},
|
||||
SourcePresence::Present));
|
||||
{
|
||||
TokenSyntax::missingToken(tok::kw_where, "where"),
|
||||
RawSyntax::missing(SyntaxKind::GenericRequirementList),
|
||||
},
|
||||
SourcePresence::Present));
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-where-clause API
|
||||
#pragma mark - generic-where-clause API
|
||||
|
||||
GenericWhereClauseSyntax::
|
||||
GenericWhereClauseSyntax(RC<SyntaxData> Root,
|
||||
const GenericWhereClauseSyntaxData *Data)
|
||||
: Syntax(Root, Data) {}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark same-type-requirement Data
|
||||
#pragma mark - same-type-requirement Data
|
||||
|
||||
SameTypeRequirementSyntaxData::
|
||||
SameTypeRequirementSyntaxData(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent)
|
||||
: SyntaxData(Raw, Parent, IndexInParent) {
|
||||
// TODO: kind assertions
|
||||
assert(Raw->Kind == SyntaxKind::SameTypeRequirement);
|
||||
assert(Raw->Layout.size() == 3);
|
||||
syntax_assert_child_kind(Raw,
|
||||
SameTypeRequirementSyntax::Cursor::LeftTypeIdentifier,
|
||||
SyntaxKind::TypeIdentifier);
|
||||
syntax_assert_child_token_text(Raw,
|
||||
SameTypeRequirementSyntax::Cursor::EqualityToken, tok::identifier, "==");
|
||||
assert(Raw->getChild(SameTypeRequirementSyntax::Cursor::RightType)->isType());
|
||||
}
|
||||
|
||||
RC<SameTypeRequirementSyntaxData>
|
||||
@@ -217,16 +331,43 @@ RC<SameTypeRequirementSyntaxData> SameTypeRequirementSyntaxData::makeBlank() {
|
||||
SourcePresence::Present));
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark same-type-requirement API
|
||||
#pragma mark - same-type-requirement API
|
||||
|
||||
SameTypeRequirementSyntax::
|
||||
SameTypeRequirementSyntax(RC<SyntaxData> Root,
|
||||
const SameTypeRequirementSyntaxData *Data)
|
||||
: Syntax(Root, Data) {}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-argument-clause Data
|
||||
#pragma mark - generic-argument-list Data
|
||||
|
||||
GenericArgumentListSyntaxData::
|
||||
GenericArgumentListSyntaxData(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent)
|
||||
: SyntaxData(Raw, Parent, IndexInParent) {
|
||||
assert(Raw->Kind == SyntaxKind::GenericArgumentList);
|
||||
}
|
||||
|
||||
RC<GenericArgumentListSyntaxData>
|
||||
GenericArgumentListSyntaxData::make(RC<RawSyntax> Raw, const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent) {
|
||||
return RC<GenericArgumentListSyntaxData> {
|
||||
new GenericArgumentListSyntaxData {
|
||||
Raw, Parent, IndexInParent
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
RC<GenericArgumentListSyntaxData> GenericArgumentListSyntaxData::makeBlank() {
|
||||
auto Raw = RawSyntax::make(SyntaxKind::GenericArgumentList, {},
|
||||
SourcePresence::Present);
|
||||
return make(Raw);
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - generic-argument-list API (TODO)
|
||||
|
||||
#pragma mark - generic-argument-clause Data
|
||||
|
||||
GenericArgumentClauseSyntaxData::
|
||||
GenericArgumentClauseSyntaxData(RC<RawSyntax> Raw, const SyntaxData *Parent,
|
||||
@@ -254,8 +395,7 @@ GenericArgumentClauseSyntaxData::makeBlank() {
|
||||
return make(Raw);
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-argument-clause API
|
||||
#pragma mark - generic-argument-clause API
|
||||
|
||||
GenericArgumentClauseSyntax::
|
||||
GenericArgumentClauseSyntax(RC<SyntaxData> Root,
|
||||
@@ -278,8 +418,7 @@ withRightAngleBracket(RC<TokenSyntax> NewRightAngleBracket) const {
|
||||
NewRightAngleBracket, Cursor::RightAngleBracketToken);
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-argument-clause Builder
|
||||
#pragma mark - generic-argument-clause Builder
|
||||
|
||||
GenericArgumentClauseBuilder::GenericArgumentClauseBuilder()
|
||||
: ArgumentListLayout(
|
||||
|
||||
Reference in New Issue
Block a user