[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:
David Farler
2017-02-20 17:11:41 -08:00
parent 4ffbeb57f6
commit c343298b8f
29 changed files with 1298 additions and 196 deletions

View File

@@ -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;

View File

@@ -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;
}
};

View 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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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"

View File

@@ -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

View File

@@ -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.

View File

@@ -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);
};

View File

@@ -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

View File

@@ -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)

View File

@@ -1,5 +1,6 @@
add_swift_library(swiftSyntax STATIC
DeclSyntax.cpp
ExprSyntax.cpp
Format.cpp
TokenSyntax.cpp
GenericSyntax.cpp

View File

@@ -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
View 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);
}

View File

@@ -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;

View File

@@ -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(

View File

@@ -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);

View File

@@ -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

View File

@@ -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,

View File

@@ -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,

View File

@@ -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 }
};
}

View File

@@ -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

View File

@@ -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";

View File

@@ -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

View File

@@ -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", {}, {});

View 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

View File

@@ -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");
}
}

View 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;
}
}
}

View File

@@ -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({}, {});