mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
This implementation required a compromise between parser performance and AST structuring. On the one hand, Parse must be fast in order to keep things in the IDE zippy, on the other we must hit the disk to properly resolve 'canImport' conditions and inject members of the active clause into the AST. Additionally, a Parse-only pass may not provide platform-specific information to the compiler invocation and so may mistakenly activate or de-activate branches in the if-configuration decl. The compromise is to perform condition evaluation only when continuing on to semantic analysis. This keeps the parser quick and avoids the unpacking that parse does for active conditions while still retaining the ability to see through to an active condition when we know we're moving on to semantic analysis anyways.
186 lines
5.4 KiB
C++
186 lines
5.4 KiB
C++
//===--- PersistentParserState.h - Parser State -----------------*- 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Parser state persistent across multiple parses.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_PARSE_PERSISTENTPARSERSTATE_H
|
|
#define SWIFT_PARSE_PERSISTENTPARSERSTATE_H
|
|
|
|
#include "swift/Basic/SourceLoc.h"
|
|
#include "swift/Parse/LocalContext.h"
|
|
#include "swift/Parse/Scope.h"
|
|
#include "llvm/ADT/DenseMap.h"
|
|
|
|
namespace swift {
|
|
class AbstractFunctionDecl;
|
|
|
|
/// \brief Parser state persistent across multiple parses.
|
|
class PersistentParserState {
|
|
public:
|
|
struct ParserPos {
|
|
SourceLoc Loc;
|
|
SourceLoc PrevLoc;
|
|
|
|
bool isValid() const { return Loc.isValid(); }
|
|
};
|
|
|
|
class FunctionBodyState {
|
|
ParserPos BodyPos;
|
|
SavedScope Scope;
|
|
friend class Parser;
|
|
|
|
SavedScope takeScope() {
|
|
return std::move(Scope);
|
|
}
|
|
|
|
public:
|
|
FunctionBodyState(SourceRange BodyRange, SourceLoc PreviousLoc,
|
|
SavedScope &&Scope)
|
|
: BodyPos{BodyRange.Start, PreviousLoc}, Scope(std::move(Scope))
|
|
{}
|
|
};
|
|
|
|
class AccessorBodyState {
|
|
ParserPos BodyPos;
|
|
SavedScope Scope;
|
|
SourceLoc LBLoc;
|
|
friend class Parser;
|
|
|
|
SavedScope takeScope() {
|
|
return std::move(Scope);
|
|
}
|
|
|
|
public:
|
|
AccessorBodyState(SourceRange BodyRange, SourceLoc PreviousLoc,
|
|
SavedScope &&Scope, SourceLoc LBLoc)
|
|
: BodyPos{BodyRange.Start, PreviousLoc}, Scope(std::move(Scope)),
|
|
LBLoc(LBLoc) {}
|
|
};
|
|
|
|
enum class DelayedDeclKind {
|
|
TopLevelCodeDecl,
|
|
Decl,
|
|
};
|
|
|
|
class DelayedDeclState {
|
|
friend class PersistentParserState;
|
|
friend class Parser;
|
|
DelayedDeclKind Kind;
|
|
unsigned Flags;
|
|
DeclContext *ParentContext;
|
|
ParserPos BodyPos;
|
|
SourceLoc BodyEnd;
|
|
SavedScope Scope;
|
|
|
|
SavedScope takeScope() {
|
|
return std::move(Scope);
|
|
}
|
|
|
|
public:
|
|
DelayedDeclState(DelayedDeclKind Kind, unsigned Flags,
|
|
DeclContext *ParentContext, SourceRange BodyRange,
|
|
SourceLoc PreviousLoc, SavedScope &&Scope)
|
|
: Kind(Kind), Flags(Flags), ParentContext(ParentContext),
|
|
BodyPos{BodyRange.Start, PreviousLoc},
|
|
BodyEnd(BodyRange.End), Scope(std::move(Scope))
|
|
{}
|
|
};
|
|
|
|
bool InPoundLineEnvironment = false;
|
|
// FIXME: When condition evaluation moves to a later phase, remove this bit
|
|
// and adjust the client call 'performParseOnly'.
|
|
bool PerformConditionEvaluation = true;
|
|
private:
|
|
ScopeInfo ScopeInfo;
|
|
typedef llvm::DenseMap<AbstractFunctionDecl *,
|
|
std::unique_ptr<FunctionBodyState>>
|
|
DelayedFunctionBodiesTy;
|
|
DelayedFunctionBodiesTy DelayedFunctionBodies;
|
|
|
|
typedef llvm::DenseMap<AbstractFunctionDecl *,
|
|
std::unique_ptr<AccessorBodyState>>
|
|
DelayedAccessorBodiesTy;
|
|
DelayedAccessorBodiesTy DelayedAccessorBodies;
|
|
|
|
/// \brief Parser sets this if it stopped parsing before the buffer ended.
|
|
ParserPos MarkedPos;
|
|
|
|
std::unique_ptr<DelayedDeclState> CodeCompletionDelayedDeclState;
|
|
|
|
/// The local context for all top-level code.
|
|
TopLevelContext TopLevelCode;
|
|
|
|
public:
|
|
swift::ScopeInfo &getScopeInfo() { return ScopeInfo; }
|
|
|
|
void delayFunctionBodyParsing(AbstractFunctionDecl *AFD,
|
|
SourceRange BodyRange,
|
|
SourceLoc PreviousLoc);
|
|
std::unique_ptr<FunctionBodyState>
|
|
takeFunctionBodyState(AbstractFunctionDecl *AFD);
|
|
|
|
bool hasFunctionBodyState(AbstractFunctionDecl *AFD);
|
|
|
|
void delayAccessorBodyParsing(AbstractFunctionDecl *AFD,
|
|
SourceRange BodyRange,
|
|
SourceLoc PreviousLoc,
|
|
SourceLoc LBLoc);
|
|
std::unique_ptr<AccessorBodyState>
|
|
takeAccessorBodyState(AbstractFunctionDecl *AFD);
|
|
|
|
void delayDecl(DelayedDeclKind Kind, unsigned Flags,
|
|
DeclContext *ParentContext,
|
|
SourceRange BodyRange, SourceLoc PreviousLoc);
|
|
|
|
void delayTopLevel(TopLevelCodeDecl *TLCD, SourceRange BodyRange,
|
|
SourceLoc PreviousLoc);
|
|
|
|
bool hasDelayedDecl() {
|
|
return CodeCompletionDelayedDeclState.get() != nullptr;
|
|
}
|
|
DelayedDeclKind getDelayedDeclKind() {
|
|
return CodeCompletionDelayedDeclState->Kind;
|
|
}
|
|
SourceLoc getDelayedDeclLoc() {
|
|
return CodeCompletionDelayedDeclState->BodyPos.Loc;
|
|
}
|
|
DeclContext *getDelayedDeclContext() {
|
|
return CodeCompletionDelayedDeclState->ParentContext;
|
|
}
|
|
std::unique_ptr<DelayedDeclState> takeDelayedDeclState() {
|
|
return std::move(CodeCompletionDelayedDeclState);
|
|
}
|
|
|
|
TopLevelContext &getTopLevelContext() {
|
|
return TopLevelCode;
|
|
}
|
|
|
|
void markParserPosition(SourceLoc Loc, SourceLoc PrevLoc,
|
|
bool InPoundLineEnvironment) {
|
|
MarkedPos = {Loc, PrevLoc};
|
|
this->InPoundLineEnvironment = InPoundLineEnvironment;
|
|
}
|
|
|
|
/// \brief Returns the marked parser position and resets it.
|
|
ParserPos takeParserPosition() {
|
|
ParserPos Pos = MarkedPos;
|
|
MarkedPos = ParserPos();
|
|
return Pos;
|
|
}
|
|
};
|
|
|
|
} // end namespace swift
|
|
|
|
#endif
|