Skip to content

Commit 5b3c928

Browse files
andrewleechdpgeorge
authored andcommitted
unix/main: Use standard pyexec REPL for unix and windows ports.
This improves REPL usage consistency across ports, by utilizing the pyexec code for the unix REPL. Only enabled when MICROPY_USE_READLINE == 1 (the default). Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
1 parent 40df953 commit 5b3c928

25 files changed

+59
-89
lines changed

ports/unix/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ SRC_C += \
220220

221221
SHARED_SRC_C += $(addprefix shared/,\
222222
runtime/gchelper_generic.c \
223+
runtime/pyexec.c \
223224
timeutils/timeutils.c \
224225
$(SHARED_SRC_C_EXTRA) \
225226
)

ports/unix/main.c

Lines changed: 15 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#include "genhdr/mpversion.h"
5656
#include "input.h"
5757
#include "stack_size.h"
58+
#include "shared/runtime/pyexec.h"
5859

5960
// Command line options, with their defaults
6061
static bool compile_only = false;
@@ -195,95 +196,34 @@ static char *strjoin(const char *s1, int sep_char, const char *s2) {
195196
#endif
196197

197198
static int do_repl(void) {
198-
mp_hal_stdout_tx_str(MICROPY_BANNER_NAME_AND_VERSION);
199-
mp_hal_stdout_tx_str("; " MICROPY_BANNER_MACHINE);
200-
mp_hal_stdout_tx_str("\nUse Ctrl-D to exit, Ctrl-E for paste mode\n");
201-
202199
#if MICROPY_USE_READLINE == 1
203200

204-
// use MicroPython supplied readline
201+
// use MicroPython supplied readline-based REPL
205202

206-
vstr_t line;
207-
vstr_init(&line, 16);
203+
int ret = 0;
204+
mp_hal_stdio_mode_raw();
208205
for (;;) {
209-
mp_hal_stdio_mode_raw();
210-
211-
input_restart:
212-
// If the GC is locked at this point there is no way out except a reset,
213-
// so force the GC to be unlocked to help the user debug what went wrong.
214-
MP_STATE_THREAD(gc_lock_depth) = 0;
215-
vstr_reset(&line);
216-
int ret = readline(&line, mp_repl_get_ps1());
217-
mp_parse_input_kind_t parse_input_kind = MP_PARSE_SINGLE_INPUT;
218-
219-
if (ret == CHAR_CTRL_C) {
220-
// cancel input
221-
mp_hal_stdout_tx_str("\r\n");
222-
goto input_restart;
223-
} else if (ret == CHAR_CTRL_D) {
224-
// EOF
225-
printf("\n");
226-
mp_hal_stdio_mode_orig();
227-
vstr_clear(&line);
228-
return 0;
229-
} else if (ret == CHAR_CTRL_E) {
230-
// paste mode
231-
mp_hal_stdout_tx_str("\npaste mode; Ctrl-C to cancel, Ctrl-D to finish\n=== ");
232-
vstr_reset(&line);
233-
for (;;) {
234-
char c = mp_hal_stdin_rx_chr();
235-
if (c == CHAR_CTRL_C) {
236-
// cancel everything
237-
mp_hal_stdout_tx_str("\n");
238-
goto input_restart;
239-
} else if (c == CHAR_CTRL_D) {
240-
// end of input
241-
mp_hal_stdout_tx_str("\n");
242-
break;
243-
} else {
244-
// add char to buffer and echo
245-
vstr_add_byte(&line, c);
246-
if (c == '\r') {
247-
mp_hal_stdout_tx_str("\n=== ");
248-
} else {
249-
mp_hal_stdout_tx_strn(&c, 1);
250-
}
251-
}
252-
}
253-
parse_input_kind = MP_PARSE_FILE_INPUT;
254-
} else if (line.len == 0) {
255-
if (ret != 0) {
256-
printf("\n");
206+
if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
207+
if ((ret = pyexec_raw_repl()) != 0) {
208+
break;
257209
}
258-
goto input_restart;
259210
} else {
260-
// got a line with non-zero length, see if it needs continuing
261-
while (mp_repl_continue_with_input(vstr_null_terminated_str(&line))) {
262-
vstr_add_byte(&line, '\n');
263-
ret = readline(&line, mp_repl_get_ps2());
264-
if (ret == CHAR_CTRL_C) {
265-
// cancel everything
266-
printf("\n");
267-
goto input_restart;
268-
} else if (ret == CHAR_CTRL_D) {
269-
// stop entering compound statement
270-
break;
271-
}
211+
if ((ret = pyexec_friendly_repl()) != 0) {
212+
break;
272213
}
273214
}
274-
275-
mp_hal_stdio_mode_orig();
276-
277-
ret = execute_from_lexer(LEX_SRC_VSTR, &line, parse_input_kind, true);
278-
if (ret & FORCED_EXIT) {
279-
return ret;
280-
}
281215
}
216+
mp_hal_stdio_mode_orig();
217+
return ret;
282218

283219
#else
284220

285221
// use simple readline
286222

223+
mp_hal_stdout_tx_str(MICROPY_BANNER_NAME_AND_VERSION);
224+
mp_hal_stdout_tx_str("; " MICROPY_BANNER_MACHINE);
225+
mp_hal_stdout_tx_str("\nUse Ctrl-D to exit, Ctrl-E for paste mode\n");
226+
287227
for (;;) {
288228
char *line = prompt((char *)mp_repl_get_ps1());
289229
if (line == NULL) {

ports/windows/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o))
8383
ifeq ($(MICROPY_USE_READLINE),1)
8484
CFLAGS += -DMICROPY_USE_READLINE=1
8585
SRC_C += shared/readline/readline.c
86+
SRC_C += shared/runtime/pyexec.c
8687
endif
8788

8889
LIB += -lws2_32

ports/windows/micropython.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
<ClCompile Include="@(PyExtModSource)" />
9090
<ClCompile Include="$(PyBaseDir)shared\readline\*.c" />
9191
<ClCompile Include="$(PyBaseDir)shared\runtime\gchelper_generic.c" />
92+
<ClCompile Include="$(PyBaseDir)shared\runtime\pyexec.c" />
9293
<ClCompile Include="$(PyBaseDir)ports\windows\*.c" />
9394
<ClCompile Include="$(PyBaseDir)ports\windows\msvc\*.c" />
9495
<ClCompile Include="$(PyBaseDir)ports\unix\gccollect.c"/>

shared/runtime/pyexec.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "py/mphal.h"
3838
#include "shared/readline/readline.h"
3939
#include "shared/runtime/pyexec.h"
40+
#include "extmod/modplatform.h"
4041
#include "genhdr/mpversion.h"
4142

4243
pyexec_mode_kind_t pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL;
@@ -103,6 +104,14 @@ static int parse_compile_execute(const void *source, mp_parse_input_kind_t input
103104
// source is a lexer, parse and compile the script
104105
qstr source_name = lex->source_name;
105106
mp_parse_tree_t parse_tree = mp_parse(lex, input_kind);
107+
#if defined(MICROPY_UNIX_COVERAGE)
108+
// allow to print the parse tree in the coverage build
109+
if (mp_verbose_flag >= 3) {
110+
printf("----------------\n");
111+
mp_parse_node_print(&mp_plat_print, parse_tree.root, 0);
112+
printf("----------------\n");
113+
}
114+
#endif
106115
module_fun = mp_compile(&parse_tree, source_name, exec_flags & EXEC_FLAG_IS_REPL);
107116
#else
108117
mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("script compilation not supported"));

tests/cmdline/cmd_sys_exit_0.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# cmdline:
2+
# test sys.exit(0) - success exit code
3+
import sys
4+
5+
sys.exit(0)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# cmdline:
2+
# test sys.exit() functionality and exit codes
3+
import sys
4+
5+
sys.exit(123)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
CRASH

tests/cmdline/cmd_sys_exit_none.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# cmdline:
2+
# test sys.exit(None) - should exit with code 0
3+
import sys
4+
5+
sys.exit(None)

0 commit comments

Comments
 (0)