py: add skeletal import functionality.
This commit is contained in:
parent
261dbf8ce5
commit
db4c361f1c
6
py/bc.h
6
py/bc.h
@ -90,9 +90,9 @@
|
|||||||
#define PYBC_CALL_METHOD_KW (0x98) // uint
|
#define PYBC_CALL_METHOD_KW (0x98) // uint
|
||||||
#define PYBC_CALL_METHOD_VAR_KW (0x99) // uint
|
#define PYBC_CALL_METHOD_VAR_KW (0x99) // uint
|
||||||
|
|
||||||
#define PYBC_IMPORT_NAME (0xe0)
|
#define PYBC_IMPORT_NAME (0xe0) // qstr
|
||||||
#define PYBC_IMPORT_FROM (0xe1)
|
#define PYBC_IMPORT_FROM (0xe1) // qstr
|
||||||
#define PYBC_IMPORT_STAR (0xe2)
|
#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);
|
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);
|
bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t **sp_in_out);
|
||||||
|
29
py/compile.c
29
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) {
|
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)) {
|
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_start);
|
||||||
EMIT(load_const_verbatim_str, "('*',)");
|
EMIT(load_const_verbatim_str, "('*',)");
|
||||||
EMIT(load_const_verbatim_end);
|
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;
|
qstr dummy_q, id1;
|
||||||
do_import_name(comp, pns->nodes[0], &dummy_q, &id1);
|
do_import_name(comp, pns->nodes[0], &dummy_q, &id1);
|
||||||
EMIT(import_star);
|
EMIT(import_star);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
EMIT(load_const_small_int, 0); // level 0 for __import__
|
||||||
|
|
||||||
|
// build the "fromlist" tuple
|
||||||
py_parse_node_t *pn_nodes;
|
py_parse_node_t *pn_nodes;
|
||||||
int n = list_get(&pns->nodes[1], PN_import_as_names, &pn_nodes);
|
int n = list_get(&pns->nodes[1], PN_import_as_names, &pn_nodes);
|
||||||
|
#if MICROPY_EMIT_CPYTHON
|
||||||
EMIT(load_const_small_int, 0); // what's this for??
|
|
||||||
EMIT(load_const_verbatim_start);
|
EMIT(load_const_verbatim_start);
|
||||||
EMIT(load_const_verbatim_str, "(");
|
EMIT(load_const_verbatim_str, "(");
|
||||||
for (int i = 0; i < n; i++) {
|
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_str, ")");
|
||||||
EMIT(load_const_verbatim_end);
|
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;
|
qstr dummy_q, id1;
|
||||||
do_import_name(comp, pns->nodes[0], &dummy_q, &id1);
|
do_import_name(comp, pns->nodes[0], &dummy_q, &id1);
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
|
33
py/runtime.c
33
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
|
// these must correspond to the respective enum
|
||||||
void *const rt_fun_table[RT_F_NUMBER_OF] = {
|
void *const rt_fun_table[RT_F_NUMBER_OF] = {
|
||||||
rt_load_const_dec,
|
rt_load_const_dec,
|
||||||
|
@ -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);
|
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_getiter(py_obj_t o);
|
||||||
py_obj_t rt_iternext(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
|
// temporary way of making C modules
|
||||||
py_obj_t py_module_new(void);
|
py_obj_t py_module_new(void);
|
||||||
|
44
py/vm.c
44
py/vm.c
@ -19,6 +19,8 @@
|
|||||||
#define DECODE_QSTR do { qstr = *ip++; if (qstr > 127) { qstr = ((qstr & 0x3f) << 8) | (*ip++); } } while (0)
|
#define DECODE_QSTR do { qstr = *ip++; if (qstr > 127) { qstr = ((qstr & 0x3f) << 8) | (*ip++); } } while (0)
|
||||||
#define PUSH(val) *--sp = (val)
|
#define PUSH(val) *--sp = (val)
|
||||||
#define POP() (*sp++)
|
#define POP() (*sp++)
|
||||||
|
#define TOP() (*sp)
|
||||||
|
#define SET_TOP(val) *sp = (val)
|
||||||
|
|
||||||
// args are in reverse order in array
|
// 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) {
|
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:
|
case PYBC_LOAD_ATTR:
|
||||||
DECODE_QSTR;
|
DECODE_QSTR;
|
||||||
*sp = rt_load_attr(*sp, qstr);
|
SET_TOP(rt_load_attr(TOP(), qstr));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PYBC_LOAD_METHOD:
|
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;
|
break;
|
||||||
|
|
||||||
case PYBC_DUP_TOP:
|
case PYBC_DUP_TOP:
|
||||||
obj1 = *sp;
|
obj1 = TOP();
|
||||||
PUSH(obj1);
|
PUSH(obj1);
|
||||||
break;
|
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:
|
case PYBC_JUMP_IF_TRUE_OR_POP:
|
||||||
DECODE_SLABEL;
|
DECODE_SLABEL;
|
||||||
if (rt_is_true(*sp)) {
|
if (rt_is_true(TOP())) {
|
||||||
ip += unum;
|
ip += unum;
|
||||||
} else {
|
} else {
|
||||||
sp++;
|
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:
|
case PYBC_JUMP_IF_FALSE_OR_POP:
|
||||||
DECODE_SLABEL;
|
DECODE_SLABEL;
|
||||||
if (rt_is_true(*sp)) {
|
if (rt_is_true(TOP())) {
|
||||||
sp++;
|
sp++;
|
||||||
} else {
|
} else {
|
||||||
ip += unum;
|
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;
|
break;
|
||||||
|
|
||||||
case PYBC_GET_ITER:
|
case PYBC_GET_ITER:
|
||||||
*sp = rt_getiter(*sp);
|
SET_TOP(rt_getiter(TOP()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PYBC_FOR_ITER:
|
case PYBC_FOR_ITER:
|
||||||
DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
|
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) {
|
if (obj1 == py_const_stop_iteration) {
|
||||||
++sp; // pop the exhausted iterator
|
++sp; // pop the exhausted iterator
|
||||||
ip += unum; // jump to after for-block
|
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:
|
case PYBC_UNARY_OP:
|
||||||
unum = *ip++;
|
unum = *ip++;
|
||||||
*sp = rt_unary_op(unum, *sp);
|
SET_TOP(rt_unary_op(unum, TOP()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PYBC_BINARY_OP:
|
case PYBC_BINARY_OP:
|
||||||
unum = *ip++;
|
unum = *ip++;
|
||||||
obj2 = POP();
|
obj2 = POP();
|
||||||
obj1 = *sp;
|
obj1 = TOP();
|
||||||
*sp = rt_binary_op(unum, obj1, obj2);
|
SET_TOP(rt_binary_op(unum, obj1, obj2));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PYBC_COMPARE_OP:
|
case PYBC_COMPARE_OP:
|
||||||
unum = *ip++;
|
unum = *ip++;
|
||||||
obj2 = POP();
|
obj2 = POP();
|
||||||
obj1 = *sp;
|
obj1 = TOP();
|
||||||
*sp = rt_compare_op(unum, obj1, obj2);
|
SET_TOP(rt_compare_op(unum, obj1, obj2));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PYBC_BUILD_TUPLE:
|
case PYBC_BUILD_TUPLE:
|
||||||
DECODE_UINT;
|
DECODE_UINT;
|
||||||
obj1 = rt_build_tuple(unum, sp);
|
obj1 = rt_build_tuple(unum, sp);
|
||||||
sp += unum - 1;
|
sp += unum - 1;
|
||||||
*sp = obj1;
|
SET_TOP(obj1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PYBC_BUILD_LIST:
|
case PYBC_BUILD_LIST:
|
||||||
DECODE_UINT;
|
DECODE_UINT;
|
||||||
obj1 = rt_build_list(unum, sp);
|
obj1 = rt_build_list(unum, sp);
|
||||||
sp += unum - 1;
|
sp += unum - 1;
|
||||||
*sp = obj1;
|
SET_TOP(obj1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PYBC_LIST_APPEND:
|
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;
|
DECODE_UINT;
|
||||||
obj1 = rt_build_set(unum, sp);
|
obj1 = rt_build_set(unum, sp);
|
||||||
sp += unum - 1;
|
sp += unum - 1;
|
||||||
*sp = obj1;
|
SET_TOP(obj1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PYBC_SET_ADD:
|
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);
|
obj1 = rt_call_method_n_kw(unum & 0xff, (unum >> 8) & 0xff, sp);
|
||||||
sp += (unum & 0xff) + ((unum >> 7) & 0x1fe) + 1;
|
sp += (unum & 0xff) + ((unum >> 7) & 0x1fe) + 1;
|
||||||
}
|
}
|
||||||
*sp = obj1;
|
SET_TOP(obj1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PYBC_RETURN_VALUE:
|
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;
|
*sp_in_out = sp;
|
||||||
return true;
|
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:
|
default:
|
||||||
printf("code %p, byte code 0x%02x not implemented\n", ip, op);
|
printf("code %p, byte code 0x%02x not implemented\n", ip, op);
|
||||||
assert(0);
|
assert(0);
|
||||||
|
Loading…
Reference in New Issue
Block a user