diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5ccefcb4e..cce65f841 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -51,15 +51,25 @@ find_package(MPFR 3.1.0) set(EXTRA_LIBS ${EXTRA_LIBS} ${MPFR_LIBRARIES}) # tcmalloc -option(tcmalloc "tcmalloc" ON) -if("${tcmalloc}" MATCHES "ON") +option(TCMALLOC "TCMALLOC" ON) +if("${TCMALLOC}" MATCHES "ON") if(${TCMALLOC_FOUND}) set(EXTRA_LIBS ${EXTRA_LIBS} ${TCMALLOC_LIBRARIES}) endif() + message(STATUS "Using tcmalloc.") else() message(STATUS "Using standard malloc.") endif() +# Readline +option(READLINE "READLINE" OFF) +if("${READLINE}" MATCHES "ON") + find_package(Readline) + set(EXTRA_LIBS ${EXTRA_LIBS} ${READLINE_LIBRARY}) + message(STATUS "Using GNU readline") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DLEAN_USE_READLINE") +endif() + include_directories(${LEAN_SOURCE_DIR}/util) include_directories(${LEAN_SOURCE_DIR}/util/numerics) include_directories(${LEAN_SOURCE_DIR}/util/sexpr) diff --git a/src/cmake/Modules/FindReadline.cmake b/src/cmake/Modules/FindReadline.cmake new file mode 100644 index 000000000..48b292ee5 --- /dev/null +++ b/src/cmake/Modules/FindReadline.cmake @@ -0,0 +1,16 @@ +FIND_PATH(READLINE_INCLUDE_DIR readline/readline.h) +FIND_LIBRARY(READLINE_LIBRARY NAMES readline) + +IF (READLINE_INCLUDE_DIR AND READLINE_LIBRARY) + SET(READLINE_FOUND TRUE) +ENDIF (READLINE_INCLUDE_DIR AND READLINE_LIBRARY) + +IF (READLINE_FOUND) + IF (NOT Readline_FIND_QUIETLY) + MESSAGE(STATUS "Found GNU readline: ${READLINE_LIBRARY}") + ENDIF (NOT Readline_FIND_QUIETLY) +ELSE (READLINE_FOUND) + IF (Readline_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find GNU readline") + ENDIF (Readline_FIND_REQUIRED) +ENDIF (READLINE_FOUND) diff --git a/src/frontends/lean/lean_parser.cpp b/src/frontends/lean/lean_parser.cpp index 0d509b719..695083866 100644 --- a/src/frontends/lean/lean_parser.cpp +++ b/src/frontends/lean/lean_parser.cpp @@ -20,6 +20,13 @@ Author: Leonardo de Moura #include "lean_scanner.h" #include "lean_notation.h" #include "lean_pp.h" +#ifdef LEAN_USE_READLINE +#include +#include +#include +#include +#include +#endif namespace lean { // ========================================== @@ -1156,12 +1163,30 @@ public: throw parser_exception(ex.what(), m_scanner.get_line(), m_scanner.get_pos()); } } - }; bool parse_commands(frontend & fe, std::istream & in, bool use_exceptions, bool interactive) { parser_fn::show_prompt(interactive, fe); return parser_fn(fe, in, use_exceptions, interactive).parse_commands(); } +bool parse_commands_from_stdin(frontend & fe) { +#ifdef LEAN_USE_READLINE + bool errors = false; + char * input; + while (true) { + input = readline("# "); + if (!input) + return errors; + std::istringstream strm(input); + if (parse_commands(fe, strm, false, false)) + add_history(input); + else + errors = true; + free(input); + } +#else + return parse_commands(fe, std::cin, false, true) ? 0 : 1; +#endif +} expr parse_expr(frontend const & fe, std::istream & in) { return parser_fn(const_cast(fe), in, true, false).parse_expr_main(); } diff --git a/src/frontends/lean/lean_parser.h b/src/frontends/lean/lean_parser.h index a22dec3c0..801c0888c 100644 --- a/src/frontends/lean/lean_parser.h +++ b/src/frontends/lean/lean_parser.h @@ -10,5 +10,6 @@ Author: Leonardo de Moura namespace lean { bool parse_commands(frontend & fe, std::istream & in, bool use_exceptions = true, bool interactive = false); +bool parse_commands_from_stdin(frontend & fe); expr parse_expr(frontend const & fe, std::istream & in); } diff --git a/src/shell/lean.cpp b/src/shell/lean.cpp index c845a2545..650e1ecdf 100644 --- a/src/shell/lean.cpp +++ b/src/shell/lean.cpp @@ -10,7 +10,7 @@ int main(int argc, char ** argv) { std::cout << "Type Ctrl-D to exit or 'Help.' for help."<< std::endl; frontend f; if (argc == 1) { - return parse_commands(f, std::cin, false, true) ? 0 : 1; + return parse_commands_from_stdin(f) ? 0 : 1; } else { bool ok = true; for (int i = 1; i < argc; i++) {