//===--- 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::make(RC Raw, const SyntaxData *Parent, CursorIndex IndexInParent) { return RC { new ExprSyntaxData { Raw, Parent, IndexInParent } }; } RC ExprSyntaxData::makeBlank() { return make(RawSyntax::missing(SyntaxKind::MissingExpr)); } #pragma mark - expression API ExprSyntax::ExprSyntax(const RC Root, const ExprSyntaxData *Data) : Syntax(Root, Data) {} #pragma mark - unknown-expression Data UnknownExprSyntaxData::UnknownExprSyntaxData(RC Raw, const SyntaxData *Parent, CursorIndex IndexInParent) : ExprSyntaxData(Raw, Parent, IndexInParent) { assert(Raw->Kind == SyntaxKind::UnknownExpr); } RC UnknownExprSyntaxData::make(RC Raw, const SyntaxData *Parent, CursorIndex IndexInParent) { return RC { new UnknownExprSyntaxData { Raw, Parent, IndexInParent } }; } #pragma mark - unknown-expression API UnknownExprSyntax::UnknownExprSyntax(const RC Root, const UnknownExprSyntaxData *Data) : ExprSyntax(Root, Data) {} #pragma mark - integer-literal-expression Data IntegerLiteralExprSyntaxData:: IntegerLiteralExprSyntaxData(RC 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::make(RC Raw, const SyntaxData *Parent, CursorIndex IndexInParent) { return RC { new IntegerLiteralExprSyntaxData { Raw, Parent, IndexInParent } }; } RC 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 Root, const IntegerLiteralExprSyntaxData *Data) : ExprSyntax(Root, Data) {} IntegerLiteralExprSyntax IntegerLiteralExprSyntax::withDigits(RC NewDigits) const { assert(NewDigits->getTokenKind() == tok::integer_literal); return Data->replaceChild(NewDigits, Cursor::Digits); } #pragma mark - symbolic-reference Data SymbolicReferenceExprSyntaxData:: SymbolicReferenceExprSyntaxData(RC 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::make(RC Raw, const SyntaxData *Parent, CursorIndex IndexInParent) { return RC { new SymbolicReferenceExprSyntaxData { Raw, Parent, IndexInParent } }; } RC 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 Root, const DataType *Data) : ExprSyntax(Root, Data) {} RC SymbolicReferenceExprSyntax::getIdentifier() const { return cast(getRaw()->getChild(Cursor::Identifier)); } SymbolicReferenceExprSyntax SymbolicReferenceExprSyntax:: withIdentifier(RC NewIdentifier) const { assert(NewIdentifier->getTokenKind() == tok::identifier); return Data->replaceChild(NewIdentifier, Cursor::Identifier); } llvm::Optional SymbolicReferenceExprSyntax::getGenericArgumentClause() const { auto RawClause = getRaw()->getChild(Cursor::GenericArgumentClause); if (RawClause->isMissing()) { return llvm::None; } auto *MyData = getUnsafeData(); auto &ChildPtr = *reinterpret_cast*>( &MyData->CachedGenericArgClause); SyntaxData::realizeSyntaxNode(ChildPtr, RawClause, MyData, cursorIndex(Cursor::GenericArgumentClause)); return llvm::Optional { GenericArgumentClauseSyntax { Root, MyData->CachedGenericArgClause.get() } }; } SymbolicReferenceExprSyntax SymbolicReferenceExprSyntax:: withGenericArgumentClause(GenericArgumentClauseSyntax NewGenericArgs) const { return Data->replaceChild( NewGenericArgs.getRaw(), Cursor::GenericArgumentClause); } #pragma mark - function-call-argument Data FunctionCallArgumentSyntaxData:: FunctionCallArgumentSyntaxData(RC 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::make(RC Raw, const SyntaxData *Parent, CursorIndex IndexInParent) { return RC { new FunctionCallArgumentSyntaxData { Raw, Parent, IndexInParent } }; } RC 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 Root, const DataType *Data) : Syntax(Root, Data) {} RC FunctionCallArgumentSyntax::getLabel() const { return cast(getRaw()->getChild(Cursor::Label)); } FunctionCallArgumentSyntax FunctionCallArgumentSyntax::withLabel(RC NewLabel) const { assert(NewLabel->getTokenKind() == tok::identifier); return Data->replaceChild(NewLabel, Cursor::Label); } RC FunctionCallArgumentSyntax::getColonToken() const { return cast(getRaw()->getChild(Cursor::Colon)); } FunctionCallArgumentSyntax FunctionCallArgumentSyntax::withColonToken(RC NewColon) const { syntax_assert_token_is(NewColon, tok::colon, ":"); return Data->replaceChild(NewColon, Cursor::Colon); } llvm::Optional FunctionCallArgumentSyntax::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() }; } FunctionCallArgumentSyntax FunctionCallArgumentSyntax::withExpression(ExprSyntax NewExpression) const { return Data->replaceChild(NewExpression.getRaw(), Cursor::Expression); } RC FunctionCallArgumentSyntax::getTrailingComma() const { return cast(getRaw()->getChild(Cursor::Comma)); } FunctionCallArgumentSyntax FunctionCallArgumentSyntax:: withTrailingComma(RC NewTrailingComma) const { syntax_assert_token_is(NewTrailingComma, tok::comma, ","); return Data->replaceChild(NewTrailingComma, FunctionCallArgumentSyntax::Cursor::Comma); } #pragma mark - function-call-argument-list Data FunctionCallArgumentListSyntaxData:: FunctionCallArgumentListSyntaxData(const RC Raw, const SyntaxData *Parent, CursorIndex IndexInParent) : SyntaxData(Raw, Parent, IndexInParent) { #ifndef NDEBUG for (auto Child : Raw->Layout) { assert(Child->Kind == SyntaxKind::FunctionCallArgument); } #endif for (size_t i = 0; i < Raw->Layout.size(); ++i) { CachedArguments.emplace_back(nullptr); } } RC FunctionCallArgumentListSyntaxData::make(RC Raw, const SyntaxData *Parent, CursorIndex IndexInParent) { return RC { new FunctionCallArgumentListSyntaxData { Raw, Parent, IndexInParent } }; } RC FunctionCallArgumentListSyntaxData::makeBlank() { auto Raw = RawSyntax::make(SyntaxKind::FunctionCallArgumentList, {}, SourcePresence::Present); return make(Raw); } #pragma mark - function-call-argument-list API FunctionCallArgumentListSyntax:: FunctionCallArgumentListSyntax(const RC Root, const DataType *Data) : Syntax(Root, Data) {} size_t FunctionCallArgumentListSyntax::getNumArguments() const { return getRaw()->Layout.size(); } FunctionCallArgumentSyntax FunctionCallArgumentListSyntax::getArgument(size_t Index) const { assert(Index <= getRaw()->Layout.size()); auto RawArg = getRaw()->Layout[Index]; auto *MyData = getUnsafeData(); auto &ChildPtr = *reinterpret_cast*>( MyData->CachedArguments.data() + Index); SyntaxData::realizeSyntaxNode(ChildPtr, RawArg, MyData, Index); return FunctionCallArgumentSyntax { Root, MyData->CachedArguments[Index].get() }; } FunctionCallArgumentListSyntax FunctionCallArgumentListSyntax::withAdditionalArgument( FunctionCallArgumentSyntax AdditionalArgument) const { auto NewRaw = getRaw()->append(AdditionalArgument.getRaw()); return Data->replaceSelf(NewRaw); } #pragma mark - function-call-expression Data RC CachedArgumentList; FunctionCallExprSyntaxData::FunctionCallExprSyntaxData(RC 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::make(RC Raw, const SyntaxData *Parent, CursorIndex IndexInParent) { return RC { new FunctionCallExprSyntaxData { Raw, Parent, IndexInParent } }; } RC 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 Root, const DataType *Data) : ExprSyntax(Root, Data) {} ExprSyntax FunctionCallExprSyntax::getCalledExpression() const { auto RawArg = getRaw()->getChild(Cursor::CalledExpression); auto *MyData = getUnsafeData(); auto &ChildPtr = *reinterpret_cast*>( &MyData->CachedCalledExpression); SyntaxData::realizeSyntaxNode( ChildPtr, RawArg, MyData, cursorIndex(Cursor::CalledExpression)); return ExprSyntax { Root, MyData->CachedCalledExpression.get(), }; } FunctionCallExprSyntax FunctionCallExprSyntax:: withCalledExpression(ExprSyntax NewBaseExpression) const { return Data->replaceChild(NewBaseExpression.getRaw(), Cursor::CalledExpression); } RC FunctionCallExprSyntax::getLeftParen() const { return cast(getRaw()->getChild(Cursor::LeftParen)); } FunctionCallExprSyntax FunctionCallExprSyntax::withLeftParen(RC NewLeftParen) const { syntax_assert_token_is(NewLeftParen, tok::l_paren, "("); return Data->replaceChild(NewLeftParen, Cursor::LeftParen); } FunctionCallArgumentListSyntax FunctionCallExprSyntax::getArgumentList() const { auto RawArg = getRaw()->getChild(Cursor::ArgumentList); auto *MyData = getUnsafeData(); auto &ChildPtr = *reinterpret_cast*>( &MyData->CachedArgumentList); SyntaxData::realizeSyntaxNode( ChildPtr, RawArg, MyData, cursorIndex(Cursor::ArgumentList)); return FunctionCallArgumentListSyntax { Root, MyData->CachedArgumentList.get(), }; } FunctionCallExprSyntax FunctionCallExprSyntax:: withArgumentList(FunctionCallArgumentListSyntax NewArgumentList) const { return Data->replaceChild(NewArgumentList.getRaw(), Cursor::ArgumentList); } RC FunctionCallExprSyntax::getRightParen() const { return cast(getRaw()->getChild(Cursor::RightParen)); } FunctionCallExprSyntax FunctionCallExprSyntax::withRightParen(RC NewRightParen) const { syntax_assert_token_is(NewRightParen, tok::r_paren, ")"); return Data->replaceChild(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 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 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() }; }