Skip to content

Commit 312f7dd

Browse files
committed
Parse Swift decls in one shot
Instead of interleaving typechecking and parsing for SIL files, first parse the file for Swift decls by skipping over any intermixed SIL decls. Then we can perform type checking, and finally SIL parsing where we now skip over Swift decls. This is an intermediate step to requestifying the parsing of a source file for its Swift decls.
1 parent 565634c commit 312f7dd

File tree

17 files changed

+213
-209
lines changed

17 files changed

+213
-209
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: 13 additions & 2 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.
@@ -661,6 +662,9 @@ class Parser {
661662
/// Returns \c true if the parser hit the eof before finding matched '}'.
662663
bool skipBracedBlock();
663664

665+
/// Skip over SIL decls until we encounter the start of a Swift decl or eof.
666+
void skipSILUntilSwiftDecl();
667+
664668
/// If the parser is generating only a syntax tree, try loading the current
665669
/// node from a previously generated syntax tree.
666670
/// Returns \c true if the node has been loaded and inserted into the current
@@ -880,11 +884,18 @@ class Parser {
880884
//===--------------------------------------------------------------------===//
881885
// Decl Parsing
882886

883-
/// Return true if parser is at the start of a Swift decl or decl-import.
887+
/// Returns true if parser is at the start of a Swift decl or decl-import.
884888
bool isStartOfSwiftDecl();
885889

890+
/// Returns true if the parser is at the start of a SIL decl.
891+
bool isStartOfSILDecl();
892+
893+
/// Parse the top-level Swift decls into the source file.
886894
void parseTopLevel();
887895

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

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)