From 554ba06782ac7fd9f428ea74573c01ebac64e505 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Thu, 26 Oct 2023 09:02:16 +1100 Subject: [PATCH] unix/main: Use standard pyexec/repl for unix & windows ports. This improves repl usage consistency across ports. Only enabled when MICROPY_USE_READLINE == 1 (default). Signed-off-by: Andrew Leech --- ports/unix/Makefile | 2 + ports/unix/main.c | 109 +++++------------------ ports/unix/modmachine.c | 3 - ports/unix/mphalport.h | 6 ++ ports/windows/Makefile | 1 + ports/windows/micropython.vcxproj | 1 + shared/runtime/pyexec.c | 1 + tests/cmdline/repl_autocomplete.py.exp | 2 +- tests/cmdline/repl_autoindent.py.exp | 2 +- tests/cmdline/repl_basic.py.exp | 2 +- tests/cmdline/repl_cont.py.exp | 2 +- tests/cmdline/repl_emacs_keys.py.exp | 2 +- tests/cmdline/repl_inspect.py.exp | 2 +- tests/cmdline/repl_micropyinspect.py.exp | 2 +- tests/cmdline/repl_sys_ps1_ps2.py.exp | 2 +- tests/cmdline/repl_words_move.py.exp | 2 +- 16 files changed, 42 insertions(+), 99 deletions(-) diff --git a/ports/unix/Makefile b/ports/unix/Makefile index d5bd6d4098..5335ecebfc 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -124,8 +124,10 @@ endif ifeq ($(MICROPY_USE_READLINE),1) INC += -I$(TOP)/shared/readline +INC += -I$(TOP)/shared/runtime CFLAGS += -DMICROPY_USE_READLINE=1 SHARED_SRC_C_EXTRA += readline/readline.c +SHARED_SRC_C_EXTRA += runtime/pyexec.c endif ifeq ($(MICROPY_PY_TERMIOS),1) CFLAGS += -DMICROPY_PY_TERMIOS=1 diff --git a/ports/unix/main.c b/ports/unix/main.c index 0cf11d37cf..db0ebc92f4 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -53,6 +53,7 @@ #include "extmod/vfs_posix.h" #include "genhdr/mpversion.h" #include "input.h" +#include "shared/runtime/pyexec.h" // Command line options, with their defaults static bool compile_only = false; @@ -193,92 +194,28 @@ static char *strjoin(const char *s1, int sep_char, const char *s2) { #endif static int do_repl(void) { + int ret = 0; + #if MICROPY_USE_READLINE == 1 + // use MicroPython supplied readline based repl + mp_hal_stdio_mode_raw(); + for (;;) { + if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { + if ((ret = pyexec_raw_repl()) != 0) { + break; + } + } else { + if ((ret = pyexec_friendly_repl()) != 0) { + break; + } + } + } + mp_hal_stdio_mode_orig(); + #else + // use simple readline mp_hal_stdout_tx_str(MICROPY_BANNER_NAME_AND_VERSION); mp_hal_stdout_tx_str("; " MICROPY_BANNER_MACHINE); mp_hal_stdout_tx_str("\nUse Ctrl-D to exit, Ctrl-E for paste mode\n"); - #if MICROPY_USE_READLINE == 1 - - // use MicroPython supplied readline - - vstr_t line; - vstr_init(&line, 16); - for (;;) { - mp_hal_stdio_mode_raw(); - - input_restart: - vstr_reset(&line); - int ret = readline(&line, mp_repl_get_ps1()); - mp_parse_input_kind_t parse_input_kind = MP_PARSE_SINGLE_INPUT; - - if (ret == CHAR_CTRL_C) { - // cancel input - mp_hal_stdout_tx_str("\r\n"); - goto input_restart; - } else if (ret == CHAR_CTRL_D) { - // EOF - printf("\n"); - mp_hal_stdio_mode_orig(); - vstr_clear(&line); - return 0; - } else if (ret == CHAR_CTRL_E) { - // paste mode - mp_hal_stdout_tx_str("\npaste mode; Ctrl-C to cancel, Ctrl-D to finish\n=== "); - vstr_reset(&line); - for (;;) { - char c = mp_hal_stdin_rx_chr(); - if (c == CHAR_CTRL_C) { - // cancel everything - mp_hal_stdout_tx_str("\n"); - goto input_restart; - } else if (c == CHAR_CTRL_D) { - // end of input - mp_hal_stdout_tx_str("\n"); - break; - } else { - // add char to buffer and echo - vstr_add_byte(&line, c); - if (c == '\r') { - mp_hal_stdout_tx_str("\n=== "); - } else { - mp_hal_stdout_tx_strn(&c, 1); - } - } - } - parse_input_kind = MP_PARSE_FILE_INPUT; - } else if (line.len == 0) { - if (ret != 0) { - printf("\n"); - } - goto input_restart; - } else { - // got a line with non-zero length, see if it needs continuing - while (mp_repl_continue_with_input(vstr_null_terminated_str(&line))) { - vstr_add_byte(&line, '\n'); - ret = readline(&line, mp_repl_get_ps2()); - if (ret == CHAR_CTRL_C) { - // cancel everything - printf("\n"); - goto input_restart; - } else if (ret == CHAR_CTRL_D) { - // stop entering compound statement - break; - } - } - } - - mp_hal_stdio_mode_orig(); - - ret = execute_from_lexer(LEX_SRC_VSTR, &line, parse_input_kind, true); - if (ret & FORCED_EXIT) { - return ret; - } - } - - #else - - // use simple readline - for (;;) { char *line = prompt((char *)mp_repl_get_ps1()); if (line == NULL) { @@ -296,16 +233,14 @@ static int do_repl(void) { line = line3; } - int ret = execute_from_lexer(LEX_SRC_STR, line, MP_PARSE_SINGLE_INPUT, true); + ret = execute_from_lexer(LEX_SRC_STR, line, MP_PARSE_SINGLE_INPUT, true); free(line); - if (ret & FORCED_EXIT) { - return ret; - } } - #endif + return ret; } + static int do_file(const char *file) { return execute_from_lexer(LEX_SRC_FILENAME, file, MP_PARSE_FILE_INPUT, false); } diff --git a/ports/unix/modmachine.c b/ports/unix/modmachine.c index 6f3ab80944..d1cdbe8619 100644 --- a/ports/unix/modmachine.c +++ b/ports/unix/modmachine.c @@ -36,9 +36,6 @@ #define MICROPY_PAGE_MASK (MICROPY_PAGE_SIZE - 1) #endif -// This variable is needed for machine.soft_reset(), but the variable is otherwise unused. -int pyexec_system_exit = 0; - uintptr_t mod_machine_mem_get_addr(mp_obj_t addr_o, uint align) { uintptr_t addr = mp_obj_get_int_truncated(addr_o); if ((addr & (align - 1)) != 0) { diff --git a/ports/unix/mphalport.h b/ports/unix/mphalport.h index 02b60d8a87..b546d94b56 100644 --- a/ports/unix/mphalport.h +++ b/ports/unix/mphalport.h @@ -48,6 +48,12 @@ void mp_hal_set_interrupt_char(char c); void mp_hal_stdio_mode_raw(void); void mp_hal_stdio_mode_orig(void); +// pyexec/repl needs stdio to be in raw mode, but this may be cleared before running code. +#if MICROPY_REPL_RESET_RAW_BEFORE_EXEC +#define MICROPY_BOARD_BEFORE_PYTHON_EXEC(input_kind, exec_flags) mp_hal_stdio_mode_orig() +#define MICROPY_BOARD_AFTER_PYTHON_EXEC(input_kind, exec_flags, ret_val, ret) mp_hal_stdio_mode_raw() +#endif + #if MICROPY_PY_BUILTINS_INPUT && MICROPY_USE_READLINE == 0 #include diff --git a/ports/windows/Makefile b/ports/windows/Makefile index bb635167da..15fa706acc 100644 --- a/ports/windows/Makefile +++ b/ports/windows/Makefile @@ -75,6 +75,7 @@ OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o)) ifeq ($(MICROPY_USE_READLINE),1) CFLAGS += -DMICROPY_USE_READLINE=1 SRC_C += shared/readline/readline.c +SRC_C += shared/runtime/pyexec.c endif LIB += -lws2_32 diff --git a/ports/windows/micropython.vcxproj b/ports/windows/micropython.vcxproj index 9326f3f4cd..f8bbec82cf 100644 --- a/ports/windows/micropython.vcxproj +++ b/ports/windows/micropython.vcxproj @@ -89,6 +89,7 @@ + diff --git a/shared/runtime/pyexec.c b/shared/runtime/pyexec.c index a305e6a5df..5771b964d0 100644 --- a/shared/runtime/pyexec.c +++ b/shared/runtime/pyexec.c @@ -41,6 +41,7 @@ #endif #include "shared/readline/readline.h" #include "shared/runtime/pyexec.h" +#include "extmod/modplatform.h" #include "genhdr/mpversion.h" pyexec_mode_kind_t pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL; diff --git a/tests/cmdline/repl_autocomplete.py.exp b/tests/cmdline/repl_autocomplete.py.exp index 75002985e3..8cf71bb447 100644 --- a/tests/cmdline/repl_autocomplete.py.exp +++ b/tests/cmdline/repl_autocomplete.py.exp @@ -1,5 +1,5 @@ MicroPython \.\+ version -Use \.\+ +Type "help()" for more information. >>> # tests for autocompletion >>> import sys >>> not_exist. diff --git a/tests/cmdline/repl_autoindent.py.exp b/tests/cmdline/repl_autoindent.py.exp index 9127a7d31d..f45bf840f0 100644 --- a/tests/cmdline/repl_autoindent.py.exp +++ b/tests/cmdline/repl_autoindent.py.exp @@ -1,5 +1,5 @@ MicroPython \.\+ version -Use \.\+ +Type "help()" for more information. >>> # tests for autoindent >>> if 1: ... print(1) diff --git a/tests/cmdline/repl_basic.py.exp b/tests/cmdline/repl_basic.py.exp index 2b390ea98b..a190684743 100644 --- a/tests/cmdline/repl_basic.py.exp +++ b/tests/cmdline/repl_basic.py.exp @@ -1,5 +1,5 @@ MicroPython \.\+ version -Use \.\+ +Type "help()" for more information. >>> # basic REPL tests >>> print(1) 1 diff --git a/tests/cmdline/repl_cont.py.exp b/tests/cmdline/repl_cont.py.exp index 834c18a4d3..d0d20adc49 100644 --- a/tests/cmdline/repl_cont.py.exp +++ b/tests/cmdline/repl_cont.py.exp @@ -1,5 +1,5 @@ MicroPython \.\+ version -Use \.\+ +Type "help()" for more information. >>> # check REPL allows to continue input >>> 1 \\\\ ... + 2 diff --git a/tests/cmdline/repl_emacs_keys.py.exp b/tests/cmdline/repl_emacs_keys.py.exp index 6102c19639..b8b7b794f2 100644 --- a/tests/cmdline/repl_emacs_keys.py.exp +++ b/tests/cmdline/repl_emacs_keys.py.exp @@ -1,5 +1,5 @@ MicroPython \.\+ version -Use \.\+ +Type "help()" for more information. >>> # REPL tests of GNU-ish readline navigation >>> # history buffer navigation >>> 1 diff --git a/tests/cmdline/repl_inspect.py.exp b/tests/cmdline/repl_inspect.py.exp index 051acfd153..89ae142019 100644 --- a/tests/cmdline/repl_inspect.py.exp +++ b/tests/cmdline/repl_inspect.py.exp @@ -1,6 +1,6 @@ test MicroPython \.\+ version -Use \.\+ +Type "help()" for more information. >>> # cmdline: -i -c print("test") >>> # -c option combined with -i option results in REPL >>> diff --git a/tests/cmdline/repl_micropyinspect.py.exp b/tests/cmdline/repl_micropyinspect.py.exp index 93ff43546e..504bb07d7d 100644 --- a/tests/cmdline/repl_micropyinspect.py.exp +++ b/tests/cmdline/repl_micropyinspect.py.exp @@ -1,5 +1,5 @@ MicroPython \.\+ version -Use \.\+ +Type "help()" for more information. >>> # cmdline: cmdline/repl_micropyinspect >>> # setting MICROPYINSPECT environment variable before program exit triggers REPL >>> diff --git a/tests/cmdline/repl_sys_ps1_ps2.py.exp b/tests/cmdline/repl_sys_ps1_ps2.py.exp index 9e82db5e31..6781660bf3 100644 --- a/tests/cmdline/repl_sys_ps1_ps2.py.exp +++ b/tests/cmdline/repl_sys_ps1_ps2.py.exp @@ -1,5 +1,5 @@ MicroPython \.\+ version -Use \.\+ +Type "help()" for more information. >>> # test changing ps1/ps2 >>> import sys >>> sys.ps1 = "PS1" diff --git a/tests/cmdline/repl_words_move.py.exp b/tests/cmdline/repl_words_move.py.exp index 86f6b77889..c4d22a0d9a 100644 --- a/tests/cmdline/repl_words_move.py.exp +++ b/tests/cmdline/repl_words_move.py.exp @@ -1,5 +1,5 @@ MicroPython \.\+ version -Use \.\+ +Type "help()" for more information. >>> # word movement >>> # backward-word, start in word >>> \.\+