Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
50 changes: 40 additions & 10 deletions clang/docs/ClangRepl.rst
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,29 @@ Lamdas:
clang-repl> welcome();
Welcome to REPL

Using Dynamic Library:
======================
Comments:
=========

.. code-block:: text

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

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 +210,30 @@ Using Dynamic Library:
clang++-17 -c -o print.o print.cpp
clang-17 -shared print.o -o print.so

Comments:
=========
Undo:
-----
The ``%undo`` command undoes 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



Just like Clang, Clang-Repl can be integrated in existing applications as a library
Expand Down
4 changes: 4 additions & 0 deletions clang/test/Interpreter/bad_percent_command.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// RUN: cat %s | clang-repl 2>&1 | FileCheck %s
%foobar
// CHECK: Invalid % command "%foobar", use "%help" to list commands
%quit
4 changes: 4 additions & 0 deletions clang/test/Interpreter/dynamic-library-bad-args.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// RUN: cat %s | clang-repl 2>&1 | FileCheck %s
%lib
// CHECK: %lib expects 1 argument: the path to a dynamic library
%quit
7 changes: 7 additions & 0 deletions clang/test/Interpreter/help.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// RUN: cat %s | clang-repl | FileCheck %s
%help
// CHECK: %help list clang-repl %commands
// CHECK-NEXT: %undo undo the previous input
// CHECK-NEXT: %lib <path> link a dynamic library
// CHECK-NEXT: %quit exit clang-repl
%quit
20 changes: 20 additions & 0 deletions clang/tools/clang-repl/ClangRepl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "llvm/Support/ManagedStatic.h" // llvm_shutdown
#include "llvm/Support/Signals.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Host.h"
#include <optional>

Expand Down Expand Up @@ -364,15 +365,34 @@ int main(int argc, const char **argv) {
}

Input += L;
// If we add more % commands, there should be better architecture than
// this.
if (Input == R"(%quit)") {
break;
}
if (Input == R"(%undo)") {
if (auto Err = Interp->Undo())
llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: ");
} else if (Input == R"(%help)") {
llvm::outs() << "%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";
} else if (Input == R"(%lib)") {
auto Err = llvm::make_error<llvm::StringError>(
"%lib expects 1 argument: the path to a dynamic library\n",
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] == '%') {
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