-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
unix/main: Use standard pyexec/repl for unix port. #12802
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
8a1a106
00a7e12
b8130f3
dbba59f
0e2f79a
4c1d286
a983716
7b41822
13ddb3a
8244a3d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -54,9 +54,10 @@ | |
#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; | ||
bool mp_compile_only = false; | ||
static uint emit_opt = MP_EMIT_OPT_NONE; | ||
|
||
#if MICROPY_ENABLE_GC | ||
|
@@ -108,72 +109,6 @@ static int handle_uncaught_exception(mp_obj_base_t *exc) { | |
return 1; | ||
} | ||
|
||
#define LEX_SRC_STR (1) | ||
#define LEX_SRC_VSTR (2) | ||
#define LEX_SRC_FILENAME (3) | ||
#define LEX_SRC_STDIN (4) | ||
|
||
// Returns standard error codes: 0 for success, 1 for all other errors, | ||
// except if FORCED_EXIT bit is set then script raised SystemExit and the | ||
// value of the exit is in the lower 8 bits of the return value | ||
static int execute_from_lexer(int source_kind, const void *source, mp_parse_input_kind_t input_kind, bool is_repl) { | ||
mp_hal_set_interrupt_char(CHAR_CTRL_C); | ||
|
||
nlr_buf_t nlr; | ||
if (nlr_push(&nlr) == 0) { | ||
// create lexer based on source kind | ||
mp_lexer_t *lex; | ||
if (source_kind == LEX_SRC_STR) { | ||
const char *line = source; | ||
lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, line, strlen(line), false); | ||
} else if (source_kind == LEX_SRC_VSTR) { | ||
const vstr_t *vstr = source; | ||
lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr->buf, vstr->len, false); | ||
} else if (source_kind == LEX_SRC_FILENAME) { | ||
const char *filename = (const char *)source; | ||
lex = mp_lexer_new_from_file(qstr_from_str(filename)); | ||
} else { // LEX_SRC_STDIN | ||
lex = mp_lexer_new_from_fd(MP_QSTR__lt_stdin_gt_, 0, false); | ||
} | ||
|
||
qstr source_name = lex->source_name; | ||
|
||
#if MICROPY_PY___FILE__ | ||
if (input_kind == MP_PARSE_FILE_INPUT) { | ||
mp_store_global(MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name)); | ||
} | ||
#endif | ||
|
||
mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); | ||
|
||
#if defined(MICROPY_UNIX_COVERAGE) | ||
// allow to print the parse tree in the coverage build | ||
if (mp_verbose_flag >= 3) { | ||
printf("----------------\n"); | ||
mp_parse_node_print(&mp_plat_print, parse_tree.root, 0); | ||
printf("----------------\n"); | ||
} | ||
#endif | ||
|
||
mp_obj_t module_fun = mp_compile(&parse_tree, source_name, is_repl); | ||
|
||
if (!compile_only) { | ||
// execute it | ||
mp_call_function_0(module_fun); | ||
} | ||
|
||
mp_hal_set_interrupt_char(-1); | ||
mp_handle_pending(true); | ||
nlr_pop(); | ||
return 0; | ||
|
||
} else { | ||
// uncaught exception | ||
mp_hal_set_interrupt_char(-1); | ||
mp_handle_pending(false); | ||
return handle_uncaught_exception(nlr.ret_val); | ||
} | ||
} | ||
|
||
#if MICROPY_USE_READLINE == 1 | ||
#include "shared/readline/readline.h" | ||
|
@@ -194,91 +129,27 @@ static char *strjoin(const char *s1, int sep_char, const char *s2) { | |
#endif | ||
|
||
static int do_repl(void) { | ||
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"); | ||
|
||
int ret = 0; | ||
#if MICROPY_USE_READLINE == 1 | ||
|
||
// use MicroPython supplied readline | ||
|
||
vstr_t line; | ||
vstr_init(&line, 16); | ||
// use MicroPython supplied readline based repl | ||
mp_hal_stdio_mode_raw(); | ||
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"); | ||
if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { | ||
if ((ret = pyexec_raw_repl()) != 0) { | ||
break; | ||
} | ||
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; | ||
} | ||
if ((ret = pyexec_friendly_repl()) != 0) { | ||
break; | ||
} | ||
} | ||
|
||
mp_hal_stdio_mode_orig(); | ||
|
||
ret = execute_from_lexer(LEX_SRC_VSTR, &line, parse_input_kind, true); | ||
if (ret & FORCED_EXIT) { | ||
return ret; | ||
} | ||
} | ||
|
||
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"); | ||
|
||
for (;;) { | ||
char *line = prompt((char *)mp_repl_get_ps1()); | ||
|
@@ -297,22 +168,40 @@ static int do_repl(void) { | |
line = line3; | ||
} | ||
|
||
int ret = execute_from_lexer(LEX_SRC_STR, line, MP_PARSE_SINGLE_INPUT, true); | ||
ret = convert_pyexec_result(pyexec_str_single(line, true)); | ||
free(line); | ||
if (ret & FORCED_EXIT) { | ||
return ret; | ||
} | ||
} | ||
|
||
#endif | ||
return ret; | ||
} | ||
|
||
|
||
// Convert pyexec return codes to unix port's expected codes | ||
// pyexec returns 1 for success, 0 for exception, PYEXEC_FORCED_EXIT for SystemExit | ||
// Convert to unix port's expected codes: 0 for success, 1 for exception, FORCED_EXIT|val for SystemExit | ||
static int convert_pyexec_result(int ret) { | ||
if (ret == 1) { | ||
return 0; // success | ||
} else if (ret & PYEXEC_FORCED_EXIT) { | ||
return ret; // SystemExit with exit value in lower 8 bits | ||
} else { | ||
return 1; // exception | ||
} | ||
} | ||
|
||
static int do_file(const char *file) { | ||
return execute_from_lexer(LEX_SRC_FILENAME, file, MP_PARSE_FILE_INPUT, false); | ||
return convert_pyexec_result(pyexec_file(file)); | ||
} | ||
|
||
static int do_str(const char *str) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be possible to replace the Might be worth doing that as part of this PR? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes, I think we should do that and get rid of
Yes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've done this as well now thanks |
||
return execute_from_lexer(LEX_SRC_STR, str, MP_PARSE_FILE_INPUT, false); | ||
vstr_t vstr; | ||
size_t len = strlen(str); | ||
vstr_init_fixed_buf(&vstr, len, (char *)str); | ||
vstr.len = len; | ||
return convert_pyexec_result(pyexec_vstr(&vstr, false)); | ||
} | ||
|
||
static void print_help(char **argv) { | ||
|
@@ -381,7 +270,7 @@ static void pre_process_options(int argc, char **argv) { | |
} | ||
if (0) { | ||
} else if (strcmp(argv[a + 1], "compile-only") == 0) { | ||
compile_only = true; | ||
mp_compile_only = true; | ||
} else if (strcmp(argv[a + 1], "emit=bytecode") == 0) { | ||
emit_opt = MP_EMIT_OPT_BYTECODE; | ||
#if MICROPY_EMIT_NATIVE | ||
|
@@ -753,7 +642,7 @@ MP_NOINLINE int main_(int argc, char **argv) { | |
ret = do_repl(); | ||
prompt_write_history(); | ||
} else { | ||
ret = execute_from_lexer(LEX_SRC_STDIN, NULL, MP_PARSE_FILE_INPUT, false); | ||
ret = convert_pyexec_result(pyexec_stdin()); | ||
} | ||
} | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.