@@ -46,20 +46,6 @@ using namespace swift::immediate;
46
46
47
47
namespace {
48
48
49
- class REPLContext {
50
- public:
51
- // / The SourceMgr buffer ID of the REPL input.
52
- unsigned CurBufferID;
53
-
54
- // / The index into the source file's Decls at which to start
55
- // / typechecking the next REPL input.
56
- unsigned CurElem;
57
-
58
- // / The index into the source file's Decls at which to start
59
- // / irgenning the next REPL input.
60
- unsigned CurIRGenElem;
61
- };
62
-
63
49
enum class REPLInputKind : int {
64
50
// / The REPL got a "quit" signal.
65
51
REPLQuit,
@@ -168,27 +154,49 @@ static void convertToUTF8(llvm::ArrayRef<wchar_t> wide,
168
154
169
155
#if HAVE_UNICODE_LIBEDIT
170
156
171
- static bool appendToREPLFile (SourceFile &SF,
172
- PersistentParserState &PersistentState,
173
- REPLContext &RC,
174
- std::unique_ptr<llvm::MemoryBuffer> Buffer) {
175
- assert (SF.Kind == SourceFileKind::REPL && " Can't append to a non-REPL file" );
176
-
177
- SourceManager &SrcMgr = SF.getParentModule ()->getASTContext ().SourceMgr ;
178
- RC.CurBufferID = SrcMgr.addNewSourceBuffer (std::move (Buffer));
157
+ static ModuleDecl *
158
+ typeCheckREPLInput (ModuleDecl *MostRecentModule, StringRef Name,
159
+ PersistentParserState &PersistentState,
160
+ std::unique_ptr<llvm::MemoryBuffer> Buffer) {
161
+ using ImplicitModuleImportKind = SourceFile::ImplicitModuleImportKind;
162
+ assert (MostRecentModule);
163
+ ASTContext &Ctx = MostRecentModule->getASTContext ();
164
+
165
+ auto REPLModule = ModuleDecl::create (Ctx.getIdentifier (Name), Ctx);
166
+ auto BufferID = Ctx.SourceMgr .addNewSourceBuffer (std::move (Buffer));
167
+ auto ImportKind = ImplicitModuleImportKind::None;
168
+ auto &REPLInputFile = *new (Ctx) SourceFile (*REPLModule, SourceFileKind::REPL,
169
+ BufferID, ImportKind);
170
+ REPLModule->addFile (REPLInputFile);
171
+
172
+ ModuleDecl::ImportedModule ImportOfMostRecentModule{
173
+ /* AccessPath*/ {}, MostRecentModule};
174
+ REPLInputFile.addImports (std::make_pair (ImportOfMostRecentModule,
175
+ SourceFile::ImportOptions ()));
176
+
177
+ SmallVector<ModuleDecl::ImportedModule, 8 > Imports;
178
+ MostRecentModule->getImportedModules (Imports,
179
+ ModuleDecl::ImportFilter::Private);
180
+ if (!Imports.empty ()) {
181
+ SmallVector<std::pair<ModuleDecl::ImportedModule,
182
+ SourceFile::ImportOptions>, 8 > ImportsWithOptions;
183
+ for (auto Import : Imports) {
184
+ ImportsWithOptions.emplace_back (Import,
185
+ SourceFile::ImportFlags::Exported);
186
+ }
187
+ REPLInputFile.addImports (ImportsWithOptions);
188
+ }
179
189
180
190
bool FoundAnySideEffects = false ;
181
- unsigned CurElem = RC.CurElem ;
182
191
bool Done;
183
192
do {
184
193
FoundAnySideEffects |=
185
- parseIntoSourceFile (SF, RC. CurBufferID , &Done, nullptr ,
194
+ parseIntoSourceFile (REPLInputFile, BufferID , &Done, nullptr ,
186
195
&PersistentState);
187
- performTypeChecking (SF, PersistentState.getTopLevelContext (), None,
188
- CurElem);
189
- CurElem = SF.Decls .size ();
190
196
} while (!Done);
191
- return FoundAnySideEffects;
197
+ performTypeChecking (REPLInputFile, PersistentState.getTopLevelContext (),
198
+ /* Options*/ None);
199
+ return REPLModule;
192
200
}
193
201
194
202
// / An arbitrary, otherwise-unused char value that editline interprets as
@@ -327,8 +335,6 @@ class REPLInput {
327
335
fflush (stdout);
328
336
el_end (e);
329
337
}
330
-
331
- SourceFile &getREPLInputFile ();
332
338
333
339
REPLInputKind getREPLInput (SmallVectorImpl<char > &Result) {
334
340
ide::SourceCompleteResult SCR;
@@ -667,6 +673,8 @@ class REPLInput {
667
673
if (trimmed > 0 )
668
674
llvm::outs () << " (and " << trimmed << " more)\n " ;
669
675
}
676
+
677
+ SourceFile &getFileForCodeCompletion ();
670
678
671
679
unsigned char onComplete (int ch) {
672
680
const LineInfoW *line = el_wline (e);
@@ -677,7 +685,7 @@ class REPLInput {
677
685
678
686
if (!completions) {
679
687
// If we aren't currently working with a completion set, generate one.
680
- completions.populate (getREPLInputFile (), Prefix);
688
+ completions.populate (getFileForCodeCompletion (), Prefix);
681
689
// Display the common root of the found completions and beep unless we
682
690
// found a unique one.
683
691
insertStringRef (completions.getRoot ());
@@ -736,11 +744,7 @@ static void printOrDumpDecl(Decl *d, PrintOrDump which) {
736
744
// / The compiler and execution environment for the REPL.
737
745
class REPLEnvironment {
738
746
CompilerInstance &CI;
739
-
740
- public:
741
- SourceFile &REPLInputFile;
742
-
743
- private:
747
+ ModuleDecl *MostRecentModule;
744
748
ProcessCmdLine CmdLine;
745
749
llvm::SmallPtrSet<swift::ModuleDecl *, 8 > ImportedModules;
746
750
SmallVector<llvm::Function*, 8 > InitFns;
@@ -757,8 +761,8 @@ class REPLEnvironment {
757
761
const SILOptions SILOpts;
758
762
759
763
REPLInput Input;
760
- REPLContext RC;
761
764
PersistentParserState PersistentState;
765
+ unsigned NextLineNumber = 0 ;
762
766
763
767
private:
764
768
@@ -858,17 +862,18 @@ class REPLEnvironment {
858
862
859
863
bool executeSwiftSource (llvm::StringRef Line, const ProcessCmdLine &CmdLine) {
860
864
// Parse the current line(s).
861
- auto InputBuf = std::unique_ptr<llvm::MemoryBuffer>(
862
- llvm::MemoryBuffer::getMemBufferCopy (Line, " <REPL Input>" ));
863
- bool ShouldRun = appendToREPLFile (REPLInputFile, PersistentState, RC,
864
- std::move (InputBuf));
865
+ auto InputBuf = llvm::MemoryBuffer::getMemBufferCopy (Line, " <REPL Input>" );
866
+ SmallString<8 > Name{" REPL_" };
867
+ llvm::raw_svector_ostream (Name) << NextLineNumber;
868
+ ++NextLineNumber;
869
+ ModuleDecl *M = typeCheckREPLInput (MostRecentModule, Name, PersistentState,
870
+ std::move (InputBuf));
865
871
866
872
// SILGen the module and produce SIL diagnostics.
867
873
std::unique_ptr<SILModule> sil;
868
874
869
875
if (!CI.getASTContext ().hadError ()) {
870
- sil = performSILGeneration (REPLInputFile, CI.getSILOptions (),
871
- RC.CurIRGenElem );
876
+ sil = performSILGeneration (M, CI.getSILOptions ());
872
877
runSILDiagnosticPasses (*sil);
873
878
runSILLoweringPasses (*sil);
874
879
}
@@ -878,34 +883,23 @@ class REPLEnvironment {
878
883
return false ;
879
884
880
885
CI.getASTContext ().Diags .resetHadAnyError ();
881
- while (REPLInputFile.Decls .size () > RC.CurElem )
882
- REPLInputFile.Decls .pop_back ();
883
-
886
+
884
887
// FIXME: Handling of "import" declarations? Is there any other
885
888
// state which needs to be reset?
886
889
887
890
return true ;
888
891
}
889
-
890
- RC.CurElem = REPLInputFile.Decls .size ();
891
-
892
+ MostRecentModule = M;
893
+
892
894
DumpSource += Line;
893
-
894
- // If we didn't see an expression, statement, or decl which might have
895
- // side-effects, keep reading.
896
- if (!ShouldRun)
897
- return true ;
898
895
899
- const PrimarySpecificPaths PSPs =
900
- CI.getPrimarySpecificPathsForAtMostOnePrimary ();
901
896
// IRGen the current line(s).
902
897
// FIXME: We shouldn't need to use the global context here, but
903
898
// something is persisting across calls to performIRGeneration.
904
899
auto LineModule = performIRGeneration (
905
- IRGenOpts, REPLInputFile, std::move (sil), " REPLLine" , PSPs,
906
- getGlobalLLVMContext (), RC.CurIRGenElem );
907
- RC.CurIRGenElem = RC.CurElem ;
908
-
900
+ IRGenOpts, M, std::move (sil), " REPLLine" , PrimarySpecificPaths (),
901
+ getGlobalLLVMContext (), /* parallelOutputFilenames*/ {});
902
+
909
903
if (CI.getASTContext ().hadError ())
910
904
return false ;
911
905
@@ -929,7 +923,7 @@ class REPLEnvironment {
929
923
llvm::Function *DumpModuleMain = DumpModule.getFunction (" main" );
930
924
DumpModuleMain->setName (" repl.line" );
931
925
932
- if (autolinkImportedModules (getMainModule () , IRGenOpts))
926
+ if (autolinkImportedModules (M , IRGenOpts))
933
927
return false ;
934
928
935
929
llvm::Module *TempModule = NewModule.get ();
@@ -959,8 +953,7 @@ class REPLEnvironment {
959
953
llvm::LLVMContext &LLVMCtx,
960
954
bool ParseStdlib)
961
955
: CI(CI),
962
- REPLInputFile (CI.getMainModule()->
963
- getMainSourceFile(SourceFileKind::REPL)),
956
+ MostRecentModule (CI.getMainModule()),
964
957
CmdLine(CmdLine),
965
958
RanGlobalInitializers(false ),
966
959
LLVMContext(LLVMCtx),
@@ -969,20 +962,19 @@ class REPLEnvironment {
969
962
IRGenOpts(),
970
963
SILOpts(),
971
964
Input(*this ),
972
- RC{
973
- /* BufferID*/ 0U ,
974
- /* CurElem*/ 0 ,
975
- /* CurIRGenElem*/ 0
976
- },
977
965
PersistentState(CI.getASTContext())
978
966
{
979
967
ASTContext &Ctx = CI.getASTContext ();
980
- if (!loadSwiftRuntime (Ctx.SearchPathOpts .RuntimeLibraryPath )) {
981
- CI.getDiags ().diagnose (SourceLoc (),
982
- diag::error_immediate_mode_missing_stdlib);
983
- return ;
968
+ Ctx.LangOpts .EnableAccessControl = false ;
969
+ if (!ParseStdlib) {
970
+ if (!loadSwiftRuntime (Ctx.SearchPathOpts .RuntimeLibraryPath )) {
971
+ CI.getDiags ().diagnose (SourceLoc (),
972
+ diag::error_immediate_mode_missing_stdlib);
973
+ return ;
974
+ }
975
+ tryLoadLibraries (CI.getLinkLibraries (), Ctx.SearchPathOpts ,
976
+ CI.getDiags ());
984
977
}
985
- tryLoadLibraries (CI.getLinkLibraries (), Ctx.SearchPathOpts , CI.getDiags ());
986
978
987
979
llvm::EngineBuilder builder{std::unique_ptr<llvm::Module>{Module}};
988
980
std::string ErrorMsg;
@@ -1008,6 +1000,10 @@ class REPLEnvironment {
1008
1000
IRGenOpts.DebugInfoLevel = IRGenDebugInfoLevel::None;
1009
1001
IRGenOpts.DebugInfoFormat = IRGenDebugInfoFormat::None;
1010
1002
1003
+ // The very first module is a dummy.
1004
+ CI.getMainModule ()->getMainSourceFile (SourceFileKind::REPL).ASTStage =
1005
+ SourceFile::TypeChecked;
1006
+
1011
1007
if (!ParseStdlib) {
1012
1008
// Force standard library to be loaded immediately. This forces any
1013
1009
// errors to appear upfront, and helps eliminate some nasty lag after the
@@ -1017,14 +1013,13 @@ class REPLEnvironment {
1017
1013
auto Buffer =
1018
1014
llvm::MemoryBuffer::getMemBufferCopy (WarmUpStmt,
1019
1015
" <REPL Initialization>" );
1020
- appendToREPLFile (REPLInputFile, PersistentState, RC, std::move (Buffer));
1016
+ (void )typeCheckREPLInput (MostRecentModule, " __Warmup" , PersistentState,
1017
+ std::move (Buffer));
1021
1018
1022
1019
if (Ctx.hadError ())
1023
1020
return ;
1024
1021
}
1025
-
1026
- RC.CurElem = RC.CurIRGenElem = REPLInputFile.Decls .size ();
1027
-
1022
+
1028
1023
if (llvm::sys::Process::StandardInIsUserInput ())
1029
1024
llvm::outs () <<
1030
1025
" *** You are running Swift's integrated REPL, ***\n "
@@ -1034,13 +1029,14 @@ class REPLEnvironment {
1034
1029
" *** Type ':help' for assistance. ***\n " ;
1035
1030
}
1036
1031
1037
- swift::ModuleDecl *getMainModule () const {
1038
- return REPLInputFile.getParentModule ();
1039
- }
1040
1032
StringRef getDumpSource () const { return DumpSource; }
1041
1033
1042
1034
// / Get the REPLInput object owned by the REPL instance.
1043
1035
REPLInput &getInput () { return Input; }
1036
+
1037
+ SourceFile &getFileForCodeCompletion () {
1038
+ return MostRecentModule->getMainSourceFile (SourceFileKind::REPL);
1039
+ }
1044
1040
1045
1041
// / Responds to a REPL input. Returns true if the repl should continue,
1046
1042
// / false if it should quit.
@@ -1070,8 +1066,6 @@ class REPLEnvironment {
1070
1066
" :constraints debug (on|off) - turn on/off the debug "
1071
1067
" output for the constraint-based type checker\n "
1072
1068
" :dump_ir - dump the LLVM IR generated by the REPL\n "
1073
- " :dump_ast - dump the AST representation of"
1074
- " the REPL input\n "
1075
1069
" :dump_decl <name> - dump the AST representation of the "
1076
1070
" named declarations\n "
1077
1071
" :dump_source - dump the user input (ignoring"
@@ -1086,17 +1080,17 @@ class REPLEnvironment {
1086
1080
return false ;
1087
1081
} else if (L.peekNextToken ().getText () == " dump_ir" ) {
1088
1082
DumpModule.print (llvm::dbgs (), nullptr , false , true );
1089
- } else if (L.peekNextToken ().getText () == " dump_ast" ) {
1090
- REPLInputFile.dump ();
1091
1083
} else if (L.peekNextToken ().getText () == " dump_decl" ||
1092
1084
L.peekNextToken ().getText () == " print_decl" ) {
1093
1085
PrintOrDump doPrint = (L.peekNextToken ().getText () == " print_decl" )
1094
1086
? PrintOrDump::Print : PrintOrDump::Dump;
1095
1087
L.lex (Tok);
1096
1088
L.lex (Tok);
1097
1089
ASTContext &ctx = CI.getASTContext ();
1098
- UnqualifiedLookup lookup (ctx.getIdentifier (Tok.getText ()),
1099
- &REPLInputFile, nullptr );
1090
+ SourceFile &SF =
1091
+ MostRecentModule->getMainSourceFile (SourceFileKind::REPL);
1092
+ UnqualifiedLookup lookup (ctx.getIdentifier (Tok.getText ()), &SF,
1093
+ nullptr );
1100
1094
for (auto result : lookup.Results ) {
1101
1095
printOrDumpDecl (result.getValueDecl (), doPrint);
1102
1096
@@ -1201,7 +1195,9 @@ class REPLEnvironment {
1201
1195
}
1202
1196
};
1203
1197
1204
- inline SourceFile &REPLInput::getREPLInputFile () { return Env.REPLInputFile ; }
1198
+ inline SourceFile &REPLInput::getFileForCodeCompletion () {
1199
+ return Env.getFileForCodeCompletion ();
1200
+ }
1205
1201
1206
1202
void PrettyStackTraceREPL::print (llvm::raw_ostream &out) const {
1207
1203
out << " while processing REPL source:\n " ;
0 commit comments