| //===--- ExprSyntax.cpp - Swift Expression Syntax Impl. -------------------===// |
| // |
| // 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/ExprSyntax.h" |
| #include "swift/Syntax/GenericSyntax.h" |
| |
| using namespace swift; |
| using namespace swift::syntax; |
| |
| #pragma mark - expression Data |
| |
| RC<ExprSyntaxData> ExprSyntaxData::make(RC<RawSyntax> Raw, |
| const SyntaxData *Parent, |
| CursorIndex IndexInParent) { |
| return RC<ExprSyntaxData> { |
| new ExprSyntaxData { |
| Raw, Parent, IndexInParent |
| } |
| }; |
| } |
| |
| RC<ExprSyntaxData> ExprSyntaxData::makeBlank() { |
| return make(RawSyntax::missing(SyntaxKind::MissingExpr)); |
| } |
| |
| #pragma mark - expression API |
| |
| ExprSyntax::ExprSyntax(const RC<SyntaxData> Root, const ExprSyntaxData *Data) |
| : Syntax(Root, Data) {} |
| |
| #pragma mark - unknown-expression Data |
| |
| UnknownExprSyntaxData::UnknownExprSyntaxData(RC<RawSyntax> Raw, |
| const SyntaxData *Parent, |
| CursorIndex IndexInParent) |
| : UnknownSyntaxData(Raw, Parent, IndexInParent) { |
| assert(Raw->Kind == SyntaxKind::UnknownExpr); |
| } |
| |
| RC<UnknownExprSyntaxData> |
| UnknownExprSyntaxData::make(RC<RawSyntax> Raw, |
| const SyntaxData *Parent, |
| CursorIndex IndexInParent) { |
| auto UnknownRaw = RawSyntax::make(SyntaxKind::UnknownExpr, Raw->Layout, |
| Raw->Presence); |
| return RC<UnknownExprSyntaxData> { |
| new UnknownExprSyntaxData { |
| UnknownRaw, Parent, IndexInParent |
| } |
| }; |
| } |
| |
| #pragma mark - unknown-expression API |
| |
| UnknownExprSyntax::UnknownExprSyntax(const RC<SyntaxData> Root, |
| const UnknownExprSyntaxData *Data) |
| : UnknownSyntax(Root, Data) {} |
| |
| #pragma mark - integer-literal-expression Data |
| |
| IntegerLiteralExprSyntaxData:: |
| IntegerLiteralExprSyntaxData(RC<RawSyntax> Raw, |
| const SyntaxData *Parent, |
| CursorIndex IndexInParent) |
| : ExprSyntaxData(Raw, Parent, IndexInParent) { |
| assert(Raw->Kind == SyntaxKind::IntegerLiteralExpr); |
| assert(Raw->Layout.size() == 2); |
| syntax_assert_child_token(Raw, IntegerLiteralExprSyntax::Cursor::Sign, |
| tok::oper_prefix); |
| syntax_assert_child_token(Raw, IntegerLiteralExprSyntax::Cursor::Digits, |
| tok::integer_literal); |
| } |
| |
| RC<IntegerLiteralExprSyntaxData> |
| IntegerLiteralExprSyntaxData::make(RC<RawSyntax> Raw, |
| const SyntaxData *Parent, |
| CursorIndex IndexInParent) { |
| return RC<IntegerLiteralExprSyntaxData> { |
| new IntegerLiteralExprSyntaxData { |
| Raw, Parent, IndexInParent |
| } |
| }; |
| } |
| RC<IntegerLiteralExprSyntaxData> IntegerLiteralExprSyntaxData::makeBlank() { |
| auto Raw = RawSyntax::make(SyntaxKind::IntegerLiteralExpr, |
| { |
| TokenSyntax::missingToken(tok::oper_prefix, ""), |
| TokenSyntax::missingToken(tok::integer_literal, "") |
| }, |
| SourcePresence::Present); |
| return make(Raw); |
| } |
| |
| #pragma mark - integer-literal-expression API |
| |
| IntegerLiteralExprSyntax:: |
| IntegerLiteralExprSyntax(const RC<SyntaxData> Root, |
| const IntegerLiteralExprSyntaxData *Data) |
| : ExprSyntax(Root, Data) {} |
| |
| IntegerLiteralExprSyntax |
| IntegerLiteralExprSyntax::withDigits(RC<TokenSyntax> NewDigits) const { |
| assert(NewDigits->getTokenKind() == tok::integer_literal); |
| return Data->replaceChild<IntegerLiteralExprSyntax>(NewDigits, |
| Cursor::Digits); |
| } |
| |
| #pragma mark - symbolic-reference Data |
| |
| SymbolicReferenceExprSyntaxData:: |
| SymbolicReferenceExprSyntaxData(RC<RawSyntax> Raw, const SyntaxData *Parent, |
| CursorIndex IndexInParent) |
| : ExprSyntaxData(Raw, Parent, IndexInParent) { |
| assert(Raw->Layout.size() == 2); |
| syntax_assert_child_token(Raw, |
| SymbolicReferenceExprSyntax::Cursor::Identifier, tok::identifier); |
| syntax_assert_child_kind(Raw, |
| SymbolicReferenceExprSyntax::Cursor::GenericArgumentClause, |
| SyntaxKind::GenericArgumentClause); |
| } |
| |
| RC<SymbolicReferenceExprSyntaxData> |
| SymbolicReferenceExprSyntaxData::make(RC<RawSyntax> Raw, |
| const SyntaxData *Parent, |
| CursorIndex IndexInParent) { |
| return RC<SymbolicReferenceExprSyntaxData> { |
| new SymbolicReferenceExprSyntaxData { |
| Raw, Parent, IndexInParent |
| } |
| }; |
| } |
| |
| RC<SymbolicReferenceExprSyntaxData> |
| SymbolicReferenceExprSyntaxData::makeBlank() { |
| auto Raw = RawSyntax::make(SyntaxKind::SymbolicReferenceExpr, |
| { |
| TokenSyntax::missingToken(tok::identifier, ""), |
| RawSyntax::missing(SyntaxKind::GenericArgumentClause), |
| }, |
| SourcePresence::Present); |
| return make(Raw); |
| } |
| |
| #pragma mark - symbolic-reference API |
| |
| SymbolicReferenceExprSyntax:: |
| SymbolicReferenceExprSyntax(const RC<SyntaxData> Root, const DataType *Data) |
| : ExprSyntax(Root, Data) {} |
| |
| RC<TokenSyntax> SymbolicReferenceExprSyntax::getIdentifier() const { |
| return cast<TokenSyntax>(getRaw()->getChild(Cursor::Identifier)); |
| } |
| |
| SymbolicReferenceExprSyntax SymbolicReferenceExprSyntax:: |
| withIdentifier(RC<TokenSyntax> NewIdentifier) const { |
| assert(NewIdentifier->getTokenKind() == tok::identifier); |
| return Data->replaceChild<SymbolicReferenceExprSyntax>(NewIdentifier, |
| Cursor::Identifier); |
| } |
| |
| llvm::Optional<GenericArgumentClauseSyntax> |
| SymbolicReferenceExprSyntax::getGenericArgumentClause() const { |
| auto RawClause = getRaw()->getChild(Cursor::GenericArgumentClause); |
| if (RawClause->isMissing()) { |
| return llvm::None; |
| } |
| |
| auto *MyData = getUnsafeData<SymbolicReferenceExprSyntax>(); |
| auto &ChildPtr = *reinterpret_cast<std::atomic<uintptr_t>*>( |
| &MyData->CachedGenericArgClause); |
| SyntaxData::realizeSyntaxNode<GenericArgumentClauseSyntax>(ChildPtr, |
| RawClause, MyData, |
| cursorIndex(Cursor::GenericArgumentClause)); |
| |
| return llvm::Optional<GenericArgumentClauseSyntax> { |
| GenericArgumentClauseSyntax { |
| Root, |
| MyData->CachedGenericArgClause.get() |
| } |
| }; |
| } |
| |
| SymbolicReferenceExprSyntax SymbolicReferenceExprSyntax:: |
| withGenericArgumentClause(GenericArgumentClauseSyntax NewGenericArgs) const { |
| return Data->replaceChild<SymbolicReferenceExprSyntax>( |
| NewGenericArgs.getRaw(), Cursor::GenericArgumentClause); |
| } |
| |
| #pragma mark - function-call-argument Data |
| |
| FunctionCallArgumentSyntaxData:: |
| FunctionCallArgumentSyntaxData(RC<RawSyntax> Raw, |
| const SyntaxData *Parent, |
| CursorIndex IndexInParent) |
| : SyntaxData(Raw, Parent, IndexInParent) { |
| syntax_assert_child_token(Raw, FunctionCallArgumentSyntax::Cursor::Label, |
| tok::identifier); |
| syntax_assert_child_token_text(Raw, |
| FunctionCallArgumentSyntax::Cursor::Colon, |
| tok::colon, ":"); |
| assert( |
| Raw->getChild(FunctionCallArgumentSyntax::Cursor::Expression)->isExpr()); |
| |
| syntax_assert_child_token_text(Raw, |
| FunctionCallArgumentSyntax::Cursor::Comma, |
| tok::comma, ","); |
| } |
| |
| RC<FunctionCallArgumentSyntaxData> |
| FunctionCallArgumentSyntaxData::make(RC<RawSyntax> Raw, |
| const SyntaxData *Parent, |
| CursorIndex IndexInParent) { |
| return RC<FunctionCallArgumentSyntaxData> { |
| new FunctionCallArgumentSyntaxData { |
| Raw, Parent, IndexInParent |
| } |
| }; |
| } |
| |
| RC<FunctionCallArgumentSyntaxData> FunctionCallArgumentSyntaxData::makeBlank() { |
| auto Raw = RawSyntax::make(SyntaxKind::FunctionCallArgument, |
| { |
| TokenSyntax::missingToken(tok::identifier, ""), |
| TokenSyntax::missingToken(tok::colon, ":"), |
| RawSyntax::missing(SyntaxKind::MissingExpr), |
| TokenSyntax::missingToken(tok::comma, ",") |
| }, |
| SourcePresence::Present); |
| return make(Raw); |
| } |
| |
| #pragma mark - function-call-argument API |
| |
| FunctionCallArgumentSyntax:: |
| FunctionCallArgumentSyntax(const RC<SyntaxData> Root, const DataType *Data) |
| : Syntax(Root, Data) {} |
| |
| RC<TokenSyntax> FunctionCallArgumentSyntax::getLabel() const { |
| return cast<TokenSyntax>(getRaw()->getChild(Cursor::Label)); |
| } |
| |
| FunctionCallArgumentSyntax |
| FunctionCallArgumentSyntax::withLabel(RC<TokenSyntax> NewLabel) const { |
| assert(NewLabel->getTokenKind() == tok::identifier); |
| return Data->replaceChild<FunctionCallArgumentSyntax>(NewLabel, |
| Cursor::Label); |
| } |
| |
| RC<TokenSyntax> FunctionCallArgumentSyntax::getColonToken() const { |
| return cast<TokenSyntax>(getRaw()->getChild(Cursor::Colon)); |
| } |
| |
| FunctionCallArgumentSyntax |
| FunctionCallArgumentSyntax::withColonToken(RC<TokenSyntax> NewColon) const { |
| syntax_assert_token_is(NewColon, tok::colon, ":"); |
| return Data->replaceChild<FunctionCallArgumentSyntax>(NewColon, |
| Cursor::Colon); |
| } |
| |
| llvm::Optional<ExprSyntax> FunctionCallArgumentSyntax::getExpression() const { |
| |
| auto RawExpression = getRaw()->getChild(Cursor::Expression); |
| if (RawExpression->isMissing()) { |
| return llvm::None; |
| } |
| |
| auto *MyData = getUnsafeData<FunctionCallArgumentSyntax>(); |
| |
| 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() }; |
| } |
| |
| FunctionCallArgumentSyntax |
| FunctionCallArgumentSyntax::withExpression(ExprSyntax NewExpression) const { |
| return Data->replaceChild<FunctionCallArgumentSyntax>(NewExpression.getRaw(), |
| Cursor::Expression); |
| } |
| |
| RC<TokenSyntax> FunctionCallArgumentSyntax::getTrailingComma() const { |
| return cast<TokenSyntax>(getRaw()->getChild(Cursor::Comma)); |
| } |
| |
| FunctionCallArgumentSyntax FunctionCallArgumentSyntax:: |
| withTrailingComma(RC<TokenSyntax> NewTrailingComma) const { |
| syntax_assert_token_is(NewTrailingComma, tok::comma, ","); |
| return Data->replaceChild<FunctionCallArgumentSyntax>(NewTrailingComma, |
| FunctionCallArgumentSyntax::Cursor::Comma); |
| } |
| |
| #pragma mark - function-call-argument-list API |
| |
| FunctionCallArgumentListSyntax:: |
| FunctionCallArgumentListSyntax(const RC<SyntaxData> Root, |
| const DataType *Data) |
| : SyntaxCollection(Root, Data) {} |
| |
| #pragma mark - function-call-expression Data |
| |
| RC<FunctionCallArgumentListSyntaxData> CachedArgumentList; |
| |
| FunctionCallExprSyntaxData::FunctionCallExprSyntaxData(RC<RawSyntax> Raw, |
| const SyntaxData *Parent, |
| CursorIndex IndexInParent) |
| : ExprSyntaxData(Raw, Parent, IndexInParent) { |
| assert(Raw->Layout.size() == 4); |
| assert(Raw->getChild(FunctionCallExprSyntax::Cursor::CalledExpression) |
| ->isExpr()); |
| syntax_assert_child_token_text(Raw, FunctionCallExprSyntax::Cursor::LeftParen, |
| tok::l_paren, "("); |
| syntax_assert_child_kind(Raw, FunctionCallExprSyntax::Cursor::ArgumentList, |
| SyntaxKind::FunctionCallArgumentList); |
| syntax_assert_child_token_text(Raw, |
| FunctionCallExprSyntax::Cursor::RightParen, |
| tok::r_paren, ")"); |
| } |
| |
| RC<FunctionCallExprSyntaxData> |
| FunctionCallExprSyntaxData::make(RC<RawSyntax> Raw, const SyntaxData *Parent, |
| CursorIndex IndexInParent) { |
| return RC<FunctionCallExprSyntaxData> { |
| new FunctionCallExprSyntaxData { |
| Raw, Parent, IndexInParent |
| } |
| }; |
| } |
| |
| RC<FunctionCallExprSyntaxData> FunctionCallExprSyntaxData::makeBlank() { |
| auto Raw = RawSyntax::make(SyntaxKind::FunctionCallExpr, |
| { |
| RawSyntax::missing(SyntaxKind::MissingExpr), |
| TokenSyntax::missingToken(tok::l_paren, "("), |
| RawSyntax::missing(SyntaxKind::FunctionCallArgumentList), |
| TokenSyntax::missingToken(tok::r_paren, ")"), |
| }, |
| SourcePresence::Present); |
| return make(Raw); |
| } |
| |
| |
| #pragma mark - function-call-expression API |
| |
| FunctionCallExprSyntax::FunctionCallExprSyntax(const RC<SyntaxData> Root, |
| const DataType *Data) |
| : ExprSyntax(Root, Data) {} |
| |
| ExprSyntax FunctionCallExprSyntax::getCalledExpression() const { |
| auto RawArg = getRaw()->getChild(Cursor::CalledExpression); |
| |
| auto *MyData = getUnsafeData<FunctionCallExprSyntax>(); |
| |
| auto &ChildPtr = *reinterpret_cast<std::atomic<uintptr_t>*>( |
| &MyData->CachedCalledExpression); |
| |
| SyntaxData::realizeSyntaxNode<ExprSyntax>( |
| ChildPtr, RawArg, MyData, cursorIndex(Cursor::CalledExpression)); |
| |
| return ExprSyntax { |
| Root, |
| MyData->CachedCalledExpression.get(), |
| }; |
| } |
| |
| FunctionCallExprSyntax FunctionCallExprSyntax:: |
| withCalledExpression(ExprSyntax NewBaseExpression) const { |
| return Data->replaceChild<FunctionCallExprSyntax>(NewBaseExpression.getRaw(), |
| Cursor::CalledExpression); |
| } |
| |
| RC<TokenSyntax> FunctionCallExprSyntax::getLeftParen() const { |
| return cast<TokenSyntax>(getRaw()->getChild(Cursor::LeftParen)); |
| } |
| |
| FunctionCallExprSyntax |
| FunctionCallExprSyntax::withLeftParen(RC<TokenSyntax> NewLeftParen) const { |
| syntax_assert_token_is(NewLeftParen, tok::l_paren, "("); |
| return Data->replaceChild<FunctionCallExprSyntax>(NewLeftParen, |
| Cursor::LeftParen); |
| } |
| |
| FunctionCallArgumentListSyntax FunctionCallExprSyntax::getArgumentList() const { |
| auto RawArg = getRaw()->getChild(Cursor::ArgumentList); |
| |
| auto *MyData = getUnsafeData<FunctionCallExprSyntax>(); |
| |
| auto &ChildPtr = *reinterpret_cast<std::atomic<uintptr_t>*>( |
| &MyData->CachedArgumentList); |
| |
| SyntaxData::realizeSyntaxNode<FunctionCallArgumentListSyntax>( |
| ChildPtr, RawArg, MyData, cursorIndex(Cursor::ArgumentList)); |
| |
| return FunctionCallArgumentListSyntax { |
| Root, |
| MyData->CachedArgumentList.get(), |
| }; |
| } |
| |
| FunctionCallExprSyntax FunctionCallExprSyntax:: |
| withArgumentList(FunctionCallArgumentListSyntax NewArgumentList) const { |
| return Data->replaceChild<FunctionCallExprSyntax>(NewArgumentList.getRaw(), |
| Cursor::ArgumentList); |
| } |
| |
| RC<TokenSyntax> FunctionCallExprSyntax::getRightParen() const { |
| return cast<TokenSyntax>(getRaw()->getChild(Cursor::RightParen)); |
| } |
| |
| FunctionCallExprSyntax |
| FunctionCallExprSyntax::withRightParen(RC<TokenSyntax> NewRightParen) const { |
| syntax_assert_token_is(NewRightParen, tok::r_paren, ")"); |
| return Data->replaceChild<FunctionCallExprSyntax>(NewRightParen, |
| Cursor::RightParen); |
| } |
| |
| #pragma mark - function-call-expression Builder |
| |
| FunctionCallExprSyntaxBuilder::FunctionCallExprSyntaxBuilder() |
| : CallLayout(FunctionCallExprSyntaxData::makeBlank()->getRaw()->Layout), |
| ListLayout( |
| FunctionCallArgumentListSyntaxData::makeBlank()->getRaw()->Layout) {} |
| |
| FunctionCallExprSyntaxBuilder & |
| FunctionCallExprSyntaxBuilder::useLeftParen(RC<TokenSyntax> LeftParen) { |
| syntax_assert_token_is(LeftParen, tok::l_paren, "("); |
| CallLayout[cursorIndex(FunctionCallExprSyntax::Cursor::LeftParen)] |
| = LeftParen; |
| return *this; |
| } |
| |
| FunctionCallExprSyntaxBuilder &FunctionCallExprSyntaxBuilder:: |
| appendArgument(FunctionCallArgumentSyntax AdditionalArgument) { |
| ListLayout.push_back(AdditionalArgument.getRaw()); |
| return *this; |
| } |
| |
| FunctionCallExprSyntaxBuilder &FunctionCallExprSyntaxBuilder:: |
| useCalledExpression(ExprSyntax CalledExpression) { |
| CallLayout[cursorIndex(FunctionCallExprSyntax::Cursor::CalledExpression)] |
| = CalledExpression.getRaw(); |
| return *this; |
| } |
| |
| FunctionCallExprSyntaxBuilder & |
| FunctionCallExprSyntaxBuilder::useRightParen(RC<TokenSyntax> RightParen) { |
| syntax_assert_token_is(RightParen, tok::r_paren, ")"); |
| CallLayout[cursorIndex(FunctionCallExprSyntax::Cursor::RightParen)] |
| = RightParen; |
| return *this; |
| } |
| |
| FunctionCallExprSyntax FunctionCallExprSyntaxBuilder::build() const { |
| auto RawArgs = RawSyntax::make(SyntaxKind::FunctionCallArgumentList, |
| ListLayout, SourcePresence::Present); |
| auto RawCall = RawSyntax::make(SyntaxKind::FunctionCallExpr, CallLayout, |
| SourcePresence::Present) |
| ->replaceChild(FunctionCallExprSyntax::Cursor::ArgumentList, RawArgs); |
| auto Data = FunctionCallExprSyntaxData::make(RawCall); |
| return { Data, Data.get() }; |
| } |