From 0bfc7638baa4c5a4a2351364ab770a188dcab302 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 7 Feb 2015 18:33:58 +0000 Subject: [PATCH] py: Protect mp_parse and mp_compile with nlr push/pop block. To enable parsing constants more efficiently, mp_parse should be allowed to raise an exception, and mp_compile can already raise a MemoryError. So these functions need to be protected by an nlr push/pop block. This patch adds that feature in all places. This allows to simplify how mp_parse and mp_compile are called: they now raise an exception if they have an error and so explicit checking is not needed anymore. --- bare-arm/main.c | 25 ++----------- cc3200/mptask.c | 1 - esp8266/main.c | 1 - minimal/main.c | 26 ++----------- py/compile.c | 2 +- py/compile.h | 1 + py/parse.c | 37 +++++++++++++------ py/parse.h | 12 ++---- py/parsehelper.c | 87 -------------------------------------------- py/parsehelper.h | 36 ------------------ py/py.mk | 1 - py/runtime.c | 54 +++++++++------------------ qemu-arm/main.c | 25 ++----------- qemu-arm/test_main.c | 23 ++---------- stmhal/pyexec.c | 39 ++++---------------- unix-cpy/main.c | 17 +-------- unix/main.c | 77 ++++++++++++++------------------------- 17 files changed, 98 insertions(+), 366 deletions(-) delete mode 100644 py/parsehelper.c delete mode 100644 py/parsehelper.h diff --git a/bare-arm/main.c b/bare-arm/main.c index a1e94313c5..61a43beec1 100644 --- a/bare-arm/main.c +++ b/bare-arm/main.c @@ -3,7 +3,6 @@ #include #include "py/nlr.h" -#include "py/parsehelper.h" #include "py/compile.h" #include "py/runtime.h" #include "py/repl.h" @@ -15,29 +14,11 @@ void do_str(const char *src) { return; } - mp_parse_error_kind_t parse_error_kind; - mp_parse_node_t pn = mp_parse(lex, MP_PARSE_SINGLE_INPUT, &parse_error_kind); - - if (pn == MP_PARSE_NODE_NULL) { - // parse error - mp_parse_show_exception(lex, parse_error_kind); - mp_lexer_free(lex); - return; - } - - // parse okay - qstr source_name = lex->source_name; - mp_lexer_free(lex); - mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, true); - - if (mp_obj_is_exception_instance(module_fun)) { - // compile error - mp_obj_print_exception(printf_wrapper, NULL, module_fun); - return; - } - nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { + qstr source_name = lex->source_name; + mp_parse_node_t pn = mp_parse(lex, MP_PARSE_SINGLE_INPUT); + mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, true); mp_call_function_0(module_fun); nlr_pop(); } else { diff --git a/cc3200/mptask.c b/cc3200/mptask.c index 21067a2138..ed69fb2f23 100644 --- a/cc3200/mptask.c +++ b/cc3200/mptask.c @@ -36,7 +36,6 @@ #include "lexer.h" #include "parse.h" #include "obj.h" -#include "parsehelper.h" #include "compile.h" #include "runtime0.h" #include "runtime.h" diff --git a/esp8266/main.c b/esp8266/main.c index 86f306cbef..b6024f3c57 100644 --- a/esp8266/main.c +++ b/esp8266/main.c @@ -28,7 +28,6 @@ #include #include "py/nlr.h" -#include "py/parsehelper.h" #include "py/compile.h" #include "py/runtime0.h" #include "py/runtime.h" diff --git a/minimal/main.c b/minimal/main.c index d25577d62d..c6c8080ade 100644 --- a/minimal/main.c +++ b/minimal/main.c @@ -3,7 +3,6 @@ #include #include "py/nlr.h" -#include "py/parsehelper.h" #include "py/compile.h" #include "py/runtime.h" #include "py/repl.h" @@ -15,32 +14,15 @@ void do_str(const char *src) { mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); if (lex == NULL) { - return; - } - - mp_parse_error_kind_t parse_error_kind; - mp_parse_node_t pn = mp_parse(lex, MP_PARSE_SINGLE_INPUT, &parse_error_kind); - - if (pn == MP_PARSE_NODE_NULL) { - // parse error - mp_parse_show_exception(lex, parse_error_kind); - mp_lexer_free(lex); - return; - } - - // parse okay - qstr source_name = lex->source_name; - mp_lexer_free(lex); - mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, true); - - if (mp_obj_is_exception_instance(module_fun)) { - // compile error - mp_obj_print_exception(printf_wrapper, NULL, module_fun); + printf("MemoryError: lexer could not allocate memory\n"); return; } nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { + qstr source_name = lex->source_name; + mp_parse_node_t pn = mp_parse(lex, MP_PARSE_SINGLE_INPUT); + mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, true); mp_call_function_0(module_fun); nlr_pop(); } else { diff --git a/py/compile.c b/py/compile.c index 8e4723f230..7023e9c403 100644 --- a/py/compile.c +++ b/py/compile.c @@ -3823,7 +3823,7 @@ mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, uint emit_opt, bool is m_del_obj(compiler_t, comp); if (compile_error != MP_OBJ_NULL) { - return compile_error; + nlr_raise(compile_error); } else { #if MICROPY_EMIT_CPYTHON // can't create code, so just return true diff --git a/py/compile.h b/py/compile.h index 9d612da532..2d15de8b9a 100644 --- a/py/compile.h +++ b/py/compile.h @@ -39,6 +39,7 @@ enum { MP_EMIT_OPT_ASM_THUMB, }; +// the compiler will raise an exception if an error occurred // the compiler will free the parse tree (pn) before it returns mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, uint emit_opt, bool is_repl); diff --git a/py/parse.c b/py/parse.c index 881a11e734..569cf257a7 100644 --- a/py/parse.c +++ b/py/parse.c @@ -30,6 +30,7 @@ #include #include +#include "py/nlr.h" #include "py/lexer.h" #include "py/parse.h" #include "py/parsenum.h" @@ -382,7 +383,7 @@ STATIC void push_result_rule(parser_t *parser, mp_uint_t src_line, const rule_t push_result_node(parser, (mp_parse_node_t)pn); } -mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_parse_error_kind_t *parse_error_kind_out) { +mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) { // initialise parser and allocate memory for its stacks @@ -717,15 +718,15 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p } } - mp_parse_node_t result; + mp_obj_t exc = MP_OBJ_NULL; + mp_parse_node_t result = MP_PARSE_NODE_NULL; // check if we had a memory error if (parser.had_memory_error) { memory_error: - *parse_error_kind_out = MP_PARSE_ERROR_MEMORY; - result = MP_PARSE_NODE_NULL; + exc = mp_obj_new_exception_msg(&mp_type_MemoryError, + "parser could not allocate enough memory"); goto finished; - } // check we are at the end of the token stream @@ -747,17 +748,30 @@ finished: // free the memory that we don't need anymore m_del(rule_stack_t, parser.rule_stack, parser.rule_stack_alloc); m_del(mp_parse_node_t, parser.result_stack, parser.result_stack_alloc); - - // return the result - return result; + // we also free the lexer on behalf of the caller (see below) + + if (exc != MP_OBJ_NULL) { + // had an error so raise the exception + // add traceback to give info about file name and location + // we don't have a 'block' name, so just pass the NULL qstr to indicate this + mp_obj_exception_add_traceback(exc, lex->source_name, lex->tok_line, MP_QSTR_NULL); + mp_lexer_free(lex); + nlr_raise(exc); + } else { + mp_lexer_free(lex); + return result; + } syntax_error: if (lex->tok_kind == MP_TOKEN_INDENT) { - *parse_error_kind_out = MP_PARSE_ERROR_UNEXPECTED_INDENT; + exc = mp_obj_new_exception_msg(&mp_type_IndentationError, + "unexpected indent"); } else if (lex->tok_kind == MP_TOKEN_DEDENT_MISMATCH) { - *parse_error_kind_out = MP_PARSE_ERROR_UNMATCHED_UNINDENT; + exc = mp_obj_new_exception_msg(&mp_type_IndentationError, + "unindent does not match any outer indentation level"); } else { - *parse_error_kind_out = MP_PARSE_ERROR_INVALID_SYNTAX; + exc = mp_obj_new_exception_msg(&mp_type_SyntaxError, + "invalid syntax"); #ifdef USE_RULE_NAME // debugging: print the rule name that failed and the token printf("rule: %s\n", rule->rule_name); @@ -766,6 +780,5 @@ syntax_error: #endif #endif } - result = MP_PARSE_NODE_NULL; goto finished; } diff --git a/py/parse.h b/py/parse.h index 4e7f2b9d19..ee0025a7b2 100644 --- a/py/parse.h +++ b/py/parse.h @@ -90,14 +90,8 @@ typedef enum { MP_PARSE_EVAL_INPUT, } mp_parse_input_kind_t; -typedef enum { - MP_PARSE_ERROR_MEMORY, - MP_PARSE_ERROR_UNEXPECTED_INDENT, - MP_PARSE_ERROR_UNMATCHED_UNINDENT, - MP_PARSE_ERROR_INVALID_SYNTAX, -} mp_parse_error_kind_t; - -// returns MP_PARSE_NODE_NULL on error, and then parse_error_kind_out is valid -mp_parse_node_t mp_parse(struct _mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_parse_error_kind_t *parse_error_kind_out); +// the parser will raise an exception if an error occurred +// the parser will free the lexer before it returns +mp_parse_node_t mp_parse(struct _mp_lexer_t *lex, mp_parse_input_kind_t input_kind); #endif // __MICROPY_INCLUDED_PY_PARSE_H__ diff --git a/py/parsehelper.c b/py/parsehelper.c deleted file mode 100644 index 904268109b..0000000000 --- a/py/parsehelper.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * This file is part of the Micro Python project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -// these functions are separate from parse.c to keep parser independent of mp_obj_t - -#include - -#include "py/parsehelper.h" - -#define STR_MEMORY "parser could not allocate enough memory" -#define STR_UNEXPECTED_INDENT "unexpected indent" -#define STR_UNMATCHED_UNINDENT "unindent does not match any outer indentation level" -#define STR_INVALID_SYNTAX "invalid syntax" - -void mp_parse_show_exception(mp_lexer_t *lex, mp_parse_error_kind_t parse_error_kind) { - printf(" File \"%s\", line " UINT_FMT ", column " UINT_FMT "\n", qstr_str(lex->source_name), lex->tok_line, lex->tok_column); - switch (parse_error_kind) { - case MP_PARSE_ERROR_MEMORY: - printf("MemoryError: %s\n", STR_MEMORY); - break; - - case MP_PARSE_ERROR_UNEXPECTED_INDENT: - printf("IndentationError: %s\n", STR_UNEXPECTED_INDENT); - break; - - case MP_PARSE_ERROR_UNMATCHED_UNINDENT: - printf("IndentationError: %s\n", STR_UNMATCHED_UNINDENT); - break; - - case MP_PARSE_ERROR_INVALID_SYNTAX: - default: - printf("SyntaxError: %s\n", STR_INVALID_SYNTAX); - break; - } -} - -mp_obj_t mp_parse_make_exception(mp_lexer_t *lex, mp_parse_error_kind_t parse_error_kind) { - // make exception object - mp_obj_t exc; - switch (parse_error_kind) { - case MP_PARSE_ERROR_MEMORY: - exc = mp_obj_new_exception_msg(&mp_type_MemoryError, STR_MEMORY); - break; - - case MP_PARSE_ERROR_UNEXPECTED_INDENT: - exc = mp_obj_new_exception_msg(&mp_type_IndentationError, STR_UNEXPECTED_INDENT); - break; - - case MP_PARSE_ERROR_UNMATCHED_UNINDENT: - exc = mp_obj_new_exception_msg(&mp_type_IndentationError, STR_UNMATCHED_UNINDENT); - break; - - case MP_PARSE_ERROR_INVALID_SYNTAX: - default: - exc = mp_obj_new_exception_msg(&mp_type_SyntaxError, STR_INVALID_SYNTAX); - break; - } - - // add traceback to give info about file name and location - // we don't have a 'block' name, so just pass the NULL qstr to indicate this - mp_obj_exception_add_traceback(exc, lex->source_name, lex->tok_line, MP_QSTR_NULL); - - return exc; -} diff --git a/py/parsehelper.h b/py/parsehelper.h deleted file mode 100644 index 1763809bad..0000000000 --- a/py/parsehelper.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * This file is part of the Micro Python project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef __MICROPY_INCLUDED_PY_PARSEHELPER_H__ -#define __MICROPY_INCLUDED_PY_PARSEHELPER_H__ - -#include "py/lexer.h" -#include "py/parse.h" -#include "py/obj.h" - -void mp_parse_show_exception(mp_lexer_t *lex, mp_parse_error_kind_t parse_error_kind); -mp_obj_t mp_parse_make_exception(mp_lexer_t *lex, mp_parse_error_kind_t parse_error_kind); - -#endif // __MICROPY_INCLUDED_PY_PARSEHELPER_H__ diff --git a/py/py.mk b/py/py.mk index 87e8e7141e..6227ad9eb4 100644 --- a/py/py.mk +++ b/py/py.mk @@ -28,7 +28,6 @@ PY_O_BASENAME = \ lexerstr.o \ lexerunix.o \ parse.o \ - parsehelper.o \ scope.o \ compile.o \ emitcommon.o \ diff --git a/py/runtime.c b/py/runtime.c index fc8d128e77..080d061cd1 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -30,7 +30,6 @@ #include "py/mpstate.h" #include "py/nlr.h" -#include "py/parsehelper.h" #include "py/parsenum.h" #include "py/compile.h" #include "py/objtuple.h" @@ -1228,47 +1227,30 @@ void mp_import_all(mp_obj_t module) { // this is implemented in this file so it can optimise access to locals/globals mp_obj_t mp_parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t parse_input_kind, mp_obj_dict_t *globals, mp_obj_dict_t *locals) { - // parse the string - mp_parse_error_kind_t parse_error_kind; - mp_parse_node_t pn = mp_parse(lex, parse_input_kind, &parse_error_kind); - - if (pn == MP_PARSE_NODE_NULL) { - // parse error; raise exception - mp_obj_t exc = mp_parse_make_exception(lex, parse_error_kind); - mp_lexer_free(lex); - nlr_raise(exc); - } - - qstr source_name = lex->source_name; - mp_lexer_free(lex); + // save context + mp_obj_dict_t *volatile old_globals = mp_globals_get(); + mp_obj_dict_t *volatile old_locals = mp_locals_get(); - // save context and set new context - mp_obj_dict_t *old_globals = mp_globals_get(); - mp_obj_dict_t *old_locals = mp_locals_get(); + // set new context mp_globals_set(globals); mp_locals_set(locals); - // compile the string - mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, false); - - // check if there was a compile error - if (mp_obj_is_exception_instance(module_fun)) { - mp_globals_set(old_globals); - mp_locals_set(old_locals); - nlr_raise(module_fun); - } - - // for compile only - if (MICROPY_PY_BUILTINS_COMPILE && globals == NULL) { - mp_globals_set(old_globals); - mp_locals_set(old_locals); - return module_fun; - } - - // complied successfully, execute it nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { - mp_obj_t ret = mp_call_function_0(module_fun); + qstr source_name = lex->source_name; + mp_parse_node_t pn = mp_parse(lex, parse_input_kind); + mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, false); + + mp_obj_t ret; + if (MICROPY_PY_BUILTINS_COMPILE && globals == NULL) { + // for compile only, return value is the module function + ret = module_fun; + } else { + // execute module function and get return value + ret = mp_call_function_0(module_fun); + } + + // finish nlr block, restore context and return value nlr_pop(); mp_globals_set(old_globals); mp_locals_set(old_locals); diff --git a/qemu-arm/main.c b/qemu-arm/main.c index 3750dde453..860014493b 100644 --- a/qemu-arm/main.c +++ b/qemu-arm/main.c @@ -5,7 +5,6 @@ #include "py/nlr.h" #include "py/obj.h" -#include "py/parsehelper.h" #include "py/compile.h" #include "py/runtime0.h" #include "py/runtime.h" @@ -20,29 +19,11 @@ void do_str(const char *src) { return; } - mp_parse_error_kind_t parse_error_kind; - mp_parse_node_t pn = mp_parse(lex, MP_PARSE_SINGLE_INPUT, &parse_error_kind); - - if (pn == MP_PARSE_NODE_NULL) { - // parse error - mp_parse_show_exception(lex, parse_error_kind); - mp_lexer_free(lex); - return; - } - - // parse okay - qstr source_name = lex->source_name; - mp_lexer_free(lex); - mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, true); - - if (mp_obj_is_exception_instance(module_fun)) { - // compile error - mp_obj_print_exception(printf_wrapper, NULL, module_fun); - return; - } - nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { + qstr source_name = lex->source_name; + mp_parse_node_t pn = mp_parse(lex, MP_PARSE_SINGLE_INPUT); + mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, true); mp_call_function_0(module_fun); nlr_pop(); } else { diff --git a/qemu-arm/test_main.c b/qemu-arm/test_main.c index cc4e15357e..d6fbfded6e 100644 --- a/qemu-arm/test_main.c +++ b/qemu-arm/test_main.c @@ -5,7 +5,6 @@ #include "py/nlr.h" #include "py/obj.h" -#include "py/parsehelper.h" #include "py/compile.h" #include "py/runtime0.h" #include "py/runtime.h" @@ -24,27 +23,11 @@ inline void do_str(const char *src) { tt_abort_msg("Lexer initialization error"); } - mp_parse_error_kind_t parse_error_kind; - mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT, &parse_error_kind); - - if (pn == MP_PARSE_NODE_NULL) { - mp_parse_show_exception(lex, parse_error_kind); - mp_lexer_free(lex); - tt_abort_msg("Parser error"); - } - - // parse okay - qstr source_name = lex->source_name; - mp_lexer_free(lex); - mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, true); - - if (mp_obj_is_exception_instance(module_fun)) { - mp_obj_print_exception(printf_wrapper, NULL, module_fun); - tt_abort_msg("Compile error"); - } - nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { + qstr source_name = lex->source_name; + mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT); + mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, true); mp_call_function_0(module_fun); nlr_pop(); } else { diff --git a/stmhal/pyexec.c b/stmhal/pyexec.c index eaad6b5d72..a59df74d6d 100644 --- a/stmhal/pyexec.c +++ b/stmhal/pyexec.c @@ -29,7 +29,6 @@ #include #include "py/nlr.h" -#include "py/parsehelper.h" #include "py/compile.h" #include "py/runtime.h" #include "py/repl.h" @@ -57,39 +56,18 @@ STATIC bool repl_display_debugging_info = 0; // EXEC_FLAG_IS_REPL is used for REPL inputs (flag passed on to mp_compile) STATIC int parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, int exec_flags) { int ret = 0; + uint32_t start = 0; - mp_parse_error_kind_t parse_error_kind; - mp_parse_node_t pn = mp_parse(lex, input_kind, &parse_error_kind); - qstr source_name = lex->source_name; - - // check for parse error - if (pn == MP_PARSE_NODE_NULL) { - if (exec_flags & EXEC_FLAG_PRINT_EOF) { - stdout_tx_strn("\x04", 1); - } - mp_parse_show_exception(lex, parse_error_kind); - mp_lexer_free(lex); - goto finish; - } - - mp_lexer_free(lex); - - mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, exec_flags & EXEC_FLAG_IS_REPL); - - // check for compile error - if (mp_obj_is_exception_instance(module_fun)) { - if (exec_flags & EXEC_FLAG_PRINT_EOF) { - stdout_tx_strn("\x04", 1); - } - mp_obj_print_exception(printf_wrapper, NULL, module_fun); - goto finish; - } - - // execute code nlr_buf_t nlr; - uint32_t start = HAL_GetTick(); if (nlr_push(&nlr) == 0) { + // parse and compile the script + qstr source_name = lex->source_name; + mp_parse_node_t pn = mp_parse(lex, input_kind); + mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, exec_flags & EXEC_FLAG_IS_REPL); + + // execute code mp_hal_set_interrupt_char(CHAR_CTRL_C); // allow ctrl-C to interrupt us + start = HAL_GetTick(); mp_call_function_0(module_fun); mp_hal_set_interrupt_char(-1); // disable interrupt nlr_pop(); @@ -131,7 +109,6 @@ STATIC int parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t input_ki gc_dump_info(); } -finish: if (exec_flags & EXEC_FLAG_PRINT_EOF) { stdout_tx_strn("\x04", 1); } diff --git a/unix-cpy/main.c b/unix-cpy/main.c index 245fc0b17a..e3803b9b3a 100644 --- a/unix-cpy/main.c +++ b/unix-cpy/main.c @@ -30,7 +30,6 @@ #include #include "py/nlr.h" -#include "py/parsehelper.h" #include "py/compile.h" #include "py/runtime.h" #include "py/pfenv.h" @@ -51,17 +50,7 @@ void do_file(const char *file) { } else { // parse - mp_parse_error_kind_t parse_error_kind; - mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT, &parse_error_kind); - - if (pn == MP_PARSE_NODE_NULL) { - // parse error - mp_parse_show_exception(lex, parse_error_kind); - mp_lexer_free(lex); - return; - } - - mp_lexer_free(lex); + mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT); if (pn != MP_PARSE_NODE_NULL) { //printf("----------------\n"); @@ -72,10 +61,6 @@ void do_file(const char *file) { mp_obj_t module_fun = mp_compile(pn, 0, MP_EMIT_OPT_NONE, false); //printf("----------------\n"); - - if (mp_obj_is_exception_instance(module_fun)) { - mp_obj_print_exception(printf_wrapper, NULL, module_fun); - } } } } diff --git a/unix/main.c b/unix/main.c index 899a6f70de..cf8609d9f2 100644 --- a/unix/main.c +++ b/unix/main.c @@ -38,7 +38,6 @@ #include "py/mpstate.h" #include "py/nlr.h" #include "py/compile.h" -#include "py/parsehelper.h" #include "py/runtime.h" #include "py/builtin.h" #include "py/repl.h" @@ -101,55 +100,10 @@ STATIC int handle_uncaught_exception(mp_obj_t exc) { // value of the exit is in the lower 8 bits of the return value STATIC int execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, bool is_repl) { if (lex == NULL) { + printf("MemoryError: lexer could not allocate memory\n"); return 1; } - if (0) { - // just tokenise - while (lex->tok_kind != MP_TOKEN_END) { - mp_lexer_show_token(lex); - mp_lexer_to_next(lex); - } - mp_lexer_free(lex); - return 0; - } - - mp_parse_error_kind_t parse_error_kind; - mp_parse_node_t pn = mp_parse(lex, input_kind, &parse_error_kind); - - if (pn == MP_PARSE_NODE_NULL) { - // parse error - mp_parse_show_exception(lex, parse_error_kind); - mp_lexer_free(lex); - return 1; - } - - 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_lexer_free(lex); - - /* - printf("----------------\n"); - mp_parse_node_print(pn, 0); - printf("----------------\n"); - */ - - mp_obj_t module_fun = mp_compile(pn, source_name, emit_opt, is_repl); - - if (mp_obj_is_exception_instance(module_fun)) { - // compile error - mp_obj_print_exception(printf_wrapper, NULL, module_fun); - return 1; - } - - if (compile_only) { - return 0; - } - #ifndef _WIN32 // enable signal handler struct sigaction sa; @@ -159,18 +113,43 @@ STATIC int execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, sa.sa_handler = SIG_DFL; #endif - // execute it nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { - mp_call_function_0(module_fun); + 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_node_t pn = mp_parse(lex, input_kind); + + /* + printf("----------------\n"); + mp_parse_node_print(pn, 0); + printf("----------------\n"); + */ + + mp_obj_t module_fun = mp_compile(pn, source_name, emit_opt, is_repl); + + if (!compile_only) { + // execute it + mp_call_function_0(module_fun); + } + #ifndef _WIN32 + // disable signal handler sigaction(SIGINT, &sa, NULL); #endif + nlr_pop(); return 0; + } else { // uncaught exception #ifndef _WIN32 + // disable signal handler sigaction(SIGINT, &sa, NULL); #endif return handle_uncaught_exception((mp_obj_t)nlr.ret_val);