mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[Syntax] Implement return-statement and integer-literal-expr
A return statement needs something to return, so implement
integer-literal-expression too. This necessarily also forced
UnknownExprSyntax, UnknownStmtSyntax, and UnknownDeclSyntax,
which are stand-in token buckets for when we don't know
how to transform/migrate an AST.
This commit also contains the core function for caching
SyntaxData children. This is highly tricky code, with some
detailed comments in SyntaxData.{h,cpp}. The gist is that
we have to atomically swap in a SyntaxData pointer into the
child field, so we can maintain pointer identity of SyntaxData
nodes, while still being able to cache them internally.
To prove that this works, there is a multithreaded test that
checks that two threads can ask for a child that hasn't been
cached yet without crashing or violating pointer identity.
https://bugs.swift.org/browse/SR-4010
This commit is contained in:
@@ -840,6 +840,14 @@ public:
|
||||
return DigitsLoc;
|
||||
}
|
||||
|
||||
SourceLoc getMinusLoc() const {
|
||||
return MinusLoc;
|
||||
}
|
||||
|
||||
SourceLoc getDigitsLoc() const {
|
||||
return DigitsLoc;
|
||||
}
|
||||
|
||||
static bool classof(const Expr *E) {
|
||||
return E->getKind() >= ExprKind::First_NumberLiteralExpr
|
||||
&& E->getKind() <= ExprKind::Last_NumberLiteralExpr;
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
namespace swift {
|
||||
namespace syntax {
|
||||
|
||||
#pragma mark declaration Data
|
||||
|
||||
class DeclSyntaxData : public SyntaxData {
|
||||
protected:
|
||||
DeclSyntaxData(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
|
||||
@@ -40,6 +42,8 @@ public:
|
||||
static bool classof(const SyntaxData *S) { return S->isDecl(); }
|
||||
};
|
||||
|
||||
#pragma mark declaration API
|
||||
|
||||
class DeclSyntax : public Syntax {
|
||||
friend class Syntax;
|
||||
using DataType = DeclSyntaxData;
|
||||
@@ -50,6 +54,39 @@ public:
|
||||
static bool classof(const SyntaxData *S) { return S->isDecl(); }
|
||||
};
|
||||
|
||||
#pragma mark - unknown-declaration Data
|
||||
|
||||
class UnknownDeclSyntaxData : public DeclSyntaxData {
|
||||
UnknownDeclSyntaxData(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
|
||||
CursorIndex IndexInParent = 0);
|
||||
public:
|
||||
static RC<UnknownDeclSyntaxData> make(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent = nullptr,
|
||||
CursorIndex IndexInParent = 0);
|
||||
|
||||
static bool classof(const SyntaxData *S) {
|
||||
return S->getKind() == SyntaxKind::UnknownDecl;
|
||||
}
|
||||
};
|
||||
|
||||
#pragma mark - unknown-declaration API
|
||||
|
||||
class UnknownDeclSyntax : public DeclSyntax {
|
||||
friend class SyntaxData;
|
||||
friend class UnknownStmtSyntaxData;
|
||||
friend class LegacyASTTransformer;
|
||||
|
||||
using DataType = UnknownDeclSyntaxData;
|
||||
|
||||
UnknownDeclSyntax(const RC<SyntaxData> Root,
|
||||
const UnknownDeclSyntaxData *Data);
|
||||
|
||||
public:
|
||||
static bool classof(const Syntax *S) {
|
||||
return S->getKind() == SyntaxKind::UnknownDecl;
|
||||
}
|
||||
};
|
||||
|
||||
#pragma mark declaration-members Data
|
||||
|
||||
class DeclMembersSyntaxData final : public SyntaxData {
|
||||
@@ -85,11 +122,7 @@ class DeclMembersSyntax final : public Syntax {
|
||||
DeclMembersSyntax(RC<SyntaxData> Root,
|
||||
const DeclMembersSyntaxData *Data);
|
||||
public:
|
||||
static DeclMembersSyntax make(const RC<SyntaxData> Root,
|
||||
const DeclMembersSyntaxData *Data);
|
||||
static DeclMembersSyntax makeBlank();
|
||||
|
||||
static bool classof(const SyntaxData *S) {
|
||||
static bool classof(const Syntax *S) {
|
||||
return S->getKind() == SyntaxKind::DeclMembers;
|
||||
}
|
||||
};
|
||||
@@ -213,8 +246,8 @@ public:
|
||||
/// Return a StructDeclSyntax with the given right brace '}' token.
|
||||
StructDeclSyntax withRightBrace(RC<TokenSyntax> NewRightBrace) const;
|
||||
|
||||
static bool classof(const SyntaxData *Data) {
|
||||
return Data->getKind() == SyntaxKind::StructDecl;
|
||||
static bool classof(const Syntax *S) {
|
||||
return S->getKind() == SyntaxKind::StructDecl;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
150
include/swift/Syntax/ExprSyntax.h
Normal file
150
include/swift/Syntax/ExprSyntax.h
Normal file
@@ -0,0 +1,150 @@
|
||||
//===--- ExprSyntax.h - Swift Expression Syntax Interface --------*- C++ -*-===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the interface for expresion-specific syntax nodes,
|
||||
// such as
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_SYNTAX_EXPRSYNTAX_H
|
||||
#define SWIFT_SYNTAX_EXPRSYNTAX_H
|
||||
|
||||
#include "swift/Syntax/RawSyntax.h"
|
||||
#include "swift/Syntax/References.h"
|
||||
#include "swift/Syntax/Syntax.h"
|
||||
#include "swift/Syntax/SyntaxData.h"
|
||||
#include "swift/Syntax/TokenSyntax.h"
|
||||
|
||||
using llvm::Optional;
|
||||
|
||||
namespace swift {
|
||||
namespace syntax {
|
||||
|
||||
class ExprSyntaxData : public SyntaxData {
|
||||
protected:
|
||||
ExprSyntaxData(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
|
||||
CursorIndex IndexInParent = 0)
|
||||
: SyntaxData(Raw, Parent, IndexInParent) {
|
||||
assert(Raw->isExpr());
|
||||
}
|
||||
public:
|
||||
static RC<ExprSyntaxData> make(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent = nullptr,
|
||||
CursorIndex IndexInParent = 0);
|
||||
static RC<ExprSyntaxData> makeBlank();
|
||||
static bool classof(const SyntaxData *S) {
|
||||
return S->isExpr();
|
||||
}
|
||||
};
|
||||
|
||||
class ExprSyntax : public Syntax {
|
||||
public:
|
||||
using DataType = ExprSyntaxData;
|
||||
|
||||
ExprSyntax(const RC<SyntaxData> Root, const ExprSyntaxData *Data);
|
||||
static bool classof(const Syntax *S) {
|
||||
return S->isExpr();
|
||||
}
|
||||
};
|
||||
|
||||
#pragma mark - unknown-expression Data
|
||||
|
||||
class UnknownExprSyntaxData : public ExprSyntaxData {
|
||||
UnknownExprSyntaxData(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
|
||||
CursorIndex IndexInParent = 0);
|
||||
public:
|
||||
static RC<UnknownExprSyntaxData> make(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent = nullptr,
|
||||
CursorIndex IndexInParent = 0);
|
||||
|
||||
static bool classof(const SyntaxData *S) {
|
||||
return S->getKind() == SyntaxKind::UnknownExpr;
|
||||
}
|
||||
};
|
||||
|
||||
#pragma mark - unknown-expression API
|
||||
|
||||
class UnknownExprSyntax : public ExprSyntax {
|
||||
friend class SyntaxData;
|
||||
friend class UnknownExprSyntaxData;
|
||||
friend class LegacyASTTransformer;
|
||||
|
||||
using DataType = UnknownExprSyntaxData;
|
||||
|
||||
UnknownExprSyntax(const RC<SyntaxData> Root,
|
||||
const UnknownExprSyntaxData *Data);
|
||||
|
||||
public:
|
||||
static bool classof(const Syntax *S) {
|
||||
return S->getKind() == SyntaxKind::UnknownExpr;
|
||||
}
|
||||
};
|
||||
|
||||
#pragma mark - integer-literal-expression Data
|
||||
|
||||
class IntegerLiteralExprSyntaxData : public ExprSyntaxData {
|
||||
friend struct SyntaxFactory;
|
||||
friend class SyntaxData;
|
||||
|
||||
IntegerLiteralExprSyntaxData(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent = nullptr,
|
||||
CursorIndex IndexInParent = 0);
|
||||
static RC<IntegerLiteralExprSyntaxData> make(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent = nullptr,
|
||||
CursorIndex IndexInParent = 0);
|
||||
static RC<IntegerLiteralExprSyntaxData> makeBlank();
|
||||
public:
|
||||
static bool classof(const SyntaxData *S) {
|
||||
return S->getKind() == SyntaxKind::IntegerLiteralExpr;
|
||||
}
|
||||
};
|
||||
|
||||
#pragma mark - integer-literal-expression API
|
||||
|
||||
class IntegerLiteralExprSyntax : public ExprSyntax {
|
||||
using DataType = IntegerLiteralExprSyntaxData;
|
||||
friend struct SyntaxFactory;
|
||||
friend class SyntaxData;
|
||||
friend class IntegerLiteralExprSyntaxData;
|
||||
|
||||
IntegerLiteralExprSyntax(const RC<SyntaxData> Root,
|
||||
const IntegerLiteralExprSyntaxData *Data);
|
||||
|
||||
enum class Cursor : CursorIndex {
|
||||
Sign,
|
||||
Digits
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
/// Get the '+' or '-' associated with this integer literal expression.
|
||||
RC<TokenSyntax> getSign() const;
|
||||
|
||||
/// Return a new IntegerLiteralExprSyntax with the given '+' or '-' sign.
|
||||
IntegerLiteralExprSyntax withSign(RC<TokenSyntax> NewSign) const;
|
||||
|
||||
/// Return the string of digits comprising the number part of the integer
|
||||
/// literal expression.
|
||||
RC<TokenSyntax> getDigits() const;
|
||||
|
||||
/// Return a new IntegerLiteralExprSyntax with the given string of digits.
|
||||
IntegerLiteralExprSyntax withDigits(RC<TokenSyntax> NewDigits) const;
|
||||
|
||||
static bool classof(const Syntax *S) {
|
||||
return S->getKind() == SyntaxKind::IntegerLiteralExpr;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace syntax
|
||||
} // end namespace swift
|
||||
|
||||
#endif // SWIFT_SYNTAX_EXPRSYNTAX_H
|
||||
@@ -30,16 +30,19 @@ class TypeSyntaxData;
|
||||
class TypeIdentifierSyntax;
|
||||
class TypeIdentifierSyntaxData;
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark conformance-requirement Data
|
||||
#pragma mark - conformance-requirement Data
|
||||
|
||||
class ConformanceRequirementSyntaxData final : public SyntaxData {
|
||||
friend class SyntaxData;
|
||||
RC<TypeIdentifierSyntaxData> CachedConformingTypeIdentifier;
|
||||
RC<TypeSyntaxData> InheritedType;
|
||||
|
||||
ConformanceRequirementSyntaxData(RC<RawSyntax> Raw);
|
||||
static RC<ConformanceRequirementSyntaxData> make(RC<RawSyntax> Raw);
|
||||
ConformanceRequirementSyntaxData(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent = nullptr,
|
||||
CursorIndex IndexInParent = 0);
|
||||
static RC<ConformanceRequirementSyntaxData>
|
||||
make(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
|
||||
CursorIndex IndexInParent = 0);
|
||||
static RC<ConformanceRequirementSyntaxData> makeBlank();
|
||||
public:
|
||||
static bool classof(const SyntaxData *S) {
|
||||
@@ -47,11 +50,13 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark conformance-requirement API
|
||||
#pragma mark - conformance-requirement API
|
||||
|
||||
/// conformance-requirement -> type-identifier : type-identifier
|
||||
class ConformanceRequirementSyntax final : public Syntax {
|
||||
|
||||
friend class ConformanceRequirementSyntaxData;
|
||||
|
||||
enum Cursor : CursorIndex {
|
||||
LeftTypeIdentifier,
|
||||
Colon,
|
||||
@@ -61,22 +66,12 @@ class ConformanceRequirementSyntax final : public Syntax {
|
||||
ConformanceRequirementSyntax(RC<SyntaxData> Root,
|
||||
ConformanceRequirementSyntaxData *Data);
|
||||
|
||||
static ConformanceRequirementSyntax make(RC<RawSyntax> Raw);
|
||||
static ConformanceRequirementSyntax make(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent = nullptr,
|
||||
CursorIndex IndexInParent = 0);
|
||||
|
||||
static ConformanceRequirementSyntax makeBlank();
|
||||
|
||||
// TODO: in make
|
||||
// ConformanceRequirementSyntax(RC<RawSyntax> Raw)
|
||||
// : Syntax(Raw, Parent) {
|
||||
// assert(Raw->Kind == SyntaxKind::ConformanceRequirement);
|
||||
// assert(Raw->Layout.size() == 3);
|
||||
// syntax_assert_child_kind(Raw, Cursor::LeftTypeIdentifier,
|
||||
// SyntaxKind::TypeIdentifier);
|
||||
// syntax_assert_child_token_text(Raw, Cursor::Colon, tok::colon, ":");
|
||||
// syntax_assert_child_kind(Raw, Cursor::RightTypeIdentifier,
|
||||
// SyntaxKind::TypeIdentifier);
|
||||
// }
|
||||
|
||||
public:
|
||||
/// Return the conforming "left-hand" type identifier in the
|
||||
/// conformance requirement.
|
||||
@@ -106,8 +101,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark same-type-requirement Data
|
||||
#pragma mark - same-type-requirement Data
|
||||
|
||||
class SameTypeRequirementSyntaxData final : public SyntaxData {
|
||||
friend struct SyntaxFactory;
|
||||
@@ -130,12 +124,12 @@ static bool classof(const SyntaxData *S) {
|
||||
}
|
||||
};
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark same-type-requirement API
|
||||
#pragma mark -same-type-requirement API
|
||||
|
||||
/// same-type-requirement -> type-identifier == type
|
||||
class SameTypeRequirementSyntax final : public Syntax {
|
||||
friend struct SyntaxFactory;
|
||||
friend class SameTypeRequirementSyntaxData;
|
||||
|
||||
enum Cursor : CursorIndex {
|
||||
LeftTypeIdentifier,
|
||||
@@ -146,18 +140,6 @@ class SameTypeRequirementSyntax final : public Syntax {
|
||||
SameTypeRequirementSyntax(RC<SyntaxData> Root,
|
||||
const SameTypeRequirementSyntaxData *Data);
|
||||
|
||||
// TODO: move to cpp: make
|
||||
// SameTypeRequirementSyntax(RC<RawSyntax> Raw)
|
||||
// : Syntax(Raw, Parent) {
|
||||
// assert(Raw->Kind == SyntaxKind::SameTypeRequirement);
|
||||
// assert(Raw->Layout.size() == 3);
|
||||
// syntax_assert_child_kind(Raw, Cursor::LeftTypeIdentifier,
|
||||
// SyntaxKind::TypeIdentifier);
|
||||
// syntax_assert_child_token_text(Raw, Cursor::EqualityToken,
|
||||
// tok::oper_binary_spaced, "==");
|
||||
// assert(Raw->getChild(Cursor::RightType)->isType());
|
||||
// }
|
||||
|
||||
public:
|
||||
|
||||
/// Return the type identifier on the left side of the same-type requirement.
|
||||
@@ -208,8 +190,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-parameter API
|
||||
#pragma mark - generic-parameter API
|
||||
|
||||
/// generic-parameter -> type-name
|
||||
/// | type-name : type-identifier
|
||||
@@ -260,14 +241,17 @@ public:
|
||||
};
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-parameter-list Data (TODO)
|
||||
#pragma mark - generic-parameter-list Data
|
||||
|
||||
class GenericParameterListSyntaxData final : public SyntaxData {
|
||||
friend class SyntaxData;
|
||||
|
||||
GenericParameterListSyntaxData(RC<RawSyntax> Raw);
|
||||
static RC<GenericParameterListSyntaxData> make(RC<RawSyntax> Raw);
|
||||
GenericParameterListSyntaxData(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent = nullptr,
|
||||
CursorIndex IndexInParent = 0);
|
||||
static RC<GenericParameterListSyntaxData>
|
||||
make(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
|
||||
CursorIndex IndexInParent = 0);
|
||||
static RC<GenericParameterListSyntaxData> makeBlank();
|
||||
|
||||
public:
|
||||
@@ -276,8 +260,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-parameter-list API (TODO)
|
||||
#pragma mark - generic-parameter-list API
|
||||
|
||||
/// generic-parameter-list -> generic-parameter
|
||||
/// | generic-parameter ',' generic-parameter-list
|
||||
@@ -309,12 +292,12 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-parameter-clause API
|
||||
#pragma mark - generic-parameter-clause API
|
||||
|
||||
/// generic-parameter-clause -> '<' generic-argument-list '>'
|
||||
class GenericParameterClauseSyntax final : public Syntax {
|
||||
friend struct SyntaxFactory;
|
||||
friend class GenericParameterClauseSyntaxData;
|
||||
friend class GenericParameterClauseBuilder;
|
||||
enum class Cursor : CursorIndex {
|
||||
LeftAngleBracketToken,
|
||||
@@ -325,19 +308,6 @@ class GenericParameterClauseSyntax final : public Syntax {
|
||||
GenericParameterClauseSyntax(RC<SyntaxData> Root,
|
||||
const GenericParameterClauseSyntaxData *Data);
|
||||
|
||||
// TODO: move to cpp make
|
||||
// GenericParameterClauseSyntax(RC<RawSyntax> Raw)
|
||||
// : Syntax(Raw) {
|
||||
// assert(Raw->Kind == SyntaxKind::GenericParameterClause);
|
||||
// assert(Raw->Layout.size() == 3);
|
||||
// syntax_assert_child_token_text(Raw, Cursor::LeftAngleBracketToken,
|
||||
// tok::l_angle, "<");
|
||||
// syntax_assert_child_kind(Raw, Cursor::GenericParameterList,
|
||||
// SyntaxKind::GenericParameterList);
|
||||
// syntax_assert_child_token_text(Raw, Cursor::RightAngleBracketToken,
|
||||
// tok::r_angle, ">");
|
||||
// }
|
||||
|
||||
public:
|
||||
/// Return the left angle bracket '<' token on the generic parameter clause.
|
||||
RC<TokenSyntax> getLeftAngleBracket() const;
|
||||
@@ -367,8 +337,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-parameter-clause Builder
|
||||
#pragma mark - generic-parameter-clause Builder
|
||||
|
||||
class GenericParameterClauseBuilder {
|
||||
RC<TokenSyntax> LeftAngleToken;
|
||||
@@ -391,16 +360,16 @@ public:
|
||||
GenericParameterClauseSyntax build() const;
|
||||
};
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-argument API
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-argument-list Data
|
||||
#pragma mark - generic-argument-list Data
|
||||
|
||||
class GenericArgumentListSyntaxData final : public SyntaxData {
|
||||
friend class SyntaxData;
|
||||
GenericArgumentListSyntaxData(RC<RawSyntax> Raw);
|
||||
static RC<GenericArgumentListSyntaxData> make(RC<RawSyntax> Raw);
|
||||
GenericArgumentListSyntaxData(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent = nullptr,
|
||||
CursorIndex IndexInParent = 0);
|
||||
static RC<GenericArgumentListSyntaxData>
|
||||
make(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
|
||||
CursorIndex IndexInParent = 0);
|
||||
static RC<GenericArgumentListSyntaxData> makeBlank();
|
||||
public:
|
||||
static bool classof(const SyntaxData *S) {
|
||||
@@ -408,8 +377,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-argument-list API
|
||||
#pragma mark - generic-argument-list API
|
||||
|
||||
/// generic-argument-list -> generic-argument
|
||||
/// | generic-argument ',' generic-argument-list
|
||||
@@ -437,8 +405,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-argument-list Data
|
||||
#pragma mark - generic-argument-clause Data
|
||||
|
||||
class GenericArgumentClauseSyntaxData final : public SyntaxData {
|
||||
friend class SyntaxData;
|
||||
@@ -460,8 +427,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-argument-clause API
|
||||
#pragma mark - generic-argument-clause API
|
||||
|
||||
/// generic-argument-clause -> '<' generic-argument-list '>'
|
||||
class GenericArgumentClauseSyntax : public Syntax {
|
||||
@@ -480,18 +446,6 @@ class GenericArgumentClauseSyntax : public Syntax {
|
||||
GenericArgumentClauseSyntax(RC<SyntaxData> Root,
|
||||
const GenericArgumentClauseSyntaxData *Data);
|
||||
|
||||
// TODO: move to cpp make
|
||||
// GenericArgumentClauseSyntax(RC<RawSyntax> Raw)
|
||||
// : Syntax(Raw) {
|
||||
// assert(Raw->Kind == SyntaxKind::GenericArgumentClause);
|
||||
// assert(Raw->Layout.size() == 3);
|
||||
// syntax_assert_child_token_text(Raw, Cursor::LeftAngleBracketToken,
|
||||
// tok::l_angle, "<");
|
||||
// syntax_assert_child_kind(Raw, Cursor::GenericArgumentList,
|
||||
// SyntaxKind::GenericArgumentList);
|
||||
// syntax_assert_child_token_text(Raw, Cursor::RightAngleBracketToken,
|
||||
// tok::r_angle, ">");
|
||||
// }
|
||||
public:
|
||||
/// Return the left angle bracket '<' token on the generic argument clause.
|
||||
RC<TokenSyntax> getLeftAngleBracket() const;
|
||||
@@ -522,8 +476,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-argument-clause Builder
|
||||
#pragma mark - generic-argument-clause Builder
|
||||
|
||||
class GenericArgumentClauseBuilder {
|
||||
RC<TokenSyntax> LeftAngleToken;
|
||||
@@ -545,13 +498,16 @@ public:
|
||||
GenericArgumentClauseSyntax build() const;
|
||||
};
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-requirement-list Data
|
||||
#pragma mark - generic-requirement-list Data
|
||||
|
||||
class GenericRequirementListSyntaxData final : public SyntaxData {
|
||||
friend class SyntaxData;
|
||||
GenericRequirementListSyntaxData(RC<RawSyntax> Raw);
|
||||
static RC<GenericRequirementListSyntaxData> make(RC<RawSyntax> Raw);
|
||||
GenericRequirementListSyntaxData(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent = nullptr,
|
||||
CursorIndex IndexInParent = 0);
|
||||
static RC<GenericRequirementListSyntaxData>
|
||||
make(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
|
||||
CursorIndex IndexInParent = 0);
|
||||
static RC<GenericRequirementListSyntaxData> makeBlank();
|
||||
public:
|
||||
static bool classof(const SyntaxData *S) {
|
||||
@@ -559,8 +515,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-requirement-list API
|
||||
#pragma mark - generic-requirement-list API
|
||||
|
||||
/// requirement-list -> requirement | requirement ',' requirement-list
|
||||
///
|
||||
@@ -584,8 +539,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-where-clause Data
|
||||
#pragma mark - generic-where-clause Data
|
||||
|
||||
class GenericWhereClauseSyntaxData final : public SyntaxData {
|
||||
friend class SyntaxData;
|
||||
@@ -607,12 +561,12 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-where-clause API
|
||||
#pragma mark - generic-where-clause API
|
||||
|
||||
/// generic-where-clause -> 'where' requirement-list
|
||||
class GenericWhereClauseSyntax final : public Syntax {
|
||||
friend struct SyntaxFactory;
|
||||
friend class GenericWhereClauseSyntaxData;
|
||||
enum class Cursor : CursorIndex {
|
||||
WhereToken,
|
||||
RequirementList,
|
||||
@@ -621,17 +575,6 @@ class GenericWhereClauseSyntax final : public Syntax {
|
||||
GenericWhereClauseSyntax(RC<SyntaxData> Root,
|
||||
const GenericWhereClauseSyntaxData *Data);
|
||||
|
||||
// TODO: move to cpp make
|
||||
// GenericWhereClauseSyntax(RC<RawSyntax> Raw)
|
||||
// : Syntax(Raw) {
|
||||
// assert(Raw->Kind == SyntaxKind::GenericWhereClause);
|
||||
// assert(Raw->Layout.size() == 2);
|
||||
// syntax_assert_child_token_text(Raw, Cursor::WhereToken, tok::kw_where,
|
||||
// "where");
|
||||
// syntax_assert_child_kind(Raw, Cursor::RequirementList,
|
||||
// SyntaxKind::GenericRequirementList);
|
||||
// }
|
||||
|
||||
public:
|
||||
/// Return the 'where' keyword in the generic where clause.
|
||||
RC<TokenSyntax> getWhereKeyword() const;
|
||||
|
||||
@@ -230,6 +230,11 @@ struct RawSyntax : public llvm::ThreadSafeRefCountedBase<RawSyntax> {
|
||||
return Kind >= SyntaxKind::First_Stmt && Kind <= SyntaxKind::Last_Stmt;
|
||||
}
|
||||
|
||||
/// Returns true if this raw syntax node is some kind of expression.
|
||||
bool isExpr() const {
|
||||
return Kind >= SyntaxKind::First_Expr && Kind <= SyntaxKind::Last_Expr;
|
||||
}
|
||||
|
||||
/// Get the absolute position of this raw syntax: its offset, line,
|
||||
/// and column.
|
||||
AbsolutePosition getAbsolutePosition(RC<RawSyntax> Root) const;
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "swift/Syntax/References.h"
|
||||
#include "swift/Syntax/DeclSyntax.h"
|
||||
#include "swift/Syntax/ExprSyntax.h"
|
||||
#include "swift/Syntax/StmtSyntax.h"
|
||||
#include "swift/Syntax/Syntax.h"
|
||||
|
||||
|
||||
@@ -23,9 +23,16 @@
|
||||
#include "swift/Syntax/Syntax.h"
|
||||
#include "swift/Syntax/SyntaxData.h"
|
||||
|
||||
using llvm::Optional;
|
||||
|
||||
namespace swift {
|
||||
namespace syntax {
|
||||
|
||||
class ExprSyntax;
|
||||
class ExprSyntaxData;
|
||||
|
||||
#pragma mark - statement Data
|
||||
|
||||
class StmtSyntaxData : public SyntaxData {
|
||||
protected:
|
||||
StmtSyntaxData(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
|
||||
@@ -37,6 +44,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#pragma mark - statement API
|
||||
|
||||
/// statement -> expression ';'?
|
||||
/// | declaration ';'?
|
||||
/// | loop-statement ';'?
|
||||
@@ -55,6 +64,39 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#pragma mark - unknown-statement Data
|
||||
|
||||
class UnknownStmtSyntaxData : public StmtSyntaxData {
|
||||
UnknownStmtSyntaxData(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
|
||||
CursorIndex IndexInParent = 0);
|
||||
public:
|
||||
static RC<UnknownStmtSyntaxData> make(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent = nullptr,
|
||||
CursorIndex IndexInParent = 0);
|
||||
|
||||
static bool classof(const SyntaxData *S) {
|
||||
return S->getKind() == SyntaxKind::UnknownStmt;
|
||||
}
|
||||
};
|
||||
|
||||
#pragma mark - unknown-statement API
|
||||
|
||||
class UnknownStmtSyntax : public StmtSyntax {
|
||||
friend class SyntaxData;
|
||||
friend class UnknownStmtSyntaxData;
|
||||
friend class LegacyASTTransformer;
|
||||
|
||||
using DataType = UnknownExprSyntaxData;
|
||||
|
||||
UnknownStmtSyntax(const RC<SyntaxData> Root,
|
||||
const UnknownStmtSyntaxData *Data);
|
||||
|
||||
public:
|
||||
static bool classof(const Syntax *S) {
|
||||
return S->getKind() == SyntaxKind::UnknownStmt;
|
||||
}
|
||||
};
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark code-block Data
|
||||
|
||||
@@ -63,8 +105,11 @@ class CodeBlockStmtSyntaxData final : public StmtSyntaxData {
|
||||
friend class CodeBlockStmtSyntax;
|
||||
friend struct SyntaxFactory;
|
||||
|
||||
CodeBlockStmtSyntaxData(RC<RawSyntax> Raw);
|
||||
static RC<CodeBlockStmtSyntaxData> make(RC<RawSyntax> Raw);
|
||||
CodeBlockStmtSyntaxData(RC<RawSyntax> Raw, const SyntaxData *Parent = nullptr,
|
||||
CursorIndex IndexInParent = 0);
|
||||
static RC<CodeBlockStmtSyntaxData> make(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent = nullptr,
|
||||
CursorIndex IndexInParent = 0);
|
||||
static RC<CodeBlockStmtSyntaxData> makeBlank();
|
||||
public:
|
||||
static bool classof(const SyntaxData *SD) {
|
||||
@@ -360,6 +405,72 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#pragma mark - return-statement Data
|
||||
|
||||
class ReturnStmtSyntaxData : public StmtSyntaxData {
|
||||
friend class SyntaxData;
|
||||
friend class ReturnStmtSyntax;
|
||||
friend struct SyntaxFactory;
|
||||
|
||||
RC<ExprSyntaxData> CachedExpression;
|
||||
|
||||
ReturnStmtSyntaxData(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent = nullptr,
|
||||
CursorIndex IndexInParent = 0);
|
||||
static RC<ReturnStmtSyntaxData> make(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent = nullptr,
|
||||
CursorIndex IndexInParent = 0);
|
||||
static RC<ReturnStmtSyntaxData> makeBlank();
|
||||
|
||||
public:
|
||||
static bool classof(const SyntaxData *SD) {
|
||||
return SD->getKind() == SyntaxKind::ReturnStmt;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#pragma mark - return-statement API
|
||||
|
||||
/// return-statement -> 'return' expression? ';'?
|
||||
class ReturnStmtSyntax : public StmtSyntax {
|
||||
friend struct SyntaxFactory;
|
||||
friend class ReturnStmtSyntaxData;
|
||||
friend class SyntaxData;
|
||||
friend class Syntax;
|
||||
|
||||
using DataType = ReturnStmtSyntaxData;
|
||||
|
||||
enum class Cursor : CursorIndex {
|
||||
ReturnKeyword,
|
||||
Expression
|
||||
};
|
||||
|
||||
ReturnStmtSyntax(const RC<SyntaxData> Root,
|
||||
const ReturnStmtSyntaxData *Data);
|
||||
|
||||
static ReturnStmtSyntax make(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent = nullptr,
|
||||
CursorIndex IndexInParent = 0);
|
||||
static ReturnStmtSyntax makeBlank();
|
||||
public:
|
||||
|
||||
/// Return the 'return' keyword associated with this return statement.
|
||||
RC<TokenSyntax> getReturnKeyword() const;
|
||||
|
||||
/// Return a new `ReturnStmtSyntax` with the given 'return' keyword.
|
||||
ReturnStmtSyntax withReturnKeyword(RC<TokenSyntax> NewReturnKeyword) const;
|
||||
|
||||
/// Return the expression of this return statement.
|
||||
Optional<ExprSyntax> getExpression() const;
|
||||
|
||||
/// Return a new `ReturnStmtSyntax` with the given destination label.
|
||||
ReturnStmtSyntax withExpression(ExprSyntax NewExpression) const;
|
||||
|
||||
static bool classof(const Syntax *S) {
|
||||
return S->getKind() == SyntaxKind::ReturnStmt;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace syntax
|
||||
} // end namespace swift
|
||||
|
||||
|
||||
@@ -69,6 +69,12 @@ protected:
|
||||
/// lazily created.
|
||||
mutable const SyntaxData *Data;
|
||||
|
||||
template <typename SyntaxNode>
|
||||
typename SyntaxNode::DataType *getUnsafeData() const {
|
||||
auto Casted = cast<typename SyntaxNode::DataType>(Data);
|
||||
return const_cast<typename SyntaxNode::DataType *>(Casted);
|
||||
}
|
||||
|
||||
public:
|
||||
Syntax(const RC<SyntaxData> Root, const SyntaxData *Data);
|
||||
|
||||
@@ -81,14 +87,18 @@ public:
|
||||
/// Returns true if the syntax node is of the given type.
|
||||
template <typename T>
|
||||
bool is() const {
|
||||
return T::classof(Data);
|
||||
return T::classof(this);
|
||||
}
|
||||
|
||||
/// Get the Data for this Syntax node.
|
||||
template <typename T>
|
||||
typename T::DataType getData() const {
|
||||
typename T::DataType &getData() const {
|
||||
assert(is<T>() && "getData<T>() node of incompatible type!");
|
||||
return reinterpret_cast<typename T::DataType *>(Data);
|
||||
return *reinterpret_cast<typename T::DataType *>(Data);
|
||||
}
|
||||
|
||||
const SyntaxData *getDataPointer() const {
|
||||
return Data;
|
||||
}
|
||||
|
||||
/// Cast this Syntax node to a more specific type, asserting it's of the
|
||||
@@ -122,6 +132,9 @@ public:
|
||||
/// Returns true if this syntax node represents a declaration.
|
||||
bool isDecl() const;
|
||||
|
||||
/// Returns true if this syntax node represents an expression.
|
||||
bool isExpr() const;
|
||||
|
||||
/// Returns true if this syntax node represents a type.
|
||||
bool isType() const;
|
||||
|
||||
@@ -134,6 +147,12 @@ public:
|
||||
|
||||
/// Print a debug representation of the syntax node to standard error.
|
||||
void dump() const;
|
||||
|
||||
bool hasSameIdentityAs(const Syntax &Other) {
|
||||
return Root == Other.Root && Data == Other.Data;
|
||||
}
|
||||
|
||||
// TODO: hasSameStructureAs ?
|
||||
};
|
||||
|
||||
/// A chunk of "unknown" syntax - effectively a sequence of tokens.
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
#include "swift/Syntax/Syntax.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
|
||||
#include <atomic>
|
||||
|
||||
namespace swift {
|
||||
namespace syntax {
|
||||
|
||||
@@ -103,6 +105,78 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
/// Unsafely instantiate a child within another node.
|
||||
///
|
||||
/// DANGER!
|
||||
///
|
||||
/// Scary thread-safe code here. This should only be used for internally
|
||||
/// mutating cached children!
|
||||
///
|
||||
/// Why do we need this?
|
||||
/// - ___SyntaxData nodes should have pointer identity.
|
||||
/// - We only want to construct parented, realized child nodes as
|
||||
/// ___SyntaxData when asked.
|
||||
///
|
||||
/// For example, if we have a ReturnStmtSyntax, and ask for its returned
|
||||
/// expression for the first time with getExpression(), two nodes can race
|
||||
/// to create and set the cached expression.
|
||||
///
|
||||
///
|
||||
/// Looking at an example - say we have a ReturnStmtSyntaxData.
|
||||
///
|
||||
/// ReturnStmtSyntaxData = {
|
||||
/// RC<RawSyntax> Raw = {
|
||||
/// RC<TokenSyntax { SyntaxKind::Token, tok::return_kw, "return" },
|
||||
/// RC<RawSyntax> { SyntaxKind::SomeExpression, ... }
|
||||
/// }
|
||||
/// RC<ExprSyntaxData> CachedExpression = { 0 };
|
||||
/// }
|
||||
///
|
||||
/// We pretend that `CachedExpression` is a std::atomic<uintptr_t> &, so that
|
||||
/// we can safely instantiate that field using the RawSyntax for the
|
||||
/// expression, i.e. getRaw()->getChild(ReturnStmtSyntax::Cursor::Expression))
|
||||
template <typename SyntaxNode>
|
||||
static
|
||||
void realizeSyntaxNode(std::atomic<uintptr_t> &Child,
|
||||
RC<RawSyntax> RawChild,
|
||||
const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent) {
|
||||
// We rely on the fact that an RC<___SyntaxData> is pointer-sized, which
|
||||
// means we can atomically compare-exchange the child field.
|
||||
// If we can't do that, we can't pretend it's a uintptr_t and use its
|
||||
// compare_exchange_strong.
|
||||
static_assert(
|
||||
sizeof(uintptr_t) == sizeof(RC<typename SyntaxNode::DataType>),
|
||||
"Can't safely atomically replace a child SyntaxData node "
|
||||
"for caching! This is the end of the world!");
|
||||
|
||||
if (Child == 0) {
|
||||
// We expect the uncached value to wrap a nullptr. If another thread
|
||||
// beats us to caching the child, it'll be non-null, so we would
|
||||
// leave it alone.
|
||||
uintptr_t Expected = 0;
|
||||
|
||||
// Make a RC<SyntaxNode::DataType> at RefCount == 1, which we'll try to
|
||||
// atomically swap in.
|
||||
RC<typename SyntaxNode::DataType> Data =
|
||||
cast<typename SyntaxNode::DataType>(
|
||||
SyntaxData::makeDataFromRaw(RawChild, Parent, IndexInParent));
|
||||
|
||||
// Try to swap in raw pointer value.
|
||||
auto SuccessfullySwapped =
|
||||
Child.compare_exchange_strong(Expected,
|
||||
reinterpret_cast<uintptr_t>(Data.get()));
|
||||
|
||||
// If we won, then leave the RefCount == 1.
|
||||
if (SuccessfullySwapped) {
|
||||
Data.resetWithoutRelease();
|
||||
}
|
||||
|
||||
// Otherwise, the Data we just made is unfortunately useless.
|
||||
// Let it die on this scope exit after its terminal release.
|
||||
}
|
||||
}
|
||||
|
||||
/// Replace a child in the raw syntax and recursively rebuild the
|
||||
/// parental chain up to the rooet.
|
||||
///
|
||||
@@ -118,6 +192,11 @@ protected:
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
static RC<SyntaxData> makeDataFromRaw(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent);
|
||||
|
||||
static RC<SyntaxData> make(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent = nullptr,
|
||||
CursorIndex IndexInParent = 0);
|
||||
@@ -160,6 +239,9 @@ public:
|
||||
/// Returns true if the data node represents declaration syntax.
|
||||
bool isDecl() const;
|
||||
|
||||
/// Returns true if the data node represents expression syntax.
|
||||
bool isExpr() const;
|
||||
|
||||
/// Dump a debug description of the syntax data for debugging to
|
||||
/// standard error.
|
||||
void dump(llvm::raw_ostream &OS) const;
|
||||
@@ -175,7 +257,9 @@ class UnknownSyntaxData final : public SyntaxData {
|
||||
CursorIndex IndexInParent = 0)
|
||||
: SyntaxData(Raw, Parent, IndexInParent) {}
|
||||
|
||||
static RC<UnknownSyntaxData> make(RC<RawSyntax> Raw);
|
||||
static RC<UnknownSyntaxData> make(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent = nullptr,
|
||||
CursorIndex IndexInParent = 0);
|
||||
public:
|
||||
static bool classof(const SyntaxData *SD);
|
||||
};
|
||||
|
||||
@@ -38,6 +38,9 @@ namespace syntax {
|
||||
|
||||
#define SYNTAX(Id, Parent) class Id##Syntax;
|
||||
#include "swift/Syntax/SyntaxKinds.def"
|
||||
class DeclSyntax;
|
||||
class ExprSyntax;
|
||||
class StmtSyntax;
|
||||
class UnknownSyntax;
|
||||
struct TokenSyntax;
|
||||
|
||||
@@ -98,7 +101,7 @@ struct SyntaxFactory {
|
||||
/// and destination label marked as missing.
|
||||
static BreakStmtSyntax makeBlankBreakStmtSyntax();
|
||||
|
||||
/// Make a continue statement with the give `continue` keyword and
|
||||
/// Make a continue statement with the given `continue` keyword and
|
||||
/// destination label.
|
||||
static ContinueStmtSyntax
|
||||
makeContinueStmt(RC<TokenSyntax> ContinueKeyword, RC<TokenSyntax> Label);
|
||||
@@ -107,6 +110,25 @@ struct SyntaxFactory {
|
||||
/// and destination label marked as missing.
|
||||
static ContinueStmtSyntax makeBlankContinueStmtSyntax();
|
||||
|
||||
/// Make a return statement with the given `return` keyword and returned
|
||||
/// expression.
|
||||
static ReturnStmtSyntax
|
||||
makeReturnStmt(RC<TokenSyntax> ReturnKeyword, ExprSyntax ReturnedExpression);
|
||||
|
||||
/// Make a return statement with the `return` keyword and return expression
|
||||
/// marked as missing.
|
||||
static ReturnStmtSyntax makeBlankReturnStmt();
|
||||
|
||||
#pragma mark - Expressions
|
||||
|
||||
/// Make an integer literal with the given '+'/'-' sign and string of digits.
|
||||
static IntegerLiteralExprSyntax
|
||||
makeIntegerLiteralExpr(RC<TokenSyntax> Sign, RC<TokenSyntax> Digits);
|
||||
|
||||
/// Make an integer literal with the sign and string of digits marked
|
||||
/// as missing.
|
||||
static IntegerLiteralExprSyntax makeBlankIntegerLiteralExpr();
|
||||
|
||||
#pragma mark - Tokens
|
||||
|
||||
/// Make a 'fallthrough' keyword with the specified leading and
|
||||
@@ -129,6 +151,11 @@ struct SyntaxFactory {
|
||||
static RC<TokenSyntax> makeContinueKeyword(const Trivia &LeadingTrivia,
|
||||
const Trivia &TrailingTrivia);
|
||||
|
||||
/// Make a 'return' keyword with the specified leading and
|
||||
/// trailing trivia.
|
||||
static RC<TokenSyntax> makeReturnKeyword(const Trivia &LeadingTrivia,
|
||||
const Trivia &TrailingTrivia);
|
||||
|
||||
/// Make a left angle '<' token with the specified leading and
|
||||
/// trailing trivia.
|
||||
static RC<TokenSyntax> makeLeftAngleToken(const Trivia &LeadingTrivia,
|
||||
@@ -235,6 +262,20 @@ struct SyntaxFactory {
|
||||
static RC<TokenSyntax> makeProtocolToken(const Trivia &LeadingTrivia,
|
||||
const Trivia &TrailingTrivia);
|
||||
|
||||
/// Make a token representing the digits of an integer literal.
|
||||
///
|
||||
/// Note: This is not a stand-in for the expression, which can contain
|
||||
/// a minus sign.
|
||||
static RC<TokenSyntax> makeIntegerLiteralToken(OwnedString Digits,
|
||||
const Trivia &LeadingTrivia,
|
||||
const Trivia &TrailingTrivia);
|
||||
|
||||
#pragma mark - Operators
|
||||
|
||||
/// Make a prefix operator with the given text.
|
||||
static RC<TokenSyntax> makePrefixOpereator(OwnedString Name,
|
||||
const Trivia &LeadingTrivia);
|
||||
|
||||
#pragma mark - Types
|
||||
|
||||
#pragma mark - type-attribute
|
||||
|
||||
@@ -36,11 +36,12 @@ SYNTAX(Unknown, Syntax)
|
||||
|
||||
// Decls
|
||||
ABSTRACT_SYNTAX(DeclSyntax, Syntax)
|
||||
MISSING_SYNTAX(MissingDecl, Decl)
|
||||
MISSING_SYNTAX(MissingDecl, DeclSyntax)
|
||||
SYNTAX(UnknownDecl, DeclSyntax)
|
||||
SYNTAX(StructDecl, DeclSyntax)
|
||||
SYNTAX(TypeAliasDecl, DeclSyntax)
|
||||
|
||||
SYNTAX_RANGE(Decl, StructDecl, TypeAliasDecl)
|
||||
SYNTAX_RANGE(Decl, MissingDecl, TypeAliasDecl)
|
||||
|
||||
SYNTAX(DeclMembers, Syntax)
|
||||
SYNTAX(GenericParameter, Syntax)
|
||||
@@ -72,11 +73,20 @@ SYNTAX_RANGE(Type, MissingType, FunctionType)
|
||||
SYNTAX(StmtList, Syntax)
|
||||
|
||||
ABSTRACT_SYNTAX(StmtSyntax, Syntax)
|
||||
SYNTAX(UnknownStmt, StmtSyntax)
|
||||
SYNTAX(CodeBlockStmt, StmtSyntax)
|
||||
SYNTAX(FallthroughStmt, StmtSyntax)
|
||||
SYNTAX(BreakStmt, StmtSyntax)
|
||||
SYNTAX(ContinueStmt, StmtSyntax)
|
||||
SYNTAX_RANGE(Stmt, CodeBlockStmt, ContinueStmt)
|
||||
SYNTAX(ReturnStmt, StmtSyntax)
|
||||
SYNTAX_RANGE(Stmt, UnknownStmt, ReturnStmt)
|
||||
|
||||
// Expressions
|
||||
ABSTRACT_SYNTAX(ExprSyntax, Syntax)
|
||||
MISSING_SYNTAX(MissingExpr, ExprSyntax)
|
||||
SYNTAX(UnknownExpr, ExprSyntax)
|
||||
SYNTAX(IntegerLiteralExpr, ExprSyntax)
|
||||
SYNTAX_RANGE(Expr, MissingExpr, IntegerLiteralExpr)
|
||||
|
||||
SYNTAX(BalancedTokens, Syntax)
|
||||
SYNTAX(TypeAttribute, Syntax)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
add_swift_library(swiftSyntax STATIC
|
||||
DeclSyntax.cpp
|
||||
ExprSyntax.cpp
|
||||
Format.cpp
|
||||
TokenSyntax.cpp
|
||||
GenericSyntax.cpp
|
||||
|
||||
@@ -31,6 +31,32 @@ DeclSyntaxData::DeclSyntaxData(RC<RawSyntax> Raw,
|
||||
DeclSyntax::DeclSyntax(const RC<SyntaxData> Root, const DeclSyntaxData *Data)
|
||||
: Syntax(Root, Data) {}
|
||||
|
||||
#pragma mark - unknown-statement Data
|
||||
|
||||
UnknownDeclSyntaxData::UnknownDeclSyntaxData(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent)
|
||||
: DeclSyntaxData(Raw, Parent, IndexInParent) {
|
||||
assert(Raw->Kind == SyntaxKind::UnknownStmt);
|
||||
}
|
||||
|
||||
RC<UnknownDeclSyntaxData>
|
||||
UnknownDeclSyntaxData::make(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent) {
|
||||
return RC<UnknownDeclSyntaxData> {
|
||||
new UnknownDeclSyntaxData {
|
||||
Raw, Parent, IndexInParent
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#pragma mark - unknown-statement API
|
||||
|
||||
UnknownDeclSyntax::UnknownDeclSyntax(const RC<SyntaxData> Root,
|
||||
const UnknownDeclSyntaxData *Data)
|
||||
: DeclSyntax(Root, Data) {}
|
||||
|
||||
#pragma mark - declaration-members Data
|
||||
|
||||
DeclMembersSyntaxData::DeclMembersSyntaxData(RC<RawSyntax> Raw,
|
||||
|
||||
113
lib/Syntax/ExprSyntax.cpp
Normal file
113
lib/Syntax/ExprSyntax.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
//===--- ExprSyntax.cpp - Swift Expression Syntax Impl. ---------*- C++ -*-===//
|
||||
//
|
||||
// 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"
|
||||
|
||||
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)
|
||||
: ExprSyntaxData(Raw, Parent, IndexInParent) {
|
||||
assert(Raw->Kind == SyntaxKind::UnknownExpr);
|
||||
}
|
||||
|
||||
RC<UnknownExprSyntaxData>
|
||||
UnknownExprSyntaxData::make(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent) {
|
||||
return RC<UnknownExprSyntaxData> {
|
||||
new UnknownExprSyntaxData {
|
||||
Raw, Parent, IndexInParent
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#pragma mark - unknown-expression API
|
||||
|
||||
UnknownExprSyntax::UnknownExprSyntax(const RC<SyntaxData> Root,
|
||||
const UnknownExprSyntaxData *Data)
|
||||
: ExprSyntax(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);
|
||||
}
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "swift/Syntax/Format.h"
|
||||
#include "swift/Syntax/DeclSyntax.h"
|
||||
#include "swift/Syntax/ExprSyntax.h"
|
||||
|
||||
using namespace swift;
|
||||
using namespace swift::syntax;
|
||||
|
||||
@@ -21,14 +21,58 @@ using llvm::None;
|
||||
using namespace swift;
|
||||
using namespace swift::syntax;
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-parameter Data
|
||||
#pragma mark - conformance-requirement Data
|
||||
|
||||
ConformanceRequirementSyntaxData::
|
||||
ConformanceRequirementSyntaxData(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent)
|
||||
: SyntaxData(Raw, Parent, IndexInParent) {
|
||||
assert(Raw->Kind == SyntaxKind::ConformanceRequirement);
|
||||
syntax_assert_child_kind(Raw,
|
||||
ConformanceRequirementSyntax::Cursor::LeftTypeIdentifier,
|
||||
SyntaxKind::TypeIdentifier);
|
||||
syntax_assert_child_token_text(Raw,
|
||||
ConformanceRequirementSyntax::Cursor::Colon,
|
||||
tok::colon, ":");
|
||||
syntax_assert_child_kind(Raw,
|
||||
ConformanceRequirementSyntax::Cursor::RightTypeIdentifier,
|
||||
SyntaxKind::TypeIdentifier);
|
||||
}
|
||||
|
||||
RC<ConformanceRequirementSyntaxData>
|
||||
ConformanceRequirementSyntaxData::make(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent) {
|
||||
return RC<ConformanceRequirementSyntaxData> {
|
||||
new ConformanceRequirementSyntaxData {
|
||||
Raw, Parent, IndexInParent
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
RC<ConformanceRequirementSyntaxData>
|
||||
ConformanceRequirementSyntaxData::makeBlank() {
|
||||
auto Raw = RawSyntax::make(SyntaxKind::ConformanceRequirement,
|
||||
{
|
||||
RawSyntax::missing(SyntaxKind::TypeIdentifier),
|
||||
TokenSyntax::missingToken(tok::colon, ":"),
|
||||
RawSyntax::missing(SyntaxKind::TypeIdentifier),
|
||||
},
|
||||
SourcePresence::Present);
|
||||
return make(Raw);
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - generic-parameter Data
|
||||
|
||||
GenericParameterSyntaxData::
|
||||
GenericParameterSyntaxData(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent)
|
||||
: SyntaxData(Raw, Parent, IndexInParent) {}
|
||||
: SyntaxData(Raw, Parent, IndexInParent) {
|
||||
assert(Raw->Kind == SyntaxKind::GenericParameter);
|
||||
}
|
||||
|
||||
RC<GenericParameterSyntaxData>
|
||||
GenericParameterSyntaxData::make(RC<RawSyntax> Raw,
|
||||
@@ -49,14 +93,40 @@ RC<GenericParameterSyntaxData> GenericParameterSyntaxData::makeBlank() {
|
||||
SourcePresence::Present));
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-parameter API
|
||||
#pragma mark - generic-parameter API
|
||||
|
||||
GenericParameterSyntax::
|
||||
GenericParameterSyntax(RC<SyntaxData> Root,
|
||||
const GenericParameterSyntaxData *Data)
|
||||
: Syntax(Root, Data) {}
|
||||
|
||||
#pragma mark - generic-parameter-list Data
|
||||
|
||||
GenericParameterListSyntaxData::
|
||||
GenericParameterListSyntaxData(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent)
|
||||
: SyntaxData(Raw, Parent, IndexInParent) {
|
||||
assert(Raw->Kind == SyntaxKind::GenericParameterList);
|
||||
}
|
||||
|
||||
RC<GenericParameterListSyntaxData>
|
||||
GenericParameterListSyntaxData::make(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent) {
|
||||
return RC<GenericParameterListSyntaxData> {
|
||||
new GenericParameterListSyntaxData {
|
||||
Raw, Parent, IndexInParent
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
RC<GenericParameterListSyntaxData> GenericParameterListSyntaxData::makeBlank() {
|
||||
auto Raw = RawSyntax::make(SyntaxKind::GenericParameterList,
|
||||
{}, SourcePresence::Present);
|
||||
return make(Raw);
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-parameter-clause Data
|
||||
|
||||
@@ -65,7 +135,17 @@ GenericParameterClauseSyntaxData(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent)
|
||||
: SyntaxData(Raw, Parent, IndexInParent) {
|
||||
// TODO: Kind assertions
|
||||
syntax_assert_child_token_text(Raw,
|
||||
GenericParameterClauseSyntax::Cursor::LeftAngleBracketToken,
|
||||
tok::l_angle, "<");
|
||||
|
||||
syntax_assert_child_kind(Raw,
|
||||
GenericParameterClauseSyntax::Cursor::GenericParameterList,
|
||||
SyntaxKind::GenericParameterList);
|
||||
|
||||
syntax_assert_child_token_text(Raw,
|
||||
GenericParameterClauseSyntax::Cursor::RightAngleBracketToken,
|
||||
tok::r_angle, ">");
|
||||
}
|
||||
|
||||
RC<GenericParameterClauseSyntaxData>
|
||||
@@ -90,16 +170,14 @@ GenericParameterClauseSyntaxData::makeBlank() {
|
||||
SourcePresence::Present));
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-parameter-clause API
|
||||
#pragma mark - generic-parameter-clause API
|
||||
|
||||
GenericParameterClauseSyntax::
|
||||
GenericParameterClauseSyntax(RC<SyntaxData> Root,
|
||||
const GenericParameterClauseSyntaxData *Data)
|
||||
: Syntax(Root, Data) {}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-parameter-clause Builder
|
||||
#pragma mark - generic-parameter-clause Builder
|
||||
|
||||
GenericParameterClauseBuilder::GenericParameterClauseBuilder()
|
||||
: LeftAngleToken(TokenSyntax::missingToken(tok::l_angle, "<")),
|
||||
@@ -148,14 +226,46 @@ GenericParameterClauseSyntax GenericParameterClauseBuilder::build() const {
|
||||
return { Data, Data.get() };
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-where-clause Data
|
||||
#pragma mark - generic-requirement-list Data
|
||||
|
||||
GenericRequirementListSyntaxData::
|
||||
GenericRequirementListSyntaxData(RC<RawSyntax> Raw, const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent)
|
||||
: SyntaxData(Raw, Parent, IndexInParent) {
|
||||
assert(Raw->Kind == SyntaxKind::GenericRequirementList);
|
||||
}
|
||||
|
||||
RC<GenericRequirementListSyntaxData>
|
||||
GenericRequirementListSyntaxData::make(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent) {
|
||||
return RC<GenericRequirementListSyntaxData> {
|
||||
new GenericRequirementListSyntaxData {
|
||||
Raw, Parent, IndexInParent
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
RC<GenericRequirementListSyntaxData>
|
||||
GenericRequirementListSyntaxData::makeBlank() {
|
||||
auto Raw = RawSyntax::make(SyntaxKind::GenericRequirementList,
|
||||
{},
|
||||
SourcePresence::Present);
|
||||
return make(Raw);
|
||||
}
|
||||
|
||||
#pragma mark - generic-where-clause Data
|
||||
|
||||
GenericWhereClauseSyntaxData::
|
||||
GenericWhereClauseSyntaxData(RC<RawSyntax> Raw, const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent)
|
||||
: SyntaxData(Raw, Parent, IndexInParent) {
|
||||
// TODO: Kind Assertions
|
||||
assert(Raw->Kind == SyntaxKind::GenericWhereClause);
|
||||
syntax_assert_child_token_text(Raw,
|
||||
GenericWhereClauseSyntax::Cursor::WhereToken, tok::kw_where, "where");
|
||||
syntax_assert_child_kind(Raw,
|
||||
GenericWhereClauseSyntax::Cursor::RequirementList,
|
||||
SyntaxKind::GenericRequirementList);
|
||||
}
|
||||
|
||||
RC<GenericWhereClauseSyntaxData>
|
||||
@@ -170,30 +280,34 @@ GenericWhereClauseSyntaxData::make(RC<RawSyntax> Raw,
|
||||
RC<GenericWhereClauseSyntaxData> GenericWhereClauseSyntaxData::makeBlank() {
|
||||
return make(RawSyntax::make(SyntaxKind::GenericWhereClause,
|
||||
{
|
||||
RawSyntax::missing(SyntaxKind::TypeIdentifier),
|
||||
TokenSyntax::missingToken(tok::equal, "="),
|
||||
RawSyntax::missing(SyntaxKind::MissingType),
|
||||
TokenSyntax::missingToken(tok::kw_where, "where"),
|
||||
RawSyntax::missing(SyntaxKind::GenericRequirementList),
|
||||
},
|
||||
SourcePresence::Present));
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-where-clause API
|
||||
#pragma mark - generic-where-clause API
|
||||
|
||||
GenericWhereClauseSyntax::
|
||||
GenericWhereClauseSyntax(RC<SyntaxData> Root,
|
||||
const GenericWhereClauseSyntaxData *Data)
|
||||
: Syntax(Root, Data) {}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark same-type-requirement Data
|
||||
#pragma mark - same-type-requirement Data
|
||||
|
||||
SameTypeRequirementSyntaxData::
|
||||
SameTypeRequirementSyntaxData(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent)
|
||||
: SyntaxData(Raw, Parent, IndexInParent) {
|
||||
// TODO: kind assertions
|
||||
assert(Raw->Kind == SyntaxKind::SameTypeRequirement);
|
||||
assert(Raw->Layout.size() == 3);
|
||||
syntax_assert_child_kind(Raw,
|
||||
SameTypeRequirementSyntax::Cursor::LeftTypeIdentifier,
|
||||
SyntaxKind::TypeIdentifier);
|
||||
syntax_assert_child_token_text(Raw,
|
||||
SameTypeRequirementSyntax::Cursor::EqualityToken, tok::identifier, "==");
|
||||
assert(Raw->getChild(SameTypeRequirementSyntax::Cursor::RightType)->isType());
|
||||
}
|
||||
|
||||
RC<SameTypeRequirementSyntaxData>
|
||||
@@ -217,16 +331,43 @@ RC<SameTypeRequirementSyntaxData> SameTypeRequirementSyntaxData::makeBlank() {
|
||||
SourcePresence::Present));
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark same-type-requirement API
|
||||
#pragma mark - same-type-requirement API
|
||||
|
||||
SameTypeRequirementSyntax::
|
||||
SameTypeRequirementSyntax(RC<SyntaxData> Root,
|
||||
const SameTypeRequirementSyntaxData *Data)
|
||||
: Syntax(Root, Data) {}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-argument-clause Data
|
||||
#pragma mark - generic-argument-list Data
|
||||
|
||||
GenericArgumentListSyntaxData::
|
||||
GenericArgumentListSyntaxData(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent)
|
||||
: SyntaxData(Raw, Parent, IndexInParent) {
|
||||
assert(Raw->Kind == SyntaxKind::GenericArgumentList);
|
||||
}
|
||||
|
||||
RC<GenericArgumentListSyntaxData>
|
||||
GenericArgumentListSyntaxData::make(RC<RawSyntax> Raw, const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent) {
|
||||
return RC<GenericArgumentListSyntaxData> {
|
||||
new GenericArgumentListSyntaxData {
|
||||
Raw, Parent, IndexInParent
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
RC<GenericArgumentListSyntaxData> GenericArgumentListSyntaxData::makeBlank() {
|
||||
auto Raw = RawSyntax::make(SyntaxKind::GenericArgumentList, {},
|
||||
SourcePresence::Present);
|
||||
return make(Raw);
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - generic-argument-list API (TODO)
|
||||
|
||||
#pragma mark - generic-argument-clause Data
|
||||
|
||||
GenericArgumentClauseSyntaxData::
|
||||
GenericArgumentClauseSyntaxData(RC<RawSyntax> Raw, const SyntaxData *Parent,
|
||||
@@ -254,8 +395,7 @@ GenericArgumentClauseSyntaxData::makeBlank() {
|
||||
return make(Raw);
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-argument-clause API
|
||||
#pragma mark - generic-argument-clause API
|
||||
|
||||
GenericArgumentClauseSyntax::
|
||||
GenericArgumentClauseSyntax(RC<SyntaxData> Root,
|
||||
@@ -278,8 +418,7 @@ withRightAngleBracket(RC<TokenSyntax> NewRightAngleBracket) const {
|
||||
NewRightAngleBracket, Cursor::RightAngleBracketToken);
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark generic-argument-clause Builder
|
||||
#pragma mark - generic-argument-clause Builder
|
||||
|
||||
GenericArgumentClauseBuilder::GenericArgumentClauseBuilder()
|
||||
: ArgumentListLayout(
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "swift/AST/AST.h"
|
||||
#include "swift/Syntax/DeclSyntax.h"
|
||||
#include "swift/Syntax/ExprSyntax.h"
|
||||
#include "swift/Syntax/GenericSyntax.h"
|
||||
#include "swift/Syntax/LegacyASTTransformer.h"
|
||||
#include "swift/Syntax/References.h"
|
||||
@@ -153,20 +154,45 @@ RC<SyntaxData> LegacyASTTransformer::getUnknownSyntax(SourceRange SR) {
|
||||
}
|
||||
|
||||
RC<SyntaxData> LegacyASTTransformer::getUnknownDecl(Decl *D) {
|
||||
auto StartLoc = getStartLocForDecl(D);
|
||||
auto EndLoc = getEndLocForDecl(D);
|
||||
return getUnknownSyntax({StartLoc, EndLoc});
|
||||
SourceRange SR {getStartLocForDecl(D),getEndLocForDecl(D)};
|
||||
auto ComprisingTokens = getTokenSyntaxsInRange(SR, SourceMgr,
|
||||
BufferID, Tokens);
|
||||
RawSyntax::LayoutList Layout;
|
||||
std::copy(ComprisingTokens.begin(),
|
||||
ComprisingTokens.end(),
|
||||
std::back_inserter(Layout));
|
||||
auto Raw = RawSyntax::make(SyntaxKind::UnknownExpr,
|
||||
Layout,
|
||||
SourcePresence::Present);
|
||||
return UnknownDeclSyntaxData::make(Raw);
|
||||
}
|
||||
|
||||
RC<SyntaxData> LegacyASTTransformer::getUnknownStmt(Stmt *S) {
|
||||
auto EndLoc = getEndLocForStmt(S);
|
||||
|
||||
return getUnknownSyntax({S->getStartLoc(), EndLoc});
|
||||
SourceRange SR { S->getStartLoc(), getEndLocForStmt(S) };
|
||||
auto ComprisingTokens = getTokenSyntaxsInRange(SR, SourceMgr,
|
||||
BufferID, Tokens);
|
||||
RawSyntax::LayoutList Layout;
|
||||
std::copy(ComprisingTokens.begin(),
|
||||
ComprisingTokens.end(),
|
||||
std::back_inserter(Layout));
|
||||
auto Raw = RawSyntax::make(SyntaxKind::UnknownExpr,
|
||||
Layout,
|
||||
SourcePresence::Present);
|
||||
return UnknownStmtSyntaxData::make(Raw);
|
||||
}
|
||||
|
||||
RC<SyntaxData> LegacyASTTransformer::getUnknownExpr(Expr *E) {
|
||||
auto EndLoc = getEndLocForExpr(E);
|
||||
return getUnknownSyntax({E->getStartLoc(), EndLoc});
|
||||
SourceRange SR { E->getStartLoc(), getEndLocForExpr(E) };
|
||||
auto ComprisingTokens = getTokenSyntaxsInRange(SR, SourceMgr,
|
||||
BufferID, Tokens);
|
||||
RawSyntax::LayoutList Layout;
|
||||
std::copy(ComprisingTokens.begin(),
|
||||
ComprisingTokens.end(),
|
||||
std::back_inserter(Layout));
|
||||
auto Raw = RawSyntax::make(SyntaxKind::UnknownExpr,
|
||||
Layout,
|
||||
SourcePresence::Present);
|
||||
return UnknownExprSyntaxData::make(Raw);
|
||||
}
|
||||
|
||||
#pragma mark - Declarations
|
||||
@@ -437,7 +463,17 @@ RC<SyntaxData>
|
||||
LegacyASTTransformer::visitReturnStmt(ReturnStmt *S,
|
||||
const SyntaxData *Parent,
|
||||
const CursorIndex IndexInParent) {
|
||||
auto ReturnKW = findTokenSyntax(tok::kw_return, "return", SourceMgr,
|
||||
S->getReturnLoc(), BufferID, Tokens);
|
||||
auto Result = transformAST(S->getResult(), Sema, SourceMgr, BufferID,
|
||||
Tokens);
|
||||
|
||||
if (!Result.hasValue()) {
|
||||
return getUnknownStmt(S);
|
||||
}
|
||||
|
||||
return SyntaxFactory::makeReturnStmt(ReturnKW,
|
||||
Result.getValue().castTo<ExprSyntax>()).Root;
|
||||
}
|
||||
|
||||
RC<SyntaxData>
|
||||
@@ -593,7 +629,15 @@ RC<SyntaxData>
|
||||
LegacyASTTransformer::visitIntegerLiteralExpr(IntegerLiteralExpr *E,
|
||||
const SyntaxData *Parent,
|
||||
const CursorIndex IndexInParent) {
|
||||
return getUnknownExpr(E);
|
||||
auto Sign = E->getMinusLoc().isValid()
|
||||
? findTokenSyntax(tok::oper_prefix, OwnedString(),
|
||||
SourceMgr, E->getMinusLoc(),
|
||||
BufferID, Tokens)
|
||||
: TokenSyntax::missingToken(tok::oper_prefix, "");
|
||||
auto Digits = findTokenSyntax(tok::integer_literal, OwnedString(),
|
||||
SourceMgr, E->getDigitsLoc(),
|
||||
BufferID, Tokens);
|
||||
return SyntaxFactory::makeIntegerLiteralExpr(Sign, Digits).Root;
|
||||
}
|
||||
|
||||
RC<SyntaxData>
|
||||
@@ -1240,9 +1284,9 @@ syntax::findTokenSyntax(tok ExpectedKind,
|
||||
auto TokStart = Pos.getOffset();
|
||||
auto TokEnd = TokStart + Tok->getText().size();
|
||||
|
||||
if (Offset >= TokStart && Offset <= TokEnd) {
|
||||
if (Offset == TokStart) {
|
||||
if (Tok->getTokenKind() == ExpectedKind &&
|
||||
(!ExpectedText.empty() && Tok->getText() == ExpectedText.str())) {
|
||||
(ExpectedText.empty() || Tok->getText() == ExpectedText.str())) {
|
||||
return Tok;
|
||||
} else {
|
||||
return TokenSyntax::missingToken(ExpectedKind, ExpectedText);
|
||||
|
||||
@@ -60,6 +60,14 @@ Include the following in each entry:
|
||||
- continue-statement
|
||||
- `ContinueStmtSyntax`
|
||||
|
||||
- return-statement
|
||||
- `ReturnStmtSyntax`
|
||||
|
||||
### Expressions
|
||||
|
||||
- integer-literal
|
||||
- `IntegerLiteralExprSyntax`
|
||||
|
||||
### Types
|
||||
|
||||
- type
|
||||
@@ -271,7 +279,6 @@ Include the following in each entry:
|
||||
- initializer-declaration
|
||||
- initializer-expression
|
||||
- initializer-head
|
||||
- integer-literal
|
||||
- interpolated-string-literal
|
||||
- interpolated-text
|
||||
- interpolated-text-item
|
||||
@@ -342,7 +349,6 @@ Include the following in each entry:
|
||||
- repeat-while-statement
|
||||
- requirement
|
||||
- requirement-list
|
||||
- return-statement
|
||||
- selector-expression
|
||||
- self-expression
|
||||
- self-initializer-expression
|
||||
|
||||
@@ -11,14 +11,43 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#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)
|
||||
: StmtSyntaxData(Raw, Parent, IndexInParent) {
|
||||
assert(Raw->Kind == SyntaxKind::UnknownStmt);
|
||||
}
|
||||
|
||||
RC<UnknownStmtSyntaxData>
|
||||
UnknownStmtSyntaxData::make(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent) {
|
||||
return RC<UnknownStmtSyntaxData> {
|
||||
new UnknownStmtSyntaxData {
|
||||
Raw, Parent, IndexInParent
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#pragma mark - unknown-statement API
|
||||
|
||||
UnknownStmtSyntax::UnknownStmtSyntax(const RC<SyntaxData> Root,
|
||||
const UnknownStmtSyntaxData *Data)
|
||||
: StmtSyntax(Root, Data) {}
|
||||
|
||||
#pragma mark fallthrough-statement Data
|
||||
|
||||
FallthroughStmtSyntaxData::FallthroughStmtSyntaxData(RC<RawSyntax> Raw,
|
||||
@@ -82,8 +111,10 @@ withFallthroughKeyword(RC<TokenSyntax> NewFallthroughKeyword) const {
|
||||
}
|
||||
|
||||
|
||||
CodeBlockStmtSyntaxData::CodeBlockStmtSyntaxData(RC<RawSyntax> Raw)
|
||||
: StmtSyntaxData(Raw) {
|
||||
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, "{");
|
||||
@@ -94,9 +125,10 @@ CodeBlockStmtSyntaxData::CodeBlockStmtSyntaxData(RC<RawSyntax> Raw)
|
||||
}
|
||||
|
||||
RC<CodeBlockStmtSyntaxData>
|
||||
CodeBlockStmtSyntaxData::make(RC<RawSyntax> Raw) {
|
||||
CodeBlockStmtSyntaxData::make(RC<RawSyntax> Raw, const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent) {
|
||||
return RC<CodeBlockStmtSyntaxData> {
|
||||
new CodeBlockStmtSyntaxData { Raw }
|
||||
new CodeBlockStmtSyntaxData { Raw, Parent, IndexInParent }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -220,7 +252,7 @@ RC<ContinueStmtSyntaxData> ContinueStmtSyntaxData::makeBlank() {
|
||||
|
||||
ContinueStmtSyntax::ContinueStmtSyntax(const RC<SyntaxData> Root,
|
||||
ContinueStmtSyntaxData *Data)
|
||||
: StmtSyntax(Root, Data) {}
|
||||
: StmtSyntax(Root, Data) {}
|
||||
|
||||
ContinueStmtSyntax ContinueStmtSyntax::make(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent,
|
||||
@@ -255,6 +287,92 @@ ContinueStmtSyntax::withLabel(RC<TokenSyntax> NewLabel) const {
|
||||
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,
|
||||
|
||||
@@ -51,6 +51,10 @@ bool Syntax::isStmt() const {
|
||||
return Data->isStmt();
|
||||
}
|
||||
|
||||
bool Syntax::isExpr() const {
|
||||
return Data->isExpr();
|
||||
}
|
||||
|
||||
#pragma mark - unknown-syntax API
|
||||
|
||||
UnknownSyntax::UnknownSyntax(const RC<SyntaxData> Root,
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/Syntax/SyntaxData.h"
|
||||
#include "swift/Syntax/DeclSyntax.h"
|
||||
#include "swift/Syntax/ExprSyntax.h"
|
||||
#include "swift/Syntax/GenericSyntax.h"
|
||||
#include "swift/Syntax/TypeSyntax.h"
|
||||
#include "swift/Syntax/StmtSyntax.h"
|
||||
|
||||
@@ -25,6 +27,24 @@ RC<SyntaxData> SyntaxData::make(RC<RawSyntax> Raw,
|
||||
};
|
||||
}
|
||||
|
||||
RC<SyntaxData> SyntaxData::makeDataFromRaw(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent) {
|
||||
switch (Raw->Kind) {
|
||||
#define SYNTAX(Id, ParentType) \
|
||||
case SyntaxKind::Id: \
|
||||
return Id##SyntaxData::make(Raw, Parent, IndexInParent);
|
||||
|
||||
#define MISSING_SYNTAX(Id, ParentType) \
|
||||
case SyntaxKind::Id: \
|
||||
return ParentType##Data::make(Raw, Parent, IndexInParent);
|
||||
|
||||
#include "swift/Syntax/SyntaxKinds.def"
|
||||
case SyntaxKind::Token:
|
||||
llvm_unreachable("Can't make a SyntaxData from a Token!");
|
||||
}
|
||||
}
|
||||
|
||||
bool SyntaxData::isType() const {
|
||||
return Raw->isType();
|
||||
}
|
||||
@@ -37,15 +57,21 @@ bool SyntaxData::isDecl() const {
|
||||
return Raw->isDecl();
|
||||
}
|
||||
|
||||
bool SyntaxData::isExpr() const {
|
||||
return Raw->isExpr();
|
||||
}
|
||||
|
||||
void SyntaxData::dump(llvm::raw_ostream &OS) const {
|
||||
Raw->dump(OS, 0);
|
||||
}
|
||||
|
||||
#pragma mark - unknown-syntax Data
|
||||
|
||||
RC<UnknownSyntaxData> UnknownSyntaxData::make(RC<RawSyntax> Raw) {
|
||||
RC<UnknownSyntaxData> UnknownSyntaxData::make(RC<RawSyntax> Raw,
|
||||
const SyntaxData *Parent,
|
||||
CursorIndex IndexInParent) {
|
||||
return RC<UnknownSyntaxData> {
|
||||
new UnknownSyntaxData(Raw)
|
||||
new UnknownSyntaxData { Raw, Parent, IndexInParent }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/Syntax/DeclSyntax.h"
|
||||
#include "swift/Syntax/ExprSyntax.h"
|
||||
#include "swift/Syntax/StmtSyntax.h"
|
||||
#include "swift/Syntax/TypeSyntax.h"
|
||||
#include "swift/Syntax/GenericSyntax.h"
|
||||
@@ -293,6 +294,61 @@ ContinueStmtSyntax SyntaxFactory::makeBlankContinueStmtSyntax() {
|
||||
return { Data, Data.get() };
|
||||
}
|
||||
|
||||
#pragma mark - return-statement
|
||||
|
||||
/// Make a return statement with the given `return` keyword and returned
|
||||
/// expression.
|
||||
ReturnStmtSyntax
|
||||
SyntaxFactory::makeReturnStmt(RC<TokenSyntax> ReturnKeyword,
|
||||
ExprSyntax ReturnedExpression) {
|
||||
auto Raw = RawSyntax::make(SyntaxKind::ReturnStmt,
|
||||
{
|
||||
ReturnKeyword,
|
||||
ReturnedExpression.getRaw(),
|
||||
},
|
||||
SourcePresence::Present);
|
||||
auto Data = ReturnStmtSyntaxData::make(Raw);
|
||||
return { Data, Data.get() };
|
||||
}
|
||||
|
||||
ReturnStmtSyntax SyntaxFactory::makeBlankReturnStmt() {
|
||||
auto Raw = RawSyntax::make(SyntaxKind::ReturnStmt,
|
||||
{
|
||||
TokenSyntax::missingToken(tok::kw_return, "return"),
|
||||
RawSyntax::missing(SyntaxKind::MissingExpr),
|
||||
},
|
||||
SourcePresence::Present);
|
||||
auto Data = ReturnStmtSyntaxData::make(Raw);
|
||||
return { Data, Data.get() };
|
||||
}
|
||||
|
||||
#pragma mark - Expressions
|
||||
|
||||
IntegerLiteralExprSyntax
|
||||
SyntaxFactory::makeIntegerLiteralExpr(RC<TokenSyntax> Sign,
|
||||
RC<TokenSyntax> Digits) {
|
||||
auto Raw = RawSyntax::make(SyntaxKind::IntegerLiteralExpr,
|
||||
{
|
||||
Sign,
|
||||
Digits,
|
||||
},
|
||||
SourcePresence::Present);
|
||||
auto Data = IntegerLiteralExprSyntaxData::make(Raw);
|
||||
return { Data, Data.get() };
|
||||
}
|
||||
|
||||
IntegerLiteralExprSyntax SyntaxFactory::makeBlankIntegerLiteralExpr() {
|
||||
auto Raw = RawSyntax::make(SyntaxKind::IntegerLiteralExpr,
|
||||
{
|
||||
TokenSyntax::missingToken(tok::oper_prefix, "-"),
|
||||
TokenSyntax::missingToken(tok::integer_literal, ""),
|
||||
},
|
||||
SourcePresence::Present);
|
||||
auto Data = IntegerLiteralExprSyntaxData::make(Raw);
|
||||
return { Data, Data.get() };
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Tokens
|
||||
|
||||
RC<TokenSyntax>
|
||||
@@ -325,6 +381,14 @@ makeContinueKeyword(const swift::syntax::Trivia &LeadingTrivia,
|
||||
LeadingTrivia, TrailingTrivia);
|
||||
}
|
||||
|
||||
RC<TokenSyntax> SyntaxFactory::
|
||||
makeReturnKeyword(const swift::syntax::Trivia &LeadingTrivia,
|
||||
const swift::syntax::Trivia &TrailingTrivia) {
|
||||
return TokenSyntax::make(tok::kw_return, "return",
|
||||
SourcePresence::Present,
|
||||
LeadingTrivia, TrailingTrivia);
|
||||
}
|
||||
|
||||
RC<TokenSyntax>
|
||||
SyntaxFactory::makeLeftAngleToken(const Trivia &LeadingTrivia,
|
||||
const Trivia &TrailingTrivia) {
|
||||
@@ -558,6 +622,17 @@ SyntaxFactory::makeProtocolToken(const Trivia &LeadingTrivia,
|
||||
};
|
||||
}
|
||||
|
||||
RC<TokenSyntax>
|
||||
SyntaxFactory::makeIntegerLiteralToken(OwnedString Digits,
|
||||
const Trivia &LeadingTrivia,
|
||||
const Trivia &TrailingTrivia) {
|
||||
return RC<TokenSyntax> {
|
||||
new TokenSyntax(tok::integer_literal, Digits, SourcePresence::Present,
|
||||
LeadingTrivia,
|
||||
TrailingTrivia)
|
||||
};
|
||||
}
|
||||
|
||||
TupleTypeSyntax SyntaxFactory::makeVoidTupleType() {
|
||||
auto Raw = RawSyntax::make(SyntaxKind::TupleType,
|
||||
{
|
||||
@@ -662,6 +737,16 @@ DictionaryTypeSyntax SyntaxFactory::makeBlankDictionaryType() {
|
||||
return DictionaryTypeSyntax { Data, Data.get() };
|
||||
}
|
||||
|
||||
#pragma mark - Operators
|
||||
|
||||
/// Make a prefix operator with the given text.
|
||||
RC<TokenSyntax>
|
||||
SyntaxFactory::makePrefixOpereator(OwnedString Name,
|
||||
const Trivia &LeadingTrivia) {
|
||||
return TokenSyntax::make(tok::oper_prefix, Name,
|
||||
SourcePresence::Present, LeadingTrivia, {});
|
||||
}
|
||||
|
||||
#pragma mark - Types
|
||||
|
||||
#pragma mark - type-attribute
|
||||
|
||||
@@ -83,7 +83,7 @@ void TokenSyntax::dumpKind(llvm::raw_ostream &OS) const {
|
||||
OS << "dollarident";
|
||||
break;
|
||||
case tok::integer_literal:
|
||||
OS << "interger_literal";
|
||||
OS << "integer_literal";
|
||||
break;
|
||||
case tok::floating_literal:
|
||||
OS << "floating_literal";
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
add_swift_unittest(SwiftSyntaxTests
|
||||
DeclSyntaxTests.cpp
|
||||
ExprSyntaxTests.cpp
|
||||
GenericSyntaxTests.cpp
|
||||
RawSyntaxTests.cpp
|
||||
StmtSyntaxTests.cpp
|
||||
ThreadSafeCachingTests.cpp
|
||||
TypeSyntaxTests.cpp)
|
||||
|
||||
target_link_libraries(SwiftSyntaxTests
|
||||
|
||||
@@ -53,7 +53,7 @@ TEST(DeclSyntaxTests, TypealiasMakeAPIs) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DeclSyntaxTest, TypealiasWithAPIs) {
|
||||
TEST(DeclSyntaxTests, TypealiasWithAPIs) {
|
||||
auto Typealias =
|
||||
SyntaxFactory::makeTypealiasKeyword({}, { Trivia::spaces(1) });
|
||||
auto MyCollection = SyntaxFactory::makeIdentifier("MyCollection", {}, {});
|
||||
|
||||
11
unittests/Syntax/ExprSyntaxTests.cpp
Normal file
11
unittests/Syntax/ExprSyntaxTests.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
#include "swift/Syntax/ExprSyntax.h"
|
||||
#include "swift/Syntax/SyntaxFactory.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace swift;
|
||||
using namespace swift::syntax;
|
||||
|
||||
#pragma mark - integer-literal-expression
|
||||
|
||||
// TODO
|
||||
@@ -1,3 +1,4 @@
|
||||
#include "swift/Syntax/ExprSyntax.h"
|
||||
#include "swift/Syntax/SyntaxFactory.h"
|
||||
#include "swift/Syntax/StmtSyntax.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
@@ -204,3 +205,69 @@ TEST(StmtSyntaxTests, ContinueStmtMakeAPIs) {
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - return-statement
|
||||
|
||||
TEST(StmtSyntaxTests, ReturnStmtMakeAPIs) {
|
||||
auto ReturnKW = SyntaxFactory::makeReturnKeyword({}, Trivia::spaces(1));
|
||||
auto Minus = SyntaxFactory::makePrefixOpereator("-", {});
|
||||
auto OneDigits = SyntaxFactory::makeIntegerLiteralToken("1", {}, {});
|
||||
auto MinusOne = SyntaxFactory::makeIntegerLiteralExpr(Minus, OneDigits);
|
||||
|
||||
{
|
||||
llvm::SmallString<48> Scratch;
|
||||
llvm::raw_svector_ostream OS(Scratch);
|
||||
SyntaxFactory::makeBlankReturnStmt().print(OS);
|
||||
ASSERT_EQ(OS.str().str(), "");
|
||||
}
|
||||
|
||||
{
|
||||
llvm::SmallString<48> Scratch;
|
||||
llvm::raw_svector_ostream OS(Scratch);
|
||||
SyntaxFactory::makeReturnStmt(ReturnKW, MinusOne).print(OS);
|
||||
ASSERT_EQ(OS.str().str(), "return -1");
|
||||
}
|
||||
}
|
||||
|
||||
TEST(StmtSyntaxTests, ReturnStmtGetAPIs) {
|
||||
auto ReturnKW = SyntaxFactory::makeReturnKeyword({}, Trivia::spaces(1));
|
||||
auto Minus = SyntaxFactory::makePrefixOpereator("-", {});
|
||||
auto OneDigits = SyntaxFactory::makeIntegerLiteralToken("1", {}, {});
|
||||
auto MinusOne = SyntaxFactory::makeIntegerLiteralExpr(Minus, OneDigits);
|
||||
auto Return = SyntaxFactory::makeReturnStmt(ReturnKW, MinusOne);
|
||||
|
||||
ASSERT_EQ(ReturnKW, Return.getReturnKeyword());
|
||||
auto GottenExpression = Return.getExpression().getValue();
|
||||
auto GottenExpression2 = Return.getExpression().getValue();
|
||||
ASSERT_TRUE(GottenExpression.hasSameIdentityAs(GottenExpression2));
|
||||
}
|
||||
|
||||
TEST(StmtSyntaxTests, ReturnStmtWithAPIs) {
|
||||
auto ReturnKW = SyntaxFactory::makeReturnKeyword({}, Trivia::spaces(1));
|
||||
auto Minus = SyntaxFactory::makePrefixOpereator("-", {});
|
||||
auto OneDigits = SyntaxFactory::makeIntegerLiteralToken("1", {}, {});
|
||||
auto MinusOne = SyntaxFactory::makeIntegerLiteralExpr(Minus, OneDigits);
|
||||
|
||||
{
|
||||
llvm::SmallString<48> Scratch;
|
||||
llvm::raw_svector_ostream OS(Scratch);
|
||||
SyntaxFactory::makeBlankReturnStmt().withReturnKeyword(ReturnKW).print(OS);
|
||||
ASSERT_EQ(OS.str().str(), "return ");
|
||||
}
|
||||
|
||||
{
|
||||
llvm::SmallString<48> Scratch;
|
||||
llvm::raw_svector_ostream OS(Scratch);
|
||||
SyntaxFactory::makeBlankReturnStmt().withExpression(MinusOne).print(OS);
|
||||
ASSERT_EQ(OS.str().str(), "-1");
|
||||
}
|
||||
|
||||
{
|
||||
llvm::SmallString<48> Scratch;
|
||||
llvm::raw_svector_ostream OS(Scratch);
|
||||
SyntaxFactory::makeBlankReturnStmt()
|
||||
.withReturnKeyword(ReturnKW)
|
||||
.withExpression(MinusOne).print(OS);
|
||||
ASSERT_EQ(OS.str().str(), "return -1");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
54
unittests/Syntax/ThreadSafeCachingTests.cpp
Normal file
54
unittests/Syntax/ThreadSafeCachingTests.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#include "swift/Syntax/ExprSyntax.h"
|
||||
#include "swift/Syntax/SyntaxFactory.h"
|
||||
#include "swift/Syntax/StmtSyntax.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <thread>
|
||||
|
||||
using namespace swift;
|
||||
using namespace swift::syntax;
|
||||
|
||||
static void getExpressionFrom(ReturnStmtSyntax Return,
|
||||
uintptr_t *DataPointer) {
|
||||
auto Expression = Return.getExpression().getValue();
|
||||
auto Data = Expression.getDataPointer();
|
||||
*DataPointer = reinterpret_cast<uintptr_t>(Data);
|
||||
}
|
||||
|
||||
// Tests that, when multiple threads ask for a child node of the same syntax
|
||||
// node:
|
||||
// - Only one thread inserts the realized child into the parent
|
||||
// - Both threads get the exact same child (by identity)
|
||||
TEST(ThreadSafeCachingTests, ReturnGetExpression) {
|
||||
auto ReturnKW = SyntaxFactory::makeReturnKeyword({}, Trivia::spaces(1));
|
||||
auto Minus = SyntaxFactory::makePrefixOpereator("-", {});
|
||||
auto One = SyntaxFactory::makeIntegerLiteralToken("1", {}, {});
|
||||
auto MinusOne = SyntaxFactory::makeIntegerLiteralExpr(Minus, One);
|
||||
|
||||
for (unsigned i = 0; i < 10000; ++i) {
|
||||
llvm::SmallString<48> Scratch;
|
||||
llvm::raw_svector_ostream OS(Scratch);
|
||||
auto Return = SyntaxFactory::makeReturnStmt(ReturnKW, MinusOne);
|
||||
|
||||
uintptr_t FirstDataPointer;
|
||||
uintptr_t SecondDataPointer;
|
||||
|
||||
std::thread first(getExpressionFrom, Return, &FirstDataPointer);
|
||||
std::thread second(getExpressionFrom, Return, &SecondDataPointer);
|
||||
first.join();
|
||||
second.join();
|
||||
|
||||
auto DataPointer = reinterpret_cast<uintptr_t>(
|
||||
Return.getExpression().getValue().getDataPointer());
|
||||
|
||||
ASSERT_EQ(FirstDataPointer, SecondDataPointer);
|
||||
ASSERT_EQ(FirstDataPointer, DataPointer);
|
||||
|
||||
if (FirstDataPointer != SecondDataPointer ||
|
||||
FirstDataPointer != DataPointer) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,7 +318,7 @@ TEST(TypeSyntaxTests, MetatypeTypeMakeAPIs) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TypeSyntaxTest, MetatypeTypeWithAPIs) {
|
||||
TEST(TypeSyntaxTests, MetatypeTypeWithAPIs) {
|
||||
auto Int = SyntaxFactory::makeTypeIdentifier("T", {}, {});
|
||||
auto Dot = SyntaxFactory::makeDotToken({}, {});
|
||||
auto Type = SyntaxFactory::makeTypeToken({}, {});
|
||||
@@ -355,7 +355,7 @@ TEST(TypeSyntaxTest, MetatypeTypeWithAPIs) {
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(TypeSyntaxTest, ArrayTypeWithAPIs) {
|
||||
TEST(TypeSyntaxTests, ArrayTypeWithAPIs) {
|
||||
{
|
||||
SmallString<16> Scratch;
|
||||
llvm::raw_svector_ostream OS(Scratch);
|
||||
@@ -371,7 +371,7 @@ TEST(TypeSyntaxTest, ArrayTypeWithAPIs) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TypeSyntaxTest, ArrayTypeMakeAPIs) {
|
||||
TEST(TypeSyntaxTests, ArrayTypeMakeAPIs) {
|
||||
{
|
||||
SmallString<16> Scratch;
|
||||
llvm::raw_svector_ostream OS(Scratch);
|
||||
@@ -384,7 +384,7 @@ TEST(TypeSyntaxTest, ArrayTypeMakeAPIs) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TypeSyntaxTest, DictionaryTypeWithAPIs) {
|
||||
TEST(TypeSyntaxTests, DictionaryTypeWithAPIs) {
|
||||
{
|
||||
SmallString<16> Scratch;
|
||||
llvm::raw_svector_ostream OS(Scratch);
|
||||
@@ -407,7 +407,7 @@ TEST(TypeSyntaxTest, DictionaryTypeWithAPIs) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TypeSyntaxTest, DictionaryTypeMakeAPIs) {
|
||||
TEST(TypeSyntaxTests, DictionaryTypeMakeAPIs) {
|
||||
{
|
||||
SmallString<16> Scratch;
|
||||
llvm::raw_svector_ostream OS(Scratch);
|
||||
@@ -424,7 +424,7 @@ TEST(TypeSyntaxTest, DictionaryTypeMakeAPIs) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TypeSyntaxTest, FunctionTypeMakeAPIs) {
|
||||
TEST(TypeSyntaxTests, FunctionTypeMakeAPIs) {
|
||||
auto Comma = SyntaxFactory::makeCommaToken({}, { Trivia::spaces(1) });
|
||||
auto LeftParen = SyntaxFactory::makeLeftParenToken({}, {});
|
||||
auto RightParen = SyntaxFactory::makeRightParenToken({},
|
||||
@@ -500,7 +500,7 @@ TEST(TypeSyntaxTest, FunctionTypeMakeAPIs) {
|
||||
|
||||
}
|
||||
|
||||
TEST(TypeSyntaxTest, FunctionTypeWithAPIs) {
|
||||
TEST(TypeSyntaxTests, FunctionTypeWithAPIs) {
|
||||
auto Comma = SyntaxFactory::makeCommaToken({}, { Trivia::spaces(1) });
|
||||
auto LeftParen = SyntaxFactory::makeLeftParenToken({}, {});
|
||||
auto RightParen = SyntaxFactory::makeRightParenToken({},
|
||||
@@ -564,7 +564,7 @@ TEST(TypeSyntaxTest, FunctionTypeWithAPIs) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TypeSyntaxTest, FunctionTypeBuilderAPIs) {
|
||||
TEST(TypeSyntaxTests, FunctionTypeBuilderAPIs) {
|
||||
auto Comma = SyntaxFactory::makeCommaToken({}, { Trivia::spaces(1) });
|
||||
auto Int = SyntaxFactory::makeTypeIdentifier("Int", {}, {});
|
||||
auto LeftParen = SyntaxFactory::makeLeftParenToken({}, {});
|
||||
|
||||
Reference in New Issue
Block a user