From db4c361f1cb805dca8e4c2d6c6a9ac61ae0c9c36 Mon Sep 17 00:00:00 2001 From: Damien Date: Tue, 10 Dec 2013 17:27:24 +0000 Subject: [PATCH] py: add skeletal import functionality. --- py/bc.h | 6 +++--- py/compile.c | 29 ++++++++++++++++++++++++++--- py/runtime.c | 33 +++++++++++++++++++++++++++++++++ py/runtime.h | 2 ++ py/vm.c | 44 +++++++++++++++++++++++++++++--------------- 5 files changed, 93 insertions(+), 21 deletions(-) diff --git a/py/bc.h b/py/bc.h index c29817150e..455d5054f6 100644 --- a/py/bc.h +++ b/py/bc.h @@ -90,9 +90,9 @@ #define PYBC_CALL_METHOD_KW (0x98) // uint #define PYBC_CALL_METHOD_VAR_KW (0x99) // uint -#define PYBC_IMPORT_NAME (0xe0) -#define PYBC_IMPORT_FROM (0xe1) -#define PYBC_IMPORT_STAR (0xe2) +#define PYBC_IMPORT_NAME (0xe0) // qstr +#define PYBC_IMPORT_FROM (0xe1) // qstr +#define PYBC_IMPORT_STAR (0xe2) py_obj_t py_execute_byte_code(const byte *code, const py_obj_t *args, uint n_args, uint n_state); bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t **sp_in_out); diff --git a/py/compile.c b/py/compile.c index f157af49f5..5e86b408c8 100644 --- a/py/compile.c +++ b/py/compile.c @@ -1168,18 +1168,30 @@ void compile_import_name(compiler_t *comp, py_parse_node_struct_t *pns) { void compile_import_from(compiler_t *comp, py_parse_node_struct_t *pns) { if (PY_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], PY_TOKEN_OP_STAR)) { - EMIT(load_const_small_int, 0); // what's this for?? + EMIT(load_const_small_int, 0); // level 0 for __import__ + + // build the "fromlist" tuple +#if MICROPY_EMIT_CPYTHON EMIT(load_const_verbatim_start); EMIT(load_const_verbatim_str, "('*',)"); EMIT(load_const_verbatim_end); +#else + EMIT(load_const_str, qstr_from_str_static("*"), false); + EMIT(build_tuple, 1); +#endif + + // do the import qstr dummy_q, id1; do_import_name(comp, pns->nodes[0], &dummy_q, &id1); EMIT(import_star); + } else { + EMIT(load_const_small_int, 0); // level 0 for __import__ + + // build the "fromlist" tuple py_parse_node_t *pn_nodes; int n = list_get(&pns->nodes[1], PN_import_as_names, &pn_nodes); - - EMIT(load_const_small_int, 0); // what's this for?? +#if MICROPY_EMIT_CPYTHON EMIT(load_const_verbatim_start); EMIT(load_const_verbatim_str, "("); for (int i = 0; i < n; i++) { @@ -1198,6 +1210,17 @@ void compile_import_from(compiler_t *comp, py_parse_node_struct_t *pns) { } EMIT(load_const_verbatim_str, ")"); EMIT(load_const_verbatim_end); +#else + for (int i = 0; i < n; i++) { + assert(PY_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name)); + py_parse_node_struct_t *pns3 = (py_parse_node_struct_t*)pn_nodes[i]; + qstr id2 = PY_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id + EMIT(load_const_str, id2, false); + } + EMIT(build_tuple, n); +#endif + + // do the import qstr dummy_q, id1; do_import_name(comp, pns->nodes[0], &dummy_q, &id1); for (int i = 0; i < n; i++) { diff --git a/py/runtime.c b/py/runtime.c index 55d8405127..df69ddf0dd 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -2216,6 +2216,39 @@ py_obj_t rt_iternext(py_obj_t o_in) { } } +py_obj_t py_builtin___import__(int n, py_obj_t *args) { + printf("import:\n"); + for (int i = 0; i < n; i++) { + printf(" "); + py_obj_print(args[i]); + printf("\n"); + } + return py_const_none; +} + +py_obj_t rt_import_name(qstr name, py_obj_t fromlist, py_obj_t level) { + // build args array + py_obj_t args[5]; + args[0] = py_obj_new_str(name); + args[1] = py_const_none; // TODO should be globals + args[2] = py_const_none; // TODO should be locals + args[3] = fromlist; + args[4] = level; // must be 0; we don't yet support other values + + // TODO lookup __import__ and call that instead of going straight to builtin implementation + return py_builtin___import__(5, args); +} + +py_obj_t rt_import_from(py_obj_t module, qstr name) { + py_obj_t x = rt_load_attr(module, name); + /* TODO convert AttributeError to ImportError + if (fail) { + (ImportError, "cannot import name %s", qstr_str(name), NULL) + } + */ + return x; +} + // these must correspond to the respective enum void *const rt_fun_table[RT_F_NUMBER_OF] = { rt_load_const_dec, diff --git a/py/runtime.h b/py/runtime.h index db16809ec1..c1d1936bf2 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -145,6 +145,8 @@ void rt_store_attr(py_obj_t base, qstr attr, py_obj_t val); void rt_store_subscr(py_obj_t base, py_obj_t index, py_obj_t val); py_obj_t rt_getiter(py_obj_t o); py_obj_t rt_iternext(py_obj_t o); +py_obj_t rt_import_name(qstr name, py_obj_t fromlist, py_obj_t level); +py_obj_t rt_import_from(py_obj_t module, qstr name); // temporary way of making C modules py_obj_t py_module_new(void); diff --git a/py/vm.c b/py/vm.c index 664cca1fb5..fabed0f02e 100644 --- a/py/vm.c +++ b/py/vm.c @@ -19,6 +19,8 @@ #define DECODE_QSTR do { qstr = *ip++; if (qstr > 127) { qstr = ((qstr & 0x3f) << 8) | (*ip++); } } while (0) #define PUSH(val) *--sp = (val) #define POP() (*sp++) +#define TOP() (*sp) +#define SET_TOP(val) *sp = (val) // args are in reverse order in array py_obj_t py_execute_byte_code(const byte *code, const py_obj_t *args, uint n_args, uint n_state) { @@ -130,7 +132,7 @@ bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t ** case PYBC_LOAD_ATTR: DECODE_QSTR; - *sp = rt_load_attr(*sp, qstr); + SET_TOP(rt_load_attr(TOP(), qstr)); break; case PYBC_LOAD_METHOD: @@ -182,7 +184,7 @@ bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t ** break; case PYBC_DUP_TOP: - obj1 = *sp; + obj1 = TOP(); PUSH(obj1); break; @@ -230,7 +232,7 @@ bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t ** case PYBC_JUMP_IF_TRUE_OR_POP: DECODE_SLABEL; - if (rt_is_true(*sp)) { + if (rt_is_true(TOP())) { ip += unum; } else { sp++; @@ -239,7 +241,7 @@ bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t ** case PYBC_JUMP_IF_FALSE_OR_POP: DECODE_SLABEL; - if (rt_is_true(*sp)) { + if (rt_is_true(TOP())) { sp++; } else { ip += unum; @@ -269,12 +271,12 @@ bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t ** break; case PYBC_GET_ITER: - *sp = rt_getiter(*sp); + SET_TOP(rt_getiter(TOP())); break; case PYBC_FOR_ITER: DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward - obj1 = rt_iternext(*sp); + obj1 = rt_iternext(TOP()); if (obj1 == py_const_stop_iteration) { ++sp; // pop the exhausted iterator ip += unum; // jump to after for-block @@ -300,35 +302,35 @@ bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t ** case PYBC_UNARY_OP: unum = *ip++; - *sp = rt_unary_op(unum, *sp); + SET_TOP(rt_unary_op(unum, TOP())); break; case PYBC_BINARY_OP: unum = *ip++; obj2 = POP(); - obj1 = *sp; - *sp = rt_binary_op(unum, obj1, obj2); + obj1 = TOP(); + SET_TOP(rt_binary_op(unum, obj1, obj2)); break; case PYBC_COMPARE_OP: unum = *ip++; obj2 = POP(); - obj1 = *sp; - *sp = rt_compare_op(unum, obj1, obj2); + obj1 = TOP(); + SET_TOP(rt_compare_op(unum, obj1, obj2)); break; case PYBC_BUILD_TUPLE: DECODE_UINT; obj1 = rt_build_tuple(unum, sp); sp += unum - 1; - *sp = obj1; + SET_TOP(obj1); break; case PYBC_BUILD_LIST: DECODE_UINT; obj1 = rt_build_list(unum, sp); sp += unum - 1; - *sp = obj1; + SET_TOP(obj1); break; case PYBC_LIST_APPEND: @@ -359,7 +361,7 @@ bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t ** DECODE_UINT; obj1 = rt_build_set(unum, sp); sp += unum - 1; - *sp = obj1; + SET_TOP(obj1); break; case PYBC_SET_ADD: @@ -400,7 +402,7 @@ bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t ** obj1 = rt_call_method_n_kw(unum & 0xff, (unum >> 8) & 0xff, sp); sp += (unum & 0xff) + ((unum >> 7) & 0x1fe) + 1; } - *sp = obj1; + SET_TOP(obj1); break; case PYBC_RETURN_VALUE: @@ -418,6 +420,18 @@ bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t ** *sp_in_out = sp; return true; + case PYBC_IMPORT_NAME: + DECODE_QSTR; + obj1 = POP(); + SET_TOP(rt_import_name(qstr, obj1, TOP())); + break; + + case PYBC_IMPORT_FROM: + DECODE_QSTR; + obj1 = rt_import_from(TOP(), qstr); + PUSH(obj1); + break; + default: printf("code %p, byte code 0x%02x not implemented\n", ip, op); assert(0);