mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
This also fixes a typo in makePrefixOperator and implements IntegerLiteralExprSyntax::withSign.
480 lines
17 KiB
C++
480 lines
17 KiB
C++
//===--- 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);
|
|
}
|
|
|
|
IntegerLiteralExprSyntax
|
|
IntegerLiteralExprSyntax::withSign(RC<swift::syntax::TokenSyntax> NewSign)
|
|
const {
|
|
assert(NewSign->getTokenKind() == tok::oper_prefix);
|
|
return Data->replaceChild<IntegerLiteralExprSyntax>(NewSign, Cursor::Sign);
|
|
}
|
|
|
|
#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() };
|
|
}
|