Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 40 additions & 8 deletions clang/docs/ClangRepl.rst
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,21 @@ Lamdas:
clang-repl> welcome();
Welcome to REPL

Using Dynamic Library:
======================
Built in Commands:
==================
clang-repl has some special commands that are of the form `%<something>`. To list all these commands, use the `%help` command:

Help:
=====
The `%help` command lists all built in clang-repl commands.

.. code-block:: text

clang-repl> %help

Using Dynamic Libraries:
========================
The `%lib` command links a dynamic library.

.. code-block:: text

Expand Down Expand Up @@ -189,21 +202,40 @@ Using Dynamic Library:
clang++-17 -c -o print.o print.cpp
clang-17 -shared print.o -o print.so

Comments:
=========
Undo:
=====
The `%undo` command reverts the previous input.

.. code-block:: text

clang-repl> // Comments in Clang-Repl
clang-repl> /* Comments in Clang-Repl */
clang-repl> int a = 1; a
(int) 1
clang-repl> %undo
clang-repl> a
In file included from <<< inputs >>>:1:
input_line_2:1:1: error: use of undeclared identifier 'a'
1 | a
* | ^
error: Parsing failed.


Closure or Termination:
Quit:
=======================
The `%quit` command terminates clang-repl.

.. code-block:: text

clang-repl>%quit
clang-repl> %quit

Comments:
=========

.. code-block:: text

clang-repl> // Comments in Clang-Repl
clang-repl> /* Comments in Clang-Repl */




Just like Clang, Clang-Repl can be integrated in existing applications as a library
Expand Down
25 changes: 24 additions & 1 deletion clang/tools/clang-repl/ClangRepl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ struct ReplListCompleter {
clang::Interpreter &MainInterp;
ReplListCompleter(clang::IncrementalCompilerBuilder &CB,
clang::Interpreter &Interp)
: CB(CB), MainInterp(Interp){};
: CB(CB), MainInterp(Interp) {};

std::vector<llvm::LineEditor::Completion> operator()(llvm::StringRef Buffer,
size_t Pos) const;
Expand Down Expand Up @@ -347,6 +347,14 @@ int main(int argc, const char **argv) {
}
}

// If we add more % commands, there should be better architecture than this.
const char *help_output = "%help\t\tlist clang-repl %commands\n"
"%undo\t\tundo the previous input\n"
"%lib\t<path>\tlink a dynamic library\n"
"%quit\t\texit clang-repl\n";

const char *lib_bad_args =
"%lib expects 1 argument: the path to a dynamic library\n";
if (OptInputs.empty()) {
llvm::LineEditor LE("clang-repl");
std::string Input;
Expand All @@ -370,9 +378,24 @@ int main(int argc, const char **argv) {
if (Input == R"(%undo)") {
if (auto Err = Interp->Undo())
llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: ");
} else if (Input == R"(%help)") {
auto Err =
llvm::make_error<llvm::StringError>(help_output, std::error_code());
llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "");
} else if (Input == R"(%lib)") {
auto Err = llvm::make_error<llvm::StringError>(lib_bad_args,
std::error_code());
llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: ");
} else if (Input.rfind("%lib ", 0) == 0) {
if (auto Err = Interp->LoadDynamicLibrary(Input.data() + 5))
llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: ");
} else if (Input[0] == '%') { // make sure this is evaluated last
auto Err = llvm::make_error<llvm::StringError>(
llvm::formatv(
"Invalid % command \"{0}\", use \"%help\" to list commands\n",
Input),
std::error_code());
llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: ");
} else if (auto Err = Interp->ParseAndExecute(Input)) {
llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: ");
}
Expand Down