From aa6a2a6130b16645e5907d82d691440f0fe6a343 Mon Sep 17 00:00:00 2001 From: Pavel Kalugin Date: Fri, 15 Dec 2023 16:06:12 +0300 Subject: [PATCH 1/3] interpreter: put all the cells inside of nested namespaces --- include/xeus-clang-repl/xparser.hpp | 7 ++++++- src/xinterpreter.cpp | 28 ++++++++++++++++++++++++++-- src/xparser.cpp | 19 ++++++++++--------- 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/include/xeus-clang-repl/xparser.hpp b/include/xeus-clang-repl/xparser.hpp index d2e81bd4..27a2cc07 100644 --- a/include/xeus-clang-repl/xparser.hpp +++ b/include/xeus-clang-repl/xparser.hpp @@ -26,7 +26,12 @@ std::vector split_line(const std::string &input, std::vector get_lines(const std::string &input); -std::vector split_from_includes(const std::string &input); +struct SplitBlock { + bool is_include; + std::string code; +}; + +std::vector split_from_includes(const std::string &input); bool short_has_arg(const std::string &opt, const std::string &short_opts); diff --git a/src/xinterpreter.cpp b/src/xinterpreter.cpp index 880ad067..ceff281d 100644 --- a/src/xinterpreter.cpp +++ b/src/xinterpreter.cpp @@ -64,7 +64,26 @@ interpreter::interpreter(int argc, const char *const *argv) interpreter::~interpreter() { restore_output(); } -nl::json interpreter::execute_request_impl(int /*execution_counter*/, + +std::string namespace_name(int namespace_number) { + const std::string NAMESPACE_PREFIX = "__xns"; + return NAMESPACE_PREFIX + std::to_string(namespace_number); +} + +std::string namespace_full_name(int namespace_number) { + std::string result; + for (int i = 1; i < namespace_number; ++i) { + result += namespace_name(i) + "::"; + } + result += namespace_name(namespace_number); + return result; +} + +std::string encapsulate_code(const std::string &code, int namespace_number) { + return "\nnamespace " + namespace_full_name(namespace_number) + " {" + code + "}"; +} + +nl::json interpreter::execute_request_impl(int execution_counter, const std::string &code, bool silent, bool /*store_history*/, nl::json /*user_expressions*/, @@ -110,7 +129,12 @@ nl::json interpreter::execute_request_impl(int /*execution_counter*/, try { Cpp::BeginStdStreamCapture(Cpp::kStdErr); Cpp::BeginStdStreamCapture(Cpp::kStdOut); - compilation_result = Cpp::Process(block.c_str()); + if (block.is_include) { + compilation_result = Cpp::Process(block.code.c_str()); + } else { + std::string encapsulated = encapsulate_code(block.code, execution_counter); + compilation_result = Cpp::Process(encapsulated.c_str()); + } out = Cpp::EndStdStreamCapture(); err = Cpp::EndStdStreamCapture(); std::cout << out; diff --git a/src/xparser.cpp b/src/xparser.cpp index 2d3be1d8..b35d2696 100644 --- a/src/xparser.cpp +++ b/src/xparser.cpp @@ -53,7 +53,7 @@ std::vector get_lines(const std::string &input) { return lines; } -std::vector split_from_includes(const std::string &input) { +std::vector split_from_includes(const std::string &input) { // this function split the input into part where we have only #include. // split input into lines @@ -63,15 +63,15 @@ std::vector split_from_includes(const std::string &input) { // part of the result std::regex incl_re("\\#include.*"); std::regex magic_re("^\\%\\w+"); - std::vector result; - result.push_back(""); + std::vector result; + result.emplace_back(false, ""); std::size_t current = 0; // 0 include, 1 other std::size_t rindex = 0; // current index of result vector for (std::size_t i = 0; i < lines.size(); ++i) { if (!lines[i].empty()) { if (std::regex_search(lines[i], magic_re)) { - result.push_back(lines[i] + "\n"); - result.push_back(""); + result.emplace_back(false, lines[i] + "\n"); + result.emplace_back(false, ""); rindex += 2; } else { if (std::regex_match(lines[i], incl_re)) { @@ -80,7 +80,7 @@ std::vector split_from_includes(const std::string &input) { // other things if (current != 0) { current = 0; - result.push_back(""); + result.emplace_back(false, ""); rindex++; } } else { @@ -89,15 +89,16 @@ std::vector split_from_includes(const std::string &input) { // the include parts if (current != 1) { current = 1; - result.push_back(""); + result.emplace_back(false, ""); rindex++; } } // if we have multiple lines, we add a semicolon at the end of the lines // that not contain #include keyword (except for the last line) - result[rindex] += lines[i]; + result[rindex].is_include = true; + result[rindex].code += lines[i]; if (i != lines.size() - 1) { - result[rindex] += "\n"; + result[rindex].code += "\n"; } } } From 70a5c73556dbe4206a7433530bd1fbdaa43029eb Mon Sep 17 00:00:00 2001 From: Pavel Kalugin Date: Fri, 15 Dec 2023 16:08:28 +0300 Subject: [PATCH 2/3] clang: add patch that fixes top-level code parsing --- .../llvm/clang17-2-fix-toplevel-code.patch | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 patches/llvm/clang17-2-fix-toplevel-code.patch diff --git a/patches/llvm/clang17-2-fix-toplevel-code.patch b/patches/llvm/clang17-2-fix-toplevel-code.patch new file mode 100644 index 00000000..a4b983d1 --- /dev/null +++ b/patches/llvm/clang17-2-fix-toplevel-code.patch @@ -0,0 +1,77 @@ +diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h +index cd0878d70825..7b1d9e8be6c5 100644 +--- a/clang/include/clang/AST/Decl.h ++++ b/clang/include/clang/AST/Decl.h +@@ -4440,7 +4440,8 @@ class TopLevelStmtDecl : public Decl { + virtual void anchor(); + + public: +- static TopLevelStmtDecl *Create(ASTContext &C, Stmt *Statement); ++ static TopLevelStmtDecl *Create(ASTContext &C, DeclContext *DC, ++ Stmt *Statement); + static TopLevelStmtDecl *CreateDeserialized(ASTContext &C, unsigned ID); + + SourceRange getSourceRange() const override LLVM_READONLY; +diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp +index 527ea6042daa..5c0f4f5b6b4c 100644 +--- a/clang/lib/AST/Decl.cpp ++++ b/clang/lib/AST/Decl.cpp +@@ -5513,13 +5513,13 @@ FileScopeAsmDecl *FileScopeAsmDecl::CreateDeserialized(ASTContext &C, + + void TopLevelStmtDecl::anchor() {} + +-TopLevelStmtDecl *TopLevelStmtDecl::Create(ASTContext &C, Stmt *Statement) { ++TopLevelStmtDecl *TopLevelStmtDecl::Create(ASTContext &C, DeclContext *DC, ++ Stmt *Statement) { + assert(Statement); + assert(C.getLangOpts().IncrementalExtensions && + "Must be used only in incremental mode"); + + SourceLocation BeginLoc = Statement->getBeginLoc(); +- DeclContext *DC = C.getTranslationUnitDecl(); + + return new (C, DC) TopLevelStmtDecl(DC, BeginLoc, Statement); + } +diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp +index 370bcbfee8b0..366610abecb0 100644 +--- a/clang/lib/Interpreter/IncrementalParser.cpp ++++ b/clang/lib/Interpreter/IncrementalParser.cpp +@@ -373,8 +373,22 @@ std::unique_ptr IncrementalParser::GenModule() { + + void IncrementalParser::CleanUpPTU(PartialTranslationUnit &PTU) { + TranslationUnitDecl *MostRecentTU = PTU.TUPart; ++ if (!MostRecentTU) { ++ return; ++ } ++ + TranslationUnitDecl *FirstTU = MostRecentTU->getFirstDecl(); +- if (StoredDeclsMap *Map = FirstTU->getPrimaryContext()->getLookupPtr()) { ++ if (!FirstTU) { ++ return; ++ } ++ ++ SmallVector contexts; ++ FirstTU->collectAllContexts(contexts); ++ if (contexts.empty()) { ++ return; ++ } ++ ++ if (StoredDeclsMap *Map = contexts.back()->getLookupPtr()) { + for (auto I = Map->begin(); I != Map->end(); ++I) { + StoredDeclsList &List = I->second; + DeclContextLookupResult R = List.getLookupResult(); +diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp +index be6a136ef37b..f78fada57f62 100644 +--- a/clang/lib/Sema/SemaDecl.cpp ++++ b/clang/lib/Sema/SemaDecl.cpp +@@ -20287,8 +20287,8 @@ Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr, + } + + Decl *Sema::ActOnTopLevelStmtDecl(Stmt *Statement) { +- auto *New = TopLevelStmtDecl::Create(Context, Statement); +- Context.getTranslationUnitDecl()->addDecl(New); ++ auto *New = TopLevelStmtDecl::Create(Context, CurContext, Statement); ++ CurContext->addDecl(New); + return New; + } + From fb218097e6b3aaba5c94324691b87309fb5365ac Mon Sep 17 00:00:00 2001 From: Pavel Kalugin Date: Fri, 15 Dec 2023 16:28:07 +0300 Subject: [PATCH 3/3] fixup include splitting --- src/xparser.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/xparser.cpp b/src/xparser.cpp index b35d2696..85e52f2f 100644 --- a/src/xparser.cpp +++ b/src/xparser.cpp @@ -64,14 +64,14 @@ std::vector split_from_includes(const std::string &input) { std::regex incl_re("\\#include.*"); std::regex magic_re("^\\%\\w+"); std::vector result; - result.emplace_back(false, ""); + result.push_back({false, ""}); std::size_t current = 0; // 0 include, 1 other std::size_t rindex = 0; // current index of result vector for (std::size_t i = 0; i < lines.size(); ++i) { if (!lines[i].empty()) { if (std::regex_search(lines[i], magic_re)) { - result.emplace_back(false, lines[i] + "\n"); - result.emplace_back(false, ""); + result.push_back({false, lines[i] + "\n"}); + result.push_back({false, ""}); rindex += 2; } else { if (std::regex_match(lines[i], incl_re)) { @@ -80,7 +80,7 @@ std::vector split_from_includes(const std::string &input) { // other things if (current != 0) { current = 0; - result.emplace_back(false, ""); + result.push_back({false, ""}); rindex++; } } else { @@ -89,13 +89,13 @@ std::vector split_from_includes(const std::string &input) { // the include parts if (current != 1) { current = 1; - result.emplace_back(false, ""); + result.push_back({false, ""}); rindex++; } } // if we have multiple lines, we add a semicolon at the end of the lines // that not contain #include keyword (except for the last line) - result[rindex].is_include = true; + result[rindex].is_include = (current == 0); result[rindex].code += lines[i]; if (i != lines.size() - 1) { result[rindex].code += "\n";