Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-apply "[Parser] Decouple the parser from AST creation (part 2)" #26883

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 82 additions & 28 deletions include/swift/Parse/ASTGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,54 +14,108 @@
#define SWIFT_PARSE_ASTGEN_H

#include "swift/AST/ASTContext.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Expr.h"
#include "swift/Parse/PersistentParserState.h"
#include "swift/Syntax/SyntaxNodes.h"
#include "llvm/ADT/DenseMap.h"

namespace swift {
/// Generates AST nodes from Syntax nodes.
class ASTGen {
ASTContext &Context;
// A stack of source locations of syntax constructs. Allows us to get the
// SourceLoc necessary to create AST nodes for nodes in not-yet-complete
// Syntax tree. The topmost item should always correspond to the token/node
// that has been parsed/transformed most recently.
// todo [gsoc]: remove when possible
llvm::SmallVector<SourceLoc, 16> LocStack;

/// Type cache to prevent multiple transformations of the same syntax node.
llvm::DenseMap<syntax::SyntaxNodeId, TypeRepr *> TypeCache;

PersistentParserState **ParserState;

// FIXME: remove when Syntax can represent all types and ASTGen can handle them
/// Types that cannot be represented by Syntax or generated by ASTGen.
llvm::DenseMap<SourceLoc, TypeRepr *> Types;

public:
explicit ASTGen(ASTContext &Context) : Context(Context) {}

IntegerLiteralExpr *generate(syntax::IntegerLiteralExprSyntax &Expr);
FloatLiteralExpr *generate(syntax::FloatLiteralExprSyntax &Expr);
NilLiteralExpr *generate(syntax::NilLiteralExprSyntax &Expr);
BooleanLiteralExpr *generate(syntax::BooleanLiteralExprSyntax &Expr);
MagicIdentifierLiteralExpr *generate(syntax::PoundFileExprSyntax &Expr);
MagicIdentifierLiteralExpr *generate(syntax::PoundLineExprSyntax &Expr);
MagicIdentifierLiteralExpr *generate(syntax::PoundColumnExprSyntax &Expr);
MagicIdentifierLiteralExpr *generate(syntax::PoundFunctionExprSyntax &Expr);
MagicIdentifierLiteralExpr *generate(syntax::PoundDsohandleExprSyntax &Expr);
Expr *generate(syntax::UnknownExprSyntax &Expr);

/// Stores source location necessary for AST creation.
void pushLoc(SourceLoc Loc);
ASTGen(ASTContext &Context, PersistentParserState **ParserState)
: Context(Context), ParserState(ParserState) {}

SourceLoc generate(syntax::TokenSyntax Tok, SourceLoc &Loc);

Expr *generate(syntax::IntegerLiteralExprSyntax &Expr, SourceLoc &Loc);
Expr *generate(syntax::FloatLiteralExprSyntax &Expr, SourceLoc &Loc);
Expr *generate(syntax::NilLiteralExprSyntax &Expr, SourceLoc &Loc);
Expr *generate(syntax::BooleanLiteralExprSyntax &Expr, SourceLoc &Loc);
Expr *generate(syntax::PoundFileExprSyntax &Expr, SourceLoc &Loc);
Expr *generate(syntax::PoundLineExprSyntax &Expr, SourceLoc &Loc);
Expr *generate(syntax::PoundColumnExprSyntax &Expr, SourceLoc &Loc);
Expr *generate(syntax::PoundFunctionExprSyntax &Expr, SourceLoc &Loc);
Expr *generate(syntax::PoundDsohandleExprSyntax &Expr, SourceLoc &Loc);
Expr *generate(syntax::UnknownExprSyntax &Expr, SourceLoc &Loc);

TypeRepr *generate(syntax::TypeSyntax Type, SourceLoc &Loc);
TypeRepr *generate(syntax::SomeTypeSyntax Type, SourceLoc &Loc);
TypeRepr *generate(syntax::CompositionTypeSyntax Type, SourceLoc &Loc);
TypeRepr *generate(syntax::SimpleTypeIdentifierSyntax Type, SourceLoc &Loc);
TypeRepr *generate(syntax::MemberTypeIdentifierSyntax Type, SourceLoc &Loc);
TypeRepr *generate(syntax::DictionaryTypeSyntax Type, SourceLoc &Loc);
TypeRepr *generate(syntax::ArrayTypeSyntax Type, SourceLoc &Loc);
TypeRepr *generate(syntax::TupleTypeSyntax Type, SourceLoc &Loc);
TypeRepr *generate(syntax::AttributedTypeSyntax Type, SourceLoc &Loc);
TypeRepr *generate(syntax::FunctionTypeSyntax Type, SourceLoc &Loc);
TypeRepr *generate(syntax::MetatypeTypeSyntax Type, SourceLoc &Loc);
TypeRepr *generate(syntax::OptionalTypeSyntax Type, SourceLoc &Loc);
TypeRepr *generate(syntax::ImplicitlyUnwrappedOptionalTypeSyntax Type, SourceLoc &Loc);
TypeRepr *generate(syntax::UnknownTypeSyntax Type, SourceLoc &Loc);

TypeRepr *generate(syntax::GenericArgumentSyntax Arg, SourceLoc &Loc);
llvm::SmallVector<TypeRepr *, 4>
generate(syntax::GenericArgumentListSyntax Args, SourceLoc &Loc);

/// Copy a numeric literal value into AST-owned memory, stripping underscores
/// so the semantic part of the value can be parsed by APInt/APFloat parsers.
static StringRef copyAndStripUnderscores(StringRef Orig, ASTContext &Context);

private:
Expr *generateMagicIdentifierLiteralExpression(syntax::TokenSyntax PoundToken,
SourceLoc &Loc);

TupleTypeRepr *generateTuple(syntax::TokenSyntax LParen,
syntax::TupleTypeElementListSyntax Elements,
syntax::TokenSyntax RParen, SourceLoc &Loc,
bool IsFunction = false);

void gatherTypeIdentifierComponents(
syntax::TypeSyntax Component, SourceLoc &Loc,
llvm::SmallVectorImpl<ComponentIdentTypeRepr *> &Components);

template <typename T>
TypeRepr *generateSimpleOrMemberIdentifier(T Type, SourceLoc &Loc);

template <typename T>
ComponentIdentTypeRepr *generateIdentifier(T Type, SourceLoc &Loc);

StringRef copyAndStripUnderscores(StringRef Orig);

SourceLoc topLoc();
static SourceLoc advanceLocBegin(const SourceLoc &Loc,
const syntax::Syntax &Node);
static SourceLoc advanceLocEnd(const SourceLoc &Loc,
const syntax::TokenSyntax &Token);
static SourceLoc advanceLocAfter(const SourceLoc &Loc,
const syntax::Syntax &Node);

static MagicIdentifierLiteralExpr::Kind getMagicIdentifierLiteralKind(tok Kind);

ValueDecl *lookupInScope(DeclName Name);

TypeRepr *cacheType(syntax::TypeSyntax Type, TypeRepr *TypeAST);

TypeRepr *lookupType(syntax::TypeSyntax Type);

public:
TypeRepr *addType(TypeRepr *Type, const SourceLoc &Loc);

MagicIdentifierLiteralExpr *
generateMagicIdentifierLiteralExpr(const syntax::TokenSyntax &PoundToken);
bool hasType(const SourceLoc &Loc) const;

/// Map magic literal tokens such as #file to their MagicIdentifierLiteralExpr
/// kind.
static MagicIdentifierLiteralExpr::Kind
getMagicIdentifierLiteralKind(tok Kind);
TypeRepr *getType(const SourceLoc &Loc) const;
};
} // namespace swift

