Skip to content

Commit 8037f2f

Browse files
authored
Merge pull request swiftlang#29619 from hamishknight/a-buffet-of-tokens
Parse Swift decls in one shot
2 parents 99856ed + 3d3a2a5 commit 8037f2f

File tree

21 files changed

+273
-277
lines changed

21 files changed

+273
-277
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,8 @@ ERROR(expected_precedencegroup_relation,none,
470470
(StringRef))
471471

472472
// SIL
473+
ERROR(expected_sil_keyword,none,
474+
"expected SIL keyword", ())
473475
ERROR(inout_not_attribute, none,
474476
"@inout is no longer an attribute", ())
475477
ERROR(only_allowed_in_sil,none,

include/swift/Parse/Parser.h

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,8 @@ class Parser {
413413
bool DelayBodyParsing = true);
414414
~Parser();
415415

416-
bool isInSILMode() const { return SIL != nullptr; }
416+
/// Returns true if the buffer being parsed is allowed to contain SIL.
417+
bool isInSILMode() const;
417418

418419
/// Calling this function to finalize libSyntax tree creation without destroying
419420
/// the parser instance.
@@ -430,9 +431,8 @@ class Parser {
430431
PreviousLoc);
431432
}
432433

433-
ParserPosition getParserPosition(const PersistentParserState::ParserPos &Pos){
434-
return ParserPosition(L->getStateForBeginningOfTokenLoc(Pos.Loc),
435-
Pos.PrevLoc);
434+
ParserPosition getParserPosition(SourceLoc loc, SourceLoc previousLoc) {
435+
return ParserPosition(L->getStateForBeginningOfTokenLoc(loc), previousLoc);
436436
}
437437

438438
void restoreParserPosition(ParserPosition PP, bool enableDiagnostics = false) {
@@ -661,6 +661,9 @@ class Parser {
661661
/// Returns \c true if the parser hit the eof before finding matched '}'.
662662
bool skipBracedBlock();
663663

664+
/// Skip over SIL decls until we encounter the start of a Swift decl or eof.
665+
void skipSILUntilSwiftDecl();
666+
664667
/// If the parser is generating only a syntax tree, try loading the current
665668
/// node from a previously generated syntax tree.
666669
/// Returns \c true if the node has been loaded and inserted into the current
@@ -880,11 +883,18 @@ class Parser {
880883
//===--------------------------------------------------------------------===//
881884
// Decl Parsing
882885

883-
/// Return true if parser is at the start of a decl or decl-import.
884-
bool isStartOfDecl();
886+
/// Returns true if parser is at the start of a Swift decl or decl-import.
887+
bool isStartOfSwiftDecl();
888+
889+
/// Returns true if the parser is at the start of a SIL decl.
890+
bool isStartOfSILDecl();
885891

892+
/// Parse the top-level Swift decls into the source file.
886893
void parseTopLevel();
887894

895+
/// Parse the top-level SIL decls into the SIL module.
896+
void parseTopLevelSIL();
897+
888898
/// Flags that control the parsing of declarations.
889899
enum ParseDeclFlags {
890900
PD_Default = 0,

include/swift/Parse/PersistentParserState.h

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -59,23 +59,12 @@ class CodeCompletionDelayedDeclState {
5959
/// Parser state persistent across multiple parses.
6060
class PersistentParserState {
6161
public:
62-
struct ParserPos {
63-
SourceLoc Loc;
64-
SourceLoc PrevLoc;
65-
66-
bool isValid() const { return Loc.isValid(); }
67-
};
68-
69-
bool InPoundLineEnvironment = false;
7062
// FIXME: When condition evaluation moves to a later phase, remove this bit
7163
// and adjust the client call 'performParseOnly'.
7264
bool PerformConditionEvaluation = true;
7365
private:
7466
swift::ScopeInfo ScopeInfo;
7567

76-
/// Parser sets this if it stopped parsing before the buffer ended.
77-
ParserPosition MarkedPos;
78-
7968
std::unique_ptr<CodeCompletionDelayedDeclState> CodeCompletionDelayedDeclStat;
8069

8170
/// The local context for all top-level code.
@@ -113,19 +102,6 @@ class PersistentParserState {
113102
TopLevelContext &getTopLevelContext() {
114103
return TopLevelCode;
115104
}
116-
117-
void markParserPosition(ParserPosition Pos,
118-
bool InPoundLineEnvironment) {
119-
MarkedPos = Pos;
120-
this->InPoundLineEnvironment = InPoundLineEnvironment;
121-
}
122-
123-
/// Returns the marked parser position and resets it.
124-
ParserPosition takeParserPosition() {
125-
ParserPosition Pos = MarkedPos;
126-
MarkedPos = ParserPosition();
127-
return Pos;
128-
}
129105
};
130106

131107
} // end namespace swift

include/swift/Subsystems.h

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -106,29 +106,21 @@ namespace swift {
106106

107107
/// Parse a single buffer into the given source file.
108108
///
109-
/// If the source file is the main file, stop parsing after the next
110-
/// stmt-brace-item with side-effects.
109+
/// \param SF The file within the module being parsed.
111110
///
112-
/// \param SF the file within the module being parsed.
111+
/// \param BufferID The buffer to parse from.
113112
///
114-
/// \param BufferID the buffer to parse from.
113+
/// \param PersistentState If non-null the same PersistentState object can be
114+
/// used to save parser state for code completion.
115115
///
116-
/// \param[out] Done set to \c true if end of the buffer was reached.
117-
///
118-
/// \param SIL if non-null, we're parsing a SIL file.
119-
///
120-
/// \param PersistentState if non-null the same PersistentState object can
121-
/// be used to resume parsing or parse delayed function bodies.
122-
void parseIntoSourceFile(SourceFile &SF, unsigned BufferID, bool *Done,
123-
SILParserState *SIL = nullptr,
116+
/// \param DelayBodyParsing Whether parsing of type and function bodies can be
117+
/// delayed.
118+
void parseIntoSourceFile(SourceFile &SF, unsigned BufferID,
124119
PersistentParserState *PersistentState = nullptr,
125120
bool DelayBodyParsing = true);
126121

127-
/// Parse a single buffer into the given source file, until the full source
128-
/// contents are parsed.
129-
void parseIntoSourceFileFull(SourceFile &SF, unsigned BufferID,
130-
PersistentParserState *PersistentState = nullptr,
131-
bool DelayBodyParsing = true);
122+
/// Parse a source file's SIL declarations into a given SIL module.
123+
void parseSourceFileSIL(SourceFile &SF, SILParserState *sil);
132124

133125
/// Finish the code completion.
134126
void performCodeCompletionSecondPass(PersistentParserState &PersistentState,

lib/Frontend/Frontend.cpp

Lines changed: 23 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -913,14 +913,8 @@ void CompilerInstance::parseLibraryFile(
913913
auto DidSuppressWarnings = Diags.getSuppressWarnings();
914914
Diags.setSuppressWarnings(DidSuppressWarnings || !IsPrimary);
915915

916-
bool Done;
917-
do {
918-
// Parser may stop at some erroneous constructions like #else, #endif
919-
// or '}' in some cases, continue parsing until we are done
920-
parseIntoSourceFile(*NextInput, BufferID, &Done, nullptr,
921-
PersistentState.get(),
922-
/*DelayedBodyParsing=*/!IsPrimary);
923-
} while (!Done);
916+
parseIntoSourceFile(*NextInput, BufferID, PersistentState.get(),
917+
/*DelayedBodyParsing=*/!IsPrimary);
924918

925919
Diags.setSuppressWarnings(DidSuppressWarnings);
926920

@@ -953,6 +947,7 @@ bool CompilerInstance::parsePartialModulesAndLibraryFiles(
953947

954948
void CompilerInstance::parseAndTypeCheckMainFileUpTo(
955949
SourceFile::ASTStage_t LimitStage) {
950+
assert(LimitStage >= SourceFile::NameBound);
956951
FrontendStatsTracer tracer(Context->Stats,
957952
"parse-and-typecheck-main-file");
958953
bool mainIsPrimary =
@@ -965,45 +960,23 @@ void CompilerInstance::parseAndTypeCheckMainFileUpTo(
965960
auto DidSuppressWarnings = Diags.getSuppressWarnings();
966961
Diags.setSuppressWarnings(DidSuppressWarnings || !mainIsPrimary);
967962

968-
SILParserState SILContext(TheSILModule.get());
969-
unsigned CurTUElem = 0;
970-
bool Done;
971-
do {
972-
// Pump the parser multiple times if necessary. It will return early
973-
// after parsing any top level code in a main module, or in SIL mode when
974-
// there are chunks of swift decls (e.g. imports and types) interspersed
975-
// with 'sil' definitions.
976-
parseIntoSourceFile(MainFile, MainFile.getBufferID().getValue(), &Done,
977-
TheSILModule ? &SILContext : nullptr,
978-
PersistentState.get(),
979-
!mainIsPrimary);
980-
981-
// For SIL we actually have to interleave parsing and type checking
982-
// because the SIL parser expects to see fully type checked declarations.
983-
if (TheSILModule) {
984-
if (Done || CurTUElem < MainFile.getTopLevelDecls().size()) {
985-
assert(mainIsPrimary);
986-
performTypeChecking(MainFile, CurTUElem);
987-
}
988-
}
963+
// Parse the Swift decls into the source file.
964+
parseIntoSourceFile(MainFile, MainBufferID, PersistentState.get(),
965+
/*delayBodyParsing*/ !mainIsPrimary);
989966

990-
CurTUElem = MainFile.getTopLevelDecls().size();
991-
} while (!Done);
992-
993-
if (!TheSILModule) {
994-
if (mainIsPrimary) {
995-
switch (LimitStage) {
996-
case SourceFile::Parsing:
997-
case SourceFile::Parsed:
998-
llvm_unreachable("invalid limit stage");
999-
case SourceFile::NameBound:
1000-
performNameBinding(MainFile);
1001-
break;
1002-
case SourceFile::TypeChecked:
1003-
performTypeChecking(MainFile);
1004-
break;
1005-
}
1006-
}
967+
// For a primary, also perform type checking if needed. Otherwise, just do
968+
// name binding.
969+
if (mainIsPrimary && LimitStage >= SourceFile::TypeChecked) {
970+
performTypeChecking(MainFile);
971+
} else {
972+
assert(!TheSILModule && "Should perform type checking for SIL");
973+
performNameBinding(MainFile);
974+
}
975+
976+
// Parse the SIL decls if needed.
977+
if (TheSILModule) {
978+
SILParserState SILContext(TheSILModule.get());
979+
parseSourceFileSIL(MainFile, &SILContext);
1007980
}
1008981

1009982
Diags.setSuppressWarnings(DidSuppressWarnings);
@@ -1012,12 +985,6 @@ void CompilerInstance::parseAndTypeCheckMainFileUpTo(
1012985
Invocation.getFrontendOptions().DebuggerTestingTransform) {
1013986
performDebuggerTestingTransform(MainFile);
1014987
}
1015-
1016-
if (!TheSILModule) {
1017-
if (!mainIsPrimary) {
1018-
performNameBinding(MainFile);
1019-
}
1020-
}
1021988
}
1022989

1023990
static void
@@ -1109,8 +1076,8 @@ void CompilerInstance::performParseOnly(bool EvaluateConditionals,
11091076
SourceFileKind::Library, SourceFile::ImplicitModuleImportKind::None,
11101077
BufferID);
11111078

1112-
parseIntoSourceFileFull(*NextInput, BufferID, PersistentState.get(),
1113-
shouldDelayBodies(BufferID));
1079+
parseIntoSourceFile(*NextInput, BufferID, PersistentState.get(),
1080+
shouldDelayBodies(BufferID));
11141081
}
11151082

11161083
// Now parse the main file.
@@ -1120,8 +1087,8 @@ void CompilerInstance::performParseOnly(bool EvaluateConditionals,
11201087
MainFile.SyntaxParsingCache = Invocation.getMainFileSyntaxParsingCache();
11211088
assert(MainBufferID == MainFile.getBufferID());
11221089

1123-
parseIntoSourceFileFull(MainFile, MainBufferID, PersistentState.get(),
1124-
shouldDelayBodies(MainBufferID));
1090+
parseIntoSourceFile(MainFile, MainBufferID, PersistentState.get(),
1091+
shouldDelayBodies(MainBufferID));
11251092
}
11261093

11271094
assert(Context->LoadedModules.size() == 1 &&

lib/IDE/CompletionInstance.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ bool CompletionInstance::performCachedOperaitonIfPossible(
217217
newSF->enableInterfaceHash();
218218
// Ensure all non-function-body tokens are hashed into the interface hash
219219
Ctx->LangOpts.EnableTypeFingerprints = false;
220-
parseIntoSourceFileFull(*newSF, tmpBufferID, &newState);
220+
parseIntoSourceFile(*newSF, tmpBufferID, &newState);
221221
// Couldn't find any completion token?
222222
if (!newState.hasCodeCompletionDelayedDeclState())
223223
return false;

lib/IDE/REPLCodeCompletion.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -208,10 +208,7 @@ doCodeCompletion(SourceFile &SF, StringRef EnteredCode, unsigned *BufferID,
208208
const unsigned OriginalDeclCount = SF.getTopLevelDecls().size();
209209

210210
PersistentParserState PersistentState;
211-
bool Done;
212-
do {
213-
parseIntoSourceFile(SF, *BufferID, &Done, nullptr, &PersistentState);
214-
} while (!Done);
211+
parseIntoSourceFile(SF, *BufferID, &PersistentState);
215212
performTypeChecking(SF, OriginalDeclCount);
216213

217214
performCodeCompletionSecondPass(PersistentState, *CompletionCallbacksFactory);

lib/Immediate/REPL.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -187,11 +187,7 @@ typeCheckREPLInput(ModuleDecl *MostRecentModule, StringRef Name,
187187
REPLInputFile.addImports(ImportsWithOptions);
188188
}
189189

190-
bool Done;
191-
do {
192-
parseIntoSourceFile(REPLInputFile, BufferID, &Done, nullptr,
193-
&PersistentState);
194-
} while (!Done);
190+
parseIntoSourceFile(REPLInputFile, BufferID, &PersistentState);
195191
performTypeChecking(REPLInputFile);
196192
return REPLModule;
197193
}

0 commit comments

Comments
 (0)