summaryrefslogtreecommitdiffstatshomepage
path: root/py
diff options
context:
space:
mode:
Diffstat (limited to 'py')
-rw-r--r--py/builtinevex.c64
-rw-r--r--py/builtinimport.c52
-rw-r--r--py/compile.h3
-rw-r--r--py/runtime.c52
4 files changed, 76 insertions, 95 deletions
diff --git a/py/builtinevex.c b/py/builtinevex.c
index a115ec669e..e24055316e 100644
--- a/py/builtinevex.c
+++ b/py/builtinevex.c
@@ -40,66 +40,34 @@
#include "runtime.h"
#include "builtin.h"
-STATIC mp_obj_t parse_compile_execute(mp_obj_t o_in, mp_parse_input_kind_t parse_input_kind) {
+STATIC mp_obj_t eval_exec_helper(mp_uint_t n_args, const mp_obj_t *args, mp_parse_input_kind_t parse_input_kind) {
mp_uint_t str_len;
- const char *str = mp_obj_str_get_data(o_in, &str_len);
+ const char *str = mp_obj_str_get_data(args[0], &str_len);
// create the lexer
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_string_gt_, str, str_len, 0);
- qstr source_name = mp_lexer_source_name(lex);
- // 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);
- }
-
- mp_lexer_free(lex);
-
- // 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)) {
- nlr_raise(module_fun);
- }
-
- // complied successfully, execute it
- return mp_call_function_0(module_fun);
-}
-
-STATIC mp_obj_t mp_builtin_eval(mp_obj_t o_in) {
- return parse_compile_execute(o_in, MP_PARSE_EVAL_INPUT);
-}
-
-MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_eval_obj, mp_builtin_eval);
-
-STATIC mp_obj_t mp_builtin_exec(uint n_args, const mp_obj_t *args) {
- // Unconditional getting/setting assumes that these operations
- // are cheap, which is the case when this comment was written.
- mp_obj_dict_t *old_globals = mp_globals_get();
- mp_obj_dict_t *old_locals = mp_locals_get();
+ // work out the context
+ mp_obj_dict_t *globals = mp_globals_get();
+ mp_obj_dict_t *locals = mp_locals_get();
if (n_args > 1) {
- mp_obj_t globals = args[1];
- mp_obj_t locals;
+ globals = args[1];
if (n_args > 2) {
locals = args[2];
} else {
locals = globals;
}
- mp_globals_set(globals);
- mp_locals_set(locals);
}
- mp_obj_t res = parse_compile_execute(args[0], MP_PARSE_FILE_INPUT);
- // TODO if the above call throws an exception, then we never get to reset the globals/locals
- mp_globals_set(old_globals);
- mp_locals_set(old_locals);
- return res;
+
+ return mp_parse_compile_execute(lex, parse_input_kind, globals, locals);
+}
+
+STATIC mp_obj_t mp_builtin_eval(mp_uint_t n_args, const mp_obj_t *args) {
+ return eval_exec_helper(n_args, args, MP_PARSE_EVAL_INPUT);
}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_eval_obj, 1, 3, mp_builtin_eval);
+STATIC mp_obj_t mp_builtin_exec(mp_uint_t n_args, const mp_obj_t *args) {
+ return eval_exec_helper(n_args, args, MP_PARSE_FILE_INPUT);
+}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_exec_obj, 1, 3, mp_builtin_exec);
diff --git a/py/builtinimport.c b/py/builtinimport.c
index 04786b2104..ffdadf0227 100644
--- a/py/builtinimport.c
+++ b/py/builtinimport.c
@@ -111,56 +111,14 @@ STATIC void do_load(mp_obj_t module_obj, vstr_t *file) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError, "No module named '%s'", vstr_str(file)));
}
- qstr source_name = mp_lexer_source_name(lex);
-
- // save the old context
- mp_obj_dict_t *old_locals = mp_locals_get();
- mp_obj_dict_t *old_globals = mp_globals_get();
-
- // set the new context
- mp_locals_set(mp_obj_module_get_globals(module_obj));
- mp_globals_set(mp_obj_module_get_globals(module_obj));
#if MICROPY_PY___FILE__
- mp_store_attr(module_obj, MP_QSTR___file__, mp_obj_new_str(vstr_str(file), vstr_len(file), false));
+ qstr source_name = mp_lexer_source_name(lex);
+ mp_store_attr(module_obj, MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name));
#endif
- // parse the imported script
- 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; clean up and raise exception
- mp_obj_t exc = mp_parse_make_exception(lex, parse_error_kind);
- mp_lexer_free(lex);
- mp_locals_set(old_locals);
- mp_globals_set(old_globals);
- nlr_raise(exc);
- }
-
- mp_lexer_free(lex);
-
- // compile the imported script
- mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, false);
-
- if (mp_obj_is_exception_instance(module_fun)) {
- mp_locals_set(old_locals);
- mp_globals_set(old_globals);
- nlr_raise(module_fun);
- }
-
- // complied successfully, execute it
- nlr_buf_t nlr;
- if (nlr_push(&nlr) == 0) {
- mp_call_function_0(module_fun);
- nlr_pop();
- } else {
- // exception; restore context and re-raise same exception
- mp_locals_set(old_locals);
- mp_globals_set(old_globals);
- nlr_raise(nlr.ret_val);
- }
- mp_locals_set(old_locals);
- mp_globals_set(old_globals);
+ // parse, compile and execute the module in its context
+ mp_obj_dict_t *mod_globals = mp_obj_module_get_globals(module_obj);
+ mp_parse_compile_execute(lex, MP_PARSE_FILE_INPUT, mod_globals, mod_globals);
}
mp_obj_t mp_builtin___import__(mp_uint_t n_args, mp_obj_t *args) {
diff --git a/py/compile.h b/py/compile.h
index 983a443e95..cef20efce2 100644
--- a/py/compile.h
+++ b/py/compile.h
@@ -35,3 +35,6 @@ enum {
// 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);
+
+// this is implemented in runtime.c
+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);
diff --git a/py/runtime.c b/py/runtime.c
index c7b95bf7dd..945713d18a 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -24,6 +24,7 @@
* THE SOFTWARE.
*/
+#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
@@ -46,6 +47,9 @@
#include "smallint.h"
#include "objgenerator.h"
#include "lexer.h"
+#include "parse.h"
+#include "parsehelper.h"
+#include "compile.h"
#include "stackctrl.h"
#if 0 // print debugging info
@@ -1153,6 +1157,54 @@ void mp_globals_set(mp_obj_dict_t *d) {
dict_globals = d;
}
+// 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 = mp_lexer_source_name(lex);
+ mp_lexer_free(lex);
+
+ // save context and set new context
+ mp_obj_dict_t *old_globals = mp_globals_get();
+ mp_obj_dict_t *old_locals = mp_locals_get();
+ 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);
+ }
+
+ // complied successfully, execute it
+ nlr_buf_t nlr;
+ if (nlr_push(&nlr) == 0) {
+ mp_obj_t ret = mp_call_function_0(module_fun);
+ nlr_pop();
+ mp_globals_set(old_globals);
+ mp_locals_set(old_locals);
+ return ret;
+ } else {
+ // exception; restore context and re-raise same exception
+ mp_globals_set(old_globals);
+ mp_locals_set(old_locals);
+ nlr_raise(nlr.ret_val);
+ }
+}
+
void *m_malloc_fail(size_t num_bytes) {
DEBUG_printf("memory allocation failed, allocating " UINT_FMT " bytes\n", num_bytes);
nlr_raise((mp_obj_t)&mp_const_MemoryError_obj);