Expand Down
27 changes: 26 additions & 1 deletion include/swift/Parse/ParsedRawSyntaxNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,20 @@ class ParsedRawSyntaxNode {
/// Primary used for a deferred missing token.
bool isMissing() const { return IsMissing; }

CharSourceRange getDeferredRange() const {
switch (DK) {
case DataKind::DeferredLayout:
return getDeferredLayoutRange();
case DataKind::DeferredToken:
return getDeferredTokenRangeWithoutBackticks();
default:
llvm_unreachable("node not deferred");
}
}

// Recorded Data ===========================================================//

CharSourceRange getRange() const {
CharSourceRange getRecordedRange() const {
assert(isRecorded());
return RecordedData.Range;
}
Expand All @@ -149,6 +160,20 @@ class ParsedRawSyntaxNode {

// Deferred Layout Data ====================================================//

CharSourceRange getDeferredLayoutRange() const {
assert(DK == DataKind::DeferredLayout);
assert(!DeferredLayout.Children.empty());
auto getLastNonNullChild = [this]() {
for (auto &&Child : llvm::reverse(getDeferredChildren()))
if (!Child.isNull())
return Child;
llvm_unreachable("layout node without non-null children");
};
auto firstRange = DeferredLayout.Children.front().getDeferredRange();
auto lastRange = getLastNonNullChild().getDeferredRange();
firstRange.widen(lastRange);
return firstRange;
}
ArrayRef<ParsedRawSyntaxNode> getDeferredChildren() const {
assert(DK == DataKind::DeferredLayout);
return DeferredLayout.Children;
Expand Down
Loading