[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:
David Farler
2017-02-20 17:11:41 -08:00
parent 4ffbeb57f6
commit c343298b8f
29 changed files with 1298 additions and 196 deletions

View File

@@ -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(