//===--- 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 Root, const StmtSyntaxData *Data) : Syntax(Root, Data) {} #pragma mark - unknown-statement Data UnknownStmtSyntaxData::UnknownStmtSyntaxData(RC Raw, const SyntaxData *Parent, CursorIndex IndexInParent) : UnknownSyntaxData(Raw, Parent, IndexInParent) { assert(Raw->Kind == SyntaxKind::UnknownStmt); } RC UnknownStmtSyntaxData::make(RC Raw, const SyntaxData *Parent, CursorIndex IndexInParent) { auto UnknownRaw = RawSyntax::make(SyntaxKind::UnknownStmt, Raw->Layout, Raw->Presence); return RC { new UnknownStmtSyntaxData { UnknownRaw, Parent, IndexInParent } }; } #pragma mark - unknown-statement API UnknownStmtSyntax::UnknownStmtSyntax(const RC Root, const UnknownStmtSyntaxData *Data) : UnknownSyntax(Root, Data) {} #pragma mark fallthrough-statement Data FallthroughStmtSyntaxData::FallthroughStmtSyntaxData(RC 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::make(RC Raw, const SyntaxData *Parent, CursorIndex IndexInParent) { return RC { new FallthroughStmtSyntaxData { Raw, Parent, IndexInParent } }; } RC 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 Root, const FallthroughStmtSyntaxData *Data) : StmtSyntax(Root, Data) {} FallthroughStmtSyntax FallthroughStmtSyntax::make(RC 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 FallthroughStmtSyntax::getFallthroughKeyword() const { return cast(getRaw()->getChild(Cursor::FallthroughKeyword)); } FallthroughStmtSyntax FallthroughStmtSyntax:: withFallthroughKeyword(RC NewFallthroughKeyword) const { syntax_assert_token_is(NewFallthroughKeyword, tok::kw_fallthrough, "fallthrough"); return Data->replaceChild(NewFallthroughKeyword, Cursor::FallthroughKeyword); } CodeBlockStmtSyntaxData::CodeBlockStmtSyntaxData(RC 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::make(RC Raw, const SyntaxData *Parent, CursorIndex IndexInParent) { return RC { new CodeBlockStmtSyntaxData { Raw, Parent, IndexInParent } }; } RC 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 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::make(RC Raw, const SyntaxData *Parent, CursorIndex IndexInParent) { return RC { new BreakStmtSyntaxData { Raw, Parent, IndexInParent } }; } RC 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 Root, BreakStmtSyntaxData *Data) : StmtSyntax(Root, Data) {} BreakStmtSyntax BreakStmtSyntax::make(RC 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 BreakStmtSyntax::getBreakKeyword() const { return cast(getRaw()->getChild(Cursor::BreakKeyword)); } BreakStmtSyntax BreakStmtSyntax::withBreakKeyword(RC NewBreakKeyword) const { syntax_assert_token_is(NewBreakKeyword, tok::kw_break, "break"); return Data->replaceChild(NewBreakKeyword, Cursor::BreakKeyword); } RC BreakStmtSyntax::getLabel() const { return cast(getRaw()->getChild(Cursor::Label)); } BreakStmtSyntax BreakStmtSyntax::withLabel(RC NewLabel) const { assert(NewLabel->getTokenKind() == tok::identifier); return Data->replaceChild(NewLabel, Cursor::Label); } #pragma mark - continue-statement Data ContinueStmtSyntaxData::ContinueStmtSyntaxData(RC 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::make(RC Raw, const SyntaxData *Parent, CursorIndex IndexInParent) { return RC { new ContinueStmtSyntaxData { Raw, Parent, IndexInParent } }; } RC 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 Root, ContinueStmtSyntaxData *Data) : StmtSyntax(Root, Data) {} ContinueStmtSyntax ContinueStmtSyntax::make(RC 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 ContinueStmtSyntax::getContinueKeyword() const { return cast(getRaw()->getChild(Cursor::ContinueKeyword)); } ContinueStmtSyntax ContinueStmtSyntax:: withContinueKeyword(RC NewContinueKeyword) const { syntax_assert_token_is(NewContinueKeyword, tok::kw_continue, "continue"); return Data->replaceChild(NewContinueKeyword, Cursor::ContinueKeyword); } RC ContinueStmtSyntax::getLabel() const { return cast(getRaw()->getChild(Cursor::Label)); } ContinueStmtSyntax ContinueStmtSyntax::withLabel(RC NewLabel) const { assert(NewLabel->getTokenKind() == tok::identifier); return Data->replaceChild(NewLabel, Cursor::Label); } #pragma mark - return-statement Data ReturnStmtSyntaxData::ReturnStmtSyntaxData(RC 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::make(RC Raw, const SyntaxData *Parent, CursorIndex IndexInParent) { return RC { new ReturnStmtSyntaxData { Raw, Parent, IndexInParent } }; } RC 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 Root, const ReturnStmtSyntaxData *Data) : StmtSyntax(Root, Data) {} ReturnStmtSyntax ReturnStmtSyntax::make(RC 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 ReturnStmtSyntax::getReturnKeyword() const { return cast(getRaw()->getChild(Cursor::ReturnKeyword)); } ReturnStmtSyntax ReturnStmtSyntax:: withReturnKeyword(RC NewReturnKeyword) const { syntax_assert_token_is(NewReturnKeyword, tok::kw_return, "return"); return Data->replaceChild(NewReturnKeyword, Cursor::ReturnKeyword); } Optional ReturnStmtSyntax::getExpression() const { auto RawExpression = getRaw()->getChild(Cursor::Expression); if (RawExpression->isMissing()) { return llvm::None; } auto *MyData = getUnsafeData(); auto &ChildPtr = *reinterpret_cast*>( &MyData->CachedExpression); SyntaxData::realizeSyntaxNode(ChildPtr, RawExpression, MyData, cursorIndex(Cursor::Expression)); return ExprSyntax { Root, MyData->CachedExpression.get() }; } ReturnStmtSyntax ReturnStmtSyntax::withExpression(ExprSyntax NewExpression) const { return Data->replaceChild(NewExpression.getRaw(), Cursor::Expression); } #pragma mark code-block API CodeBlockStmtSyntax::CodeBlockStmtSyntax(const RC Root, CodeBlockStmtSyntaxData *Data) : StmtSyntax(Root, Data) {}