mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
383 lines
14 KiB
C++
383 lines
14 KiB
C++
//===--- StmtSyntax.cpp - Swift Statement Syntax Implementation -----------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "swift/Syntax/TokenSyntax.h"
|
|
#include "swift/Syntax/ExprSyntax.h"
|
|
#include "swift/Syntax/StmtSyntax.h"
|
|
|
|
using namespace swift;
|
|
using namespace swift::syntax;
|
|
|
|
#pragma mark - statement API
|
|
|
|
StmtSyntax::StmtSyntax(const RC<SyntaxData> Root, const StmtSyntaxData *Data)
|
|
: Syntax(Root, Data) {}
|
|
|
|
#pragma mark - unknown-statement Data
|
|
|
|
UnknownStmtSyntaxData::UnknownStmtSyntaxData(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent,
|
|
CursorIndex IndexInParent)
|
|
: UnknownSyntaxData(Raw, Parent, IndexInParent) {
|
|
assert(Raw->Kind == SyntaxKind::UnknownStmt);
|
|
}
|
|
|
|
RC<UnknownStmtSyntaxData>
|
|
UnknownStmtSyntaxData::make(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent,
|
|
CursorIndex IndexInParent) {
|
|
auto UnknownRaw = RawSyntax::make(SyntaxKind::UnknownStmt, Raw->Layout,
|
|
Raw->Presence);
|
|
return RC<UnknownStmtSyntaxData> {
|
|
new UnknownStmtSyntaxData {
|
|
UnknownRaw, Parent, IndexInParent
|
|
}
|
|
};
|
|
}
|
|
|
|
#pragma mark - unknown-statement API
|
|
|
|
UnknownStmtSyntax::UnknownStmtSyntax(const RC<SyntaxData> Root,
|
|
const UnknownStmtSyntaxData *Data)
|
|
: UnknownSyntax(Root, Data) {}
|
|
|
|
#pragma mark fallthrough-statement Data
|
|
|
|
FallthroughStmtSyntaxData::FallthroughStmtSyntaxData(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent,
|
|
CursorIndex IndexInParent)
|
|
: StmtSyntaxData(Raw, Parent, IndexInParent) {
|
|
assert(Raw->Kind == SyntaxKind::FallthroughStmt);
|
|
assert(Raw->Layout.size() == 1);
|
|
syntax_assert_child_token_text(Raw,
|
|
FallthroughStmtSyntax::Cursor::FallthroughKeyword,
|
|
tok::kw_fallthrough, "fallthrough");
|
|
}
|
|
|
|
RC<FallthroughStmtSyntaxData>
|
|
FallthroughStmtSyntaxData::make(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent,
|
|
CursorIndex IndexInParent) {
|
|
return RC<FallthroughStmtSyntaxData> {
|
|
new FallthroughStmtSyntaxData { Raw, Parent, IndexInParent }
|
|
};
|
|
}
|
|
|
|
RC<FallthroughStmtSyntaxData> FallthroughStmtSyntaxData::makeBlank() {
|
|
return make(RawSyntax::make(SyntaxKind::FallthroughStmt,
|
|
{
|
|
TokenSyntax::missingToken(tok::kw_fallthrough, "fallthrough"),
|
|
},
|
|
SourcePresence::Present));
|
|
}
|
|
|
|
#pragma mark fallthrough-statement API
|
|
|
|
FallthroughStmtSyntax::
|
|
FallthroughStmtSyntax(const RC<SyntaxData> Root,
|
|
const FallthroughStmtSyntaxData *Data)
|
|
: StmtSyntax(Root, Data) {}
|
|
|
|
FallthroughStmtSyntax
|
|
FallthroughStmtSyntax::make(RC<RawSyntax> Raw, const SyntaxData *Parent,
|
|
CursorIndex IndexInParent) {
|
|
assert(Raw->Layout.size() == 1);
|
|
syntax_assert_child_token_text(Raw,
|
|
Cursor::FallthroughKeyword,
|
|
tok::kw_fallthrough, "fallthrough");
|
|
auto Data = FallthroughStmtSyntaxData::make(Raw, Parent, IndexInParent);
|
|
return FallthroughStmtSyntax {
|
|
Data, Data.get(),
|
|
};
|
|
}
|
|
|
|
RC<TokenSyntax> FallthroughStmtSyntax::getFallthroughKeyword() const {
|
|
return cast<TokenSyntax>(getRaw()->getChild(Cursor::FallthroughKeyword));
|
|
}
|
|
|
|
FallthroughStmtSyntax FallthroughStmtSyntax::
|
|
withFallthroughKeyword(RC<TokenSyntax> NewFallthroughKeyword) const {
|
|
syntax_assert_token_is(NewFallthroughKeyword, tok::kw_fallthrough,
|
|
"fallthrough");
|
|
return Data->replaceChild<FallthroughStmtSyntax>(NewFallthroughKeyword,
|
|
Cursor::FallthroughKeyword);
|
|
}
|
|
|
|
|
|
CodeBlockStmtSyntaxData::CodeBlockStmtSyntaxData(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent,
|
|
CursorIndex IndexInParent)
|
|
: StmtSyntaxData(Raw, Parent, IndexInParent) {
|
|
assert(Raw->Kind == SyntaxKind::CodeBlockStmt);
|
|
syntax_assert_child_token_text(Raw, CodeBlockStmtSyntax::Cursor::LeftBrace,
|
|
tok::l_brace, "{");
|
|
syntax_assert_child_kind(Raw, CodeBlockStmtSyntax::Cursor::Elements,
|
|
SyntaxKind::StmtList);
|
|
syntax_assert_child_token_text(Raw, CodeBlockStmtSyntax::Cursor::RightBrace,
|
|
tok::r_brace, "}");
|
|
}
|
|
|
|
RC<CodeBlockStmtSyntaxData>
|
|
CodeBlockStmtSyntaxData::make(RC<RawSyntax> Raw, const SyntaxData *Parent,
|
|
CursorIndex IndexInParent) {
|
|
return RC<CodeBlockStmtSyntaxData> {
|
|
new CodeBlockStmtSyntaxData { Raw, Parent, IndexInParent }
|
|
};
|
|
}
|
|
|
|
RC<CodeBlockStmtSyntaxData>
|
|
CodeBlockStmtSyntaxData::makeBlank() {
|
|
return make(RawSyntax::make(SyntaxKind::CodeBlockStmt,
|
|
{
|
|
TokenSyntax::missingToken(tok::l_brace, "{"),
|
|
RawSyntax::missing(SyntaxKind::StmtList),
|
|
TokenSyntax::missingToken(tok::r_brace, "}"),
|
|
},
|
|
SourcePresence::Present));
|
|
}
|
|
|
|
#pragma mark - break-statement Data
|
|
|
|
BreakStmtSyntaxData::BreakStmtSyntaxData(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent,
|
|
CursorIndex IndexInParent)
|
|
: StmtSyntaxData(Raw, Parent, IndexInParent) {
|
|
assert(Raw->Layout.size() == 2);
|
|
syntax_assert_child_token_text(Raw, BreakStmtSyntax::Cursor::BreakKeyword,
|
|
tok::kw_break, "break");
|
|
syntax_assert_child_token(Raw, BreakStmtSyntax::Cursor::Label,
|
|
tok::identifier);
|
|
}
|
|
|
|
RC<BreakStmtSyntaxData>
|
|
BreakStmtSyntaxData::make(RC<RawSyntax> Raw, const SyntaxData *Parent,
|
|
CursorIndex IndexInParent) {
|
|
return RC<BreakStmtSyntaxData> {
|
|
new BreakStmtSyntaxData {
|
|
Raw, Parent, IndexInParent
|
|
}
|
|
};
|
|
}
|
|
|
|
RC<BreakStmtSyntaxData> BreakStmtSyntaxData::makeBlank() {
|
|
return make(RawSyntax::make(SyntaxKind::BreakStmt,
|
|
{
|
|
TokenSyntax::missingToken(tok::kw_break,
|
|
"break"),
|
|
TokenSyntax::missingToken(tok::identifier, ""),
|
|
},
|
|
SourcePresence::Present));
|
|
}
|
|
|
|
#pragma mark - break-statement API
|
|
|
|
BreakStmtSyntax::BreakStmtSyntax(const RC<SyntaxData> Root,
|
|
BreakStmtSyntaxData *Data)
|
|
: StmtSyntax(Root, Data) {}
|
|
|
|
BreakStmtSyntax BreakStmtSyntax::make(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent,
|
|
CursorIndex IndexInParent) {
|
|
auto Data = BreakStmtSyntaxData::make(Raw, Parent, IndexInParent);
|
|
return { Data, Data.get() };
|
|
}
|
|
|
|
BreakStmtSyntax BreakStmtSyntax::makeBlank() {
|
|
auto Data = BreakStmtSyntaxData::makeBlank();
|
|
return { Data, Data.get() };
|
|
}
|
|
|
|
RC<TokenSyntax> BreakStmtSyntax::getBreakKeyword() const {
|
|
return cast<TokenSyntax>(getRaw()->getChild(Cursor::BreakKeyword));
|
|
}
|
|
|
|
BreakStmtSyntax
|
|
BreakStmtSyntax::withBreakKeyword(RC<TokenSyntax> NewBreakKeyword) const {
|
|
syntax_assert_token_is(NewBreakKeyword, tok::kw_break, "break");
|
|
return Data->replaceChild<BreakStmtSyntax>(NewBreakKeyword,
|
|
Cursor::BreakKeyword);
|
|
}
|
|
|
|
RC<TokenSyntax> BreakStmtSyntax::getLabel() const {
|
|
return cast<TokenSyntax>(getRaw()->getChild(Cursor::Label));
|
|
}
|
|
|
|
BreakStmtSyntax BreakStmtSyntax::withLabel(RC<TokenSyntax> NewLabel) const {
|
|
assert(NewLabel->getTokenKind() == tok::identifier);
|
|
return Data->replaceChild<BreakStmtSyntax>(NewLabel, Cursor::Label);
|
|
}
|
|
|
|
#pragma mark - continue-statement Data
|
|
|
|
ContinueStmtSyntaxData::ContinueStmtSyntaxData(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent,
|
|
CursorIndex IndexInParent)
|
|
: StmtSyntaxData(Raw, Parent, IndexInParent) {
|
|
assert(Raw->Layout.size() == 2);
|
|
syntax_assert_child_token_text(Raw,
|
|
ContinueStmtSyntax::Cursor::ContinueKeyword,
|
|
tok::kw_continue, "continue");
|
|
syntax_assert_child_token(Raw, ContinueStmtSyntax::Cursor::Label,
|
|
tok::identifier);
|
|
}
|
|
|
|
RC<ContinueStmtSyntaxData>
|
|
ContinueStmtSyntaxData::make(RC<RawSyntax> Raw, const SyntaxData *Parent,
|
|
CursorIndex IndexInParent) {
|
|
return RC<ContinueStmtSyntaxData> {
|
|
new ContinueStmtSyntaxData {
|
|
Raw, Parent, IndexInParent
|
|
}
|
|
};
|
|
}
|
|
|
|
RC<ContinueStmtSyntaxData> ContinueStmtSyntaxData::makeBlank() {
|
|
return make(RawSyntax::make(SyntaxKind::ContinueStmt,
|
|
{
|
|
TokenSyntax::missingToken(tok::kw_continue,
|
|
"continue"),
|
|
TokenSyntax::missingToken(tok::identifier, ""),
|
|
},
|
|
SourcePresence::Present));
|
|
}
|
|
|
|
#pragma mark - continue-statement API
|
|
|
|
ContinueStmtSyntax::ContinueStmtSyntax(const RC<SyntaxData> Root,
|
|
ContinueStmtSyntaxData *Data)
|
|
: StmtSyntax(Root, Data) {}
|
|
|
|
ContinueStmtSyntax ContinueStmtSyntax::make(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent,
|
|
CursorIndex IndexInParent) {
|
|
auto Data = ContinueStmtSyntaxData::make(Raw, Parent, IndexInParent);
|
|
return { Data, Data.get() };
|
|
}
|
|
|
|
ContinueStmtSyntax ContinueStmtSyntax::makeBlank() {
|
|
auto Data = ContinueStmtSyntaxData::makeBlank();
|
|
return { Data, Data.get() };
|
|
}
|
|
|
|
RC<TokenSyntax> ContinueStmtSyntax::getContinueKeyword() const {
|
|
return cast<TokenSyntax>(getRaw()->getChild(Cursor::ContinueKeyword));
|
|
}
|
|
|
|
ContinueStmtSyntax ContinueStmtSyntax::
|
|
withContinueKeyword(RC<TokenSyntax> NewContinueKeyword) const {
|
|
syntax_assert_token_is(NewContinueKeyword, tok::kw_continue, "continue");
|
|
return Data->replaceChild<ContinueStmtSyntax>(NewContinueKeyword,
|
|
Cursor::ContinueKeyword);
|
|
}
|
|
|
|
RC<TokenSyntax> ContinueStmtSyntax::getLabel() const {
|
|
return cast<TokenSyntax>(getRaw()->getChild(Cursor::Label));
|
|
}
|
|
|
|
ContinueStmtSyntax
|
|
ContinueStmtSyntax::withLabel(RC<TokenSyntax> NewLabel) const {
|
|
assert(NewLabel->getTokenKind() == tok::identifier);
|
|
return Data->replaceChild<ContinueStmtSyntax>(NewLabel, Cursor::Label);
|
|
}
|
|
|
|
#pragma mark - return-statement Data
|
|
|
|
ReturnStmtSyntaxData::ReturnStmtSyntaxData(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent,
|
|
CursorIndex IndexInParent)
|
|
: StmtSyntaxData(Raw, Parent, IndexInParent) {
|
|
assert(Raw->Layout.size() == 2);
|
|
syntax_assert_child_token_text(Raw,
|
|
ReturnStmtSyntax::Cursor::ReturnKeyword,
|
|
tok::kw_return, "return");
|
|
assert(Raw->getChild(ReturnStmtSyntax::Cursor::Expression)->isExpr());
|
|
}
|
|
|
|
RC<ReturnStmtSyntaxData>
|
|
ReturnStmtSyntaxData::make(RC<RawSyntax> Raw, const SyntaxData *Parent,
|
|
CursorIndex IndexInParent) {
|
|
return RC<ReturnStmtSyntaxData> {
|
|
new ReturnStmtSyntaxData {
|
|
Raw, Parent, IndexInParent
|
|
}
|
|
};
|
|
}
|
|
|
|
RC<ReturnStmtSyntaxData> ReturnStmtSyntaxData::makeBlank() {
|
|
return make(RawSyntax::make(SyntaxKind::ReturnStmt,
|
|
{
|
|
TokenSyntax::missingToken(tok::kw_return,
|
|
"return"),
|
|
RawSyntax::missing(SyntaxKind::MissingExpr),
|
|
},
|
|
SourcePresence::Present));
|
|
}
|
|
|
|
#pragma mark - return-statement API
|
|
|
|
ReturnStmtSyntax::ReturnStmtSyntax(const RC<SyntaxData> Root,
|
|
const ReturnStmtSyntaxData *Data)
|
|
: StmtSyntax(Root, Data) {}
|
|
|
|
ReturnStmtSyntax ReturnStmtSyntax::make(RC<RawSyntax> Raw,
|
|
const SyntaxData *Parent,
|
|
CursorIndex IndexInParent) {
|
|
auto Data = ReturnStmtSyntaxData::make(Raw, Parent, IndexInParent);
|
|
return { Data, Data.get() };
|
|
}
|
|
|
|
ReturnStmtSyntax ReturnStmtSyntax::makeBlank() {
|
|
auto Data = ReturnStmtSyntaxData::makeBlank();
|
|
return { Data, Data.get() };
|
|
}
|
|
|
|
RC<TokenSyntax> ReturnStmtSyntax::getReturnKeyword() const {
|
|
return cast<TokenSyntax>(getRaw()->getChild(Cursor::ReturnKeyword));
|
|
}
|
|
|
|
ReturnStmtSyntax ReturnStmtSyntax::
|
|
withReturnKeyword(RC<TokenSyntax> NewReturnKeyword) const {
|
|
syntax_assert_token_is(NewReturnKeyword, tok::kw_return, "return");
|
|
return Data->replaceChild<ReturnStmtSyntax>(NewReturnKeyword,
|
|
Cursor::ReturnKeyword);
|
|
}
|
|
|
|
Optional<ExprSyntax> ReturnStmtSyntax::getExpression() const {
|
|
auto RawExpression = getRaw()->getChild(Cursor::Expression);
|
|
if (RawExpression->isMissing()) {
|
|
return llvm::None;
|
|
}
|
|
|
|
auto *MyData = getUnsafeData<ReturnStmtSyntax>();
|
|
|
|
auto &ChildPtr = *reinterpret_cast<std::atomic<uintptr_t>*>(
|
|
&MyData->CachedExpression);
|
|
|
|
SyntaxData::realizeSyntaxNode<ExprSyntax>(ChildPtr, RawExpression, MyData,
|
|
cursorIndex(Cursor::Expression));
|
|
|
|
return ExprSyntax { Root, MyData->CachedExpression.get() };
|
|
}
|
|
|
|
ReturnStmtSyntax
|
|
ReturnStmtSyntax::withExpression(ExprSyntax NewExpression) const {
|
|
return Data->replaceChild<ReturnStmtSyntax>(NewExpression.getRaw(),
|
|
Cursor::Expression);
|
|
}
|
|
|
|
|
|
#pragma mark code-block API
|
|
|
|
CodeBlockStmtSyntax::CodeBlockStmtSyntax(const RC<SyntaxData> Root,
|
|
CodeBlockStmtSyntaxData *Data)
|
|
: StmtSyntax(Root, Data) {}
|