From d99b05282d14ceb0163cbcd059aa37bdb415af43 Mon Sep 17 00:00:00 2001 From: Damien <damien.p.george@gmail.com> Date: Sat, 21 Dec 2013 18:17:45 +0000 Subject: [PATCH] Change object representation from 1 big union to individual structs. A big change. Micro Python objects are allocated as individual structs with the first element being a pointer to the type information (which is itself an object). This scheme follows CPython. Much more flexible, not necessarily slower, uses same heap memory, and can allocate objects statically. Also change name prefix, from py_ to mp_ (mp for Micro Python). --- py/asmthumb.c | 2 +- py/bc.h | 103 +-- py/bc0.h | 98 +++ py/builtin.c | 321 ++++---- py/builtin.h | 51 +- py/compile.c | 1228 ++++++++++++++--------------- py/compile.h | 2 +- py/emit.h | 6 +- py/emitbc.c | 186 ++--- py/emitcommon.c | 4 +- py/emitcpy.c | 10 +- py/emitinlinethumb.c | 32 +- py/emitnative.c | 30 +- py/emitpass1.c | 4 +- py/gc.c | 2 +- py/lexer.c | 184 ++--- py/lexer.h | 262 +++---- py/map.c | 93 +-- py/map.h | 45 +- py/misc.h | 2 + py/obj.c | 444 +++-------- py/obj.h | 256 +++++- py/objbool.c | 39 + py/objboundmeth.c | 54 ++ py/objcell.c | 43 ++ py/objclass.c | 85 ++ py/objclosure.c | 35 + py/objcomplex.c | 105 +++ py/objdict.c | 80 ++ py/objexcept.c | 86 +++ py/objfloat.c | 85 ++ py/objfun.c | 280 +++++++ py/objgenerator.c | 130 ++++ py/objinstance.c | 109 +++ py/objlist.c | 204 +++++ py/objnone.c | 35 + py/objprivate.h | 140 ---- py/objrange.c | 88 +++ py/objset.c | 58 ++ py/objstr.c | 151 ++++ py/objtuple.c | 133 ++++ py/objtype.c | 23 + py/parse.c | 152 ++-- py/parse.h | 76 +- py/repl.c | 2 +- py/repl.h | 2 +- py/runtime.c | 1246 ++++++++---------------------- py/runtime.h | 190 ++--- py/runtime0.h | 87 +++ py/scope.c | 8 +- py/scope.h | 4 +- py/showbc.c | 123 ++- py/vm.c | 172 +++-- stm/Makefile | 22 +- stm/audio.c | 23 +- stm/lcd.c | 53 +- stm/led.c | 62 ++ stm/led.h | 2 + stm/lexerstm.c | 22 +- stm/lexerstm.h | 8 +- stm/main.c | 451 ++++------- stm/malloc0.c | 2 +- stm/{mpyconfig.h => mpconfig.h} | 1 + stm/pybwlan.c | 77 +- stm/servo.c | 160 ++++ stm/servo.h | 5 + stm/stm32fxxx_it.c | 3 + stm/storage.c | 2 + stm/timer.c | 33 +- unix/Makefile | 25 +- unix/lexerunix.c | 10 +- unix/lexerunix.h | 4 +- unix/main.c | 114 +-- unix/{mpyconfig.h => mpconfig.h} | 1 + 74 files changed, 4805 insertions(+), 3665 deletions(-) create mode 100644 py/bc0.h create mode 100644 py/objbool.c create mode 100644 py/objboundmeth.c create mode 100644 py/objcell.c create mode 100644 py/objclass.c create mode 100644 py/objclosure.c create mode 100644 py/objcomplex.c create mode 100644 py/objdict.c create mode 100644 py/objexcept.c create mode 100644 py/objfloat.c create mode 100644 py/objfun.c create mode 100644 py/objgenerator.c create mode 100644 py/objinstance.c create mode 100644 py/objlist.c create mode 100644 py/objnone.c delete mode 100644 py/objprivate.h create mode 100644 py/objrange.c create mode 100644 py/objset.c create mode 100644 py/objstr.c create mode 100644 py/objtuple.c create mode 100644 py/objtype.c create mode 100644 py/runtime0.h rename stm/{mpyconfig.h => mpconfig.h} (89%) create mode 100644 stm/servo.c create mode 100644 stm/servo.h rename unix/{mpyconfig.h => mpconfig.h} (89%) diff --git a/py/asmthumb.c b/py/asmthumb.c index 602caeb2d..a6fe4be80 100644 --- a/py/asmthumb.c +++ b/py/asmthumb.c @@ -4,7 +4,7 @@ #include <string.h> #include "misc.h" -#include "mpyconfig.h" +#include "mpconfig.h" #include "asmthumb.h" #define UNSIGNED_FIT8(x) (((x) & 0xffffff00) == 0) diff --git a/py/bc.h b/py/bc.h index 6dc1dbbd4..35847f458 100644 --- a/py/bc.h +++ b/py/bc.h @@ -1,101 +1,2 @@ -#define PYBC_LOAD_CONST_FALSE (0x10) -#define PYBC_LOAD_CONST_NONE (0x11) -#define PYBC_LOAD_CONST_TRUE (0x12) -#define PYBC_LOAD_CONST_SMALL_INT (0x13) // 24-bit, in excess -#define PYBC_LOAD_CONST_INT (0x14) // qstr -#define PYBC_LOAD_CONST_DEC (0x15) // qstr -#define PYBC_LOAD_CONST_ID (0x16) // qstr -#define PYBC_LOAD_CONST_BYTES (0x17) // qstr -#define PYBC_LOAD_CONST_STRING (0x18) // qstr - -#define PYBC_LOAD_FAST_0 (0x20) -#define PYBC_LOAD_FAST_1 (0x21) -#define PYBC_LOAD_FAST_2 (0x22) -#define PYBC_LOAD_FAST_N (0x23) // uint -#define PYBC_LOAD_DEREF (0x24) // uint -#define PYBC_LOAD_CLOSURE (0x25) // uint -#define PYBC_LOAD_NAME (0x26) // qstr -#define PYBC_LOAD_GLOBAL (0x27) // qstr -#define PYBC_LOAD_ATTR (0x28) // qstr -#define PYBC_LOAD_METHOD (0x29) // qstr -#define PYBC_LOAD_BUILD_CLASS (0x2a) - -#define PYBC_STORE_FAST_0 (0x30) -#define PYBC_STORE_FAST_1 (0x31) -#define PYBC_STORE_FAST_2 (0x32) -#define PYBC_STORE_FAST_N (0x33) // uint -#define PYBC_STORE_DEREF (0x34) // uint -#define PYBC_STORE_NAME (0x35) // qstr -#define PYBC_STORE_GLOBAL (0x36) // qstr -#define PYBC_STORE_ATTR (0x37) // qstr -#define PYBC_STORE_SUBSCR (0x38) - -#define PYBC_DELETE_FAST_N (0x39) // uint -#define PYBC_DELETE_DEREF (0x3a) // uint -#define PYBC_DELETE_NAME (0x3b) // qstr -#define PYBC_DELETE_GLOBAL (0x3c) // qstr -#define PYBC_DELETE_ATTR (0x3d) // qstr -#define PYBC_DELETE_SUBSCR (0x3e) - -#define PYBC_DUP_TOP (0x40) -#define PYBC_DUP_TOP_TWO (0x41) -#define PYBC_POP_TOP (0x42) -#define PYBC_ROT_TWO (0x43) -#define PYBC_ROT_THREE (0x44) - -#define PYBC_JUMP (0x45) // rel byte code offset, 16-bit signed, in excess -#define PYBC_POP_JUMP_IF_TRUE (0x46) // rel byte code offset, 16-bit signed, in excess -#define PYBC_POP_JUMP_IF_FALSE (0x47) // rel byte code offset, 16-bit signed, in excess -#define PYBC_JUMP_IF_TRUE_OR_POP (0x48) // rel byte code offset, 16-bit signed, in excess -#define PYBC_JUMP_IF_FALSE_OR_POP (0x49) // rel byte code offset, 16-bit signed, in excess -#define PYBC_SETUP_LOOP (0x4a) // rel byte code offset, 16-bit unsigned -#define PYBC_BREAK_LOOP (0x4b) // rel byte code offset, 16-bit unsigned -#define PYBC_CONTINUE_LOOP (0x4c) // rel byte code offset, 16-bit unsigned -#define PYBC_SETUP_WITH (0x4d) // rel byte code offset, 16-bit unsigned -#define PYBC_WITH_CLEANUP (0x4e) -#define PYBC_SETUP_EXCEPT (0x4f) // rel byte code offset, 16-bit unsigned -#define PYBC_SETUP_FINALLY (0x50) // rel byte code offset, 16-bit unsigned -#define PYBC_END_FINALLY (0x51) -#define PYBC_GET_ITER (0x52) -#define PYBC_FOR_ITER (0x53) // rel byte code offset, 16-bit unsigned -#define PYBC_POP_BLOCK (0x54) -#define PYBC_POP_EXCEPT (0x55) - -#define PYBC_UNARY_OP (0x60) // byte -#define PYBC_BINARY_OP (0x61) // byte -#define PYBC_COMPARE_OP (0x62) // byte - -#define PYBC_BUILD_TUPLE (0x70) // uint -#define PYBC_BUILD_LIST (0x71) // uint -#define PYBC_LIST_APPEND (0x72) // uint -#define PYBC_BUILD_MAP (0x73) // uint -#define PYBC_STORE_MAP (0x74) -#define PYBC_MAP_ADD (0x75) // uint -#define PYBC_BUILD_SET (0x76) // uint -#define PYBC_SET_ADD (0x77) // uint -#define PYBC_BUILD_SLICE (0x78) // uint -#define PYBC_UNPACK_SEQUENCE (0x79) // uint -#define PYBC_UNPACK_EX (0x7a) // uint - -#define PYBC_RETURN_VALUE (0x80) -#define PYBC_RAISE_VARARGS (0x81) // uint -#define PYBC_YIELD_VALUE (0x82) -#define PYBC_YIELD_FROM (0x83) - -#define PYBC_MAKE_FUNCTION (0x90) // uint -#define PYBC_MAKE_CLOSURE (0x91) // uint -#define PYBC_CALL_FUNCTION (0x92) // uint -#define PYBC_CALL_FUNCTION_VAR (0x93) // uint -#define PYBC_CALL_FUNCTION_KW (0x94) // uint -#define PYBC_CALL_FUNCTION_VAR_KW (0x95) // uint -#define PYBC_CALL_METHOD (0x96) // uint -#define PYBC_CALL_METHOD_VAR (0x97) // uint -#define PYBC_CALL_METHOD_KW (0x98) // uint -#define PYBC_CALL_METHOD_VAR_KW (0x99) // uint - -#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); +mp_obj_t mp_execute_byte_code(const byte *code, const mp_obj_t *args, uint n_args, uint n_state); +bool mp_execute_byte_code_2(const byte **ip_in_out, mp_obj_t *fastn, mp_obj_t **sp_in_out); diff --git a/py/bc0.h b/py/bc0.h new file mode 100644 index 000000000..e6dc84277 --- /dev/null +++ b/py/bc0.h @@ -0,0 +1,98 @@ +#define MP_BC_LOAD_CONST_FALSE (0x10) +#define MP_BC_LOAD_CONST_NONE (0x11) +#define MP_BC_LOAD_CONST_TRUE (0x12) +#define MP_BC_LOAD_CONST_SMALL_INT (0x13) // 24-bit, in excess +#define MP_BC_LOAD_CONST_INT (0x14) // qstr +#define MP_BC_LOAD_CONST_DEC (0x15) // qstr +#define MP_BC_LOAD_CONST_ID (0x16) // qstr +#define MP_BC_LOAD_CONST_BYTES (0x17) // qstr +#define MP_BC_LOAD_CONST_STRING (0x18) // qstr + +#define MP_BC_LOAD_FAST_0 (0x20) +#define MP_BC_LOAD_FAST_1 (0x21) +#define MP_BC_LOAD_FAST_2 (0x22) +#define MP_BC_LOAD_FAST_N (0x23) // uint +#define MP_BC_LOAD_DEREF (0x24) // uint +#define MP_BC_LOAD_CLOSURE (0x25) // uint +#define MP_BC_LOAD_NAME (0x26) // qstr +#define MP_BC_LOAD_GLOBAL (0x27) // qstr +#define MP_BC_LOAD_ATTR (0x28) // qstr +#define MP_BC_LOAD_METHOD (0x29) // qstr +#define MP_BC_LOAD_BUILD_CLASS (0x2a) + +#define MP_BC_STORE_FAST_0 (0x30) +#define MP_BC_STORE_FAST_1 (0x31) +#define MP_BC_STORE_FAST_2 (0x32) +#define MP_BC_STORE_FAST_N (0x33) // uint +#define MP_BC_STORE_DEREF (0x34) // uint +#define MP_BC_STORE_NAME (0x35) // qstr +#define MP_BC_STORE_GLOBAL (0x36) // qstr +#define MP_BC_STORE_ATTR (0x37) // qstr +#define MP_BC_STORE_SUBSCR (0x38) + +#define MP_BC_DELETE_FAST_N (0x39) // uint +#define MP_BC_DELETE_DEREF (0x3a) // uint +#define MP_BC_DELETE_NAME (0x3b) // qstr +#define MP_BC_DELETE_GLOBAL (0x3c) // qstr +#define MP_BC_DELETE_ATTR (0x3d) // qstr +#define MP_BC_DELETE_SUBSCR (0x3e) + +#define MP_BC_DUP_TOP (0x40) +#define MP_BC_DUP_TOP_TWO (0x41) +#define MP_BC_POP_TOP (0x42) +#define MP_BC_ROT_TWO (0x43) +#define MP_BC_ROT_THREE (0x44) + +#define MP_BC_JUMP (0x45) // rel byte code offset, 16-bit signed, in excess +#define MP_BC_POP_JUMP_IF_TRUE (0x46) // rel byte code offset, 16-bit signed, in excess +#define MP_BC_POP_JUMP_IF_FALSE (0x47) // rel byte code offset, 16-bit signed, in excess +#define MP_BC_JUMP_IF_TRUE_OR_POP (0x48) // rel byte code offset, 16-bit signed, in excess +#define MP_BC_JUMP_IF_FALSE_OR_POP (0x49) // rel byte code offset, 16-bit signed, in excess +#define MP_BC_SETUP_LOOP (0x4a) // rel byte code offset, 16-bit unsigned +#define MP_BC_BREAK_LOOP (0x4b) // rel byte code offset, 16-bit unsigned +#define MP_BC_CONTINUE_LOOP (0x4c) // rel byte code offset, 16-bit unsigned +#define MP_BC_SETUP_WITH (0x4d) // rel byte code offset, 16-bit unsigned +#define MP_BC_WITH_CLEANUP (0x4e) +#define MP_BC_SETUP_EXCEPT (0x4f) // rel byte code offset, 16-bit unsigned +#define MP_BC_SETUP_FINALLY (0x50) // rel byte code offset, 16-bit unsigned +#define MP_BC_END_FINALLY (0x51) +#define MP_BC_GET_ITER (0x52) +#define MP_BC_FOR_ITER (0x53) // rel byte code offset, 16-bit unsigned +#define MP_BC_POP_BLOCK (0x54) +#define MP_BC_POP_EXCEPT (0x55) + +#define MP_BC_UNARY_OP (0x60) // byte +#define MP_BC_BINARY_OP (0x61) // byte +#define MP_BC_COMPARE_OP (0x62) // byte + +#define MP_BC_BUILD_TUPLE (0x70) // uint +#define MP_BC_BUILD_LIST (0x71) // uint +#define MP_BC_LIST_APPEND (0x72) // uint +#define MP_BC_BUILD_MAP (0x73) // uint +#define MP_BC_STORE_MAP (0x74) +#define MP_BC_MAP_ADD (0x75) // uint +#define MP_BC_BUILD_SET (0x76) // uint +#define MP_BC_SET_ADD (0x77) // uint +#define MP_BC_BUILD_SLICE (0x78) // uint +#define MP_BC_UNPACK_SEQUENCE (0x79) // uint +#define MP_BC_UNPACK_EX (0x7a) // uint + +#define MP_BC_RETURN_VALUE (0x80) +#define MP_BC_RAISE_VARARGS (0x81) // uint +#define MP_BC_YIELD_VALUE (0x82) +#define MP_BC_YIELD_FROM (0x83) + +#define MP_BC_MAKE_FUNCTION (0x90) // uint +#define MP_BC_MAKE_CLOSURE (0x91) // uint +#define MP_BC_CALL_FUNCTION (0x92) // uint +#define MP_BC_CALL_FUNCTION_VAR (0x93) // uint +#define MP_BC_CALL_FUNCTION_KW (0x94) // uint +#define MP_BC_CALL_FUNCTION_VAR_KW (0x95) // uint +#define MP_BC_CALL_METHOD (0x96) // uint +#define MP_BC_CALL_METHOD_VAR (0x97) // uint +#define MP_BC_CALL_METHOD_KW (0x98) // uint +#define MP_BC_CALL_METHOD_VAR_KW (0x99) // uint + +#define MP_BC_IMPORT_NAME (0xe0) // qstr +#define MP_BC_IMPORT_FROM (0xe1) // qstr +#define MP_BC_IMPORT_STAR (0xe2) diff --git a/py/builtin.c b/py/builtin.c index e45cdc98b..11e19fdea 100644 --- a/py/builtin.c +++ b/py/builtin.c @@ -7,253 +7,258 @@ #include "nlr.h" #include "misc.h" -#include "mpyconfig.h" +#include "mpconfig.h" +#include "obj.h" +#include "runtime0.h" #include "runtime.h" -#include "bc.h" - +//#include "bc.h" #include "map.h" -#include "obj.h" -#include "objprivate.h" #include "builtin.h" -py_obj_t py_builtin___build_class__(py_obj_t o_class_fun, py_obj_t o_class_name) { +mp_obj_t mp_builtin___build_class__(mp_obj_t o_class_fun, mp_obj_t o_class_name) { // we differ from CPython: we set the new __locals__ object here - py_map_t *old_locals = rt_get_map_locals(); - py_map_t *class_locals = py_map_new(MAP_QSTR, 0); + mp_map_t *old_locals = rt_get_map_locals(); + mp_map_t *class_locals = mp_map_new(MP_MAP_QSTR, 0); rt_set_map_locals(class_locals); // call the class code - rt_call_function_1(o_class_fun, (py_obj_t)0xdeadbeef); + rt_call_function_1(o_class_fun, (mp_obj_t)0xdeadbeef); // restore old __locals__ object rt_set_map_locals(old_locals); // create and return the new class - py_obj_base_t *o = m_new(py_obj_base_t, 1); - o->kind = O_CLASS; - o->u_class.locals = class_locals; - return o; + return mp_obj_new_class(class_locals); } -py_obj_t py_builtin___import__(int n, py_obj_t *args) { +mp_obj_t mp_builtin___import__(int n, mp_obj_t *args) { printf("import:\n"); for (int i = 0; i < n; i++) { printf(" "); - py_obj_print(args[i]); + mp_obj_print(args[i]); printf("\n"); } - return py_const_none; + return mp_const_none; } -py_obj_t py_builtin___repl_print__(py_obj_t o) { - if (o != py_const_none) { - py_obj_print(o); +mp_obj_t mp_builtin___repl_print__(mp_obj_t o) { + if (o != mp_const_none) { + mp_obj_print(o); printf("\n"); } - return py_const_none; + return mp_const_none; } -py_obj_t py_builtin_abs(py_obj_t o_in) { - if (IS_SMALL_INT(o_in)) { - py_small_int_t val = FROM_SMALL_INT(o_in); +mp_obj_t mp_builtin_abs(mp_obj_t o_in) { + if (MP_OBJ_IS_SMALL_INT(o_in)) { + mp_small_int_t val = MP_OBJ_SMALL_INT_VALUE(o_in); if (val < 0) { val = -val; } - return TO_SMALL_INT(val); + return MP_OBJ_NEW_SMALL_INT(val); #if MICROPY_ENABLE_FLOAT - } else if (IS_O(o_in, O_FLOAT)) { - py_obj_base_t *o = o_in; + } else if (MP_OBJ_IS_TYPE(o_in, &float_type)) { + mp_float_t value = mp_obj_float_get(o_in); // TODO check for NaN etc - if (o->u_float < 0) { - return py_obj_new_float(-o->u_float); + if (value < 0) { + return mp_obj_new_float(-value); } else { return o_in; } - } else if (IS_O(o_in, O_COMPLEX)) { - py_obj_base_t *o = o_in; - return py_obj_new_float(machine_sqrt(o->u_complex.real*o->u_complex.real + o->u_complex.imag*o->u_complex.imag)); + } else if (MP_OBJ_IS_TYPE(o_in, &complex_type)) { + mp_float_t real, imag; + mp_obj_complex_get(o_in, &real, &imag); + return mp_obj_new_float(machine_sqrt(real*real + imag*imag)); #endif } else { assert(0); - return py_const_none; + return mp_const_none; } } -py_obj_t py_builtin_all(py_obj_t o_in) { - py_obj_t iterable = rt_getiter(o_in); - py_obj_t item; - while ((item = rt_iternext(iterable)) != py_const_stop_iteration) { +mp_obj_t mp_builtin_all(mp_obj_t o_in) { + mp_obj_t iterable = rt_getiter(o_in); + mp_obj_t item; + while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) { if (!rt_is_true(item)) { - return py_const_false; + return mp_const_false; } } - return py_const_true; + return mp_const_true; } -py_obj_t py_builtin_any(py_obj_t o_in) { - py_obj_t iterable = rt_getiter(o_in); - py_obj_t item; - while ((item = rt_iternext(iterable)) != py_const_stop_iteration) { +mp_obj_t mp_builtin_any(mp_obj_t o_in) { + mp_obj_t iterable = rt_getiter(o_in); + mp_obj_t item; + while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) { if (rt_is_true(item)) { - return py_const_true; + return mp_const_true; } } - return py_const_false; + return mp_const_false; } -py_obj_t py_builtin_bool(int n_args, const py_obj_t *args) { +mp_obj_t mp_builtin_bool(int n_args, const mp_obj_t *args) { switch (n_args) { - case 0: return py_const_false; - case 1: if (rt_is_true(args[0])) { return py_const_true; } else { return py_const_false; } - default: nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "bool() takes at most 1 argument (%d given)", (void*)(machine_int_t)n_args, NULL)); + case 0: return mp_const_false; + case 1: if (rt_is_true(args[0])) { return mp_const_true; } else { return mp_const_false; } + default: nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "bool() takes at most 1 argument (%d given)", (void*)(machine_int_t)n_args)); } } -py_obj_t py_builtin_callable(py_obj_t o_in) { - if (py_obj_is_callable(o_in)) { - return py_const_true; +mp_obj_t mp_builtin_callable(mp_obj_t o_in) { + if (mp_obj_is_callable(o_in)) { + return mp_const_true; } else { - return py_const_false; + return mp_const_false; } } #if MICROPY_ENABLE_FLOAT -py_obj_t py_builtin_complex(int n_args, const py_obj_t *args) { +mp_obj_t mp_builtin_complex(int n_args, const mp_obj_t *args) { switch (n_args) { case 0: - return py_obj_new_complex(0, 0); + return mp_obj_new_complex(0, 0); case 1: // TODO allow string as first arg - if (IS_O(args[0], O_COMPLEX)) { + if (MP_OBJ_IS_TYPE(args[0], &complex_type)) { return args[0]; } else { - return py_obj_new_complex(py_obj_get_float(args[0]), 0); + return mp_obj_new_complex(mp_obj_get_float(args[0]), 0); } case 2: { - py_float_t real, imag; - if (IS_O(args[0], O_COMPLEX)) { - py_obj_get_complex(args[0], &real, &imag); + mp_float_t real, imag; + if (MP_OBJ_IS_TYPE(args[0], &complex_type)) { + mp_obj_get_complex(args[0], &real, &imag); } else { - real = py_obj_get_float(args[0]); + real = mp_obj_get_float(args[0]); imag = 0; } - if (IS_O(args[1], O_COMPLEX)) { - py_float_t real2, imag2; - py_obj_get_complex(args[1], &real2, &imag2); + if (MP_OBJ_IS_TYPE(args[1], &complex_type)) { + mp_float_t real2, imag2; + mp_obj_get_complex(args[1], &real2, &imag2); real -= imag2; imag += real2; } else { - imag += py_obj_get_float(args[1]); + imag += mp_obj_get_float(args[1]); } - return py_obj_new_complex(real, imag); + return mp_obj_new_complex(real, imag); } - default: nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "comlpex() takes at most 2 arguments (%d given)", (void*)(machine_int_t)n_args, NULL)); + default: nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "comlpex() takes at most 2 arguments (%d given)", (void*)(machine_int_t)n_args)); } } #endif -py_obj_t py_builtin_chr(py_obj_t o_in) { - int ord = py_obj_get_int(o_in); +mp_obj_t mp_builtin_chr(mp_obj_t o_in) { + int ord = mp_obj_get_int(o_in); if (0 <= ord && ord <= 0x10ffff) { char *str = m_new(char, 2); str[0] = ord; str[1] = '\0'; - return py_obj_new_str(qstr_from_str_take(str)); + return mp_obj_new_str(qstr_from_str_take(str)); } else { - nlr_jump(py_obj_new_exception_2(rt_q_ValueError, "chr() arg not in range(0x110000)", NULL, NULL)); + nlr_jump(mp_obj_new_exception_msg(rt_q_ValueError, "chr() arg not in range(0x110000)")); } } -py_obj_t py_builtin_dict(void) { +mp_obj_t mp_builtin_dict(void) { // TODO create from an iterable! return rt_build_map(0); } -py_obj_t py_builtin_divmod(py_obj_t o1_in, py_obj_t o2_in) { - if (IS_SMALL_INT(o1_in) && IS_SMALL_INT(o2_in)) { - py_small_int_t i1 = FROM_SMALL_INT(o1_in); - py_small_int_t i2 = FROM_SMALL_INT(o2_in); - py_obj_t revs_args[2]; - revs_args[1] = TO_SMALL_INT(i1 / i2); - revs_args[0] = TO_SMALL_INT(i1 % i2); +mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) { + if (MP_OBJ_IS_SMALL_INT(o1_in) && MP_OBJ_IS_SMALL_INT(o2_in)) { + mp_small_int_t i1 = MP_OBJ_SMALL_INT_VALUE(o1_in); + mp_small_int_t i2 = MP_OBJ_SMALL_INT_VALUE(o2_in); + mp_obj_t revs_args[2]; + revs_args[1] = MP_OBJ_NEW_SMALL_INT(i1 / i2); + revs_args[0] = MP_OBJ_NEW_SMALL_INT(i1 % i2); return rt_build_tuple(2, revs_args); } else { - nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "unsupported operand type(s) for divmod(): '%s' and '%s'", py_obj_get_type_str(o1_in), py_obj_get_type_str(o2_in))); + nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_TypeError, "unsupported operand type(s) for divmod(): '%s' and '%s'", mp_obj_get_type_str(o1_in), mp_obj_get_type_str(o2_in))); } } -py_obj_t py_builtin_hash(py_obj_t o_in) { +static mp_obj_t mp_builtin_hash(mp_obj_t o_in) { // TODO hash will generally overflow small integer; can we safely truncate it? - return py_obj_new_int(py_obj_hash(o_in)); + return mp_obj_new_int(mp_obj_hash(o_in)); } -py_obj_t py_builtin_iter(py_obj_t o_in) { - return rt_getiter(o_in); -} +MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_hash_obj, mp_builtin_hash); -py_obj_t py_builtin_next(py_obj_t o_in) { - return rt_gen_instance_next(o_in); +static mp_obj_t mp_builtin_iter(mp_obj_t o_in) { + return rt_getiter(o_in); } -py_obj_t py_builtin_len(py_obj_t o_in) { - py_small_int_t len = 0; - if (IS_O(o_in, O_STR)) { - py_obj_base_t *o = o_in; - len = strlen(qstr_str(o->u_str)); - } else if (IS_O(o_in, O_TUPLE) || IS_O(o_in, O_LIST)) { - py_obj_base_t *o = o_in; - len = o->u_tuple_list.len; - } else if (IS_O(o_in, O_MAP)) { - py_obj_base_t *o = o_in; +MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_iter_obj, mp_builtin_iter); + +mp_obj_t mp_builtin_len(mp_obj_t o_in) { + mp_small_int_t len = 0; + if (MP_OBJ_IS_TYPE(o_in, &str_type)) { + len = strlen(qstr_str(mp_obj_str_get(o_in))); + } else if (MP_OBJ_IS_TYPE(o_in, &tuple_type)) { + uint seq_len; + mp_obj_t *seq_items; + mp_obj_tuple_get(o_in, &seq_len, &seq_items); + len = seq_len; + } else if (MP_OBJ_IS_TYPE(o_in, &list_type)) { + uint seq_len; + mp_obj_t *seq_items; + mp_obj_list_get(o_in, &seq_len, &seq_items); + len = seq_len; + /* TODO + } else if (MP_OBJ_IS_TYPE(o_in, &dict_type)) { + mp_obj_base_t *o = o_in; len = o->u_map.used; + */ } else { - nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "object of type '%s' has no len()", py_obj_get_type_str(o_in), NULL)); + nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "object of type '%s' has no len()", mp_obj_get_type_str(o_in))); } - return TO_SMALL_INT(len); + return MP_OBJ_NEW_SMALL_INT(len); } -py_obj_t py_builtin_list(int n_args, const py_obj_t *args) { +mp_obj_t mp_builtin_list(int n_args, const mp_obj_t *args) { switch (n_args) { case 0: return rt_build_list(0, NULL); case 1: { // make list from iterable - py_obj_t iterable = rt_getiter(args[0]); - py_obj_t list = rt_build_list(0, NULL); - py_obj_t item; - while ((item = rt_iternext(iterable)) != py_const_stop_iteration) { + mp_obj_t iterable = rt_getiter(args[0]); + mp_obj_t list = rt_build_list(0, NULL); + mp_obj_t item; + while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) { rt_list_append(list, item); } return list; } - default: nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "list() takes at most 1 argument (%d given)", (void*)(machine_int_t)n_args, NULL)); + default: nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "list() takes at most 1 argument (%d given)", (void*)(machine_int_t)n_args)); } } -py_obj_t py_builtin_max(int n_args, const py_obj_t *args) { +mp_obj_t mp_builtin_max(int n_args, const mp_obj_t *args) { if (n_args == 1) { // given an iterable - py_obj_t iterable = rt_getiter(args[0]); - py_obj_t max_obj = NULL; - py_obj_t item; - while ((item = rt_iternext(iterable)) != py_const_stop_iteration) { - if (max_obj == NULL || py_obj_less(max_obj, item)) { + mp_obj_t iterable = rt_getiter(args[0]); + mp_obj_t max_obj = NULL; + mp_obj_t item; + while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) { + if (max_obj == NULL || mp_obj_less(max_obj, item)) { max_obj = item; } } if (max_obj == NULL) { - nlr_jump(py_obj_new_exception_2(rt_q_ValueError, "max() arg is an empty sequence", NULL, NULL)); + nlr_jump(mp_obj_new_exception_msg(rt_q_ValueError, "max() arg is an empty sequence")); } return max_obj; } else { // given many args - py_obj_t max_obj = args[0]; + mp_obj_t max_obj = args[0]; for (int i = 1; i < n_args; i++) { - if (py_obj_less(max_obj, args[i])) { + if (mp_obj_less(max_obj, args[i])) { max_obj = args[i]; } } @@ -261,26 +266,26 @@ py_obj_t py_builtin_max(int n_args, const py_obj_t *args) { } } -py_obj_t py_builtin_min(int n_args, const py_obj_t *args) { +mp_obj_t mp_builtin_min(int n_args, const mp_obj_t *args) { if (n_args == 1) { // given an iterable - py_obj_t iterable = rt_getiter(args[0]); - py_obj_t min_obj = NULL; - py_obj_t item; - while ((item = rt_iternext(iterable)) != py_const_stop_iteration) { - if (min_obj == NULL || py_obj_less(item, min_obj)) { + mp_obj_t iterable = rt_getiter(args[0]); + mp_obj_t min_obj = NULL; + mp_obj_t item; + while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) { + if (min_obj == NULL || mp_obj_less(item, min_obj)) { min_obj = item; } } if (min_obj == NULL) { - nlr_jump(py_obj_new_exception_2(rt_q_ValueError, "min() arg is an empty sequence", NULL, NULL)); + nlr_jump(mp_obj_new_exception_msg(rt_q_ValueError, "min() arg is an empty sequence")); } return min_obj; } else { // given many args - py_obj_t min_obj = args[0]; + mp_obj_t min_obj = args[0]; for (int i = 1; i < n_args; i++) { - if (py_obj_less(args[i], min_obj)) { + if (mp_obj_less(args[i], min_obj)) { min_obj = args[i]; } } @@ -288,59 +293,85 @@ py_obj_t py_builtin_min(int n_args, const py_obj_t *args) { } } -py_obj_t py_builtin_ord(py_obj_t o_in) { - const char *str = qstr_str(py_obj_get_qstr(o_in)); +static mp_obj_t mp_builtin_next(mp_obj_t o_in) { + return mp_obj_gen_instance_next(o_in); +} + +MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_next_obj, mp_builtin_next); + +mp_obj_t mp_builtin_ord(mp_obj_t o_in) { + const char *str = qstr_str(mp_obj_get_qstr(o_in)); if (strlen(str) == 1) { - return py_obj_new_int(str[0]); + return mp_obj_new_int(str[0]); } else { - nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "ord() expected a character, but string of length %d found", (void*)(machine_int_t)strlen(str), NULL)); + nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "ord() expected a character, but string of length %d found", (void*)(machine_int_t)strlen(str))); } } -py_obj_t py_builtin_pow(int n_args, const py_obj_t *args) { +mp_obj_t mp_builtin_pow(int n_args, const mp_obj_t *args) { switch (n_args) { case 2: return rt_binary_op(RT_BINARY_OP_POWER, args[0], args[1]); case 3: return rt_binary_op(RT_BINARY_OP_MODULO, rt_binary_op(RT_BINARY_OP_POWER, args[0], args[1]), args[2]); // TODO optimise... - default: nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "pow expected at most 3 arguments, got %d", (void*)(machine_int_t)n_args, NULL)); + default: nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "pow expected at most 3 arguments, got %d", (void*)(machine_int_t)n_args)); } } -py_obj_t py_builtin_print(int n_args, const py_obj_t *args) { +mp_obj_t mp_builtin_print(int n_args, const mp_obj_t *args) { for (int i = 0; i < n_args; i++) { if (i > 0) { printf(" "); } - if (IS_O(args[i], O_STR)) { + if (MP_OBJ_IS_TYPE(args[i], &str_type)) { // special case, print string raw - printf("%s", qstr_str(((py_obj_base_t*)args[i])->u_str)); + printf("%s", qstr_str(mp_obj_str_get(args[i]))); } else { // print the object Python style - py_obj_print(args[i]); + mp_obj_print(args[i]); } } printf("\n"); - return py_const_none; + return mp_const_none; } -py_obj_t py_builtin_range(int n_args, const py_obj_t *args) { +mp_obj_t mp_builtin_range(int n_args, const mp_obj_t *args) { switch (n_args) { - case 1: return py_obj_new_range(0, py_obj_get_int(args[0]), 1); - case 2: return py_obj_new_range(py_obj_get_int(args[0]), py_obj_get_int(args[1]), 1); - case 3: return py_obj_new_range(py_obj_get_int(args[0]), py_obj_get_int(args[1]), py_obj_get_int(args[2])); - default: nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "range expected at most 3 arguments, got %d", (void*)(machine_int_t)n_args, NULL)); + case 1: return mp_obj_new_range(0, mp_obj_get_int(args[0]), 1); + case 2: return mp_obj_new_range(mp_obj_get_int(args[0]), mp_obj_get_int(args[1]), 1); + case 3: return mp_obj_new_range(mp_obj_get_int(args[0]), mp_obj_get_int(args[1]), mp_obj_get_int(args[2])); + default: nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "range expected at most 3 arguments, got %d", (void*)(machine_int_t)n_args)); + } +} + +static mp_obj_t mp_builtin_set(int n_args, const mp_obj_t *args) { + assert(0 <= n_args && n_args <= 1); + + if (n_args == 0) { + // return a new, empty set + return mp_obj_new_set(0, NULL); + } else { + // 1 argument, an iterable from which we make a new set + mp_obj_t set = mp_obj_new_set(0, NULL); + mp_obj_t iterable = rt_getiter(args[0]); + mp_obj_t item; + while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) { + mp_obj_set_store(set, item); + } + return set; } } -py_obj_t py_builtin_sum(int n_args, const py_obj_t *args) { - py_obj_t value; +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_set_obj, 0, 1, mp_builtin_set); + +mp_obj_t mp_builtin_sum(int n_args, const mp_obj_t *args) { + mp_obj_t value; switch (n_args) { - case 1: value = py_obj_new_int(0); break; + case 1: value = mp_obj_new_int(0); break; case 2: value = args[1]; break; - default: nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "sum expected at most 2 arguments, got %d", (void*)(machine_int_t)n_args, NULL)); + default: nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "sum expected at most 2 arguments, got %d", (void*)(machine_int_t)n_args)); } - py_obj_t iterable = rt_getiter(args[0]); - py_obj_t item; - while ((item = rt_iternext(iterable)) != py_const_stop_iteration) { + mp_obj_t iterable = rt_getiter(args[0]); + mp_obj_t item; + while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) { value = rt_binary_op(RT_BINARY_OP_ADD, value, item); } return value; diff --git a/py/builtin.h b/py/builtin.h index 0a0470a84..c164a7661 100644 --- a/py/builtin.h +++ b/py/builtin.h @@ -1,24 +1,27 @@ -py_obj_t py_builtin___build_class__(py_obj_t o_class_fun, py_obj_t o_class_name); -py_obj_t py_builtin___import__(int n, py_obj_t *args); -py_obj_t py_builtin___repl_print__(py_obj_t o); -py_obj_t py_builtin_abs(py_obj_t o_in); -py_obj_t py_builtin_all(py_obj_t o_in); -py_obj_t py_builtin_any(py_obj_t o_in); -py_obj_t py_builtin_bool(int n_args, const py_obj_t *args); -py_obj_t py_builtin_callable(py_obj_t o_in); -py_obj_t py_builtin_complex(int n_args, const py_obj_t *args); -py_obj_t py_builtin_chr(py_obj_t o_in); -py_obj_t py_builtin_dict(void); -py_obj_t py_builtin_divmod(py_obj_t o1_in, py_obj_t o2_in); -py_obj_t py_builtin_hash(py_obj_t o_in); -py_obj_t py_builtin_iter(py_obj_t o_in); -py_obj_t py_builtin_len(py_obj_t o_in); -py_obj_t py_builtin_list(int n_args, const py_obj_t *args); -py_obj_t py_builtin_max(int n_args, const py_obj_t *args); -py_obj_t py_builtin_min(int n_args, const py_obj_t *args); -py_obj_t py_builtin_next(py_obj_t o_in); -py_obj_t py_builtin_ord(py_obj_t o_in); -py_obj_t py_builtin_pow(int n_args, const py_obj_t *args); -py_obj_t py_builtin_print(int n_args, const py_obj_t *args); -py_obj_t py_builtin_range(int n_args, const py_obj_t *args); -py_obj_t py_builtin_sum(int n_args, const py_obj_t *args); +// TODO convert all these to objects using MP_DECLARE and MP_DEFINE + +mp_obj_t mp_builtin___build_class__(mp_obj_t o_class_fun, mp_obj_t o_class_name); +mp_obj_t mp_builtin___import__(int n, mp_obj_t *args); +mp_obj_t mp_builtin___repl_print__(mp_obj_t o); +mp_obj_t mp_builtin_abs(mp_obj_t o_in); +mp_obj_t mp_builtin_all(mp_obj_t o_in); +mp_obj_t mp_builtin_any(mp_obj_t o_in); +mp_obj_t mp_builtin_bool(int n_args, const mp_obj_t *args); +mp_obj_t mp_builtin_callable(mp_obj_t o_in); +mp_obj_t mp_builtin_complex(int n_args, const mp_obj_t *args); +mp_obj_t mp_builtin_chr(mp_obj_t o_in); +mp_obj_t mp_builtin_dict(void); +mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in); +MP_DECLARE_CONST_FUN_OBJ(mp_builtin_hash_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_builtin_iter_obj); +mp_obj_t mp_builtin_len(mp_obj_t o_in); +mp_obj_t mp_builtin_list(int n_args, const mp_obj_t *args); +mp_obj_t mp_builtin_max(int n_args, const mp_obj_t *args); +mp_obj_t mp_builtin_min(int n_args, const mp_obj_t *args); +MP_DECLARE_CONST_FUN_OBJ(mp_builtin_next_obj); +mp_obj_t mp_builtin_ord(mp_obj_t o_in); +mp_obj_t mp_builtin_pow(int n_args, const mp_obj_t *args); +mp_obj_t mp_builtin_print(int n_args, const mp_obj_t *args); +mp_obj_t mp_builtin_range(int n_args, const mp_obj_t *args); +MP_DECLARE_CONST_FUN_OBJ(mp_builtin_set_obj); +mp_obj_t mp_builtin_sum(int n_args, const mp_obj_t *args); diff --git a/py/compile.c b/py/compile.c index 42bac7d28..38f14155d 100644 --- a/py/compile.c +++ b/py/compile.c @@ -6,12 +6,12 @@ #include <assert.h> #include "misc.h" -#include "mpyconfig.h" +#include "mpconfig.h" #include "lexer.h" #include "parse.h" #include "scope.h" #include "compile.h" -#include "runtime.h" +#include "runtime0.h" #include "emit.h" // TODO need to mangle __attr names @@ -78,28 +78,28 @@ typedef struct _compiler_t { const emit_inline_asm_method_table_t *emit_inline_asm_method_table; // current emit method table for inline asm } compiler_t; -py_parse_node_t fold_constants(py_parse_node_t pn) { - if (PY_PARSE_NODE_IS_STRUCT(pn)) { - py_parse_node_struct_t *pns = (py_parse_node_struct_t*)pn; - int n = PY_PARSE_NODE_STRUCT_NUM_NODES(pns); +mp_parse_node_t fold_constants(mp_parse_node_t pn) { + if (MP_PARSE_NODE_IS_STRUCT(pn)) { + mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; + int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); // fold arguments first for (int i = 0; i < n; i++) { pns->nodes[i] = fold_constants(pns->nodes[i]); } - switch (PY_PARSE_NODE_STRUCT_KIND(pns)) { + switch (MP_PARSE_NODE_STRUCT_KIND(pns)) { case PN_shift_expr: - if (n == 3 && PY_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && PY_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) { - int arg0 = PY_PARSE_NODE_LEAF_ARG(pns->nodes[0]); - int arg1 = PY_PARSE_NODE_LEAF_ARG(pns->nodes[2]); - if (PY_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], PY_TOKEN_OP_DBL_LESS)) { + if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) { + int arg0 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); + int arg1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[2]); + if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_LESS)) { #if MICROPY_EMIT_CPYTHON // can overflow; enabled only to compare with CPython - pn = py_parse_node_new_leaf(PY_PARSE_NODE_SMALL_INT, arg0 << arg1); + pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 << arg1); #endif - } else if (PY_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], PY_TOKEN_OP_DBL_MORE)) { - pn = py_parse_node_new_leaf(PY_PARSE_NODE_SMALL_INT, arg0 >> arg1); + } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_MORE)) { + pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 >> arg1); } else { // shouldn't happen assert(0); @@ -109,42 +109,42 @@ py_parse_node_t fold_constants(py_parse_node_t pn) { case PN_arith_expr: // overflow checking here relies on SMALL_INT being strictly smaller than machine_int_t - if (n == 3 && PY_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && PY_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) { - machine_int_t arg0 = PY_PARSE_NODE_LEAF_ARG(pns->nodes[0]); - machine_int_t arg1 = PY_PARSE_NODE_LEAF_ARG(pns->nodes[2]); + if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) { + machine_int_t arg0 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); + machine_int_t arg1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[2]); machine_int_t res; - if (PY_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], PY_TOKEN_OP_PLUS)) { + if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PLUS)) { res = arg0 + arg1; - } else if (PY_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], PY_TOKEN_OP_MINUS)) { + } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_MINUS)) { res = arg0 - arg1; } else { // shouldn't happen assert(0); res = 0; } - if (PY_FIT_SMALL_INT(res)) { - pn = py_parse_node_new_leaf(PY_PARSE_NODE_SMALL_INT, res); + if (MP_FIT_SMALL_INT(res)) { + pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, res); } } break; case PN_term: - if (n == 3 && PY_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && PY_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) { - int arg0 = PY_PARSE_NODE_LEAF_ARG(pns->nodes[0]); - int arg1 = PY_PARSE_NODE_LEAF_ARG(pns->nodes[2]); - if (PY_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], PY_TOKEN_OP_STAR)) { + if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) { + int arg0 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); + int arg1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[2]); + if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) { #if MICROPY_EMIT_CPYTHON // can overflow; enabled only to compare with CPython - pn = py_parse_node_new_leaf(PY_PARSE_NODE_SMALL_INT, arg0 * arg1); + pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 * arg1); #endif - } else if (PY_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], PY_TOKEN_OP_SLASH)) { + } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_SLASH)) { ; // pass - } else if (PY_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], PY_TOKEN_OP_PERCENT)) { + } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PERCENT)) { // XXX implement this properly as Python's % operator acts differently to C's - pn = py_parse_node_new_leaf(PY_PARSE_NODE_SMALL_INT, arg0 % arg1); - } else if (PY_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], PY_TOKEN_OP_DBL_SLASH)) { + pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 % arg1); + } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_SLASH)) { // XXX implement this properly as Python's // operator acts differently to C's - pn = py_parse_node_new_leaf(PY_PARSE_NODE_SMALL_INT, arg0 / arg1); + pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 / arg1); } else { // shouldn't happen assert(0); @@ -153,14 +153,14 @@ py_parse_node_t fold_constants(py_parse_node_t pn) { break; case PN_factor_2: - if (PY_PARSE_NODE_IS_SMALL_INT(pns->nodes[1])) { - machine_int_t arg = PY_PARSE_NODE_LEAF_ARG(pns->nodes[1]); - if (PY_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], PY_TOKEN_OP_PLUS)) { - pn = py_parse_node_new_leaf(PY_PARSE_NODE_SMALL_INT, arg); - } else if (PY_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], PY_TOKEN_OP_MINUS)) { - pn = py_parse_node_new_leaf(PY_PARSE_NODE_SMALL_INT, -arg); - } else if (PY_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], PY_TOKEN_OP_TILDE)) { - pn = py_parse_node_new_leaf(PY_PARSE_NODE_SMALL_INT, ~arg); + if (MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[1])) { + machine_int_t arg = MP_PARSE_NODE_LEAF_ARG(pns->nodes[1]); + if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_PLUS)) { + pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg); + } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_MINUS)) { + pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, -arg); + } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_TILDE)) { + pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, ~arg); } else { // shouldn't happen assert(0); @@ -171,17 +171,17 @@ py_parse_node_t fold_constants(py_parse_node_t pn) { #if MICROPY_EMIT_CPYTHON case PN_power: // can overflow; enabled only to compare with CPython - if (PY_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && PY_PARSE_NODE_IS_NULL(pns->nodes[1]) && !PY_PARSE_NODE_IS_NULL(pns->nodes[2])) { - py_parse_node_struct_t* pns2 = (py_parse_node_struct_t*)pns->nodes[2]; - if (PY_PARSE_NODE_IS_SMALL_INT(pns2->nodes[0])) { - int power = PY_PARSE_NODE_LEAF_ARG(pns2->nodes[0]); + if (MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_NULL(pns->nodes[1]) && !MP_PARSE_NODE_IS_NULL(pns->nodes[2])) { + mp_parse_node_struct_t* pns2 = (mp_parse_node_struct_t*)pns->nodes[2]; + if (MP_PARSE_NODE_IS_SMALL_INT(pns2->nodes[0])) { + int power = MP_PARSE_NODE_LEAF_ARG(pns2->nodes[0]); if (power >= 0) { int ans = 1; - int base = PY_PARSE_NODE_LEAF_ARG(pns->nodes[0]); + int base = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); for (; power > 0; power--) { ans *= base; } - pn = py_parse_node_new_leaf(PY_PARSE_NODE_SMALL_INT, ans); + pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, ans); } } } @@ -193,13 +193,13 @@ py_parse_node_t fold_constants(py_parse_node_t pn) { return pn; } -void compile_node(compiler_t *comp, py_parse_node_t pn); +void compile_node(compiler_t *comp, mp_parse_node_t pn); static int comp_next_label(compiler_t *comp) { return comp->next_label++; } -static scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, py_parse_node_t pn, uint emit_options) { +static scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, mp_parse_node_t pn, uint emit_options) { scope_t *scope = scope_new(kind, pn, rt_get_unique_code_id(kind == SCOPE_MODULE), emit_options); scope->parent = comp->scope_cur; scope->next = NULL; @@ -215,68 +215,68 @@ static scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, py_parse return scope; } -static int list_len(py_parse_node_t pn, int pn_kind) { - if (PY_PARSE_NODE_IS_NULL(pn)) { +static int list_len(mp_parse_node_t pn, int pn_kind) { + if (MP_PARSE_NODE_IS_NULL(pn)) { return 0; - } else if (PY_PARSE_NODE_IS_LEAF(pn)) { + } else if (MP_PARSE_NODE_IS_LEAF(pn)) { return 1; } else { - py_parse_node_struct_t *pns = (py_parse_node_struct_t*)pn; - if (PY_PARSE_NODE_STRUCT_KIND(pns) != pn_kind) { + mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; + if (MP_PARSE_NODE_STRUCT_KIND(pns) != pn_kind) { return 1; } else { - return PY_PARSE_NODE_STRUCT_NUM_NODES(pns); + return MP_PARSE_NODE_STRUCT_NUM_NODES(pns); } } } -static void apply_to_single_or_list(compiler_t *comp, py_parse_node_t pn, int pn_list_kind, void (*f)(compiler_t*, py_parse_node_t)) { - if (PY_PARSE_NODE_IS_STRUCT(pn) && PY_PARSE_NODE_STRUCT_KIND((py_parse_node_struct_t*)pn) == pn_list_kind) { - py_parse_node_struct_t *pns = (py_parse_node_struct_t*)pn; - int num_nodes = PY_PARSE_NODE_STRUCT_NUM_NODES(pns); +static void apply_to_single_or_list(compiler_t *comp, mp_parse_node_t pn, int pn_list_kind, void (*f)(compiler_t*, mp_parse_node_t)) { + if (MP_PARSE_NODE_IS_STRUCT(pn) && MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn) == pn_list_kind) { + mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; + int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); for (int i = 0; i < num_nodes; i++) { f(comp, pns->nodes[i]); } - } else if (!PY_PARSE_NODE_IS_NULL(pn)) { + } else if (!MP_PARSE_NODE_IS_NULL(pn)) { f(comp, pn); } } -static int list_get(py_parse_node_t *pn, int pn_kind, py_parse_node_t **nodes) { - if (PY_PARSE_NODE_IS_NULL(*pn)) { +static int list_get(mp_parse_node_t *pn, int pn_kind, mp_parse_node_t **nodes) { + if (MP_PARSE_NODE_IS_NULL(*pn)) { *nodes = NULL; return 0; - } else if (PY_PARSE_NODE_IS_LEAF(*pn)) { + } else if (MP_PARSE_NODE_IS_LEAF(*pn)) { *nodes = pn; return 1; } else { - py_parse_node_struct_t *pns = (py_parse_node_struct_t*)(*pn); - if (PY_PARSE_NODE_STRUCT_KIND(pns) != pn_kind) { + mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)(*pn); + if (MP_PARSE_NODE_STRUCT_KIND(pns) != pn_kind) { *nodes = pn; return 1; } else { *nodes = pns->nodes; - return PY_PARSE_NODE_STRUCT_NUM_NODES(pns); + return MP_PARSE_NODE_STRUCT_NUM_NODES(pns); } } } -void compile_do_nothing(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_do_nothing(compiler_t *comp, mp_parse_node_struct_t *pns) { } -void compile_generic_all_nodes(compiler_t *comp, py_parse_node_struct_t *pns) { - int num_nodes = PY_PARSE_NODE_STRUCT_NUM_NODES(pns); +void compile_generic_all_nodes(compiler_t *comp, mp_parse_node_struct_t *pns) { + int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); for (int i = 0; i < num_nodes; i++) { compile_node(comp, pns->nodes[i]); } } #if MICROPY_EMIT_CPYTHON -static bool cpython_c_tuple_is_const(py_parse_node_t pn) { - if (!PY_PARSE_NODE_IS_LEAF(pn)) { +static bool cpython_c_tuple_is_const(mp_parse_node_t pn) { + if (!MP_PARSE_NODE_IS_LEAF(pn)) { return false; } - if (PY_PARSE_NODE_IS_ID(pn)) { + if (MP_PARSE_NODE_IS_ID(pn)) { return false; } return true; @@ -322,21 +322,21 @@ static void cpython_c_print_quoted_str(vstr_t *vstr, qstr qstr, bool bytes) { } } -static void cpython_c_tuple_emit_const(compiler_t *comp, py_parse_node_t pn, vstr_t *vstr) { - assert(PY_PARSE_NODE_IS_LEAF(pn)); - int arg = PY_PARSE_NODE_LEAF_ARG(pn); - switch (PY_PARSE_NODE_LEAF_KIND(pn)) { - case PY_PARSE_NODE_ID: assert(0); - case PY_PARSE_NODE_SMALL_INT: vstr_printf(vstr, "%d", arg); break; - case PY_PARSE_NODE_INTEGER: vstr_printf(vstr, "%s", qstr_str(arg)); break; - case PY_PARSE_NODE_DECIMAL: vstr_printf(vstr, "%s", qstr_str(arg)); break; - case PY_PARSE_NODE_STRING: cpython_c_print_quoted_str(vstr, arg, false); break; - case PY_PARSE_NODE_BYTES: cpython_c_print_quoted_str(vstr, arg, true); break; - case PY_PARSE_NODE_TOKEN: +static void cpython_c_tuple_emit_const(compiler_t *comp, mp_parse_node_t pn, vstr_t *vstr) { + assert(MP_PARSE_NODE_IS_LEAF(pn)); + int arg = MP_PARSE_NODE_LEAF_ARG(pn); + switch (MP_PARSE_NODE_LEAF_KIND(pn)) { + case MP_PARSE_NODE_ID: assert(0); + case MP_PARSE_NODE_SMALL_INT: vstr_printf(vstr, "%d", arg); break; + case MP_PARSE_NODE_INTEGER: vstr_printf(vstr, "%s", qstr_str(arg)); break; + case MP_PARSE_NODE_DECIMAL: vstr_printf(vstr, "%s", qstr_str(arg)); break; + case MP_PARSE_NODE_STRING: cpython_c_print_quoted_str(vstr, arg, false); break; + case MP_PARSE_NODE_BYTES: cpython_c_print_quoted_str(vstr, arg, true); break; + case MP_PARSE_NODE_TOKEN: switch (arg) { - case PY_TOKEN_KW_FALSE: vstr_printf(vstr, "False"); break; - case PY_TOKEN_KW_NONE: vstr_printf(vstr, "None"); break; - case PY_TOKEN_KW_TRUE: vstr_printf(vstr, "True"); break; + case MP_TOKEN_KW_FALSE: vstr_printf(vstr, "False"); break; + case MP_TOKEN_KW_NONE: vstr_printf(vstr, "None"); break; + case MP_TOKEN_KW_TRUE: vstr_printf(vstr, "True"); break; default: assert(0); } break; @@ -344,14 +344,14 @@ static void cpython_c_tuple_emit_const(compiler_t *comp, py_parse_node_t pn, vst } } -static void cpython_c_tuple(compiler_t *comp, py_parse_node_t pn, py_parse_node_struct_t *pns_list) { +static void cpython_c_tuple(compiler_t *comp, mp_parse_node_t pn, mp_parse_node_struct_t *pns_list) { int n = 0; if (pns_list != NULL) { - n = PY_PARSE_NODE_STRUCT_NUM_NODES(pns_list); + n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_list); } int total = n; bool is_const = true; - if (!PY_PARSE_NODE_IS_NULL(pn)) { + if (!MP_PARSE_NODE_IS_NULL(pn)) { total += 1; if (!cpython_c_tuple_is_const(pn)) { is_const = false; @@ -367,7 +367,7 @@ static void cpython_c_tuple(compiler_t *comp, py_parse_node_t pn, py_parse_node_ bool need_comma = false; vstr_t *vstr = vstr_new(); vstr_printf(vstr, "("); - if (!PY_PARSE_NODE_IS_NULL(pn)) { + if (!MP_PARSE_NODE_IS_NULL(pn)) { cpython_c_tuple_emit_const(comp, pn, vstr); need_comma = true; } @@ -386,7 +386,7 @@ static void cpython_c_tuple(compiler_t *comp, py_parse_node_t pn, py_parse_node_ EMIT(load_const_verbatim_str, vstr_str(vstr)); vstr_free(vstr); } else { - if (!PY_PARSE_NODE_IS_NULL(pn)) { + if (!MP_PARSE_NODE_IS_NULL(pn)) { compile_node(comp, pn); } for (int i = 0; i < n; i++) { @@ -398,17 +398,17 @@ static void cpython_c_tuple(compiler_t *comp, py_parse_node_t pn, py_parse_node_ #endif // funnelling all tuple creations through this function is purely so we can optionally agree with CPython -void c_tuple(compiler_t *comp, py_parse_node_t pn, py_parse_node_struct_t *pns_list) { +void c_tuple(compiler_t *comp, mp_parse_node_t pn, mp_parse_node_struct_t *pns_list) { #if MICROPY_EMIT_CPYTHON cpython_c_tuple(comp, pn, pns_list); #else int total = 0; - if (!PY_PARSE_NODE_IS_NULL(pn)) { + if (!MP_PARSE_NODE_IS_NULL(pn)) { compile_node(comp, pn); total += 1; } if (pns_list != NULL) { - int n = PY_PARSE_NODE_STRUCT_NUM_NODES(pns_list); + int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_list); for (int i = 0; i < n; i++) { compile_node(comp, pns_list->nodes[i]); } @@ -418,23 +418,23 @@ void c_tuple(compiler_t *comp, py_parse_node_t pn, py_parse_node_struct_t *pns_l #endif } -void compile_generic_tuple(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_generic_tuple(compiler_t *comp, mp_parse_node_struct_t *pns) { // a simple tuple expression - c_tuple(comp, PY_PARSE_NODE_NULL, pns); + c_tuple(comp, MP_PARSE_NODE_NULL, pns); } -static bool node_is_const_false(py_parse_node_t pn) { - return PY_PARSE_NODE_IS_TOKEN_KIND(pn, PY_TOKEN_KW_FALSE); - // untested: || (PY_PARSE_NODE_IS_SMALL_INT(pn) && PY_PARSE_NODE_LEAF_ARG(pn) == 1); +static bool node_is_const_false(mp_parse_node_t pn) { + return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_FALSE); + // untested: || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_ARG(pn) == 1); } -static bool node_is_const_true(py_parse_node_t pn) { - return PY_PARSE_NODE_IS_TOKEN_KIND(pn, PY_TOKEN_KW_TRUE) || (PY_PARSE_NODE_IS_SMALL_INT(pn) && PY_PARSE_NODE_LEAF_ARG(pn) == 1); +static bool node_is_const_true(mp_parse_node_t pn) { + return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_TRUE) || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_ARG(pn) == 1); } #if MICROPY_EMIT_CPYTHON // the is_nested variable is purely to match with CPython, which doesn't fully optimise not's -static void cpython_c_if_cond(compiler_t *comp, py_parse_node_t pn, bool jump_if, int label, bool is_nested) { +static void cpython_c_if_cond(compiler_t *comp, mp_parse_node_t pn, bool jump_if, int label, bool is_nested) { if (node_is_const_false(pn)) { if (jump_if == false) { EMIT(jump, label); @@ -445,10 +445,10 @@ static void cpython_c_if_cond(compiler_t *comp, py_parse_node_t pn, bool jump_if EMIT(jump, label); } return; - } else if (PY_PARSE_NODE_IS_STRUCT(pn)) { - py_parse_node_struct_t *pns = (py_parse_node_struct_t*)pn; - int n = PY_PARSE_NODE_STRUCT_NUM_NODES(pns); - if (PY_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) { + } else if (MP_PARSE_NODE_IS_STRUCT(pn)) { + mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; + int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); + if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) { if (jump_if == false) { int label2 = comp_next_label(comp); for (int i = 0; i < n - 1; i++) { @@ -462,7 +462,7 @@ static void cpython_c_if_cond(compiler_t *comp, py_parse_node_t pn, bool jump_if } } return; - } else if (PY_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) { + } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) { if (jump_if == false) { for (int i = 0; i < n; i++) { cpython_c_if_cond(comp, pns->nodes[i], false, label, true); @@ -476,7 +476,7 @@ static void cpython_c_if_cond(compiler_t *comp, py_parse_node_t pn, bool jump_if EMIT(label_assign, label2); } return; - } else if (!is_nested && PY_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) { + } else if (!is_nested && MP_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) { cpython_c_if_cond(comp, pns->nodes[0], !jump_if, label, true); return; } @@ -492,7 +492,7 @@ static void cpython_c_if_cond(compiler_t *comp, py_parse_node_t pn, bool jump_if } #endif -static void c_if_cond(compiler_t *comp, py_parse_node_t pn, bool jump_if, int label) { +static void c_if_cond(compiler_t *comp, mp_parse_node_t pn, bool jump_if, int label) { #if MICROPY_EMIT_CPYTHON cpython_c_if_cond(comp, pn, jump_if, label, false); #else @@ -506,10 +506,10 @@ static void c_if_cond(compiler_t *comp, py_parse_node_t pn, bool jump_if, int la EMIT(jump, label); } return; - } else if (PY_PARSE_NODE_IS_STRUCT(pn)) { - py_parse_node_struct_t *pns = (py_parse_node_struct_t*)pn; - int n = PY_PARSE_NODE_STRUCT_NUM_NODES(pns); - if (PY_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) { + } else if (MP_PARSE_NODE_IS_STRUCT(pn)) { + mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; + int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); + if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) { if (jump_if == false) { int label2 = comp_next_label(comp); for (int i = 0; i < n - 1; i++) { @@ -523,7 +523,7 @@ static void c_if_cond(compiler_t *comp, py_parse_node_t pn, bool jump_if, int la } } return; - } else if (PY_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) { + } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) { if (jump_if == false) { for (int i = 0; i < n; i++) { c_if_cond(comp, pns->nodes[i], false, label); @@ -537,7 +537,7 @@ static void c_if_cond(compiler_t *comp, py_parse_node_t pn, bool jump_if, int la EMIT(label_assign, label2); } return; - } else if (PY_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) { + } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) { c_if_cond(comp, pns->nodes[0], !jump_if, label); return; } @@ -554,29 +554,29 @@ static void c_if_cond(compiler_t *comp, py_parse_node_t pn, bool jump_if, int la } typedef enum { ASSIGN_STORE, ASSIGN_AUG_LOAD, ASSIGN_AUG_STORE } assign_kind_t; -void c_assign(compiler_t *comp, py_parse_node_t pn, assign_kind_t kind); +void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t kind); -void c_assign_power(compiler_t *comp, py_parse_node_struct_t *pns, assign_kind_t assign_kind) { +void c_assign_power(compiler_t *comp, mp_parse_node_struct_t *pns, assign_kind_t assign_kind) { if (assign_kind != ASSIGN_AUG_STORE) { compile_node(comp, pns->nodes[0]); } - if (PY_PARSE_NODE_IS_STRUCT(pns->nodes[1])) { - py_parse_node_struct_t *pns1 = (py_parse_node_struct_t*)pns->nodes[1]; - if (PY_PARSE_NODE_STRUCT_KIND(pns1) == PN_power_trailers) { - int n = PY_PARSE_NODE_STRUCT_NUM_NODES(pns1); + if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) { + mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1]; + if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_power_trailers) { + int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1); if (assign_kind != ASSIGN_AUG_STORE) { for (int i = 0; i < n - 1; i++) { compile_node(comp, pns1->nodes[i]); } } - assert(PY_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1])); - pns1 = (py_parse_node_struct_t*)pns1->nodes[n - 1]; + assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1])); + pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1]; } - if (PY_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_paren) { + if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_paren) { printf("SyntaxError: can't assign to function call\n"); return; - } else if (PY_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) { + } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) { if (assign_kind == ASSIGN_AUG_STORE) { EMIT(rot_three); EMIT(store_subscr); @@ -589,16 +589,16 @@ void c_assign_power(compiler_t *comp, py_parse_node_struct_t *pns, assign_kind_t EMIT(store_subscr); } } - } else if (PY_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) { - assert(PY_PARSE_NODE_IS_ID(pns1->nodes[0])); + } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) { + assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0])); if (assign_kind == ASSIGN_AUG_LOAD) { EMIT(dup_top); - EMIT(load_attr, PY_PARSE_NODE_LEAF_ARG(pns1->nodes[0])); + EMIT(load_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0])); } else { if (assign_kind == ASSIGN_AUG_STORE) { EMIT(rot_two); } - EMIT(store_attr, PY_PARSE_NODE_LEAF_ARG(pns1->nodes[0])); + EMIT(store_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0])); } } else { // shouldn't happen @@ -609,17 +609,17 @@ void c_assign_power(compiler_t *comp, py_parse_node_struct_t *pns, assign_kind_t assert(0); } - if (!PY_PARSE_NODE_IS_NULL(pns->nodes[2])) { + if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) { // SyntaxError, cannot assign assert(0); } } -void c_assign_tuple(compiler_t *comp, int n, py_parse_node_t *nodes) { +void c_assign_tuple(compiler_t *comp, int n, mp_parse_node_t *nodes) { assert(n >= 0); int have_star_index = -1; for (int i = 0; i < n; i++) { - if (PY_PARSE_NODE_IS_STRUCT_KIND(nodes[i], PN_star_expr)) { + if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[i], PN_star_expr)) { if (have_star_index < 0) { EMIT(unpack_ex, i, n - i - 1); have_star_index = i; @@ -634,7 +634,7 @@ void c_assign_tuple(compiler_t *comp, int n, py_parse_node_t *nodes) { } for (int i = 0; i < n; i++) { if (i == have_star_index) { - c_assign(comp, ((py_parse_node_struct_t*)nodes[i])->nodes[0], ASSIGN_STORE); + c_assign(comp, ((mp_parse_node_struct_t*)nodes[i])->nodes[0], ASSIGN_STORE); } else { c_assign(comp, nodes[i], ASSIGN_STORE); } @@ -642,13 +642,13 @@ void c_assign_tuple(compiler_t *comp, int n, py_parse_node_t *nodes) { } // assigns top of stack to pn -void c_assign(compiler_t *comp, py_parse_node_t pn, assign_kind_t assign_kind) { +void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) { tail_recursion: - if (PY_PARSE_NODE_IS_NULL(pn)) { + if (MP_PARSE_NODE_IS_NULL(pn)) { assert(0); - } else if (PY_PARSE_NODE_IS_LEAF(pn)) { - if (PY_PARSE_NODE_IS_ID(pn)) { - int arg = PY_PARSE_NODE_LEAF_ARG(pn); + } else if (MP_PARSE_NODE_IS_LEAF(pn)) { + if (MP_PARSE_NODE_IS_ID(pn)) { + int arg = MP_PARSE_NODE_LEAF_ARG(pn); switch (assign_kind) { case ASSIGN_STORE: case ASSIGN_AUG_STORE: @@ -663,8 +663,8 @@ void c_assign(compiler_t *comp, py_parse_node_t pn, assign_kind_t assign_kind) { return; } } else { - py_parse_node_struct_t *pns = (py_parse_node_struct_t*)pn; - switch (PY_PARSE_NODE_STRUCT_KIND(pns)) { + mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; + switch (MP_PARSE_NODE_STRUCT_KIND(pns)) { case PN_power: // lhs is an index or attribute c_assign_power(comp, pns, assign_kind); @@ -676,17 +676,17 @@ void c_assign(compiler_t *comp, py_parse_node_t pn, assign_kind_t assign_kind) { if (assign_kind != ASSIGN_STORE) { goto bad_aug; } - c_assign_tuple(comp, PY_PARSE_NODE_STRUCT_NUM_NODES(pns), pns->nodes); + c_assign_tuple(comp, MP_PARSE_NODE_STRUCT_NUM_NODES(pns), pns->nodes); break; case PN_atom_paren: // lhs is something in parenthesis - if (PY_PARSE_NODE_IS_NULL(pns->nodes[0])) { + if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) { // empty tuple printf("SyntaxError: can't assign to ()\n"); return; - } else if (PY_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) { - pns = (py_parse_node_struct_t*)pns->nodes[0]; + } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) { + pns = (mp_parse_node_struct_t*)pns->nodes[0]; goto testlist_comp; } else { // parenthesis around 1 item, is just that item @@ -700,11 +700,11 @@ void c_assign(compiler_t *comp, py_parse_node_t pn, assign_kind_t assign_kind) { if (assign_kind != ASSIGN_STORE) { goto bad_aug; } - if (PY_PARSE_NODE_IS_NULL(pns->nodes[0])) { + if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) { // empty list, assignment allowed c_assign_tuple(comp, 0, NULL); - } else if (PY_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) { - pns = (py_parse_node_struct_t*)pns->nodes[0]; + } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) { + pns = (mp_parse_node_struct_t*)pns->nodes[0]; goto testlist_comp; } else { // brackets around 1 item @@ -713,29 +713,29 @@ void c_assign(compiler_t *comp, py_parse_node_t pn, assign_kind_t assign_kind) { break; default: - printf("unknown assign, %u\n", (uint)PY_PARSE_NODE_STRUCT_KIND(pns)); + printf("unknown assign, %u\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns)); assert(0); } return; testlist_comp: // lhs is a sequence - if (PY_PARSE_NODE_IS_STRUCT(pns->nodes[1])) { - py_parse_node_struct_t *pns2 = (py_parse_node_struct_t*)pns->nodes[1]; - if (PY_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) { + if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) { + mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1]; + if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) { // sequence of one item, with trailing comma - assert(PY_PARSE_NODE_IS_NULL(pns2->nodes[0])); + assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0])); c_assign_tuple(comp, 1, &pns->nodes[0]); - } else if (PY_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) { + } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) { // sequence of many items // TODO call c_assign_tuple instead - int n = PY_PARSE_NODE_STRUCT_NUM_NODES(pns2); + int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns2); EMIT(unpack_sequence, 1 + n); c_assign(comp, pns->nodes[0], ASSIGN_STORE); for (int i = 0; i < n; i++) { c_assign(comp, pns2->nodes[i], ASSIGN_STORE); } - } else if (PY_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) { + } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) { // TODO not implemented assert(0); } else { @@ -786,16 +786,16 @@ void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int n_dict_ } } -void compile_funcdef_param(compiler_t *comp, py_parse_node_t pn) { - if (PY_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_name)) { - py_parse_node_struct_t *pns = (py_parse_node_struct_t*)pn; - if (!PY_PARSE_NODE_IS_NULL(pns->nodes[2])) { +void compile_funcdef_param(compiler_t *comp, mp_parse_node_t pn) { + if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_name)) { + mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; + if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) { // this parameter has a default value // in CPython, None (and True, False?) as default parameters are loaded with LOAD_NAME; don't understandy why if (comp->have_bare_star) { comp->param_pass_num_dict_params += 1; if (comp->param_pass == 1) { - EMIT(load_const_id, PY_PARSE_NODE_LEAF_ARG(pns->nodes[0])); + EMIT(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); compile_node(comp, pns->nodes[2]); } } else { @@ -805,9 +805,9 @@ void compile_funcdef_param(compiler_t *comp, py_parse_node_t pn) { } } } - } else if (PY_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_star)) { - py_parse_node_struct_t *pns = (py_parse_node_struct_t*)pn; - if (PY_PARSE_NODE_IS_NULL(pns->nodes[0])) { + } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_star)) { + mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; + if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) { // bare star comp->have_bare_star = true; } @@ -816,12 +816,12 @@ void compile_funcdef_param(compiler_t *comp, py_parse_node_t pn) { // leaves function object on stack // returns function name -qstr compile_funcdef_helper(compiler_t *comp, py_parse_node_struct_t *pns, uint emit_options) { +qstr compile_funcdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) { if (comp->pass == PASS_1) { // create a new scope for this function - scope_t *s = scope_new_and_link(comp, SCOPE_FUNCTION, (py_parse_node_t)pns, emit_options); + scope_t *s = scope_new_and_link(comp, SCOPE_FUNCTION, (mp_parse_node_t)pns, emit_options); // store the function scope so the compiling function can use it at each pass - pns->nodes[4] = (py_parse_node_t)s; + pns->nodes[4] = (mp_parse_node_t)s; } // save variables (probably don't need to do this, since we can't have nested definitions..?) @@ -860,12 +860,12 @@ qstr compile_funcdef_helper(compiler_t *comp, py_parse_node_struct_t *pns, uint // leaves class object on stack // returns class name -qstr compile_classdef_helper(compiler_t *comp, py_parse_node_struct_t *pns, uint emit_options) { +qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) { if (comp->pass == PASS_1) { // create a new scope for this class - scope_t *s = scope_new_and_link(comp, SCOPE_CLASS, (py_parse_node_t)pns, emit_options); + scope_t *s = scope_new_and_link(comp, SCOPE_CLASS, (mp_parse_node_t)pns, emit_options); // store the class scope so the compiling function can use it at each pass - pns->nodes[3] = (py_parse_node_t)s; + pns->nodes[3] = (mp_parse_node_t)s; } EMIT(load_build_class); @@ -880,7 +880,7 @@ qstr compile_classdef_helper(compiler_t *comp, py_parse_node_struct_t *pns, uint EMIT(load_const_id, cscope->simple_name); // nodes[1] has parent classes, if any - if (PY_PARSE_NODE_IS_NULL(pns->nodes[1])) { + if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) { // no parent classes EMIT(call_function, 2, 0, false, false); } else { @@ -895,8 +895,8 @@ qstr compile_classdef_helper(compiler_t *comp, py_parse_node_struct_t *pns, uint } // returns true if it was a built-in decorator (even if the built-in had an error) -static bool compile_built_in_decorator(compiler_t *comp, int name_len, py_parse_node_t *name_nodes, uint *emit_options) { - if (PY_PARSE_NODE_LEAF_ARG(name_nodes[0]) != comp->qstr_micropython) { +static bool compile_built_in_decorator(compiler_t *comp, int name_len, mp_parse_node_t *name_nodes, uint *emit_options) { + if (MP_PARSE_NODE_LEAF_ARG(name_nodes[0]) != comp->qstr_micropython) { return false; } @@ -905,7 +905,7 @@ static bool compile_built_in_decorator(compiler_t *comp, int name_len, py_parse_ return true; } - qstr attr = PY_PARSE_NODE_LEAF_ARG(name_nodes[1]); + qstr attr = MP_PARSE_NODE_LEAF_ARG(name_nodes[1]); if (attr == comp->qstr_byte_code) { *emit_options = EMIT_OPT_BYTE_CODE; #if MICROPY_EMIT_NATIVE @@ -925,9 +925,9 @@ static bool compile_built_in_decorator(compiler_t *comp, int name_len, py_parse_ return true; } -void compile_decorated(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_decorated(compiler_t *comp, mp_parse_node_struct_t *pns) { // get the list of decorators - py_parse_node_t *nodes; + mp_parse_node_t *nodes; int n = list_get(&pns->nodes[0], PN_decorators, &nodes); // inherit emit options for this function/class definition @@ -936,11 +936,11 @@ void compile_decorated(compiler_t *comp, py_parse_node_struct_t *pns) { // compile each decorator int num_built_in_decorators = 0; for (int i = 0; i < n; i++) { - assert(PY_PARSE_NODE_IS_STRUCT_KIND(nodes[i], PN_decorator)); // should be - py_parse_node_struct_t *pns_decorator = (py_parse_node_struct_t*)nodes[i]; + assert(MP_PARSE_NODE_IS_STRUCT_KIND(nodes[i], PN_decorator)); // should be + mp_parse_node_struct_t *pns_decorator = (mp_parse_node_struct_t*)nodes[i]; // nodes[0] contains the decorator function, which is a dotted name - py_parse_node_t *name_nodes; + mp_parse_node_t *name_nodes; int name_len = list_get(&pns_decorator->nodes[0], PN_dotted_name, &name_nodes); // check for built-in decorators @@ -954,12 +954,12 @@ void compile_decorated(compiler_t *comp, py_parse_node_struct_t *pns) { // compile the decorator function compile_node(comp, name_nodes[0]); for (int i = 1; i < name_len; i++) { - assert(PY_PARSE_NODE_IS_ID(name_nodes[i])); // should be - EMIT(load_attr, PY_PARSE_NODE_LEAF_ARG(name_nodes[i])); + assert(MP_PARSE_NODE_IS_ID(name_nodes[i])); // should be + EMIT(load_attr, MP_PARSE_NODE_LEAF_ARG(name_nodes[i])); } // nodes[1] contains arguments to the decorator function, if any - if (!PY_PARSE_NODE_IS_NULL(pns_decorator->nodes[1])) { + if (!MP_PARSE_NODE_IS_NULL(pns_decorator->nodes[1])) { // call the decorator function with the arguments in nodes[1] compile_node(comp, pns_decorator->nodes[1]); } @@ -967,11 +967,11 @@ void compile_decorated(compiler_t *comp, py_parse_node_struct_t *pns) { } // compile the body (funcdef or classdef) and get its name - py_parse_node_struct_t *pns_body = (py_parse_node_struct_t*)pns->nodes[1]; + mp_parse_node_struct_t *pns_body = (mp_parse_node_struct_t*)pns->nodes[1]; qstr body_name = 0; - if (PY_PARSE_NODE_STRUCT_KIND(pns_body) == PN_funcdef) { + if (MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_funcdef) { body_name = compile_funcdef_helper(comp, pns_body, emit_options); - } else if (PY_PARSE_NODE_STRUCT_KIND(pns_body) == PN_classdef) { + } else if (MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_classdef) { body_name = compile_classdef_helper(comp, pns_body, emit_options); } else { // shouldn't happen @@ -987,39 +987,39 @@ void compile_decorated(compiler_t *comp, py_parse_node_struct_t *pns) { EMIT(store_id, body_name); } -void compile_funcdef(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_funcdef(compiler_t *comp, mp_parse_node_struct_t *pns) { qstr fname = compile_funcdef_helper(comp, pns, comp->scope_cur->emit_options); // store function object into function name EMIT(store_id, fname); } -void c_del_stmt(compiler_t *comp, py_parse_node_t pn) { - if (PY_PARSE_NODE_IS_ID(pn)) { - EMIT(delete_id, PY_PARSE_NODE_LEAF_ARG(pn)); - } else if (PY_PARSE_NODE_IS_STRUCT_KIND(pn, PN_power)) { - py_parse_node_struct_t *pns = (py_parse_node_struct_t*)pn; +void c_del_stmt(compiler_t *comp, mp_parse_node_t pn) { + if (MP_PARSE_NODE_IS_ID(pn)) { + EMIT(delete_id, MP_PARSE_NODE_LEAF_ARG(pn)); + } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_power)) { + mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; compile_node(comp, pns->nodes[0]); // base of the power node - if (PY_PARSE_NODE_IS_STRUCT(pns->nodes[1])) { - py_parse_node_struct_t *pns1 = (py_parse_node_struct_t*)pns->nodes[1]; - if (PY_PARSE_NODE_STRUCT_KIND(pns1) == PN_power_trailers) { - int n = PY_PARSE_NODE_STRUCT_NUM_NODES(pns1); + if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) { + mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1]; + if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_power_trailers) { + int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1); for (int i = 0; i < n - 1; i++) { compile_node(comp, pns1->nodes[i]); } - assert(PY_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1])); - pns1 = (py_parse_node_struct_t*)pns1->nodes[n - 1]; + assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1])); + pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1]; } - if (PY_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_paren) { + if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_paren) { // SyntaxError: can't delete a function call assert(0); - } else if (PY_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) { + } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) { compile_node(comp, pns1->nodes[0]); EMIT(delete_subscr); - } else if (PY_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) { - assert(PY_PARSE_NODE_IS_ID(pns1->nodes[0])); - EMIT(delete_attr, PY_PARSE_NODE_LEAF_ARG(pns1->nodes[0])); + } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) { + assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0])); + EMIT(delete_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0])); } else { // shouldn't happen assert(0); @@ -1029,30 +1029,30 @@ void c_del_stmt(compiler_t *comp, py_parse_node_t pn) { assert(0); } - if (!PY_PARSE_NODE_IS_NULL(pns->nodes[2])) { + if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) { // SyntaxError, cannot delete assert(0); } - } else if (PY_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_paren)) { - pn = ((py_parse_node_struct_t*)pn)->nodes[0]; - if (PY_PARSE_NODE_IS_STRUCT_KIND(pn, PN_testlist_comp)) { - py_parse_node_struct_t *pns = (py_parse_node_struct_t*)pn; + } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_paren)) { + pn = ((mp_parse_node_struct_t*)pn)->nodes[0]; + if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_testlist_comp)) { + mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; // TODO perhaps factorise testlist_comp code with other uses of PN_testlist_comp - if (PY_PARSE_NODE_IS_STRUCT(pns->nodes[1])) { - py_parse_node_struct_t *pns1 = (py_parse_node_struct_t*)pns->nodes[1]; - if (PY_PARSE_NODE_STRUCT_KIND(pns1) == PN_testlist_comp_3b) { + if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) { + mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1]; + if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_testlist_comp_3b) { // sequence of one item, with trailing comma - assert(PY_PARSE_NODE_IS_NULL(pns1->nodes[0])); + assert(MP_PARSE_NODE_IS_NULL(pns1->nodes[0])); c_del_stmt(comp, pns->nodes[0]); - } else if (PY_PARSE_NODE_STRUCT_KIND(pns1) == PN_testlist_comp_3c) { + } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_testlist_comp_3c) { // sequence of many items - int n = PY_PARSE_NODE_STRUCT_NUM_NODES(pns1); + int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1); c_del_stmt(comp, pns->nodes[0]); for (int i = 0; i < n; i++) { c_del_stmt(comp, pns1->nodes[i]); } - } else if (PY_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) { + } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) { // TODO not implemented; can't del comprehension? assert(0); } else { @@ -1075,18 +1075,18 @@ void c_del_stmt(compiler_t *comp, py_parse_node_t pn) { } } -void compile_del_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_del_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { apply_to_single_or_list(comp, pns->nodes[0], PN_exprlist, c_del_stmt); } -void compile_break_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_break_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { if (comp->break_label == 0) { printf("ERROR: cannot break from here\n"); } EMIT(break_loop, comp->break_label); } -void compile_continue_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_continue_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { if (comp->continue_label == 0) { printf("ERROR: cannot continue from here\n"); } @@ -1097,19 +1097,19 @@ void compile_continue_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { } } -void compile_return_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_return_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { if (comp->scope_cur->kind != SCOPE_FUNCTION) { printf("SyntaxError: 'return' outside function\n"); comp->had_error = true; return; } - if (PY_PARSE_NODE_IS_NULL(pns->nodes[0])) { + if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) { // no argument to 'return', so return None - EMIT(load_const_tok, PY_TOKEN_KW_NONE); - } else if (PY_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_test_if_expr)) { + EMIT(load_const_tok, MP_TOKEN_KW_NONE); + } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_test_if_expr)) { // special case when returning an if-expression; to match CPython optimisation - py_parse_node_struct_t *pns_test_if_expr = (py_parse_node_struct_t*)pns->nodes[0]; - py_parse_node_struct_t *pns_test_if_else = (py_parse_node_struct_t*)pns_test_if_expr->nodes[1]; + mp_parse_node_struct_t *pns_test_if_expr = (mp_parse_node_struct_t*)pns->nodes[0]; + mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t*)pns_test_if_expr->nodes[1]; int l_fail = comp_next_label(comp); c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition @@ -1123,18 +1123,18 @@ void compile_return_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { EMIT(return_value); } -void compile_yield_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_yield_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { compile_node(comp, pns->nodes[0]); EMIT(pop_top); } -void compile_raise_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { - if (PY_PARSE_NODE_IS_NULL(pns->nodes[0])) { +void compile_raise_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { + if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) { // raise EMIT(raise_varargs, 0); - } else if (PY_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_raise_stmt_arg)) { + } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_raise_stmt_arg)) { // raise x from y - pns = (py_parse_node_struct_t*)pns->nodes[0]; + pns = (mp_parse_node_struct_t*)pns->nodes[0]; compile_node(comp, pns->nodes[0]); compile_node(comp, pns->nodes[1]); EMIT(raise_varargs, 2); @@ -1148,33 +1148,33 @@ void compile_raise_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { // q1 holds the base, q2 the full name // eg a -> q1=q2=a // a.b.c -> q1=a, q2=a.b.c -void do_import_name(compiler_t *comp, py_parse_node_t pn, qstr *q1, qstr *q2) { +void do_import_name(compiler_t *comp, mp_parse_node_t pn, qstr *q1, qstr *q2) { bool is_as = false; - if (PY_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dotted_as_name)) { - py_parse_node_struct_t *pns = (py_parse_node_struct_t*)pn; + if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dotted_as_name)) { + mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; // a name of the form x as y; unwrap it - *q1 = PY_PARSE_NODE_LEAF_ARG(pns->nodes[1]); + *q1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[1]); pn = pns->nodes[0]; is_as = true; } - if (PY_PARSE_NODE_IS_ID(pn)) { + if (MP_PARSE_NODE_IS_ID(pn)) { // just a simple name - *q2 = PY_PARSE_NODE_LEAF_ARG(pn); + *q2 = MP_PARSE_NODE_LEAF_ARG(pn); if (!is_as) { *q1 = *q2; } EMIT(import_name, *q2); - } else if (PY_PARSE_NODE_IS_STRUCT(pn)) { - py_parse_node_struct_t *pns = (py_parse_node_struct_t*)pn; - if (PY_PARSE_NODE_STRUCT_KIND(pns) == PN_dotted_name) { + } else if (MP_PARSE_NODE_IS_STRUCT(pn)) { + mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; + if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dotted_name) { // a name of the form a.b.c if (!is_as) { - *q1 = PY_PARSE_NODE_LEAF_ARG(pns->nodes[0]); + *q1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); } - int n = PY_PARSE_NODE_STRUCT_NUM_NODES(pns); + int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); int len = n - 1; for (int i = 0; i < n; i++) { - len += strlen(qstr_str(PY_PARSE_NODE_LEAF_ARG(pns->nodes[i]))); + len += strlen(qstr_str(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]))); } char *str = m_new(char, len + 1); str[0] = 0; @@ -1182,13 +1182,13 @@ void do_import_name(compiler_t *comp, py_parse_node_t pn, qstr *q1, qstr *q2) { if (i > 0) { strcat(str, "."); } - strcat(str, qstr_str(PY_PARSE_NODE_LEAF_ARG(pns->nodes[i]))); + strcat(str, qstr_str(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]))); } *q2 = qstr_from_str_take(str); EMIT(import_name, *q2); if (is_as) { for (int i = 1; i < n; i++) { - EMIT(load_attr, PY_PARSE_NODE_LEAF_ARG(pns->nodes[i])); + EMIT(load_attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i])); } } } else { @@ -1201,20 +1201,20 @@ void do_import_name(compiler_t *comp, py_parse_node_t pn, qstr *q1, qstr *q2) { } } -void compile_dotted_as_name(compiler_t *comp, py_parse_node_t pn) { +void compile_dotted_as_name(compiler_t *comp, mp_parse_node_t pn) { EMIT(load_const_small_int, 0); // ?? - EMIT(load_const_tok, PY_TOKEN_KW_NONE); + EMIT(load_const_tok, MP_TOKEN_KW_NONE); qstr q1, q2; do_import_name(comp, pn, &q1, &q2); EMIT(store_id, q1); } -void compile_import_name(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_import_name(compiler_t *comp, mp_parse_node_struct_t *pns) { apply_to_single_or_list(comp, pns->nodes[0], PN_dotted_as_names, compile_dotted_as_name); } -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)) { +void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) { + if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) { EMIT(load_const_small_int, 0); // level 0 for __import__ // build the "fromlist" tuple @@ -1234,16 +1234,16 @@ void compile_import_from(compiler_t *comp, py_parse_node_struct_t *pns) { EMIT(load_const_small_int, 0); // level 0 for __import__ // build the "fromlist" tuple - py_parse_node_t *pn_nodes; + mp_parse_node_t *pn_nodes; int n = list_get(&pns->nodes[1], PN_import_as_names, &pn_nodes); #if MICROPY_EMIT_CPYTHON { vstr_t *vstr = vstr_new(); vstr_printf(vstr, "("); 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 + assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name)); + mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i]; + qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id if (i > 0) { vstr_printf(vstr, ", "); } @@ -1260,9 +1260,9 @@ void compile_import_from(compiler_t *comp, py_parse_node_struct_t *pns) { } #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 + assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name)); + mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i]; + qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id EMIT(load_const_str, id2, false); } EMIT(build_tuple, n); @@ -1272,53 +1272,53 @@ void compile_import_from(compiler_t *comp, py_parse_node_struct_t *pns) { qstr dummy_q, id1; do_import_name(comp, pns->nodes[0], &dummy_q, &id1); 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 + assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name)); + mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i]; + qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id EMIT(import_from, id2); - if (PY_PARSE_NODE_IS_NULL(pns3->nodes[1])) { + if (MP_PARSE_NODE_IS_NULL(pns3->nodes[1])) { EMIT(store_id, id2); } else { - EMIT(store_id, PY_PARSE_NODE_LEAF_ARG(pns3->nodes[1])); + EMIT(store_id, MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1])); } } EMIT(pop_top); } } -void compile_global_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_global_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { if (comp->pass == PASS_1) { - if (PY_PARSE_NODE_IS_LEAF(pns->nodes[0])) { - scope_declare_global(comp->scope_cur, PY_PARSE_NODE_LEAF_ARG(pns->nodes[0])); + if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) { + scope_declare_global(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); } else { - pns = (py_parse_node_struct_t*)pns->nodes[0]; - int num_nodes = PY_PARSE_NODE_STRUCT_NUM_NODES(pns); + pns = (mp_parse_node_struct_t*)pns->nodes[0]; + int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); for (int i = 0; i < num_nodes; i++) { - scope_declare_global(comp->scope_cur, PY_PARSE_NODE_LEAF_ARG(pns->nodes[i])); + scope_declare_global(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i])); } } } } -void compile_nonlocal_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { if (comp->pass == PASS_1) { - if (PY_PARSE_NODE_IS_LEAF(pns->nodes[0])) { - scope_declare_nonlocal(comp->scope_cur, PY_PARSE_NODE_LEAF_ARG(pns->nodes[0])); + if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) { + scope_declare_nonlocal(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); } else { - pns = (py_parse_node_struct_t*)pns->nodes[0]; - int num_nodes = PY_PARSE_NODE_STRUCT_NUM_NODES(pns); + pns = (mp_parse_node_struct_t*)pns->nodes[0]; + int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); for (int i = 0; i < num_nodes; i++) { - scope_declare_nonlocal(comp->scope_cur, PY_PARSE_NODE_LEAF_ARG(pns->nodes[i])); + scope_declare_nonlocal(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i])); } } } } -void compile_assert_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { int l_end = comp_next_label(comp); c_if_cond(comp, pns->nodes[0], true, l_end); EMIT(load_id, comp->qstr_assertion_error); - if (!PY_PARSE_NODE_IS_NULL(pns->nodes[1])) { + if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) { // assertion message compile_node(comp, pns->nodes[1]); EMIT(call_function, 1, 0, false, false); @@ -1327,7 +1327,7 @@ void compile_assert_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { EMIT(label_assign, l_end); } -void compile_if_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_if_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { // TODO proper and/or short circuiting int l_end = comp_next_label(comp); @@ -1336,7 +1336,7 @@ void compile_if_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { c_if_cond(comp, pns->nodes[0], false, l_fail); // if condition compile_node(comp, pns->nodes[1]); // if block - //if (!(PY_PARSE_NODE_IS_NULL(pns->nodes[2]) && PY_PARSE_NODE_IS_NULL(pns->nodes[3]))) { // optimisation; doesn't align with CPython + //if (!(MP_PARSE_NODE_IS_NULL(pns->nodes[2]) && MP_PARSE_NODE_IS_NULL(pns->nodes[3]))) { // optimisation; doesn't align with CPython // jump over elif/else blocks if they exist if (!EMIT(last_emit_was_return_value)) { // simple optimisation to align with CPython EMIT(jump, l_end); @@ -1344,17 +1344,17 @@ void compile_if_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { //} EMIT(label_assign, l_fail); - if (!PY_PARSE_NODE_IS_NULL(pns->nodes[2])) { + if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) { // compile elif blocks - py_parse_node_struct_t *pns_elif = (py_parse_node_struct_t*)pns->nodes[2]; + mp_parse_node_struct_t *pns_elif = (mp_parse_node_struct_t*)pns->nodes[2]; - if (PY_PARSE_NODE_STRUCT_KIND(pns_elif) == PN_if_stmt_elif_list) { + if (MP_PARSE_NODE_STRUCT_KIND(pns_elif) == PN_if_stmt_elif_list) { // multiple elif blocks - int n = PY_PARSE_NODE_STRUCT_NUM_NODES(pns_elif); + int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_elif); for (int i = 0; i < n; i++) { - py_parse_node_struct_t *pns_elif2 = (py_parse_node_struct_t*)pns_elif->nodes[i]; + mp_parse_node_struct_t *pns_elif2 = (mp_parse_node_struct_t*)pns_elif->nodes[i]; l_fail = comp_next_label(comp); c_if_cond(comp, pns_elif2->nodes[0], false, l_fail); // elif condition @@ -1385,7 +1385,7 @@ void compile_if_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { EMIT(label_assign, l_end); } -void compile_while_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_while_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { int old_break_label = comp->break_label; int old_continue_label = comp->continue_label; @@ -1431,7 +1431,7 @@ void compile_while_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { // TODO preload end and step onto stack if they are not constants // TODO check if step is negative and do opposite test -void compile_for_stmt_optimised_range(compiler_t *comp, py_parse_node_t pn_var, py_parse_node_t pn_start, py_parse_node_t pn_end, py_parse_node_t pn_step, py_parse_node_t pn_body, py_parse_node_t pn_else) { +void compile_for_stmt_optimised_range(compiler_t *comp, mp_parse_node_t pn_var, mp_parse_node_t pn_start, mp_parse_node_t pn_end, mp_parse_node_t pn_step, mp_parse_node_t pn_body, mp_parse_node_t pn_else) { int old_break_label = comp->break_label; int old_continue_label = comp->continue_label; @@ -1476,29 +1476,29 @@ void compile_for_stmt_optimised_range(compiler_t *comp, py_parse_node_t pn_var, EMIT(label_assign, break_label); } -void compile_for_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { #if !MICROPY_EMIT_CPYTHON // this bit optimises: for <x> in range(...), turning it into an explicitly incremented variable // this is actually slower, but uses no heap memory // for viper it will be much, much faster - if (/*comp->scope_cur->emit_options == EMIT_OPT_VIPER &&*/ PY_PARSE_NODE_IS_ID(pns->nodes[0]) && PY_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_power)) { - py_parse_node_struct_t *pns_it = (py_parse_node_struct_t*)pns->nodes[1]; - if (PY_PARSE_NODE_IS_ID(pns_it->nodes[0]) && PY_PARSE_NODE_LEAF_ARG(pns_it->nodes[0]) == comp->qstr_range && PY_PARSE_NODE_IS_STRUCT_KIND(pns_it->nodes[1], PN_trailer_paren) && PY_PARSE_NODE_IS_NULL(pns_it->nodes[2])) { - py_parse_node_t pn_range_args = ((py_parse_node_struct_t*)pns_it->nodes[1])->nodes[0]; - py_parse_node_t *args; + if (/*comp->scope_cur->emit_options == EMIT_OPT_VIPER &&*/ MP_PARSE_NODE_IS_ID(pns->nodes[0]) && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_power)) { + mp_parse_node_struct_t *pns_it = (mp_parse_node_struct_t*)pns->nodes[1]; + if (MP_PARSE_NODE_IS_ID(pns_it->nodes[0]) && MP_PARSE_NODE_LEAF_ARG(pns_it->nodes[0]) == comp->qstr_range && MP_PARSE_NODE_IS_STRUCT_KIND(pns_it->nodes[1], PN_trailer_paren) && MP_PARSE_NODE_IS_NULL(pns_it->nodes[2])) { + mp_parse_node_t pn_range_args = ((mp_parse_node_struct_t*)pns_it->nodes[1])->nodes[0]; + mp_parse_node_t *args; int n_args = list_get(&pn_range_args, PN_arglist, &args); if (1 <= n_args && n_args <= 3) { - py_parse_node_t pn_range_start; - py_parse_node_t pn_range_end; - py_parse_node_t pn_range_step; + mp_parse_node_t pn_range_start; + mp_parse_node_t pn_range_end; + mp_parse_node_t pn_range_step; if (n_args == 1) { - pn_range_start = py_parse_node_new_leaf(PY_PARSE_NODE_SMALL_INT, 0); + pn_range_start = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 0); pn_range_end = args[0]; - pn_range_step = py_parse_node_new_leaf(PY_PARSE_NODE_SMALL_INT, 1); + pn_range_step = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 1); } else if (n_args == 2) { pn_range_start = args[0]; pn_range_end = args[1]; - pn_range_step = py_parse_node_new_leaf(PY_PARSE_NODE_SMALL_INT, 1); + pn_range_step = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 1); } else { pn_range_start = args[0]; pn_range_end = args[1]; @@ -1554,7 +1554,7 @@ void compile_for_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { EMIT(label_assign, end_label); } -void compile_try_except(compiler_t *comp, py_parse_node_t pn_body, int n_except, py_parse_node_t *pn_excepts, py_parse_node_t pn_else) { +void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_except, mp_parse_node_t *pn_excepts, mp_parse_node_t pn_else) { // this function is a bit of a hack at the moment // don't understand how the stack works with exceptions, so we force it to return to the correct value @@ -1571,13 +1571,13 @@ void compile_try_except(compiler_t *comp, py_parse_node_t pn_body, int n_except, int l2 = comp_next_label(comp); for (int i = 0; i < n_except; i++) { - assert(PY_PARSE_NODE_IS_STRUCT_KIND(pn_excepts[i], PN_try_stmt_except)); // should be - py_parse_node_struct_t *pns_except = (py_parse_node_struct_t*)pn_excepts[i]; + assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_excepts[i], PN_try_stmt_except)); // should be + mp_parse_node_struct_t *pns_except = (mp_parse_node_struct_t*)pn_excepts[i]; qstr qstr_exception_local = 0; int end_finally_label = comp_next_label(comp); - if (PY_PARSE_NODE_IS_NULL(pns_except->nodes[0])) { + if (MP_PARSE_NODE_IS_NULL(pns_except->nodes[0])) { // this is a catch all exception handler if (i + 1 != n_except) { printf("SyntaxError: default 'except:' must be last\n"); @@ -1585,13 +1585,13 @@ void compile_try_except(compiler_t *comp, py_parse_node_t pn_body, int n_except, } } else { // this exception handler requires a match to a certain type of exception - py_parse_node_t pns_exception_expr = pns_except->nodes[0]; - if (PY_PARSE_NODE_IS_STRUCT(pns_exception_expr)) { - py_parse_node_struct_t *pns3 = (py_parse_node_struct_t*)pns_exception_expr; - if (PY_PARSE_NODE_STRUCT_KIND(pns3) == PN_try_stmt_as_name) { + mp_parse_node_t pns_exception_expr = pns_except->nodes[0]; + if (MP_PARSE_NODE_IS_STRUCT(pns_exception_expr)) { + mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pns_exception_expr; + if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_try_stmt_as_name) { // handler binds the exception to a local pns_exception_expr = pns3->nodes[0]; - qstr_exception_local = PY_PARSE_NODE_LEAF_ARG(pns3->nodes[1]); + qstr_exception_local = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]); } } EMIT(dup_top); @@ -1621,9 +1621,9 @@ void compile_try_except(compiler_t *comp, py_parse_node_t pn_body, int n_except, } EMIT(pop_except); if (qstr_exception_local != 0) { - EMIT(load_const_tok, PY_TOKEN_KW_NONE); + EMIT(load_const_tok, MP_TOKEN_KW_NONE); EMIT(label_assign, l3); - EMIT(load_const_tok, PY_TOKEN_KW_NONE); + EMIT(load_const_tok, MP_TOKEN_KW_NONE); EMIT(store_id, qstr_exception_local); EMIT(delete_id, qstr_exception_local); EMIT(end_finally); @@ -1640,47 +1640,47 @@ void compile_try_except(compiler_t *comp, py_parse_node_t pn_body, int n_except, EMIT(set_stack_size, stack_size); } -void compile_try_finally(compiler_t *comp, py_parse_node_t pn_body, int n_except, py_parse_node_t *pn_except, py_parse_node_t pn_else, py_parse_node_t pn_finally) { +void compile_try_finally(compiler_t *comp, mp_parse_node_t pn_body, int n_except, mp_parse_node_t *pn_except, mp_parse_node_t pn_else, mp_parse_node_t pn_finally) { // don't understand how the stack works with exceptions, so we force it to return to the correct value int stack_size = EMIT(get_stack_size); int l_finally_block = comp_next_label(comp); EMIT(setup_finally, l_finally_block); if (n_except == 0) { - assert(PY_PARSE_NODE_IS_NULL(pn_else)); + assert(MP_PARSE_NODE_IS_NULL(pn_else)); compile_node(comp, pn_body); } else { compile_try_except(comp, pn_body, n_except, pn_except, pn_else); } EMIT(pop_block); - EMIT(load_const_tok, PY_TOKEN_KW_NONE); + EMIT(load_const_tok, MP_TOKEN_KW_NONE); EMIT(label_assign, l_finally_block); compile_node(comp, pn_finally); EMIT(end_finally); EMIT(set_stack_size, stack_size); } -void compile_try_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { - if (PY_PARSE_NODE_IS_STRUCT(pns->nodes[1])) { - py_parse_node_struct_t *pns2 = (py_parse_node_struct_t*)pns->nodes[1]; - if (PY_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_finally) { +void compile_try_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { + if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) { + mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1]; + if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_finally) { // just try-finally - compile_try_finally(comp, pns->nodes[0], 0, NULL, PY_PARSE_NODE_NULL, pns2->nodes[0]); - } else if (PY_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_except_and_more) { + compile_try_finally(comp, pns->nodes[0], 0, NULL, MP_PARSE_NODE_NULL, pns2->nodes[0]); + } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_except_and_more) { // try-except and possibly else and/or finally - py_parse_node_t *pn_excepts; + mp_parse_node_t *pn_excepts; int n_except = list_get(&pns2->nodes[0], PN_try_stmt_except_list, &pn_excepts); - if (PY_PARSE_NODE_IS_NULL(pns2->nodes[2])) { + if (MP_PARSE_NODE_IS_NULL(pns2->nodes[2])) { // no finally compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, pns2->nodes[1]); } else { // have finally - compile_try_finally(comp, pns->nodes[0], n_except, pn_excepts, pns2->nodes[1], ((py_parse_node_struct_t*)pns2->nodes[2])->nodes[0]); + compile_try_finally(comp, pns->nodes[0], n_except, pn_excepts, pns2->nodes[1], ((mp_parse_node_struct_t*)pns2->nodes[2])->nodes[0]); } } else { // just try-except - py_parse_node_t *pn_excepts; + mp_parse_node_t *pn_excepts; int n_except = list_get(&pns->nodes[1], PN_try_stmt_except_list, &pn_excepts); - compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, PY_PARSE_NODE_NULL); + compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, MP_PARSE_NODE_NULL); } } else { // shouldn't happen @@ -1688,15 +1688,15 @@ void compile_try_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { } } -void compile_with_stmt_helper(compiler_t *comp, int n, py_parse_node_t *nodes, py_parse_node_t body) { +void compile_with_stmt_helper(compiler_t *comp, int n, mp_parse_node_t *nodes, mp_parse_node_t body) { if (n == 0) { // no more pre-bits, compile the body of the with compile_node(comp, body); } else { int l_end = comp_next_label(comp); - if (PY_PARSE_NODE_IS_STRUCT_KIND(nodes[0], PN_with_item)) { + if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[0], PN_with_item)) { // this pre-bit is of the form "a as b" - py_parse_node_struct_t *pns = (py_parse_node_struct_t*)nodes[0]; + mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)nodes[0]; compile_node(comp, pns->nodes[0]); EMIT(setup_with, l_end); c_assign(comp, pns->nodes[1], ASSIGN_STORE); @@ -1710,16 +1710,16 @@ void compile_with_stmt_helper(compiler_t *comp, int n, py_parse_node_t *nodes, p compile_with_stmt_helper(comp, n - 1, nodes + 1, body); // finish this with block EMIT(pop_block); - EMIT(load_const_tok, PY_TOKEN_KW_NONE); + EMIT(load_const_tok, MP_TOKEN_KW_NONE); EMIT(label_assign, l_end); EMIT(with_cleanup); EMIT(end_finally); } } -void compile_with_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { // get the nodes for the pre-bit of the with (the a as b, c as d, ... bit) - py_parse_node_t *nodes; + mp_parse_node_t *nodes; int n = list_get(&pns->nodes[0], PN_with_stmt_list, &nodes); assert(n > 0); @@ -1727,8 +1727,8 @@ void compile_with_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { compile_with_stmt_helper(comp, n, nodes, pns->nodes[1]); } -void compile_expr_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { - if (PY_PARSE_NODE_IS_NULL(pns->nodes[1])) { +void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { + if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) { if (comp->is_repl && comp->scope_cur->kind == SCOPE_MODULE) { // for REPL, evaluate then print the expression EMIT(load_id, qstr_from_str_static("__repl_print__")); @@ -1738,7 +1738,7 @@ void compile_expr_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { } else { // for non-REPL, evaluate then discard the expression - if (PY_PARSE_NODE_IS_LEAF(pns->nodes[0]) && !PY_PARSE_NODE_IS_ID(pns->nodes[0])) { + if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0]) && !MP_PARSE_NODE_IS_ID(pns->nodes[0])) { // do nothing with a lonely constant } else { compile_node(comp, pns->nodes[0]); // just an expression @@ -1746,32 +1746,32 @@ void compile_expr_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { } } } else { - py_parse_node_struct_t *pns1 = (py_parse_node_struct_t*)pns->nodes[1]; - int kind = PY_PARSE_NODE_STRUCT_KIND(pns1); + mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1]; + int kind = MP_PARSE_NODE_STRUCT_KIND(pns1); if (kind == PN_expr_stmt_augassign) { c_assign(comp, pns->nodes[0], ASSIGN_AUG_LOAD); // lhs load for aug assign compile_node(comp, pns1->nodes[1]); // rhs - assert(PY_PARSE_NODE_IS_TOKEN(pns1->nodes[0])); + assert(MP_PARSE_NODE_IS_TOKEN(pns1->nodes[0])); // note that we don't really need to implement separate inplace ops, just normal binary ops will suffice - switch (PY_PARSE_NODE_LEAF_ARG(pns1->nodes[0])) { - case PY_TOKEN_DEL_PIPE_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_OR); break; - case PY_TOKEN_DEL_CARET_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_XOR); break; - case PY_TOKEN_DEL_AMPERSAND_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_AND); break; - case PY_TOKEN_DEL_DBL_LESS_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_LSHIFT); break; - case PY_TOKEN_DEL_DBL_MORE_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_RSHIFT); break; - case PY_TOKEN_DEL_PLUS_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_ADD); break; - case PY_TOKEN_DEL_MINUS_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_SUBTRACT); break; - case PY_TOKEN_DEL_STAR_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_MULTIPLY); break; - case PY_TOKEN_DEL_DBL_SLASH_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_FLOOR_DIVIDE); break; - case PY_TOKEN_DEL_SLASH_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_TRUE_DIVIDE); break; - case PY_TOKEN_DEL_PERCENT_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_MODULO); break; - case PY_TOKEN_DEL_DBL_STAR_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_POWER); break; + switch (MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0])) { + case MP_TOKEN_DEL_PIPE_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_OR); break; + case MP_TOKEN_DEL_CARET_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_XOR); break; + case MP_TOKEN_DEL_AMPERSAND_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_AND); break; + case MP_TOKEN_DEL_DBL_LESS_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_LSHIFT); break; + case MP_TOKEN_DEL_DBL_MORE_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_RSHIFT); break; + case MP_TOKEN_DEL_PLUS_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_ADD); break; + case MP_TOKEN_DEL_MINUS_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_SUBTRACT); break; + case MP_TOKEN_DEL_STAR_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_MULTIPLY); break; + case MP_TOKEN_DEL_DBL_SLASH_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_FLOOR_DIVIDE); break; + case MP_TOKEN_DEL_SLASH_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_TRUE_DIVIDE); break; + case MP_TOKEN_DEL_PERCENT_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_MODULO); break; + case MP_TOKEN_DEL_DBL_STAR_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_POWER); break; default: assert(0); // shouldn't happen } c_assign(comp, pns->nodes[0], ASSIGN_AUG_STORE); // lhs store for aug assign } else if (kind == PN_expr_stmt_assign_list) { - int rhs = PY_PARSE_NODE_STRUCT_NUM_NODES(pns1) - 1; - compile_node(comp, ((py_parse_node_struct_t*)pns1->nodes[rhs])->nodes[0]); // rhs + int rhs = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1) - 1; + compile_node(comp, ((mp_parse_node_struct_t*)pns1->nodes[rhs])->nodes[0]); // rhs // following CPython, we store left-most first if (rhs > 0) { EMIT(dup_top); @@ -1781,28 +1781,28 @@ void compile_expr_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { if (i + 1 < rhs) { EMIT(dup_top); } - c_assign(comp, ((py_parse_node_struct_t*)pns1->nodes[i])->nodes[0], ASSIGN_STORE); // middle store + c_assign(comp, ((mp_parse_node_struct_t*)pns1->nodes[i])->nodes[0], ASSIGN_STORE); // middle store } } else if (kind == PN_expr_stmt_assign) { - if (PY_PARSE_NODE_IS_STRUCT_KIND(pns1->nodes[0], PN_testlist_star_expr) - && PY_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr) - && PY_PARSE_NODE_STRUCT_NUM_NODES((py_parse_node_struct_t*)pns1->nodes[0]) == 2 - && PY_PARSE_NODE_STRUCT_NUM_NODES((py_parse_node_struct_t*)pns->nodes[0]) == 2) { + if (MP_PARSE_NODE_IS_STRUCT_KIND(pns1->nodes[0], PN_testlist_star_expr) + && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr) + && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns1->nodes[0]) == 2 + && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 2) { // optimisation for a, b = c, d; to match CPython's optimisation - py_parse_node_struct_t* pns10 = (py_parse_node_struct_t*)pns1->nodes[0]; - py_parse_node_struct_t* pns0 = (py_parse_node_struct_t*)pns->nodes[0]; + mp_parse_node_struct_t* pns10 = (mp_parse_node_struct_t*)pns1->nodes[0]; + mp_parse_node_struct_t* pns0 = (mp_parse_node_struct_t*)pns->nodes[0]; compile_node(comp, pns10->nodes[0]); // rhs compile_node(comp, pns10->nodes[1]); // rhs EMIT(rot_two); c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store - } else if (PY_PARSE_NODE_IS_STRUCT_KIND(pns1->nodes[0], PN_testlist_star_expr) - && PY_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr) - && PY_PARSE_NODE_STRUCT_NUM_NODES((py_parse_node_struct_t*)pns1->nodes[0]) == 3 - && PY_PARSE_NODE_STRUCT_NUM_NODES((py_parse_node_struct_t*)pns->nodes[0]) == 3) { + } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns1->nodes[0], PN_testlist_star_expr) + && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr) + && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns1->nodes[0]) == 3 + && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 3) { // optimisation for a, b, c = d, e, f; to match CPython's optimisation - py_parse_node_struct_t* pns10 = (py_parse_node_struct_t*)pns1->nodes[0]; - py_parse_node_struct_t* pns0 = (py_parse_node_struct_t*)pns->nodes[0]; + mp_parse_node_struct_t* pns10 = (mp_parse_node_struct_t*)pns1->nodes[0]; + mp_parse_node_struct_t* pns0 = (mp_parse_node_struct_t*)pns->nodes[0]; compile_node(comp, pns10->nodes[0]); // rhs compile_node(comp, pns10->nodes[1]); // rhs compile_node(comp, pns10->nodes[2]); // rhs @@ -1822,8 +1822,8 @@ void compile_expr_stmt(compiler_t *comp, py_parse_node_struct_t *pns) { } } -void c_binary_op(compiler_t *comp, py_parse_node_struct_t *pns, rt_binary_op_t binary_op) { - int num_nodes = PY_PARSE_NODE_STRUCT_NUM_NODES(pns); +void c_binary_op(compiler_t *comp, mp_parse_node_struct_t *pns, rt_binary_op_t binary_op) { + int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); compile_node(comp, pns->nodes[0]); for (int i = 1; i < num_nodes; i += 1) { compile_node(comp, pns->nodes[i]); @@ -1831,9 +1831,9 @@ void c_binary_op(compiler_t *comp, py_parse_node_struct_t *pns, rt_binary_op_t b } } -void compile_test_if_expr(compiler_t *comp, py_parse_node_struct_t *pns) { - assert(PY_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_test_if_else)); - py_parse_node_struct_t *pns_test_if_else = (py_parse_node_struct_t*)pns->nodes[1]; +void compile_test_if_expr(compiler_t *comp, mp_parse_node_struct_t *pns) { + assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_test_if_else)); + mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t*)pns->nodes[1]; int stack_size = EMIT(get_stack_size); int l_fail = comp_next_label(comp); @@ -1847,16 +1847,16 @@ void compile_test_if_expr(compiler_t *comp, py_parse_node_struct_t *pns) { EMIT(label_assign, l_end); } -void compile_lambdef(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_lambdef(compiler_t *comp, mp_parse_node_struct_t *pns) { // TODO default params etc for lambda; possibly just use funcdef code - //py_parse_node_t pn_params = pns->nodes[0]; - //py_parse_node_t pn_body = pns->nodes[1]; + //mp_parse_node_t pn_params = pns->nodes[0]; + //mp_parse_node_t pn_body = pns->nodes[1]; if (comp->pass == PASS_1) { // create a new scope for this lambda - scope_t *s = scope_new_and_link(comp, SCOPE_LAMBDA, (py_parse_node_t)pns, comp->scope_cur->emit_options); + scope_t *s = scope_new_and_link(comp, SCOPE_LAMBDA, (mp_parse_node_t)pns, comp->scope_cur->emit_options); // store the lambda scope so the compiling function (this one) can use it at each pass - pns->nodes[2] = (py_parse_node_t)s; + pns->nodes[2] = (mp_parse_node_t)s; } // get the scope for this lambda @@ -1866,9 +1866,9 @@ void compile_lambdef(compiler_t *comp, py_parse_node_struct_t *pns) { close_over_variables_etc(comp, this_scope, 0, 0); } -void compile_or_test(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_or_test(compiler_t *comp, mp_parse_node_struct_t *pns) { int l_end = comp_next_label(comp); - int n = PY_PARSE_NODE_STRUCT_NUM_NODES(pns); + int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); for (int i = 0; i < n; i += 1) { compile_node(comp, pns->nodes[i]); if (i + 1 < n) { @@ -1878,9 +1878,9 @@ void compile_or_test(compiler_t *comp, py_parse_node_struct_t *pns) { EMIT(label_assign, l_end); } -void compile_and_test(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_and_test(compiler_t *comp, mp_parse_node_struct_t *pns) { int l_end = comp_next_label(comp); - int n = PY_PARSE_NODE_STRUCT_NUM_NODES(pns); + int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); for (int i = 0; i < n; i += 1) { compile_node(comp, pns->nodes[i]); if (i + 1 < n) { @@ -1890,14 +1890,14 @@ void compile_and_test(compiler_t *comp, py_parse_node_struct_t *pns) { EMIT(label_assign, l_end); } -void compile_not_test_2(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_not_test_2(compiler_t *comp, mp_parse_node_struct_t *pns) { compile_node(comp, pns->nodes[0]); EMIT(unary_op, RT_UNARY_OP_NOT); } -void compile_comparison(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) { int stack_size = EMIT(get_stack_size); - int num_nodes = PY_PARSE_NODE_STRUCT_NUM_NODES(pns); + int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); compile_node(comp, pns->nodes[0]); bool multi = (num_nodes > 3); int l_fail = 0; @@ -1910,27 +1910,27 @@ void compile_comparison(compiler_t *comp, py_parse_node_struct_t *pns) { EMIT(dup_top); EMIT(rot_three); } - if (PY_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], PY_TOKEN_OP_LESS)) { + if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_LESS)) { EMIT(compare_op, RT_COMPARE_OP_LESS); - } else if (PY_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], PY_TOKEN_OP_MORE)) { + } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_MORE)) { EMIT(compare_op, RT_COMPARE_OP_MORE); - } else if (PY_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], PY_TOKEN_OP_DBL_EQUAL)) { + } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_EQUAL)) { EMIT(compare_op, RT_COMPARE_OP_EQUAL); - } else if (PY_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], PY_TOKEN_OP_LESS_EQUAL)) { + } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_LESS_EQUAL)) { EMIT(compare_op, RT_COMPARE_OP_LESS_EQUAL); - } else if (PY_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], PY_TOKEN_OP_MORE_EQUAL)) { + } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_MORE_EQUAL)) { EMIT(compare_op, RT_COMPARE_OP_MORE_EQUAL); - } else if (PY_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], PY_TOKEN_OP_NOT_EQUAL)) { + } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_NOT_EQUAL)) { EMIT(compare_op, RT_COMPARE_OP_NOT_EQUAL); - } else if (PY_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], PY_TOKEN_KW_IN)) { + } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_KW_IN)) { EMIT(compare_op, RT_COMPARE_OP_IN); - } else if (PY_PARSE_NODE_IS_STRUCT(pns->nodes[i])) { - py_parse_node_struct_t *pns2 = (py_parse_node_struct_t*)pns->nodes[i]; - int kind = PY_PARSE_NODE_STRUCT_KIND(pns2); + } else if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[i])) { + mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[i]; + int kind = MP_PARSE_NODE_STRUCT_KIND(pns2); if (kind == PN_comp_op_not_in) { EMIT(compare_op, RT_COMPARE_OP_NOT_IN); } else if (kind == PN_comp_op_is) { - if (PY_PARSE_NODE_IS_NULL(pns2->nodes[0])) { + if (MP_PARSE_NODE_IS_NULL(pns2->nodes[0])) { EMIT(compare_op, RT_COMPARE_OP_IS); } else { EMIT(compare_op, RT_COMPARE_OP_IS_NOT); @@ -1958,33 +1958,33 @@ void compile_comparison(compiler_t *comp, py_parse_node_struct_t *pns) { } } -void compile_star_expr(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_star_expr(compiler_t *comp, mp_parse_node_struct_t *pns) { // TODO assert(0); compile_node(comp, pns->nodes[0]); //EMIT(unary_op, "UNARY_STAR"); } -void compile_expr(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_expr(compiler_t *comp, mp_parse_node_struct_t *pns) { c_binary_op(comp, pns, RT_BINARY_OP_OR); } -void compile_xor_expr(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_xor_expr(compiler_t *comp, mp_parse_node_struct_t *pns) { c_binary_op(comp, pns, RT_BINARY_OP_XOR); } -void compile_and_expr(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_and_expr(compiler_t *comp, mp_parse_node_struct_t *pns) { c_binary_op(comp, pns, RT_BINARY_OP_AND); } -void compile_shift_expr(compiler_t *comp, py_parse_node_struct_t *pns) { - int num_nodes = PY_PARSE_NODE_STRUCT_NUM_NODES(pns); +void compile_shift_expr(compiler_t *comp, mp_parse_node_struct_t *pns) { + int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); compile_node(comp, pns->nodes[0]); for (int i = 1; i + 1 < num_nodes; i += 2) { compile_node(comp, pns->nodes[i + 1]); - if (PY_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], PY_TOKEN_OP_DBL_LESS)) { + if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_LESS)) { EMIT(binary_op, RT_BINARY_OP_LSHIFT); - } else if (PY_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], PY_TOKEN_OP_DBL_MORE)) { + } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_MORE)) { EMIT(binary_op, RT_BINARY_OP_RSHIFT); } else { // shouldn't happen @@ -1993,14 +1993,14 @@ void compile_shift_expr(compiler_t *comp, py_parse_node_struct_t *pns) { } } -void compile_arith_expr(compiler_t *comp, py_parse_node_struct_t *pns) { - int num_nodes = PY_PARSE_NODE_STRUCT_NUM_NODES(pns); +void compile_arith_expr(compiler_t *comp, mp_parse_node_struct_t *pns) { + int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); compile_node(comp, pns->nodes[0]); for (int i = 1; i + 1 < num_nodes; i += 2) { compile_node(comp, pns->nodes[i + 1]); - if (PY_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], PY_TOKEN_OP_PLUS)) { + if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_PLUS)) { EMIT(binary_op, RT_BINARY_OP_ADD); - } else if (PY_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], PY_TOKEN_OP_MINUS)) { + } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_MINUS)) { EMIT(binary_op, RT_BINARY_OP_SUBTRACT); } else { // shouldn't happen @@ -2009,18 +2009,18 @@ void compile_arith_expr(compiler_t *comp, py_parse_node_struct_t *pns) { } } -void compile_term(compiler_t *comp, py_parse_node_struct_t *pns) { - int num_nodes = PY_PARSE_NODE_STRUCT_NUM_NODES(pns); +void compile_term(compiler_t *comp, mp_parse_node_struct_t *pns) { + int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); compile_node(comp, pns->nodes[0]); for (int i = 1; i + 1 < num_nodes; i += 2) { compile_node(comp, pns->nodes[i + 1]); - if (PY_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], PY_TOKEN_OP_STAR)) { + if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_STAR)) { EMIT(binary_op, RT_BINARY_OP_MULTIPLY); - } else if (PY_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], PY_TOKEN_OP_DBL_SLASH)) { + } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_SLASH)) { EMIT(binary_op, RT_BINARY_OP_FLOOR_DIVIDE); - } else if (PY_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], PY_TOKEN_OP_SLASH)) { + } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_SLASH)) { EMIT(binary_op, RT_BINARY_OP_TRUE_DIVIDE); - } else if (PY_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], PY_TOKEN_OP_PERCENT)) { + } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_PERCENT)) { EMIT(binary_op, RT_BINARY_OP_MODULO); } else { // shouldn't happen @@ -2029,13 +2029,13 @@ void compile_term(compiler_t *comp, py_parse_node_struct_t *pns) { } } -void compile_factor_2(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_factor_2(compiler_t *comp, mp_parse_node_struct_t *pns) { compile_node(comp, pns->nodes[1]); - if (PY_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], PY_TOKEN_OP_PLUS)) { + if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_PLUS)) { EMIT(unary_op, RT_UNARY_OP_POSITIVE); - } else if (PY_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], PY_TOKEN_OP_MINUS)) { + } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_MINUS)) { EMIT(unary_op, RT_UNARY_OP_NEGATIVE); - } else if (PY_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], PY_TOKEN_OP_TILDE)) { + } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_TILDE)) { EMIT(unary_op, RT_UNARY_OP_INVERT); } else { // shouldn't happen @@ -2043,7 +2043,7 @@ void compile_factor_2(compiler_t *comp, py_parse_node_struct_t *pns) { } } -void compile_trailer_paren_helper(compiler_t *comp, py_parse_node_struct_t *pns, bool is_method_call) { +void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_struct_t *pns, bool is_method_call) { // function to call is on top of stack int old_n_arg_keyword = comp->n_arg_keyword; @@ -2075,14 +2075,14 @@ void compile_trailer_paren_helper(compiler_t *comp, py_parse_node_struct_t *pns, comp->have_dbl_star_arg = old_have_dbl_star_arg; } -void compile_power_trailers(compiler_t *comp, py_parse_node_struct_t *pns) { - int num_nodes = PY_PARSE_NODE_STRUCT_NUM_NODES(pns); +void compile_power_trailers(compiler_t *comp, mp_parse_node_struct_t *pns) { + int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); for (int i = 0; i < num_nodes; i++) { - if (i + 1 < num_nodes && PY_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[i], PN_trailer_period) && PY_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[i + 1], PN_trailer_paren)) { + if (i + 1 < num_nodes && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[i], PN_trailer_period) && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[i + 1], PN_trailer_paren)) { // optimisation for method calls a.f(...), following PyPy - py_parse_node_struct_t *pns_period = (py_parse_node_struct_t*)pns->nodes[i]; - py_parse_node_struct_t *pns_paren = (py_parse_node_struct_t*)pns->nodes[i + 1]; - EMIT(load_method, PY_PARSE_NODE_LEAF_ARG(pns_period->nodes[0])); // get the method + mp_parse_node_struct_t *pns_period = (mp_parse_node_struct_t*)pns->nodes[i]; + mp_parse_node_struct_t *pns_paren = (mp_parse_node_struct_t*)pns->nodes[i + 1]; + EMIT(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0])); // get the method compile_trailer_paren_helper(comp, pns_paren, true); i += 1; } else { @@ -2091,29 +2091,29 @@ void compile_power_trailers(compiler_t *comp, py_parse_node_struct_t *pns) { } } -void compile_power_dbl_star(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_power_dbl_star(compiler_t *comp, mp_parse_node_struct_t *pns) { compile_node(comp, pns->nodes[0]); EMIT(binary_op, RT_BINARY_OP_POWER); } -void compile_atom_string(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_atom_string(compiler_t *comp, mp_parse_node_struct_t *pns) { // a list of strings // check type of list (string or bytes) and count total number of bytes - int n = PY_PARSE_NODE_STRUCT_NUM_NODES(pns); + int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); int n_bytes = 0; - int string_kind = PY_PARSE_NODE_NULL; + int string_kind = MP_PARSE_NODE_NULL; for (int i = 0; i < n; i++) { - assert(PY_PARSE_NODE_IS_LEAF(pns->nodes[i])); - int pn_kind = PY_PARSE_NODE_LEAF_KIND(pns->nodes[i]); - assert(pn_kind == PY_PARSE_NODE_STRING || pn_kind == PY_PARSE_NODE_BYTES); + assert(MP_PARSE_NODE_IS_LEAF(pns->nodes[i])); + int pn_kind = MP_PARSE_NODE_LEAF_KIND(pns->nodes[i]); + assert(pn_kind == MP_PARSE_NODE_STRING || pn_kind == MP_PARSE_NODE_BYTES); if (i == 0) { string_kind = pn_kind; } else if (pn_kind != string_kind) { printf("SyntaxError: cannot mix bytes and nonbytes literals\n"); return; } - const char *str = qstr_str(PY_PARSE_NODE_LEAF_ARG(pns->nodes[i])); + const char *str = qstr_str(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i])); n_bytes += strlen(str); } @@ -2123,24 +2123,24 @@ void compile_atom_string(compiler_t *comp, py_parse_node_struct_t *pns) { // concatenate string/bytes for (int i = 0; i < n; i++) { - const char *str = qstr_str(PY_PARSE_NODE_LEAF_ARG(pns->nodes[i])); + const char *str = qstr_str(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i])); strcat(cat_str, str); } - EMIT(load_const_str, qstr_from_str_take(cat_str), string_kind == PY_PARSE_NODE_BYTES); + EMIT(load_const_str, qstr_from_str_take(cat_str), string_kind == MP_PARSE_NODE_BYTES); } // pns needs to have 2 nodes, first is lhs of comprehension, second is PN_comp_for node -void compile_comprehension(compiler_t *comp, py_parse_node_struct_t *pns, scope_kind_t kind) { - assert(PY_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2); - assert(PY_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for)); - py_parse_node_struct_t *pns_comp_for = (py_parse_node_struct_t*)pns->nodes[1]; +void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind) { + assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2); + assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for)); + mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1]; if (comp->pass == PASS_1) { // create a new scope for this comprehension - scope_t *s = scope_new_and_link(comp, kind, (py_parse_node_t)pns, comp->scope_cur->emit_options); + scope_t *s = scope_new_and_link(comp, kind, (mp_parse_node_t)pns, comp->scope_cur->emit_options); // store the comprehension scope so the compiling function (this one) can use it at each pass - pns_comp_for->nodes[3] = (py_parse_node_t)s; + pns_comp_for->nodes[3] = (mp_parse_node_t)s; } // get the scope for this comprehension @@ -2154,23 +2154,23 @@ void compile_comprehension(compiler_t *comp, py_parse_node_struct_t *pns, scope_ EMIT(call_function, 1, 0, false, false); } -void compile_atom_paren(compiler_t *comp, py_parse_node_struct_t *pns) { - if (PY_PARSE_NODE_IS_NULL(pns->nodes[0])) { +void compile_atom_paren(compiler_t *comp, mp_parse_node_struct_t *pns) { + if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) { // an empty tuple - c_tuple(comp, PY_PARSE_NODE_NULL, NULL); - } else if (PY_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) { - pns = (py_parse_node_struct_t*)pns->nodes[0]; - assert(!PY_PARSE_NODE_IS_NULL(pns->nodes[1])); - if (PY_PARSE_NODE_IS_STRUCT(pns->nodes[1])) { - py_parse_node_struct_t *pns2 = (py_parse_node_struct_t*)pns->nodes[1]; - if (PY_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) { + c_tuple(comp, MP_PARSE_NODE_NULL, NULL); + } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) { + pns = (mp_parse_node_struct_t*)pns->nodes[0]; + assert(!MP_PARSE_NODE_IS_NULL(pns->nodes[1])); + if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) { + mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1]; + if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) { // tuple of one item, with trailing comma - assert(PY_PARSE_NODE_IS_NULL(pns2->nodes[0])); + assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0])); c_tuple(comp, pns->nodes[0], NULL); - } else if (PY_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) { + } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) { // tuple of many items c_tuple(comp, pns->nodes[0], pns2); - } else if (PY_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) { + } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) { // generator expression compile_comprehension(comp, pns, SCOPE_GEN_EXPR); } else { @@ -2180,7 +2180,7 @@ void compile_atom_paren(compiler_t *comp, py_parse_node_struct_t *pns) { } else { // tuple with 2 items tuple_with_2_items: - c_tuple(comp, PY_PARSE_NODE_NULL, pns); + c_tuple(comp, MP_PARSE_NODE_NULL, pns); } } else { // parenthesis around a single item, is just that item @@ -2188,25 +2188,25 @@ void compile_atom_paren(compiler_t *comp, py_parse_node_struct_t *pns) { } } -void compile_atom_bracket(compiler_t *comp, py_parse_node_struct_t *pns) { - if (PY_PARSE_NODE_IS_NULL(pns->nodes[0])) { +void compile_atom_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) { + if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) { // empty list EMIT(build_list, 0); - } else if (PY_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) { - py_parse_node_struct_t *pns2 = (py_parse_node_struct_t*)pns->nodes[0]; - if (PY_PARSE_NODE_IS_STRUCT(pns2->nodes[1])) { - py_parse_node_struct_t *pns3 = (py_parse_node_struct_t*)pns2->nodes[1]; - if (PY_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3b) { + } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) { + mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[0]; + if (MP_PARSE_NODE_IS_STRUCT(pns2->nodes[1])) { + mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pns2->nodes[1]; + if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3b) { // list of one item, with trailing comma - assert(PY_PARSE_NODE_IS_NULL(pns3->nodes[0])); + assert(MP_PARSE_NODE_IS_NULL(pns3->nodes[0])); compile_node(comp, pns2->nodes[0]); EMIT(build_list, 1); - } else if (PY_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3c) { + } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3c) { // list of many items compile_node(comp, pns2->nodes[0]); compile_generic_all_nodes(comp, pns3); - EMIT(build_list, 1 + PY_PARSE_NODE_STRUCT_NUM_NODES(pns3)); - } else if (PY_PARSE_NODE_STRUCT_KIND(pns3) == PN_comp_for) { + EMIT(build_list, 1 + MP_PARSE_NODE_STRUCT_NUM_NODES(pns3)); + } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_comp_for) { // list comprehension compile_comprehension(comp, pns2, SCOPE_LIST_COMP); } else { @@ -2227,31 +2227,31 @@ void compile_atom_bracket(compiler_t *comp, py_parse_node_struct_t *pns) { } } -void compile_atom_brace(compiler_t *comp, py_parse_node_struct_t *pns) { - py_parse_node_t pn = pns->nodes[0]; - if (PY_PARSE_NODE_IS_NULL(pn)) { +void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) { + mp_parse_node_t pn = pns->nodes[0]; + if (MP_PARSE_NODE_IS_NULL(pn)) { // empty dict EMIT(build_map, 0); - } else if (PY_PARSE_NODE_IS_STRUCT(pn)) { - pns = (py_parse_node_struct_t*)pn; - if (PY_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker_item) { + } else if (MP_PARSE_NODE_IS_STRUCT(pn)) { + pns = (mp_parse_node_struct_t*)pn; + if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker_item) { // dict with one element EMIT(build_map, 1); compile_node(comp, pn); EMIT(store_map); - } else if (PY_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker) { - assert(PY_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should succeed - py_parse_node_struct_t *pns1 = (py_parse_node_struct_t*)pns->nodes[1]; - if (PY_PARSE_NODE_STRUCT_KIND(pns1) == PN_dictorsetmaker_list) { + } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker) { + assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should succeed + mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1]; + if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_dictorsetmaker_list) { // dict/set with multiple elements // get tail elements (2nd, 3rd, ...) - py_parse_node_t *nodes; + mp_parse_node_t *nodes; int n = list_get(&pns1->nodes[0], PN_dictorsetmaker_list2, &nodes); // first element sets whether it's a dict or set bool is_dict; - if (PY_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) { + if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) { // a dictionary EMIT(build_map, 1 + n); compile_node(comp, pns->nodes[0]); @@ -2265,8 +2265,8 @@ void compile_atom_brace(compiler_t *comp, py_parse_node_struct_t *pns) { // process rest of elements for (int i = 0; i < n; i++) { - py_parse_node_t pn = nodes[i]; - bool is_key_value = PY_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dictorsetmaker_item); + mp_parse_node_t pn = nodes[i]; + bool is_key_value = MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dictorsetmaker_item); compile_node(comp, pn); if (is_dict) { if (!is_key_value) { @@ -2286,9 +2286,9 @@ void compile_atom_brace(compiler_t *comp, py_parse_node_struct_t *pns) { if (!is_dict) { EMIT(build_set, 1 + n); } - } else if (PY_PARSE_NODE_STRUCT_KIND(pns1) == PN_comp_for) { + } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_comp_for) { // dict/set comprehension - if (PY_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) { + if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) { // a dictionary comprehension compile_comprehension(comp, pns, SCOPE_DICT_COMP); } else { @@ -2311,34 +2311,34 @@ void compile_atom_brace(compiler_t *comp, py_parse_node_struct_t *pns) { } } -void compile_trailer_paren(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_trailer_paren(compiler_t *comp, mp_parse_node_struct_t *pns) { compile_trailer_paren_helper(comp, pns, false); } -void compile_trailer_bracket(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_trailer_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) { // object who's index we want is on top of stack compile_node(comp, pns->nodes[0]); // the index EMIT(binary_op, RT_BINARY_OP_SUBSCR); } -void compile_trailer_period(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_trailer_period(compiler_t *comp, mp_parse_node_struct_t *pns) { // object who's attribute we want is on top of stack - EMIT(load_attr, PY_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // attribute to get + EMIT(load_attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // attribute to get } -void compile_subscript_3_helper(compiler_t *comp, py_parse_node_struct_t *pns) { - assert(PY_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3); // should always be - py_parse_node_t pn = pns->nodes[0]; - if (PY_PARSE_NODE_IS_NULL(pn)) { +void compile_subscript_3_helper(compiler_t *comp, mp_parse_node_struct_t *pns) { + assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3); // should always be + mp_parse_node_t pn = pns->nodes[0]; + if (MP_PARSE_NODE_IS_NULL(pn)) { // [?:] - EMIT(load_const_tok, PY_TOKEN_KW_NONE); + EMIT(load_const_tok, MP_TOKEN_KW_NONE); EMIT(build_slice, 2); - } else if (PY_PARSE_NODE_IS_STRUCT(pn)) { - pns = (py_parse_node_struct_t*)pn; - if (PY_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3c) { - EMIT(load_const_tok, PY_TOKEN_KW_NONE); + } else if (MP_PARSE_NODE_IS_STRUCT(pn)) { + pns = (mp_parse_node_struct_t*)pn; + if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3c) { + EMIT(load_const_tok, MP_TOKEN_KW_NONE); pn = pns->nodes[0]; - if (PY_PARSE_NODE_IS_NULL(pn)) { + if (MP_PARSE_NODE_IS_NULL(pn)) { // [?::] EMIT(build_slice, 2); } else { @@ -2346,12 +2346,12 @@ void compile_subscript_3_helper(compiler_t *comp, py_parse_node_struct_t *pns) { compile_node(comp, pn); EMIT(build_slice, 3); } - } else if (PY_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3d) { + } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3d) { compile_node(comp, pns->nodes[0]); - assert(PY_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be - pns = (py_parse_node_struct_t*)pns->nodes[1]; - assert(PY_PARSE_NODE_STRUCT_KIND(pns) == PN_sliceop); // should always be - if (PY_PARSE_NODE_IS_NULL(pns->nodes[0])) { + assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be + pns = (mp_parse_node_struct_t*)pns->nodes[1]; + assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_sliceop); // should always be + if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) { // [?:x:] EMIT(build_slice, 2); } else { @@ -2371,30 +2371,30 @@ void compile_subscript_3_helper(compiler_t *comp, py_parse_node_struct_t *pns) { } } -void compile_subscript_2(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_subscript_2(compiler_t *comp, mp_parse_node_struct_t *pns) { compile_node(comp, pns->nodes[0]); // start of slice - assert(PY_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be - compile_subscript_3_helper(comp, (py_parse_node_struct_t*)pns->nodes[1]); + assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be + compile_subscript_3_helper(comp, (mp_parse_node_struct_t*)pns->nodes[1]); } -void compile_subscript_3(compiler_t *comp, py_parse_node_struct_t *pns) { - EMIT(load_const_tok, PY_TOKEN_KW_NONE); +void compile_subscript_3(compiler_t *comp, mp_parse_node_struct_t *pns) { + EMIT(load_const_tok, MP_TOKEN_KW_NONE); compile_subscript_3_helper(comp, pns); } -void compile_dictorsetmaker_item(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_dictorsetmaker_item(compiler_t *comp, mp_parse_node_struct_t *pns) { // if this is called then we are compiling a dict key:value pair compile_node(comp, pns->nodes[1]); // value compile_node(comp, pns->nodes[0]); // key } -void compile_classdef(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_classdef(compiler_t *comp, mp_parse_node_struct_t *pns) { qstr cname = compile_classdef_helper(comp, pns, comp->scope_cur->emit_options); // store class object into class name EMIT(store_id, cname); } -void compile_arglist_star(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_arglist_star(compiler_t *comp, mp_parse_node_struct_t *pns) { if (comp->have_star_arg) { printf("SyntaxError?: can't have multiple *x\n"); return; @@ -2403,7 +2403,7 @@ void compile_arglist_star(compiler_t *comp, py_parse_node_struct_t *pns) { compile_node(comp, pns->nodes[0]); } -void compile_arglist_dbl_star(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_arglist_dbl_star(compiler_t *comp, mp_parse_node_struct_t *pns) { if (comp->have_dbl_star_arg) { printf("SyntaxError?: can't have multiple **x\n"); return; @@ -2412,18 +2412,18 @@ void compile_arglist_dbl_star(compiler_t *comp, py_parse_node_struct_t *pns) { compile_node(comp, pns->nodes[0]); } -void compile_argument(compiler_t *comp, py_parse_node_struct_t *pns) { - assert(PY_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be - py_parse_node_struct_t *pns2 = (py_parse_node_struct_t*)pns->nodes[1]; - if (PY_PARSE_NODE_STRUCT_KIND(pns2) == PN_argument_3) { - if (!PY_PARSE_NODE_IS_ID(pns->nodes[0])) { +void compile_argument(compiler_t *comp, mp_parse_node_struct_t *pns) { + assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be + mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1]; + if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_argument_3) { + if (!MP_PARSE_NODE_IS_ID(pns->nodes[0])) { printf("SyntaxError?: lhs of keyword argument must be an id\n"); return; } - EMIT(load_const_id, PY_PARSE_NODE_LEAF_ARG(pns->nodes[0])); + EMIT(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); compile_node(comp, pns2->nodes[0]); comp->n_arg_keyword += 1; - } else if (PY_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) { + } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) { compile_comprehension(comp, pns, SCOPE_GEN_EXPR); } else { // shouldn't happen @@ -2431,19 +2431,19 @@ void compile_argument(compiler_t *comp, py_parse_node_struct_t *pns) { } } -void compile_yield_expr(compiler_t *comp, py_parse_node_struct_t *pns) { +void compile_yield_expr(compiler_t *comp, mp_parse_node_struct_t *pns) { if (comp->scope_cur->kind != SCOPE_FUNCTION) { printf("SyntaxError: 'yield' outside function\n"); return; } - if (PY_PARSE_NODE_IS_NULL(pns->nodes[0])) { - EMIT(load_const_tok, PY_TOKEN_KW_NONE); + if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) { + EMIT(load_const_tok, MP_TOKEN_KW_NONE); EMIT(yield_value); - } else if (PY_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_yield_arg_from)) { - pns = (py_parse_node_struct_t*)pns->nodes[0]; + } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_yield_arg_from)) { + pns = (mp_parse_node_struct_t*)pns->nodes[0]; compile_node(comp, pns->nodes[0]); EMIT(get_iter); - EMIT(load_const_tok, PY_TOKEN_KW_NONE); + EMIT(load_const_tok, MP_TOKEN_KW_NONE); EMIT(yield_from); } else { compile_node(comp, pns->nodes[0]); @@ -2451,7 +2451,7 @@ void compile_yield_expr(compiler_t *comp, py_parse_node_struct_t *pns) { } } -typedef void (*compile_function_t)(compiler_t*, py_parse_node_struct_t*); +typedef void (*compile_function_t)(compiler_t*, mp_parse_node_struct_t*); static compile_function_t compile_function[] = { NULL, #define nc NULL @@ -2463,20 +2463,20 @@ static compile_function_t compile_function[] = { #undef DEF_RULE }; -void compile_node(compiler_t *comp, py_parse_node_t pn) { - if (PY_PARSE_NODE_IS_NULL(pn)) { +void compile_node(compiler_t *comp, mp_parse_node_t pn) { + if (MP_PARSE_NODE_IS_NULL(pn)) { // pass - } else if (PY_PARSE_NODE_IS_LEAF(pn)) { - int arg = PY_PARSE_NODE_LEAF_ARG(pn); - switch (PY_PARSE_NODE_LEAF_KIND(pn)) { - case PY_PARSE_NODE_ID: EMIT(load_id, arg); break; - case PY_PARSE_NODE_SMALL_INT: EMIT(load_const_small_int, arg); break; - case PY_PARSE_NODE_INTEGER: EMIT(load_const_int, arg); break; - case PY_PARSE_NODE_DECIMAL: EMIT(load_const_dec, arg); break; - case PY_PARSE_NODE_STRING: EMIT(load_const_str, arg, false); break; - case PY_PARSE_NODE_BYTES: EMIT(load_const_str, arg, true); break; - case PY_PARSE_NODE_TOKEN: - if (arg == PY_TOKEN_NEWLINE) { + } else if (MP_PARSE_NODE_IS_LEAF(pn)) { + int arg = MP_PARSE_NODE_LEAF_ARG(pn); + switch (MP_PARSE_NODE_LEAF_KIND(pn)) { + case MP_PARSE_NODE_ID: EMIT(load_id, arg); break; + case MP_PARSE_NODE_SMALL_INT: EMIT(load_const_small_int, arg); break; + case MP_PARSE_NODE_INTEGER: EMIT(load_const_int, arg); break; + case MP_PARSE_NODE_DECIMAL: EMIT(load_const_dec, arg); break; + case MP_PARSE_NODE_STRING: EMIT(load_const_str, arg, false); break; + case MP_PARSE_NODE_BYTES: EMIT(load_const_str, arg, true); break; + case MP_PARSE_NODE_TOKEN: + if (arg == MP_TOKEN_NEWLINE) { // this can occur when file_input lets through a NEWLINE (eg if file starts with a newline) // or when single_input lets through a NEWLINE (user enters a blank line) // do nothing @@ -2487,11 +2487,11 @@ void compile_node(compiler_t *comp, py_parse_node_t pn) { default: assert(0); } } else { - py_parse_node_struct_t *pns = (py_parse_node_struct_t*)pn; - compile_function_t f = compile_function[PY_PARSE_NODE_STRUCT_KIND(pns)]; + mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; + compile_function_t f = compile_function[MP_PARSE_NODE_STRUCT_KIND(pns)]; if (f == NULL) { - printf("node %u cannot be compiled\n", (uint)PY_PARSE_NODE_STRUCT_KIND(pns)); - py_parse_node_show(pn, 0); + printf("node %u cannot be compiled\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns)); + mp_parse_node_show(pn, 0); assert(0); } else { f(comp, pns); @@ -2499,32 +2499,32 @@ void compile_node(compiler_t *comp, py_parse_node_t pn) { } } -void compile_scope_func_lambda_param(compiler_t *comp, py_parse_node_t pn, pn_kind_t pn_name, pn_kind_t pn_star, pn_kind_t pn_dbl_star, bool allow_annotations) { +void compile_scope_func_lambda_param(compiler_t *comp, mp_parse_node_t pn, pn_kind_t pn_name, pn_kind_t pn_star, pn_kind_t pn_dbl_star, bool allow_annotations) { // TODO verify that *k and **k are last etc qstr param_name = 0; - py_parse_node_t pn_annotation = PY_PARSE_NODE_NULL; - if (PY_PARSE_NODE_IS_ID(pn)) { - param_name = PY_PARSE_NODE_LEAF_ARG(pn); + mp_parse_node_t pn_annotation = MP_PARSE_NODE_NULL; + if (MP_PARSE_NODE_IS_ID(pn)) { + param_name = MP_PARSE_NODE_LEAF_ARG(pn); if (comp->have_bare_star) { // comes after a bare star, so doesn't count as a parameter } else { comp->scope_cur->num_params += 1; } } else { - assert(PY_PARSE_NODE_IS_STRUCT(pn)); - py_parse_node_struct_t *pns = (py_parse_node_struct_t*)pn; - if (PY_PARSE_NODE_STRUCT_KIND(pns) == pn_name) { - param_name = PY_PARSE_NODE_LEAF_ARG(pns->nodes[0]); + assert(MP_PARSE_NODE_IS_STRUCT(pn)); + mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; + if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_name) { + param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); //int node_index = 1; unused if (allow_annotations) { - if (!PY_PARSE_NODE_IS_NULL(pns->nodes[1])) { + if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) { // this parameter has an annotation pn_annotation = pns->nodes[1]; } //node_index = 2; unused } /* this is obsolete now that num dict/default params are calculated in compile_funcdef_param - if (!PY_PARSE_NODE_IS_NULL(pns->nodes[node_index])) { + if (!MP_PARSE_NODE_IS_NULL(pns->nodes[node_index])) { // this parameter has a default value if (comp->have_bare_star) { comp->scope_cur->num_dict_params += 1; @@ -2538,29 +2538,29 @@ void compile_scope_func_lambda_param(compiler_t *comp, py_parse_node_t pn, pn_ki } else { comp->scope_cur->num_params += 1; } - } else if (PY_PARSE_NODE_STRUCT_KIND(pns) == pn_star) { - if (PY_PARSE_NODE_IS_NULL(pns->nodes[0])) { + } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_star) { + if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) { // bare star // TODO see http://www.python.org/dev/peps/pep-3102/ comp->have_bare_star = true; //assert(comp->scope_cur->num_dict_params == 0); - } else if (PY_PARSE_NODE_IS_ID(pns->nodes[0])) { + } else if (MP_PARSE_NODE_IS_ID(pns->nodes[0])) { // named star comp->scope_cur->flags |= SCOPE_FLAG_VARARGS; - param_name = PY_PARSE_NODE_LEAF_ARG(pns->nodes[0]); - } else if (allow_annotations && PY_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_tfpdef)) { + param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); + } else if (allow_annotations && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_tfpdef)) { // named star with annotation comp->scope_cur->flags |= SCOPE_FLAG_VARARGS; - pns = (py_parse_node_struct_t*)pns->nodes[0]; - param_name = PY_PARSE_NODE_LEAF_ARG(pns->nodes[0]); + pns = (mp_parse_node_struct_t*)pns->nodes[0]; + param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); pn_annotation = pns->nodes[1]; } else { // shouldn't happen assert(0); } - } else if (PY_PARSE_NODE_STRUCT_KIND(pns) == pn_dbl_star) { - param_name = PY_PARSE_NODE_LEAF_ARG(pns->nodes[0]); - if (allow_annotations && !PY_PARSE_NODE_IS_NULL(pns->nodes[1])) { + } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_dbl_star) { + param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); + if (allow_annotations && !MP_PARSE_NODE_IS_NULL(pns->nodes[1])) { // this parameter has an annotation pn_annotation = pns->nodes[1]; } @@ -2572,7 +2572,7 @@ void compile_scope_func_lambda_param(compiler_t *comp, py_parse_node_t pn, pn_ki } if (param_name != 0) { - if (!PY_PARSE_NODE_IS_NULL(pn_annotation)) { + if (!MP_PARSE_NODE_IS_NULL(pn_annotation)) { // TODO this parameter has an annotation } bool added; @@ -2586,17 +2586,17 @@ void compile_scope_func_lambda_param(compiler_t *comp, py_parse_node_t pn, pn_ki } } -void compile_scope_func_param(compiler_t *comp, py_parse_node_t pn) { +void compile_scope_func_param(compiler_t *comp, mp_parse_node_t pn) { compile_scope_func_lambda_param(comp, pn, PN_typedargslist_name, PN_typedargslist_star, PN_typedargslist_dbl_star, true); } -void compile_scope_lambda_param(compiler_t *comp, py_parse_node_t pn) { +void compile_scope_lambda_param(compiler_t *comp, mp_parse_node_t pn) { compile_scope_func_lambda_param(comp, pn, PN_varargslist_name, PN_varargslist_star, PN_varargslist_dbl_star, false); } -void compile_scope_comp_iter(compiler_t *comp, py_parse_node_t pn_iter, py_parse_node_t pn_inner_expr, int l_top, int for_depth) { +void compile_scope_comp_iter(compiler_t *comp, mp_parse_node_t pn_iter, mp_parse_node_t pn_inner_expr, int l_top, int for_depth) { tail_recursion: - if (PY_PARSE_NODE_IS_NULL(pn_iter)) { + if (MP_PARSE_NODE_IS_NULL(pn_iter)) { // no more nested if/for; compile inner expression compile_node(comp, pn_inner_expr); if (comp->scope_cur->kind == SCOPE_LIST_COMP) { @@ -2609,15 +2609,15 @@ void compile_scope_comp_iter(compiler_t *comp, py_parse_node_t pn_iter, py_parse EMIT(yield_value); EMIT(pop_top); } - } else if (PY_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_if)) { + } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_if)) { // if condition - py_parse_node_struct_t *pns_comp_if = (py_parse_node_struct_t*)pn_iter; + mp_parse_node_struct_t *pns_comp_if = (mp_parse_node_struct_t*)pn_iter; c_if_cond(comp, pns_comp_if->nodes[0], false, l_top); pn_iter = pns_comp_if->nodes[1]; goto tail_recursion; - } else if (PY_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_for)) { + } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_for)) { // for loop - py_parse_node_struct_t *pns_comp_for2 = (py_parse_node_struct_t*)pn_iter; + mp_parse_node_struct_t *pns_comp_for2 = (mp_parse_node_struct_t*)pn_iter; compile_node(comp, pns_comp_for2->nodes[1]); int l_end2 = comp_next_label(comp); int l_top2 = comp_next_label(comp); @@ -2635,37 +2635,37 @@ void compile_scope_comp_iter(compiler_t *comp, py_parse_node_t pn_iter, py_parse } } -void check_for_doc_string(compiler_t *comp, py_parse_node_t pn) { +void check_for_doc_string(compiler_t *comp, mp_parse_node_t pn) { // see http://www.python.org/dev/peps/pep-0257/ // look for the first statement - if (PY_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) { + if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) { // a statement; fall through - } else if (PY_PARSE_NODE_IS_STRUCT_KIND(pn, PN_file_input_2)) { + } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_file_input_2)) { // file input; find the first non-newline node - py_parse_node_struct_t *pns = (py_parse_node_struct_t*)pn; - int num_nodes = PY_PARSE_NODE_STRUCT_NUM_NODES(pns); + mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; + int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); for (int i = 0; i < num_nodes; i++) { pn = pns->nodes[i]; - if (!(PY_PARSE_NODE_IS_LEAF(pn) && PY_PARSE_NODE_LEAF_KIND(pn) == PY_PARSE_NODE_TOKEN && PY_PARSE_NODE_LEAF_ARG(pn) == PY_TOKEN_NEWLINE)) { + if (!(MP_PARSE_NODE_IS_LEAF(pn) && MP_PARSE_NODE_LEAF_KIND(pn) == MP_PARSE_NODE_TOKEN && MP_PARSE_NODE_LEAF_ARG(pn) == MP_TOKEN_NEWLINE)) { // not a newline, so this is the first statement; finish search break; } } // if we didn't find a non-newline then it's okay to fall through; pn will be a newline and so doc-string test below will fail gracefully - } else if (PY_PARSE_NODE_IS_STRUCT_KIND(pn, PN_suite_block_stmts)) { + } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_suite_block_stmts)) { // a list of statements; get the first one - pn = ((py_parse_node_struct_t*)pn)->nodes[0]; + pn = ((mp_parse_node_struct_t*)pn)->nodes[0]; } else { return; } // check the first statement for a doc string - if (PY_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) { - py_parse_node_struct_t* pns = (py_parse_node_struct_t*)pn; - if (PY_PARSE_NODE_IS_LEAF(pns->nodes[0])) { - int kind = PY_PARSE_NODE_LEAF_KIND(pns->nodes[0]); - if (kind == PY_PARSE_NODE_STRING) { + if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) { + mp_parse_node_struct_t* pns = (mp_parse_node_struct_t*)pn; + if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) { + int kind = MP_PARSE_NODE_LEAF_KIND(pns->nodes[0]); + if (kind == MP_PARSE_NODE_STRING) { compile_node(comp, pns->nodes[0]); // a doc string // store doc string EMIT(store_id, comp->qstr___doc__); @@ -2696,12 +2696,12 @@ void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { check_for_doc_string(comp, scope->pn); } compile_node(comp, scope->pn); - EMIT(load_const_tok, PY_TOKEN_KW_NONE); + EMIT(load_const_tok, MP_TOKEN_KW_NONE); EMIT(return_value); } else if (scope->kind == SCOPE_FUNCTION) { - assert(PY_PARSE_NODE_IS_STRUCT(scope->pn)); - py_parse_node_struct_t *pns = (py_parse_node_struct_t*)scope->pn; - assert(PY_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef); + assert(MP_PARSE_NODE_IS_STRUCT(scope->pn)); + mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn; + assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef); // work out number of parameters, keywords and default parameters, and add them to the id_info array // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc) @@ -2710,18 +2710,18 @@ void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_scope_func_param); } - assert(PY_PARSE_NODE_IS_NULL(pns->nodes[2])); // 2 is something... + assert(MP_PARSE_NODE_IS_NULL(pns->nodes[2])); // 2 is something... compile_node(comp, pns->nodes[3]); // 3 is function body // emit return if it wasn't the last opcode if (!EMIT(last_emit_was_return_value)) { - EMIT(load_const_tok, PY_TOKEN_KW_NONE); + EMIT(load_const_tok, MP_TOKEN_KW_NONE); EMIT(return_value); } } else if (scope->kind == SCOPE_LAMBDA) { - assert(PY_PARSE_NODE_IS_STRUCT(scope->pn)); - py_parse_node_struct_t *pns = (py_parse_node_struct_t*)scope->pn; - assert(PY_PARSE_NODE_STRUCT_NUM_NODES(pns) == 3); + assert(MP_PARSE_NODE_IS_STRUCT(scope->pn)); + mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn; + assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 3); // work out number of parameters, keywords and default parameters, and add them to the id_info array // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc) @@ -2735,11 +2735,11 @@ void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { } else if (scope->kind == SCOPE_LIST_COMP || scope->kind == SCOPE_DICT_COMP || scope->kind == SCOPE_SET_COMP || scope->kind == SCOPE_GEN_EXPR) { // a bit of a hack at the moment - assert(PY_PARSE_NODE_IS_STRUCT(scope->pn)); - py_parse_node_struct_t *pns = (py_parse_node_struct_t*)scope->pn; - assert(PY_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2); - assert(PY_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for)); - py_parse_node_struct_t *pns_comp_for = (py_parse_node_struct_t*)pns->nodes[1]; + assert(MP_PARSE_NODE_IS_STRUCT(scope->pn)); + mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn; + assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2); + assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for)); + mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1]; qstr qstr_arg = qstr_from_str_static(".0"); if (comp->pass == PASS_1) { @@ -2770,14 +2770,14 @@ void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { EMIT(for_iter_end); if (scope->kind == SCOPE_GEN_EXPR) { - EMIT(load_const_tok, PY_TOKEN_KW_NONE); + EMIT(load_const_tok, MP_TOKEN_KW_NONE); } EMIT(return_value); } else { assert(scope->kind == SCOPE_CLASS); - assert(PY_PARSE_NODE_IS_STRUCT(scope->pn)); - py_parse_node_struct_t *pns = (py_parse_node_struct_t*)scope->pn; - assert(PY_PARSE_NODE_STRUCT_KIND(pns) == PN_classdef); + assert(MP_PARSE_NODE_IS_STRUCT(scope->pn)); + mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn; + assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_classdef); if (comp->pass == PASS_1) { bool added; @@ -2795,7 +2795,7 @@ void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { EMIT(store_locals); EMIT(load_id, comp->qstr___name__); EMIT(store_id, comp->qstr___module__); - EMIT(load_const_id, PY_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // 0 is class name + EMIT(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // 0 is class name EMIT(store_id, comp->qstr___qualname__); check_for_doc_string(comp, pns->nodes[2]); @@ -2804,7 +2804,7 @@ void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { id_info_t *id = scope_find(scope, comp->qstr___class__); assert(id != NULL); if (id->kind == ID_INFO_KIND_LOCAL) { - EMIT(load_const_tok, PY_TOKEN_KW_NONE); + EMIT(load_const_tok, MP_TOKEN_KW_NONE); } else { EMIT(load_closure, comp->qstr___class__, 0); // XXX check this is the correct local num } @@ -2830,23 +2830,23 @@ void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass } // get the function definition parse node - assert(PY_PARSE_NODE_IS_STRUCT(scope->pn)); - py_parse_node_struct_t *pns = (py_parse_node_struct_t*)scope->pn; - assert(PY_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef); + assert(MP_PARSE_NODE_IS_STRUCT(scope->pn)); + mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn; + assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef); - //qstr f_id = PY_PARSE_NODE_LEAF_ARG(pns->nodes[0]); // function name + //qstr f_id = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); // function name // parameters are in pns->nodes[1] if (comp->pass == PASS_2) { - py_parse_node_t *pn_params; + mp_parse_node_t *pn_params; int n_params = list_get(&pns->nodes[1], PN_typedargslist, &pn_params); scope->num_params = EMIT_INLINE_ASM(count_params, n_params, pn_params); } - assert(PY_PARSE_NODE_IS_NULL(pns->nodes[2])); // type + assert(MP_PARSE_NODE_IS_NULL(pns->nodes[2])); // type - py_parse_node_t pn_body = pns->nodes[3]; // body - py_parse_node_t *nodes; + mp_parse_node_t pn_body = pns->nodes[3]; // body + mp_parse_node_t *nodes; int num = list_get(&pn_body, PN_suite_block_stmts, &nodes); if (comp->pass == PASS_3) { @@ -2855,30 +2855,30 @@ void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass } for (int i = 0; i < num; i++) { - assert(PY_PARSE_NODE_IS_STRUCT(nodes[i])); - py_parse_node_struct_t *pns2 = (py_parse_node_struct_t*)nodes[i]; - assert(PY_PARSE_NODE_STRUCT_KIND(pns2) == PN_expr_stmt); - assert(PY_PARSE_NODE_IS_STRUCT(pns2->nodes[0])); - assert(PY_PARSE_NODE_IS_NULL(pns2->nodes[1])); - pns2 = (py_parse_node_struct_t*)pns2->nodes[0]; - assert(PY_PARSE_NODE_STRUCT_KIND(pns2) == PN_power); - assert(PY_PARSE_NODE_IS_ID(pns2->nodes[0])); - assert(PY_PARSE_NODE_IS_STRUCT_KIND(pns2->nodes[1], PN_trailer_paren)); - assert(PY_PARSE_NODE_IS_NULL(pns2->nodes[2])); - qstr op = PY_PARSE_NODE_LEAF_ARG(pns2->nodes[0]); - pns2 = (py_parse_node_struct_t*)pns2->nodes[1]; // PN_trailer_paren - py_parse_node_t *pn_arg; + assert(MP_PARSE_NODE_IS_STRUCT(nodes[i])); + mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)nodes[i]; + assert(MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_expr_stmt); + assert(MP_PARSE_NODE_IS_STRUCT(pns2->nodes[0])); + assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[1])); + pns2 = (mp_parse_node_struct_t*)pns2->nodes[0]; + assert(MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_power); + assert(MP_PARSE_NODE_IS_ID(pns2->nodes[0])); + assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns2->nodes[1], PN_trailer_paren)); + assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[2])); + qstr op = MP_PARSE_NODE_LEAF_ARG(pns2->nodes[0]); + pns2 = (mp_parse_node_struct_t*)pns2->nodes[1]; // PN_trailer_paren + mp_parse_node_t *pn_arg; int n_args = list_get(&pns2->nodes[0], PN_arglist, &pn_arg); // emit instructions if (strcmp(qstr_str(op), "label") == 0) { - if (!(n_args == 1 && PY_PARSE_NODE_IS_ID(pn_arg[0]))) { + if (!(n_args == 1 && MP_PARSE_NODE_IS_ID(pn_arg[0]))) { printf("SyntaxError: inline assembler 'label' requires 1 argument\n"); return; } int lab = comp_next_label(comp); if (pass > PASS_1) { - EMIT_INLINE_ASM(label, lab, PY_PARSE_NODE_LEAF_ARG(pn_arg[0])); + EMIT_INLINE_ASM(label, lab, MP_PARSE_NODE_LEAF_ARG(pn_arg[0])); } } else { if (pass > PASS_1) { @@ -2975,7 +2975,7 @@ void compile_scope_compute_things(compiler_t *comp, scope_t *scope) { } } -bool py_compile(py_parse_node_t pn, bool is_repl) { +bool mp_compile(mp_parse_node_t pn, bool is_repl) { compiler_t *comp = m_new(compiler_t, 1); comp->qstr___class__ = qstr_from_str_static("__class__"); diff --git a/py/compile.h b/py/compile.h index c15b40aa6..e283442bb 100644 --- a/py/compile.h +++ b/py/compile.h @@ -1 +1 @@ -bool py_compile(py_parse_node_t pn, bool is_repl); +bool mp_compile(mp_parse_node_t pn, bool is_repl); diff --git a/py/emit.h b/py/emit.h index 62a149e10..ea6573103 100644 --- a/py/emit.h +++ b/py/emit.h @@ -32,7 +32,7 @@ typedef struct _emit_method_table_t { void (*import_name)(emit_t *emit, qstr qstr); void (*import_from)(emit_t *emit, qstr qstr); void (*import_star)(emit_t *emit); - void (*load_const_tok)(emit_t *emit, py_token_kind_t tok); + void (*load_const_tok)(emit_t *emit, mp_token_kind_t tok); void (*load_const_small_int)(emit_t *emit, int arg); void (*load_const_int)(emit_t *emit, qstr qstr); void (*load_const_dec)(emit_t *emit, qstr qstr); @@ -129,9 +129,9 @@ typedef struct _emit_inline_asm_t emit_inline_asm_t; typedef struct _emit_inline_asm_method_table_t { void (*start_pass)(emit_inline_asm_t *emit, pass_kind_t pass, scope_t *scope); void (*end_pass)(emit_inline_asm_t *emit); - int (*count_params)(emit_inline_asm_t *emit, int n_params, py_parse_node_t *pn_params); + int (*count_params)(emit_inline_asm_t *emit, int n_params, mp_parse_node_t *pn_params); void (*label)(emit_inline_asm_t *emit, int label_num, qstr label_id); - void (*op)(emit_inline_asm_t *emit, qstr op, int n_args, py_parse_node_t *pn_args); + void (*op)(emit_inline_asm_t *emit, qstr op, int n_args, mp_parse_node_t *pn_args); } emit_inline_asm_method_table_t; extern const emit_inline_asm_method_table_t emit_inline_thumb_method_table; diff --git a/py/emitbc.c b/py/emitbc.c index e1632f37f..a10a3b96e 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -6,14 +6,14 @@ #include <assert.h> #include "misc.h" -#include "mpyconfig.h" +#include "mpconfig.h" #include "lexer.h" #include "parse.h" #include "compile.h" #include "scope.h" -#include "runtime.h" +#include "runtime0.h" #include "emit.h" -#include "bc.h" +#include "bc0.h" struct _emit_t { pass_kind_t pass; @@ -214,55 +214,55 @@ static void emit_bc_label_assign(emit_t *emit, int l) { static void emit_bc_import_name(emit_t *emit, qstr qstr) { emit_pre(emit, -1); - emit_write_byte_1_qstr(emit, PYBC_IMPORT_NAME, qstr); + emit_write_byte_1_qstr(emit, MP_BC_IMPORT_NAME, qstr); } static void emit_bc_import_from(emit_t *emit, qstr qstr) { emit_pre(emit, 1); - emit_write_byte_1_qstr(emit, PYBC_IMPORT_FROM, qstr); + emit_write_byte_1_qstr(emit, MP_BC_IMPORT_FROM, qstr); } static void emit_bc_import_star(emit_t *emit) { emit_pre(emit, -1); - emit_write_byte_1(emit, PYBC_IMPORT_STAR); + emit_write_byte_1(emit, MP_BC_IMPORT_STAR); } -static void emit_bc_load_const_tok(emit_t *emit, py_token_kind_t tok) { +static void emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok) { emit_pre(emit, 1); switch (tok) { - case PY_TOKEN_KW_FALSE: emit_write_byte_1(emit, PYBC_LOAD_CONST_FALSE); break; - case PY_TOKEN_KW_NONE: emit_write_byte_1(emit, PYBC_LOAD_CONST_NONE); break; - case PY_TOKEN_KW_TRUE: emit_write_byte_1(emit, PYBC_LOAD_CONST_TRUE); break; + case MP_TOKEN_KW_FALSE: emit_write_byte_1(emit, MP_BC_LOAD_CONST_FALSE); break; + case MP_TOKEN_KW_NONE: emit_write_byte_1(emit, MP_BC_LOAD_CONST_NONE); break; + case MP_TOKEN_KW_TRUE: emit_write_byte_1(emit, MP_BC_LOAD_CONST_TRUE); break; default: assert(0); } } static void emit_bc_load_const_small_int(emit_t *emit, int arg) { emit_pre(emit, 1); - emit_write_byte_1_int(emit, PYBC_LOAD_CONST_SMALL_INT, arg); + emit_write_byte_1_int(emit, MP_BC_LOAD_CONST_SMALL_INT, arg); } static void emit_bc_load_const_int(emit_t *emit, qstr qstr) { emit_pre(emit, 1); - emit_write_byte_1_qstr(emit, PYBC_LOAD_CONST_INT, qstr); + emit_write_byte_1_qstr(emit, MP_BC_LOAD_CONST_INT, qstr); } static void emit_bc_load_const_dec(emit_t *emit, qstr qstr) { emit_pre(emit, 1); - emit_write_byte_1_qstr(emit, PYBC_LOAD_CONST_DEC, qstr); + emit_write_byte_1_qstr(emit, MP_BC_LOAD_CONST_DEC, qstr); } static void emit_bc_load_const_id(emit_t *emit, qstr qstr) { emit_pre(emit, 1); - emit_write_byte_1_qstr(emit, PYBC_LOAD_CONST_ID, qstr); + emit_write_byte_1_qstr(emit, MP_BC_LOAD_CONST_ID, qstr); } static void emit_bc_load_const_str(emit_t *emit, qstr qstr, bool bytes) { emit_pre(emit, 1); if (bytes) { - emit_write_byte_1_qstr(emit, PYBC_LOAD_CONST_BYTES, qstr); + emit_write_byte_1_qstr(emit, MP_BC_LOAD_CONST_BYTES, qstr); } else { - emit_write_byte_1_qstr(emit, PYBC_LOAD_CONST_STRING, qstr); + emit_write_byte_1_qstr(emit, MP_BC_LOAD_CONST_STRING, qstr); } } @@ -275,219 +275,219 @@ static void emit_bc_load_fast(emit_t *emit, qstr qstr, int local_num) { assert(local_num >= 0); emit_pre(emit, 1); switch (local_num) { - case 0: emit_write_byte_1(emit, PYBC_LOAD_FAST_0); break; - case 1: emit_write_byte_1(emit, PYBC_LOAD_FAST_1); break; - case 2: emit_write_byte_1(emit, PYBC_LOAD_FAST_2); break; - default: emit_write_byte_1_uint(emit, PYBC_LOAD_FAST_N, local_num); break; + case 0: emit_write_byte_1(emit, MP_BC_LOAD_FAST_0); break; + case 1: emit_write_byte_1(emit, MP_BC_LOAD_FAST_1); break; + case 2: emit_write_byte_1(emit, MP_BC_LOAD_FAST_2); break; + default: emit_write_byte_1_uint(emit, MP_BC_LOAD_FAST_N, local_num); break; } } static void emit_bc_load_deref(emit_t *emit, qstr qstr, int local_num) { emit_pre(emit, 1); - emit_write_byte_1_uint(emit, PYBC_LOAD_DEREF, local_num); + emit_write_byte_1_uint(emit, MP_BC_LOAD_DEREF, local_num); } static void emit_bc_load_closure(emit_t *emit, qstr qstr, int local_num) { emit_pre(emit, 1); - emit_write_byte_1_uint(emit, PYBC_LOAD_CLOSURE, local_num); + emit_write_byte_1_uint(emit, MP_BC_LOAD_CLOSURE, local_num); } static void emit_bc_load_name(emit_t *emit, qstr qstr) { emit_pre(emit, 1); - emit_write_byte_1_qstr(emit, PYBC_LOAD_NAME, qstr); + emit_write_byte_1_qstr(emit, MP_BC_LOAD_NAME, qstr); } static void emit_bc_load_global(emit_t *emit, qstr qstr) { emit_pre(emit, 1); - emit_write_byte_1_qstr(emit, PYBC_LOAD_GLOBAL, qstr); + emit_write_byte_1_qstr(emit, MP_BC_LOAD_GLOBAL, qstr); } static void emit_bc_load_attr(emit_t *emit, qstr qstr) { emit_pre(emit, 0); - emit_write_byte_1_qstr(emit, PYBC_LOAD_ATTR, qstr); + emit_write_byte_1_qstr(emit, MP_BC_LOAD_ATTR, qstr); } static void emit_bc_load_method(emit_t *emit, qstr qstr) { emit_pre(emit, 0); - emit_write_byte_1_qstr(emit, PYBC_LOAD_METHOD, qstr); + emit_write_byte_1_qstr(emit, MP_BC_LOAD_METHOD, qstr); } static void emit_bc_load_build_class(emit_t *emit) { emit_pre(emit, 1); - emit_write_byte_1(emit, PYBC_LOAD_BUILD_CLASS); + emit_write_byte_1(emit, MP_BC_LOAD_BUILD_CLASS); } static void emit_bc_store_fast(emit_t *emit, qstr qstr, int local_num) { assert(local_num >= 0); emit_pre(emit, -1); switch (local_num) { - case 0: emit_write_byte_1(emit, PYBC_STORE_FAST_0); break; - case 1: emit_write_byte_1(emit, PYBC_STORE_FAST_1); break; - case 2: emit_write_byte_1(emit, PYBC_STORE_FAST_2); break; - default: emit_write_byte_1_uint(emit, PYBC_STORE_FAST_N, local_num); break; + case 0: emit_write_byte_1(emit, MP_BC_STORE_FAST_0); break; + case 1: emit_write_byte_1(emit, MP_BC_STORE_FAST_1); break; + case 2: emit_write_byte_1(emit, MP_BC_STORE_FAST_2); break; + default: emit_write_byte_1_uint(emit, MP_BC_STORE_FAST_N, local_num); break; } } static void emit_bc_store_deref(emit_t *emit, qstr qstr, int local_num) { emit_pre(emit, -1); - emit_write_byte_1_uint(emit, PYBC_STORE_DEREF, local_num); + emit_write_byte_1_uint(emit, MP_BC_STORE_DEREF, local_num); } static void emit_bc_store_name(emit_t *emit, qstr qstr) { emit_pre(emit, -1); - emit_write_byte_1_qstr(emit, PYBC_STORE_NAME, qstr); + emit_write_byte_1_qstr(emit, MP_BC_STORE_NAME, qstr); } static void emit_bc_store_global(emit_t *emit, qstr qstr) { emit_pre(emit, -1); - emit_write_byte_1_qstr(emit, PYBC_STORE_GLOBAL, qstr); + emit_write_byte_1_qstr(emit, MP_BC_STORE_GLOBAL, qstr); } static void emit_bc_store_attr(emit_t *emit, qstr qstr) { emit_pre(emit, -2); - emit_write_byte_1_qstr(emit, PYBC_STORE_ATTR, qstr); + emit_write_byte_1_qstr(emit, MP_BC_STORE_ATTR, qstr); } static void emit_bc_store_subscr(emit_t *emit) { emit_pre(emit, -3); - emit_write_byte_1(emit, PYBC_STORE_SUBSCR); + emit_write_byte_1(emit, MP_BC_STORE_SUBSCR); } static void emit_bc_store_locals(emit_t *emit) { // not needed emit_pre(emit, -1); - emit_write_byte_1(emit, PYBC_POP_TOP); + emit_write_byte_1(emit, MP_BC_POP_TOP); } static void emit_bc_delete_fast(emit_t *emit, qstr qstr, int local_num) { assert(local_num >= 0); emit_pre(emit, 0); - emit_write_byte_1_uint(emit, PYBC_DELETE_FAST_N, local_num); + emit_write_byte_1_uint(emit, MP_BC_DELETE_FAST_N, local_num); } static void emit_bc_delete_deref(emit_t *emit, qstr qstr, int local_num) { emit_pre(emit, 0); - emit_write_byte_1_qstr(emit, PYBC_DELETE_DEREF, local_num); + emit_write_byte_1_qstr(emit, MP_BC_DELETE_DEREF, local_num); } static void emit_bc_delete_name(emit_t *emit, qstr qstr) { emit_pre(emit, 0); - emit_write_byte_1_qstr(emit, PYBC_DELETE_NAME, qstr); + emit_write_byte_1_qstr(emit, MP_BC_DELETE_NAME, qstr); } static void emit_bc_delete_global(emit_t *emit, qstr qstr) { emit_pre(emit, 0); - emit_write_byte_1_qstr(emit, PYBC_DELETE_GLOBAL, qstr); + emit_write_byte_1_qstr(emit, MP_BC_DELETE_GLOBAL, qstr); } static void emit_bc_delete_attr(emit_t *emit, qstr qstr) { emit_pre(emit, -1); - emit_write_byte_1_qstr(emit, PYBC_DELETE_ATTR, qstr); + emit_write_byte_1_qstr(emit, MP_BC_DELETE_ATTR, qstr); } static void emit_bc_delete_subscr(emit_t *emit) { emit_pre(emit, -2); - emit_write_byte_1(emit, PYBC_DELETE_SUBSCR); + emit_write_byte_1(emit, MP_BC_DELETE_SUBSCR); } static void emit_bc_dup_top(emit_t *emit) { emit_pre(emit, 1); - emit_write_byte_1(emit, PYBC_DUP_TOP); + emit_write_byte_1(emit, MP_BC_DUP_TOP); } static void emit_bc_dup_top_two(emit_t *emit) { emit_pre(emit, 2); - emit_write_byte_1(emit, PYBC_DUP_TOP_TWO); + emit_write_byte_1(emit, MP_BC_DUP_TOP_TWO); } static void emit_bc_pop_top(emit_t *emit) { emit_pre(emit, -1); - emit_write_byte_1(emit, PYBC_POP_TOP); + emit_write_byte_1(emit, MP_BC_POP_TOP); } static void emit_bc_rot_two(emit_t *emit) { emit_pre(emit, 0); - emit_write_byte_1(emit, PYBC_ROT_TWO); + emit_write_byte_1(emit, MP_BC_ROT_TWO); } static void emit_bc_rot_three(emit_t *emit) { emit_pre(emit, 0); - emit_write_byte_1(emit, PYBC_ROT_THREE); + emit_write_byte_1(emit, MP_BC_ROT_THREE); } static void emit_bc_jump(emit_t *emit, int label) { emit_pre(emit, 0); - emit_write_byte_1_signed_label(emit, PYBC_JUMP, label); + emit_write_byte_1_signed_label(emit, MP_BC_JUMP, label); } static void emit_bc_pop_jump_if_true(emit_t *emit, int label) { emit_pre(emit, -1); - emit_write_byte_1_signed_label(emit, PYBC_POP_JUMP_IF_TRUE, label); + emit_write_byte_1_signed_label(emit, MP_BC_POP_JUMP_IF_TRUE, label); } static void emit_bc_pop_jump_if_false(emit_t *emit, int label) { emit_pre(emit, -1); - emit_write_byte_1_signed_label(emit, PYBC_POP_JUMP_IF_FALSE, label); + emit_write_byte_1_signed_label(emit, MP_BC_POP_JUMP_IF_FALSE, label); } static void emit_bc_jump_if_true_or_pop(emit_t *emit, int label) { emit_pre(emit, -1); - emit_write_byte_1_signed_label(emit, PYBC_JUMP_IF_TRUE_OR_POP, label); + emit_write_byte_1_signed_label(emit, MP_BC_JUMP_IF_TRUE_OR_POP, label); } static void emit_bc_jump_if_false_or_pop(emit_t *emit, int label) { emit_pre(emit, -1); - emit_write_byte_1_signed_label(emit, PYBC_JUMP_IF_FALSE_OR_POP, label); + emit_write_byte_1_signed_label(emit, MP_BC_JUMP_IF_FALSE_OR_POP, label); } static void emit_bc_setup_loop(emit_t *emit, int label) { emit_pre(emit, 0); - emit_write_byte_1_unsigned_label(emit, PYBC_SETUP_LOOP, label); + emit_write_byte_1_unsigned_label(emit, MP_BC_SETUP_LOOP, label); } static void emit_bc_break_loop(emit_t *emit, int label) { emit_pre(emit, 0); - emit_write_byte_1_unsigned_label(emit, PYBC_BREAK_LOOP, label); + emit_write_byte_1_unsigned_label(emit, MP_BC_BREAK_LOOP, label); } static void emit_bc_continue_loop(emit_t *emit, int label) { emit_pre(emit, 0); - emit_write_byte_1_unsigned_label(emit, PYBC_CONTINUE_LOOP, label); + emit_write_byte_1_unsigned_label(emit, MP_BC_CONTINUE_LOOP, label); } static void emit_bc_setup_with(emit_t *emit, int label) { emit_pre(emit, 7); - emit_write_byte_1_unsigned_label(emit, PYBC_SETUP_WITH, label); + emit_write_byte_1_unsigned_label(emit, MP_BC_SETUP_WITH, label); } static void emit_bc_with_cleanup(emit_t *emit) { emit_pre(emit, -7); - emit_write_byte_1(emit, PYBC_WITH_CLEANUP); + emit_write_byte_1(emit, MP_BC_WITH_CLEANUP); } static void emit_bc_setup_except(emit_t *emit, int label) { emit_pre(emit, 6); - emit_write_byte_1_unsigned_label(emit, PYBC_SETUP_EXCEPT, label); + emit_write_byte_1_unsigned_label(emit, MP_BC_SETUP_EXCEPT, label); } static void emit_bc_setup_finally(emit_t *emit, int label) { emit_pre(emit, 6); - emit_write_byte_1_unsigned_label(emit, PYBC_SETUP_FINALLY, label); + emit_write_byte_1_unsigned_label(emit, MP_BC_SETUP_FINALLY, label); } static void emit_bc_end_finally(emit_t *emit) { emit_pre(emit, -1); - emit_write_byte_1(emit, PYBC_END_FINALLY); + emit_write_byte_1(emit, MP_BC_END_FINALLY); } static void emit_bc_get_iter(emit_t *emit) { emit_pre(emit, 0); - emit_write_byte_1(emit, PYBC_GET_ITER); + emit_write_byte_1(emit, MP_BC_GET_ITER); } static void emit_bc_for_iter(emit_t *emit, int label) { emit_pre(emit, 1); - emit_write_byte_1_unsigned_label(emit, PYBC_FOR_ITER, label); + emit_write_byte_1_unsigned_label(emit, MP_BC_FOR_ITER, label); } static void emit_bc_for_iter_end(emit_t *emit) { @@ -496,104 +496,104 @@ static void emit_bc_for_iter_end(emit_t *emit) { static void emit_bc_pop_block(emit_t *emit) { emit_pre(emit, 0); - emit_write_byte_1(emit, PYBC_POP_BLOCK); + emit_write_byte_1(emit, MP_BC_POP_BLOCK); } static void emit_bc_pop_except(emit_t *emit) { emit_pre(emit, 0); - emit_write_byte_1(emit, PYBC_POP_EXCEPT); + emit_write_byte_1(emit, MP_BC_POP_EXCEPT); } static void emit_bc_unary_op(emit_t *emit, rt_unary_op_t op) { emit_pre(emit, 0); - emit_write_byte_1_byte(emit, PYBC_UNARY_OP, op); + emit_write_byte_1_byte(emit, MP_BC_UNARY_OP, op); } static void emit_bc_binary_op(emit_t *emit, rt_binary_op_t op) { emit_pre(emit, -1); - emit_write_byte_1_byte(emit, PYBC_BINARY_OP, op); + emit_write_byte_1_byte(emit, MP_BC_BINARY_OP, op); } static void emit_bc_compare_op(emit_t *emit, rt_compare_op_t op) { emit_pre(emit, -1); - emit_write_byte_1_byte(emit, PYBC_COMPARE_OP, op); + emit_write_byte_1_byte(emit, MP_BC_COMPARE_OP, op); } static void emit_bc_build_tuple(emit_t *emit, int n_args) { assert(n_args >= 0); emit_pre(emit, 1 - n_args); - emit_write_byte_1_uint(emit, PYBC_BUILD_TUPLE, n_args); + emit_write_byte_1_uint(emit, MP_BC_BUILD_TUPLE, n_args); } static void emit_bc_build_list(emit_t *emit, int n_args) { assert(n_args >= 0); emit_pre(emit, 1 - n_args); - emit_write_byte_1_uint(emit, PYBC_BUILD_LIST, n_args); + emit_write_byte_1_uint(emit, MP_BC_BUILD_LIST, n_args); } static void emit_bc_list_append(emit_t *emit, int list_stack_index) { assert(list_stack_index >= 0); emit_pre(emit, -1); - emit_write_byte_1_uint(emit, PYBC_LIST_APPEND, list_stack_index); + emit_write_byte_1_uint(emit, MP_BC_LIST_APPEND, list_stack_index); } static void emit_bc_build_map(emit_t *emit, int n_args) { assert(n_args >= 0); emit_pre(emit, 1); - emit_write_byte_1_uint(emit, PYBC_BUILD_MAP, n_args); + emit_write_byte_1_uint(emit, MP_BC_BUILD_MAP, n_args); } static void emit_bc_store_map(emit_t *emit) { emit_pre(emit, -2); - emit_write_byte_1(emit, PYBC_STORE_MAP); + emit_write_byte_1(emit, MP_BC_STORE_MAP); } static void emit_bc_map_add(emit_t *emit, int map_stack_index) { assert(map_stack_index >= 0); emit_pre(emit, -2); - emit_write_byte_1_uint(emit, PYBC_MAP_ADD, map_stack_index); + emit_write_byte_1_uint(emit, MP_BC_MAP_ADD, map_stack_index); } static void emit_bc_build_set(emit_t *emit, int n_args) { assert(n_args >= 0); emit_pre(emit, 1 - n_args); - emit_write_byte_1_uint(emit, PYBC_BUILD_SET, n_args); + emit_write_byte_1_uint(emit, MP_BC_BUILD_SET, n_args); } static void emit_bc_set_add(emit_t *emit, int set_stack_index) { assert(set_stack_index >= 0); emit_pre(emit, -1); - emit_write_byte_1_uint(emit, PYBC_SET_ADD, set_stack_index); + emit_write_byte_1_uint(emit, MP_BC_SET_ADD, set_stack_index); } static void emit_bc_build_slice(emit_t *emit, int n_args) { assert(n_args >= 0); emit_pre(emit, 1 - n_args); - emit_write_byte_1_uint(emit, PYBC_BUILD_SLICE, n_args); + emit_write_byte_1_uint(emit, MP_BC_BUILD_SLICE, n_args); } static void emit_bc_unpack_sequence(emit_t *emit, int n_args) { assert(n_args >= 0); emit_pre(emit, -1 + n_args); - emit_write_byte_1_uint(emit, PYBC_UNPACK_SEQUENCE, n_args); + emit_write_byte_1_uint(emit, MP_BC_UNPACK_SEQUENCE, n_args); } static void emit_bc_unpack_ex(emit_t *emit, int n_left, int n_right) { assert(n_left >=0 && n_right >= 0); emit_pre(emit, -1 + n_left + n_right + 1); - emit_write_byte_1_uint(emit, PYBC_UNPACK_EX, n_left | (n_right << 8)); + emit_write_byte_1_uint(emit, MP_BC_UNPACK_EX, n_left | (n_right << 8)); } static void emit_bc_make_function(emit_t *emit, scope_t *scope, int n_dict_params, int n_default_params) { assert(n_default_params == 0 && n_dict_params == 0); emit_pre(emit, 1); - emit_write_byte_1_uint(emit, PYBC_MAKE_FUNCTION, scope->unique_code_id); + emit_write_byte_1_uint(emit, MP_BC_MAKE_FUNCTION, scope->unique_code_id); } static void emit_bc_make_closure(emit_t *emit, scope_t *scope, int n_dict_params, int n_default_params) { assert(n_default_params == 0 && n_dict_params == 0); emit_pre(emit, 0); - emit_write_byte_1_uint(emit, PYBC_MAKE_CLOSURE, scope->unique_code_id); + emit_write_byte_1_uint(emit, MP_BC_MAKE_CLOSURE, scope->unique_code_id); } static void emit_bc_call_function(emit_t *emit, int n_positional, int n_keyword, bool have_star_arg, bool have_dbl_star_arg) { @@ -608,15 +608,15 @@ static void emit_bc_call_function(emit_t *emit, int n_positional, int n_keyword, int op; if (have_star_arg) { if (have_dbl_star_arg) { - op = PYBC_CALL_FUNCTION_VAR_KW; + op = MP_BC_CALL_FUNCTION_VAR_KW; } else { - op = PYBC_CALL_FUNCTION_VAR; + op = MP_BC_CALL_FUNCTION_VAR; } } else { if (have_dbl_star_arg) { - op = PYBC_CALL_FUNCTION_KW; + op = MP_BC_CALL_FUNCTION_KW; } else { - op = PYBC_CALL_FUNCTION; + op = MP_BC_CALL_FUNCTION; } } emit_write_byte_1_uint(emit, op, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints @@ -634,15 +634,15 @@ static void emit_bc_call_method(emit_t *emit, int n_positional, int n_keyword, b int op; if (have_star_arg) { if (have_dbl_star_arg) { - op = PYBC_CALL_METHOD_VAR_KW; + op = MP_BC_CALL_METHOD_VAR_KW; } else { - op = PYBC_CALL_METHOD_VAR; + op = MP_BC_CALL_METHOD_VAR; } } else { if (have_dbl_star_arg) { - op = PYBC_CALL_METHOD_KW; + op = MP_BC_CALL_METHOD_KW; } else { - op = PYBC_CALL_METHOD; + op = MP_BC_CALL_METHOD; } } emit_write_byte_1_uint(emit, op, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints @@ -651,13 +651,13 @@ static void emit_bc_call_method(emit_t *emit, int n_positional, int n_keyword, b static void emit_bc_return_value(emit_t *emit) { emit_pre(emit, -1); emit->last_emit_was_return_value = true; - emit_write_byte_1(emit, PYBC_RETURN_VALUE); + emit_write_byte_1(emit, MP_BC_RETURN_VALUE); } static void emit_bc_raise_varargs(emit_t *emit, int n_args) { assert(n_args >= 0); emit_pre(emit, -n_args); - emit_write_byte_1_uint(emit, PYBC_RAISE_VARARGS, n_args); + emit_write_byte_1_uint(emit, MP_BC_RAISE_VARARGS, n_args); } static void emit_bc_yield_value(emit_t *emit) { @@ -665,7 +665,7 @@ static void emit_bc_yield_value(emit_t *emit) { if (emit->pass == PASS_2) { emit->scope->flags |= SCOPE_FLAG_GENERATOR; } - emit_write_byte_1(emit, PYBC_YIELD_VALUE); + emit_write_byte_1(emit, MP_BC_YIELD_VALUE); } static void emit_bc_yield_from(emit_t *emit) { @@ -673,7 +673,7 @@ static void emit_bc_yield_from(emit_t *emit) { if (emit->pass == PASS_2) { emit->scope->flags |= SCOPE_FLAG_GENERATOR; } - emit_write_byte_1(emit, PYBC_YIELD_FROM); + emit_write_byte_1(emit, MP_BC_YIELD_FROM); } const emit_method_table_t emit_bc_method_table = { diff --git a/py/emitcommon.c b/py/emitcommon.c index 0dfe96d89..e30cad749 100644 --- a/py/emitcommon.c +++ b/py/emitcommon.c @@ -5,11 +5,11 @@ #include <assert.h> #include "misc.h" -#include "mpyconfig.h" +#include "mpconfig.h" #include "lexer.h" #include "parse.h" #include "scope.h" -#include "runtime.h" +#include "runtime0.h" #include "emit.h" #define EMIT(fun, arg...) (emit_method_table->fun(emit, ##arg)) diff --git a/py/emitcpy.c b/py/emitcpy.c index cb8bef479..52f804925 100644 --- a/py/emitcpy.c +++ b/py/emitcpy.c @@ -6,12 +6,12 @@ #include <assert.h> #include "misc.h" -#include "mpyconfig.h" +#include "mpconfig.h" #include "lexer.h" #include "parse.h" #include "compile.h" #include "scope.h" -#include "runtime.h" +#include "runtime0.h" #include "emit.h" #if MICROPY_EMIT_CPYTHON @@ -136,9 +136,9 @@ static void emit_cpy_load_const_tok(emit_t *emit, py_token_kind_t tok) { if (emit->pass == PASS_3) { printf("LOAD_CONST "); switch (tok) { - case PY_TOKEN_KW_FALSE: printf("False"); break; - case PY_TOKEN_KW_NONE: printf("None"); break; - case PY_TOKEN_KW_TRUE: printf("True"); break; + case MP_TOKEN_KW_FALSE: printf("False"); break; + case MP_TOKEN_KW_NONE: printf("None"); break; + case MP_TOKEN_KW_TRUE: printf("True"); break; default: printf("?=%d\n", tok); return; assert(0); } printf("\n"); diff --git a/py/emitinlinethumb.c b/py/emitinlinethumb.c index 4a57235da..073dfa060 100644 --- a/py/emitinlinethumb.c +++ b/py/emitinlinethumb.c @@ -6,11 +6,11 @@ #include <assert.h> #include "misc.h" -#include "mpyconfig.h" +#include "mpconfig.h" #include "lexer.h" #include "parse.h" #include "scope.h" -#include "runtime.h" +#include "runtime0.h" #include "emit.h" #include "asmthumb.h" @@ -45,22 +45,22 @@ static void emit_inline_thumb_end_pass(emit_inline_asm_t *emit) { asm_thumb_end_pass(emit->as); if (emit->pass == PASS_3) { - py_fun_t f = asm_thumb_get_code(emit->as); + void *f = asm_thumb_get_code(emit->as); rt_assign_inline_asm_code(emit->scope->unique_code_id, f, asm_thumb_get_code_size(emit->as), emit->scope->num_params); } } -static int emit_inline_thumb_count_params(emit_inline_asm_t *emit, int n_params, py_parse_node_t *pn_params) { +static int emit_inline_thumb_count_params(emit_inline_asm_t *emit, int n_params, mp_parse_node_t *pn_params) { if (n_params > 4) { printf("SyntaxError: can only have up to 4 parameters to inline thumb assembly\n"); return 0; } for (int i = 0; i < n_params; i++) { - if (!PY_PARSE_NODE_IS_ID(pn_params[i])) { + if (!MP_PARSE_NODE_IS_ID(pn_params[i])) { printf("SyntaxError: parameter to inline assembler must be an identifier\n"); return 0; } - const char *p = qstr_str(PY_PARSE_NODE_LEAF_ARG(pn_params[i])); + const char *p = qstr_str(MP_PARSE_NODE_LEAF_ARG(pn_params[i])); if (!(strlen(p) == 2 && p[0] == 'r' && p[1] == '0' + i)) { printf("SyntaxError: parameter %d to inline assembler must be r%d\n", i + 1, i); return 0; @@ -84,12 +84,12 @@ static bool check_n_arg(qstr op, int n_args, int wanted_n_args) { } } -static uint get_arg_rlo(qstr op, py_parse_node_t *pn_args, int wanted_arg_num) { - if (!PY_PARSE_NODE_IS_ID(pn_args[wanted_arg_num])) { +static uint get_arg_rlo(qstr op, mp_parse_node_t *pn_args, int wanted_arg_num) { + if (!MP_PARSE_NODE_IS_ID(pn_args[wanted_arg_num])) { printf("SyntaxError: '%s' expects a register in position %d\n", qstr_str(op), wanted_arg_num); return 0; } - qstr reg_qstr = PY_PARSE_NODE_LEAF_ARG(pn_args[wanted_arg_num]); + qstr reg_qstr = MP_PARSE_NODE_LEAF_ARG(pn_args[wanted_arg_num]); const char *reg_str = qstr_str(reg_qstr); if (!(strlen(reg_str) == 2 && reg_str[0] == 'r' && ('0' <= reg_str[1] && reg_str[1] <= '7'))) { printf("SyntaxError: '%s' expects a register in position %d\n", qstr_str(op), wanted_arg_num); @@ -98,12 +98,12 @@ static uint get_arg_rlo(qstr op, py_parse_node_t *pn_args, int wanted_arg_num) { return reg_str[1] - '0'; } -static int get_arg_i(qstr op, py_parse_node_t *pn_args, int wanted_arg_num, int fit_mask) { - if (!PY_PARSE_NODE_IS_SMALL_INT(pn_args[wanted_arg_num])) { +static int get_arg_i(qstr op, mp_parse_node_t *pn_args, int wanted_arg_num, int fit_mask) { + if (!MP_PARSE_NODE_IS_SMALL_INT(pn_args[wanted_arg_num])) { printf("SyntaxError: '%s' expects an integer in position %d\n", qstr_str(op), wanted_arg_num); return 0; } - int i = PY_PARSE_NODE_LEAF_ARG(pn_args[wanted_arg_num]); + int i = MP_PARSE_NODE_LEAF_ARG(pn_args[wanted_arg_num]); if ((i & (~fit_mask)) != 0) { printf("SyntaxError: '%s' integer 0x%x does not fit in mask 0x%x\n", qstr_str(op), i, fit_mask); return 0; @@ -111,12 +111,12 @@ static int get_arg_i(qstr op, py_parse_node_t *pn_args, int wanted_arg_num, int return i; } -static int get_arg_label(emit_inline_asm_t *emit, qstr op, py_parse_node_t *pn_args, int wanted_arg_num) { - if (!PY_PARSE_NODE_IS_ID(pn_args[wanted_arg_num])) { +static int get_arg_label(emit_inline_asm_t *emit, qstr op, mp_parse_node_t *pn_args, int wanted_arg_num) { + if (!MP_PARSE_NODE_IS_ID(pn_args[wanted_arg_num])) { printf("SyntaxError: '%s' expects a label in position %d\n", qstr_str(op), wanted_arg_num); return 0; } - qstr label_qstr = PY_PARSE_NODE_LEAF_ARG(pn_args[wanted_arg_num]); + qstr label_qstr = MP_PARSE_NODE_LEAF_ARG(pn_args[wanted_arg_num]); for (int i = 0; i < emit->max_num_labels; i++) { if (emit->label_lookup[i] == label_qstr) { return i; @@ -129,7 +129,7 @@ static int get_arg_label(emit_inline_asm_t *emit, qstr op, py_parse_node_t *pn_a return 0; } -static void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, int n_args, py_parse_node_t *pn_args) { +static void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, int n_args, mp_parse_node_t *pn_args) { // TODO perhaps make two tables: // one_args = // "b", LAB, asm_thumb_b_n, diff --git a/py/emitnative.c b/py/emitnative.c index 17d217c97..a29922d96 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -24,12 +24,14 @@ #include <assert.h> #include "misc.h" -#include "mpyconfig.h" +#include "mpconfig.h" #include "lexer.h" #include "parse.h" #include "scope.h" -#include "runtime.h" +#include "runtime0.h" #include "emit.h" +#include "obj.h" +#include "runtime.h" // wrapper around everything in this file #if N_X64 || N_THUMB @@ -258,10 +260,10 @@ static void emit_native_end_pass(emit_t *emit) { if (emit->pass == PASS_3) { #if N_X64 - py_fun_t f = asm_x64_get_code(emit->as); + void *f = asm_x64_get_code(emit->as); rt_assign_native_code(emit->scope->unique_code_id, f, asm_x64_get_code_size(emit->as), emit->scope->num_params); #elif N_THUMB - py_fun_t f = asm_thumb_get_code(emit->as); + void *f = asm_thumb_get_code(emit->as); rt_assign_native_code(emit->scope->unique_code_id, f, asm_thumb_get_code_size(emit->as), emit->scope->num_params); #endif } @@ -460,9 +462,9 @@ static void emit_get_stack_pointer_to_reg_for_pop(emit_t *emit, int reg_dest, in case VTYPE_BOOL: si->vtype = VTYPE_PYOBJ; if (si->u_imm == 0) { - ASM_MOV_IMM_TO_LOCAL_USING((machine_uint_t)py_const_false, emit->stack_start + emit->stack_size - 1 - i, reg_dest); + ASM_MOV_IMM_TO_LOCAL_USING((machine_uint_t)mp_const_false, emit->stack_start + emit->stack_size - 1 - i, reg_dest); } else { - ASM_MOV_IMM_TO_LOCAL_USING((machine_uint_t)py_const_true, emit->stack_start + emit->stack_size - 1 - i, reg_dest); + ASM_MOV_IMM_TO_LOCAL_USING((machine_uint_t)mp_const_true, emit->stack_start + emit->stack_size - 1 - i, reg_dest); } break; case VTYPE_INT: @@ -561,23 +563,23 @@ static void emit_native_import_star(emit_t *emit) { assert(0); } -static void emit_native_load_const_tok(emit_t *emit, py_token_kind_t tok) { +static void emit_native_load_const_tok(emit_t *emit, mp_token_kind_t tok) { emit_pre(emit); int vtype; machine_uint_t val; if (emit->do_viper_types) { switch (tok) { - case PY_TOKEN_KW_NONE: vtype = VTYPE_PTR_NONE; val = 0; break; - case PY_TOKEN_KW_FALSE: vtype = VTYPE_BOOL; val = 0; break; - case PY_TOKEN_KW_TRUE: vtype = VTYPE_BOOL; val = 1; break; + case MP_TOKEN_KW_NONE: vtype = VTYPE_PTR_NONE; val = 0; break; + case MP_TOKEN_KW_FALSE: vtype = VTYPE_BOOL; val = 0; break; + case MP_TOKEN_KW_TRUE: vtype = VTYPE_BOOL; val = 1; break; default: assert(0); vtype = 0; val = 0; // shouldn't happen } } else { vtype = VTYPE_PYOBJ; switch (tok) { - case PY_TOKEN_KW_NONE: val = (machine_uint_t)py_const_none; break; - case PY_TOKEN_KW_FALSE: val = (machine_uint_t)py_const_false; break; - case PY_TOKEN_KW_TRUE: val = (machine_uint_t)py_const_true; break; + case MP_TOKEN_KW_NONE: val = (machine_uint_t)mp_const_none; break; + case MP_TOKEN_KW_FALSE: val = (machine_uint_t)mp_const_false; break; + case MP_TOKEN_KW_TRUE: val = (machine_uint_t)mp_const_true; break; default: assert(0); vtype = 0; val = 0; // shouldn't happen } } @@ -956,7 +958,7 @@ static void emit_native_for_iter(emit_t *emit, int label) { emit_access_stack(emit, 1, &vtype, REG_ARG_1); assert(vtype == VTYPE_PYOBJ); emit_call(emit, RT_F_ITERNEXT, rt_iternext); - ASM_MOV_IMM_TO_REG((machine_uint_t)py_const_stop_iteration, REG_TEMP1); + ASM_MOV_IMM_TO_REG((machine_uint_t)mp_const_stop_iteration, REG_TEMP1); #if N_X64 asm_x64_cmp_r64_with_r64(emit->as, REG_RET, REG_TEMP1); asm_x64_jcc_label(emit->as, JCC_JE, label); diff --git a/py/emitpass1.c b/py/emitpass1.c index 5526c2d5d..551f30eb4 100644 --- a/py/emitpass1.c +++ b/py/emitpass1.c @@ -6,12 +6,12 @@ #include <assert.h> #include "misc.h" -#include "mpyconfig.h" +#include "mpconfig.h" #include "lexer.h" #include "parse.h" #include "compile.h" #include "scope.h" -#include "runtime.h" +#include "runtime0.h" #include "emit.h" struct _emit_t { diff --git a/py/gc.c b/py/gc.c index 690503d92..7d4cac6e7 100644 --- a/py/gc.c +++ b/py/gc.c @@ -3,7 +3,7 @@ #include <stdint.h> #include <string.h> -#include "mpyconfig.h" +#include "mpconfig.h" #include "gc.h" // a machine word is big enough to hold a pointer diff --git a/py/lexer.c b/py/lexer.c index cd2e05ece..cf9eae553 100644 --- a/py/lexer.c +++ b/py/lexer.c @@ -13,11 +13,11 @@ // TODO seems that CPython allows NULL byte in the input stream // don't know if that's intentional or not, but we don't allow it -struct _py_lexer_t { +struct _mp_lexer_t { const char *name; // name of source void *stream_data; // data for stream - py_lexer_stream_next_char_t stream_next_char; // stream callback to get next char - py_lexer_stream_close_t stream_close; // stream callback to free + mp_lexer_stream_next_char_t stream_next_char; // stream callback to get next char + mp_lexer_stream_close_t stream_close; // stream callback to free unichar chr0, chr1, chr2; // current cached characters from source @@ -32,7 +32,7 @@ struct _py_lexer_t { uint16_t *indent_level; vstr_t vstr; - py_token_t tok_cur; + mp_token_t tok_cur; }; bool str_strn_equal(const char *str, const char *strn, int len) { @@ -47,7 +47,7 @@ bool str_strn_equal(const char *str, const char *strn, int len) { return i == len && *str == 0; } -void py_token_show(const py_token_t *tok) { +void mp_token_show(const mp_token_t *tok) { printf("(%s:%d:%d) kind:%d str:%p len:%d", tok->src_name, tok->src_line, tok->src_column, tok->kind, tok->str, tok->len); if (tok->str != NULL && tok->len > 0) { const char *i = tok->str; @@ -66,83 +66,83 @@ void py_token_show(const py_token_t *tok) { printf("\n"); } -void py_token_show_error_prefix(const py_token_t *tok) { +void mp_token_show_error_prefix(const mp_token_t *tok) { printf("(%s:%d:%d) ", tok->src_name, tok->src_line, tok->src_column); } -bool py_token_show_error(const py_token_t *tok, const char *msg) { +bool mp_token_show_error(const mp_token_t *tok, const char *msg) { printf("(%s:%d:%d) %s\n", tok->src_name, tok->src_line, tok->src_column, msg); return false; } #define CUR_CHAR(lex) ((lex)->chr0) -static bool is_end(py_lexer_t *lex) { - return lex->chr0 == PY_LEXER_CHAR_EOF; +static bool is_end(mp_lexer_t *lex) { + return lex->chr0 == MP_LEXER_CHAR_EOF; } -static bool is_physical_newline(py_lexer_t *lex) { +static bool is_physical_newline(mp_lexer_t *lex) { return lex->chr0 == '\n' || lex->chr0 == '\r'; } -static bool is_char(py_lexer_t *lex, char c) { +static bool is_char(mp_lexer_t *lex, char c) { return lex->chr0 == c; } -static bool is_char_or(py_lexer_t *lex, char c1, char c2) { +static bool is_char_or(mp_lexer_t *lex, char c1, char c2) { return lex->chr0 == c1 || lex->chr0 == c2; } -static bool is_char_or3(py_lexer_t *lex, char c1, char c2, char c3) { +static bool is_char_or3(mp_lexer_t *lex, char c1, char c2, char c3) { return lex->chr0 == c1 || lex->chr0 == c2 || lex->chr0 == c3; } /* -static bool is_char_following(py_lexer_t *lex, char c) { +static bool is_char_following(mp_lexer_t *lex, char c) { return lex->chr1 == c; } */ -static bool is_char_following_or(py_lexer_t *lex, char c1, char c2) { +static bool is_char_following_or(mp_lexer_t *lex, char c1, char c2) { return lex->chr1 == c1 || lex->chr1 == c2; } -static bool is_char_following_following_or(py_lexer_t *lex, char c1, char c2) { +static bool is_char_following_following_or(mp_lexer_t *lex, char c1, char c2) { return lex->chr2 == c1 || lex->chr2 == c2; } -static bool is_char_and(py_lexer_t *lex, char c1, char c2) { +static bool is_char_and(mp_lexer_t *lex, char c1, char c2) { return lex->chr0 == c1 && lex->chr1 == c2; } -static bool is_whitespace(py_lexer_t *lex) { +static bool is_whitespace(mp_lexer_t *lex) { return g_unichar_isspace(lex->chr0); } -static bool is_letter(py_lexer_t *lex) { +static bool is_letter(mp_lexer_t *lex) { return g_unichar_isalpha(lex->chr0); } -static bool is_digit(py_lexer_t *lex) { +static bool is_digit(mp_lexer_t *lex) { return g_unichar_isdigit(lex->chr0); } -static bool is_following_digit(py_lexer_t *lex) { +static bool is_following_digit(mp_lexer_t *lex) { return g_unichar_isdigit(lex->chr1); } // TODO UNICODE include unicode characters in definition of identifiers -static bool is_head_of_identifier(py_lexer_t *lex) { +static bool is_head_of_identifier(mp_lexer_t *lex) { return is_letter(lex) || lex->chr0 == '_'; } // TODO UNICODE include unicode characters in definition of identifiers -static bool is_tail_of_identifier(py_lexer_t *lex) { +static bool is_tail_of_identifier(mp_lexer_t *lex) { return is_head_of_identifier(lex) || is_digit(lex); } -static void next_char(py_lexer_t *lex) { - if (lex->chr0 == PY_LEXER_CHAR_EOF) { +static void next_char(mp_lexer_t *lex) { + if (lex->chr0 == MP_LEXER_CHAR_EOF) { return; } @@ -172,16 +172,16 @@ static void next_char(py_lexer_t *lex) { lex->chr0 = lex->chr1; lex->chr1 = lex->chr2; lex->chr2 = lex->stream_next_char(lex->stream_data); - if (lex->chr2 == PY_LEXER_CHAR_EOF) { + if (lex->chr2 == MP_LEXER_CHAR_EOF) { // EOF - if (lex->chr1 != PY_LEXER_CHAR_EOF && lex->chr1 != '\n' && lex->chr1 != '\r') { + if (lex->chr1 != MP_LEXER_CHAR_EOF && lex->chr1 != '\n' && lex->chr1 != '\r') { lex->chr2 = '\n'; // insert newline at end of file } } } } -void indent_push(py_lexer_t *lex, uint indent) { +void indent_push(mp_lexer_t *lex, uint indent) { if (lex->num_indent_level >= lex->alloc_indent_level) { lex->alloc_indent_level *= 2; lex->indent_level = m_renew(uint16_t, lex->indent_level, lex->alloc_indent_level); @@ -189,11 +189,11 @@ void indent_push(py_lexer_t *lex, uint indent) { lex->indent_level[lex->num_indent_level++] = indent; } -uint indent_top(py_lexer_t *lex) { +uint indent_top(mp_lexer_t *lex) { return lex->indent_level[lex->num_indent_level - 1]; } -void indent_pop(py_lexer_t *lex) { +void indent_pop(mp_lexer_t *lex) { lex->num_indent_level -= 1; } @@ -222,24 +222,24 @@ static const char *tok_enc = // TODO static assert that number of tokens is less than 256 so we can safely make this table with byte sized entries static const uint8_t tok_enc_kind[] = { - PY_TOKEN_DEL_PAREN_OPEN, PY_TOKEN_DEL_PAREN_CLOSE, - PY_TOKEN_DEL_BRACKET_OPEN, PY_TOKEN_DEL_BRACKET_CLOSE, - PY_TOKEN_DEL_BRACE_OPEN, PY_TOKEN_DEL_BRACE_CLOSE, - PY_TOKEN_DEL_COMMA, PY_TOKEN_DEL_COLON, PY_TOKEN_DEL_SEMICOLON, PY_TOKEN_DEL_AT, PY_TOKEN_OP_TILDE, - - PY_TOKEN_OP_LESS, PY_TOKEN_OP_LESS_EQUAL, PY_TOKEN_OP_DBL_LESS, PY_TOKEN_DEL_DBL_LESS_EQUAL, - PY_TOKEN_OP_MORE, PY_TOKEN_OP_MORE_EQUAL, PY_TOKEN_OP_DBL_MORE, PY_TOKEN_DEL_DBL_MORE_EQUAL, - PY_TOKEN_OP_STAR, PY_TOKEN_DEL_STAR_EQUAL, PY_TOKEN_OP_DBL_STAR, PY_TOKEN_DEL_DBL_STAR_EQUAL, - PY_TOKEN_OP_PLUS, PY_TOKEN_DEL_PLUS_EQUAL, - PY_TOKEN_OP_MINUS, PY_TOKEN_DEL_MINUS_EQUAL, PY_TOKEN_DEL_MINUS_MORE, - PY_TOKEN_OP_AMPERSAND, PY_TOKEN_DEL_AMPERSAND_EQUAL, - PY_TOKEN_OP_PIPE, PY_TOKEN_DEL_PIPE_EQUAL, - PY_TOKEN_OP_SLASH, PY_TOKEN_DEL_SLASH_EQUAL, PY_TOKEN_OP_DBL_SLASH, PY_TOKEN_DEL_DBL_SLASH_EQUAL, - PY_TOKEN_OP_PERCENT, PY_TOKEN_DEL_PERCENT_EQUAL, - PY_TOKEN_OP_CARET, PY_TOKEN_DEL_CARET_EQUAL, - PY_TOKEN_DEL_EQUAL, PY_TOKEN_OP_DBL_EQUAL, - PY_TOKEN_OP_NOT_EQUAL, - PY_TOKEN_DEL_PERIOD, PY_TOKEN_ELLIPSES, + MP_TOKEN_DEL_PAREN_OPEN, MP_TOKEN_DEL_PAREN_CLOSE, + MP_TOKEN_DEL_BRACKET_OPEN, MP_TOKEN_DEL_BRACKET_CLOSE, + MP_TOKEN_DEL_BRACE_OPEN, MP_TOKEN_DEL_BRACE_CLOSE, + MP_TOKEN_DEL_COMMA, MP_TOKEN_DEL_COLON, MP_TOKEN_DEL_SEMICOLON, MP_TOKEN_DEL_AT, MP_TOKEN_OP_TILDE, + + MP_TOKEN_OP_LESS, MP_TOKEN_OP_LESS_EQUAL, MP_TOKEN_OP_DBL_LESS, MP_TOKEN_DEL_DBL_LESS_EQUAL, + MP_TOKEN_OP_MORE, MP_TOKEN_OP_MORE_EQUAL, MP_TOKEN_OP_DBL_MORE, MP_TOKEN_DEL_DBL_MORE_EQUAL, + MP_TOKEN_OP_STAR, MP_TOKEN_DEL_STAR_EQUAL, MP_TOKEN_OP_DBL_STAR, MP_TOKEN_DEL_DBL_STAR_EQUAL, + MP_TOKEN_OP_PLUS, MP_TOKEN_DEL_PLUS_EQUAL, + MP_TOKEN_OP_MINUS, MP_TOKEN_DEL_MINUS_EQUAL, MP_TOKEN_DEL_MINUS_MORE, + MP_TOKEN_OP_AMPERSAND, MP_TOKEN_DEL_AMPERSAND_EQUAL, + MP_TOKEN_OP_PIPE, MP_TOKEN_DEL_PIPE_EQUAL, + MP_TOKEN_OP_SLASH, MP_TOKEN_DEL_SLASH_EQUAL, MP_TOKEN_OP_DBL_SLASH, MP_TOKEN_DEL_DBL_SLASH_EQUAL, + MP_TOKEN_OP_PERCENT, MP_TOKEN_DEL_PERCENT_EQUAL, + MP_TOKEN_OP_CARET, MP_TOKEN_DEL_CARET_EQUAL, + MP_TOKEN_DEL_EQUAL, MP_TOKEN_OP_DBL_EQUAL, + MP_TOKEN_OP_NOT_EQUAL, + MP_TOKEN_DEL_PERIOD, MP_TOKEN_ELLIPSES, }; // must have the same order as enum in lexer.h @@ -280,7 +280,7 @@ static const char *tok_kw[] = { NULL, }; -static void py_lexer_next_token_into(py_lexer_t *lex, py_token_t *tok, bool first_token) { +static void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool first_token) { // skip white space and comments bool had_physical_newline = false; while (!is_end(lex)) { @@ -322,18 +322,18 @@ static void py_lexer_next_token_into(py_lexer_t *lex, py_token_t *tok, bool firs // if first token is not on first line, we get a physical newline and // this check is done as part of normal indent/dedent checking below // (done to get equivalence with CPython) - tok->kind = PY_TOKEN_INDENT; + tok->kind = MP_TOKEN_INDENT; } else if (lex->emit_dent < 0) { - tok->kind = PY_TOKEN_DEDENT; + tok->kind = MP_TOKEN_DEDENT; lex->emit_dent += 1; } else if (lex->emit_dent > 0) { - tok->kind = PY_TOKEN_INDENT; + tok->kind = MP_TOKEN_INDENT; lex->emit_dent -= 1; } else if (had_physical_newline && lex->nested_bracket_level == 0) { - tok->kind = PY_TOKEN_NEWLINE; + tok->kind = MP_TOKEN_NEWLINE; uint num_spaces = lex->column - 1; lex->emit_dent = 0; @@ -347,20 +347,20 @@ static void py_lexer_next_token_into(py_lexer_t *lex, py_token_t *tok, bool firs lex->emit_dent -= 1; } if (num_spaces != indent_top(lex)) { - tok->kind = PY_TOKEN_DEDENT_MISMATCH; + tok->kind = MP_TOKEN_DEDENT_MISMATCH; } } } else if (is_end(lex)) { if (indent_top(lex) > 0) { - tok->kind = PY_TOKEN_NEWLINE; + tok->kind = MP_TOKEN_NEWLINE; lex->emit_dent = 0; while (indent_top(lex) > 0) { indent_pop(lex); lex->emit_dent -= 1; } } else { - tok->kind = PY_TOKEN_END; + tok->kind = MP_TOKEN_END; } } else if (is_char_or(lex, '\'', '\"') @@ -391,9 +391,9 @@ static void py_lexer_next_token_into(py_lexer_t *lex, py_token_t *tok, bool firs // set token kind if (is_bytes) { - tok->kind = PY_TOKEN_BYTES; + tok->kind = MP_TOKEN_BYTES; } else { - tok->kind = PY_TOKEN_STRING; + tok->kind = MP_TOKEN_STRING; } // get first quoting character @@ -427,8 +427,8 @@ static void py_lexer_next_token_into(py_lexer_t *lex, py_token_t *tok, bool firs next_char(lex); unichar c = CUR_CHAR(lex); switch (c) { - case PY_LEXER_CHAR_EOF: break; // TODO a proper error message? - case '\n': c = PY_LEXER_CHAR_EOF; break; // TODO check this works correctly (we are supposed to ignore it + case MP_LEXER_CHAR_EOF: break; // TODO a proper error message? + case '\n': c = MP_LEXER_CHAR_EOF; break; // TODO check this works correctly (we are supposed to ignore it case '\\': break; case '\'': break; case '"': break; @@ -446,7 +446,7 @@ static void py_lexer_next_token_into(py_lexer_t *lex, py_token_t *tok, bool firs case 'U': // TODO \Uxxxxxxxx only in strings default: break; // TODO error message } - if (c != PY_LEXER_CHAR_EOF) { + if (c != MP_LEXER_CHAR_EOF) { vstr_add_char(&lex->vstr, c); } } else { @@ -458,14 +458,14 @@ static void py_lexer_next_token_into(py_lexer_t *lex, py_token_t *tok, bool firs // check we got the required end quotes if (n_closing < num_quotes) { - tok->kind = PY_TOKEN_LONELY_STRING_OPEN; + tok->kind = MP_TOKEN_LONELY_STRING_OPEN; } // cut off the end quotes from the token text vstr_cut_tail(&lex->vstr, n_closing); } else if (is_head_of_identifier(lex)) { - tok->kind = PY_TOKEN_NAME; + tok->kind = MP_TOKEN_NAME; // get first char vstr_add_char(&lex->vstr, CUR_CHAR(lex)); @@ -478,7 +478,7 @@ static void py_lexer_next_token_into(py_lexer_t *lex, py_token_t *tok, bool firs } } else if (is_digit(lex) || (is_char(lex, '.') && is_following_digit(lex))) { - tok->kind = PY_TOKEN_NUMBER; + tok->kind = MP_TOKEN_NUMBER; // get first char vstr_add_char(&lex->vstr, CUR_CHAR(lex)); @@ -520,7 +520,7 @@ static void py_lexer_next_token_into(py_lexer_t *lex, py_token_t *tok, bool firs if (*t == 0) { // didn't match any delimiter or operator characters - tok->kind = PY_TOKEN_INVALID; + tok->kind = MP_TOKEN_INVALID; } else { // matched a delimiter or operator character @@ -545,7 +545,7 @@ static void py_lexer_next_token_into(py_lexer_t *lex, py_token_t *tok, bool firs next_char(lex); tok_enc_index = t_index; } else { - tok->kind = PY_TOKEN_INVALID; + tok->kind = MP_TOKEN_INVALID; } break; } @@ -569,9 +569,9 @@ static void py_lexer_next_token_into(py_lexer_t *lex, py_token_t *tok, bool firs tok->kind = tok_enc_kind[tok_enc_index]; // compute bracket level for implicit line joining - if (tok->kind == PY_TOKEN_DEL_PAREN_OPEN || tok->kind == PY_TOKEN_DEL_BRACKET_OPEN || tok->kind == PY_TOKEN_DEL_BRACE_OPEN) { + if (tok->kind == MP_TOKEN_DEL_PAREN_OPEN || tok->kind == MP_TOKEN_DEL_BRACKET_OPEN || tok->kind == MP_TOKEN_DEL_BRACE_OPEN) { lex->nested_bracket_level += 1; - } else if (tok->kind == PY_TOKEN_DEL_PAREN_CLOSE || tok->kind == PY_TOKEN_DEL_BRACKET_CLOSE || tok->kind == PY_TOKEN_DEL_BRACE_CLOSE) { + } else if (tok->kind == MP_TOKEN_DEL_PAREN_CLOSE || tok->kind == MP_TOKEN_DEL_BRACKET_CLOSE || tok->kind == MP_TOKEN_DEL_BRACE_CLOSE) { lex->nested_bracket_level -= 1; } } @@ -582,18 +582,18 @@ static void py_lexer_next_token_into(py_lexer_t *lex, py_token_t *tok, bool firs tok->len = vstr_len(&lex->vstr); // check for keywords - if (tok->kind == PY_TOKEN_NAME) { + if (tok->kind == MP_TOKEN_NAME) { for (int i = 0; tok_kw[i] != NULL; i++) { if (str_strn_equal(tok_kw[i], tok->str, tok->len)) { - tok->kind = PY_TOKEN_KW_FALSE + i; + tok->kind = MP_TOKEN_KW_FALSE + i; break; } } } } -py_lexer_t *py_lexer_new(const char *src_name, void *stream_data, py_lexer_stream_next_char_t stream_next_char, py_lexer_stream_close_t stream_close) { - py_lexer_t *lex = m_new(py_lexer_t, 1); +mp_lexer_t *mp_lexer_new(const char *src_name, void *stream_data, mp_lexer_stream_next_char_t stream_next_char, mp_lexer_stream_close_t stream_close) { + mp_lexer_t *lex = m_new(mp_lexer_t, 1); lex->name = src_name; // TODO do we need to strdup this? lex->stream_data = stream_data; @@ -615,25 +615,25 @@ py_lexer_t *py_lexer_new(const char *src_name, void *stream_data, py_lexer_strea lex->chr2 = stream_next_char(stream_data); // if input stream is 0, 1 or 2 characters long and doesn't end in a newline, then insert a newline at the end - if (lex->chr0 == PY_LEXER_CHAR_EOF) { + if (lex->chr0 == MP_LEXER_CHAR_EOF) { lex->chr0 = '\n'; - } else if (lex->chr1 == PY_LEXER_CHAR_EOF) { + } else if (lex->chr1 == MP_LEXER_CHAR_EOF) { if (lex->chr0 != '\n' && lex->chr0 != '\r') { lex->chr1 = '\n'; } - } else if (lex->chr2 == PY_LEXER_CHAR_EOF) { + } else if (lex->chr2 == MP_LEXER_CHAR_EOF) { if (lex->chr1 != '\n' && lex->chr1 != '\r') { lex->chr2 = '\n'; } } // preload first token - py_lexer_next_token_into(lex, &lex->tok_cur, true); + mp_lexer_next_token_into(lex, &lex->tok_cur, true); return lex; } -void py_lexer_free(py_lexer_t *lex) { +void mp_lexer_free(mp_lexer_t *lex) { if (lex) { if (lex->stream_close) { lex->stream_close(lex->stream_data); @@ -643,45 +643,45 @@ void py_lexer_free(py_lexer_t *lex) { } } -void py_lexer_to_next(py_lexer_t *lex) { - py_lexer_next_token_into(lex, &lex->tok_cur, false); +void mp_lexer_to_next(mp_lexer_t *lex) { + mp_lexer_next_token_into(lex, &lex->tok_cur, false); } -const py_token_t *py_lexer_cur(const py_lexer_t *lex) { +const mp_token_t *mp_lexer_cur(const mp_lexer_t *lex) { return &lex->tok_cur; } -bool py_lexer_is_kind(py_lexer_t *lex, py_token_kind_t kind) { +bool mp_lexer_is_kind(mp_lexer_t *lex, mp_token_kind_t kind) { return lex->tok_cur.kind == kind; } /* -bool py_lexer_is_str(py_lexer_t *lex, const char *str) { - return py_token_is_str(&lex->tok_cur, str); +bool mp_lexer_is_str(mp_lexer_t *lex, const char *str) { + return mp_token_is_str(&lex->tok_cur, str); } -bool py_lexer_opt_kind(py_lexer_t *lex, py_token_kind_t kind) { - if (py_lexer_is_kind(lex, kind)) { - py_lexer_to_next(lex); +bool mp_lexer_opt_kind(mp_lexer_t *lex, mp_token_kind_t kind) { + if (mp_lexer_is_kind(lex, kind)) { + mp_lexer_to_next(lex); return true; } return false; } -bool py_lexer_opt_str(py_lexer_t *lex, const char *str) { - if (py_lexer_is_str(lex, str)) { - py_lexer_to_next(lex); +bool mp_lexer_opt_str(mp_lexer_t *lex, const char *str) { + if (mp_lexer_is_str(lex, str)) { + mp_lexer_to_next(lex); return true; } return false; } */ -bool py_lexer_show_error(py_lexer_t *lex, const char *msg) { - return py_token_show_error(&lex->tok_cur, msg); +bool mp_lexer_show_error(mp_lexer_t *lex, const char *msg) { + return mp_token_show_error(&lex->tok_cur, msg); } -bool py_lexer_show_error_pythonic(py_lexer_t *lex, const char *msg) { +bool mp_lexer_show_error_pythonic(mp_lexer_t *lex, const char *msg) { printf(" File \"%s\", line %d column %d\n%s\n", lex->tok_cur.src_name, lex->tok_cur.src_line, lex->tok_cur.src_column, msg); return false; } diff --git a/py/lexer.h b/py/lexer.h index 347237060..f58a38e92 100644 --- a/py/lexer.h +++ b/py/lexer.h @@ -1,146 +1,140 @@ -/* lexer.h -- simple tokeniser for Python implementation +/* lexer.h -- simple tokeniser for Micro Python + * + * Uses (byte) length instead of null termination. + * Tokens are the same - UTF-8 with (byte) length. */ -#ifndef INCLUDED_LEXER_H -#define INCLUDED_LEXER_H - -/* uses (byte) length instead of null termination - * tokens are the same - UTF-8 with (byte) length - */ - -typedef enum _py_token_kind_t { - PY_TOKEN_END, // 0 - - PY_TOKEN_INVALID, - PY_TOKEN_DEDENT_MISMATCH, - PY_TOKEN_LONELY_STRING_OPEN, - - PY_TOKEN_NEWLINE, // 4 - PY_TOKEN_INDENT, // 5 - PY_TOKEN_DEDENT, // 6 - - PY_TOKEN_NAME, // 7 - PY_TOKEN_NUMBER, - PY_TOKEN_STRING, - PY_TOKEN_BYTES, - - PY_TOKEN_ELLIPSES, - - PY_TOKEN_KW_FALSE, // 12 - PY_TOKEN_KW_NONE, - PY_TOKEN_KW_TRUE, - PY_TOKEN_KW_AND, - PY_TOKEN_KW_AS, - PY_TOKEN_KW_ASSERT, - PY_TOKEN_KW_BREAK, - PY_TOKEN_KW_CLASS, - PY_TOKEN_KW_CONTINUE, - PY_TOKEN_KW_DEF, // 21 - PY_TOKEN_KW_DEL, - PY_TOKEN_KW_ELIF, - PY_TOKEN_KW_ELSE, - PY_TOKEN_KW_EXCEPT, - PY_TOKEN_KW_FINALLY, - PY_TOKEN_KW_FOR, - PY_TOKEN_KW_FROM, - PY_TOKEN_KW_GLOBAL, - PY_TOKEN_KW_IF, - PY_TOKEN_KW_IMPORT, // 31 - PY_TOKEN_KW_IN, - PY_TOKEN_KW_IS, - PY_TOKEN_KW_LAMBDA, - PY_TOKEN_KW_NONLOCAL, - PY_TOKEN_KW_NOT, - PY_TOKEN_KW_OR, - PY_TOKEN_KW_PASS, - PY_TOKEN_KW_RAISE, - PY_TOKEN_KW_RETURN, - PY_TOKEN_KW_TRY, // 41 - PY_TOKEN_KW_WHILE, - PY_TOKEN_KW_WITH, - PY_TOKEN_KW_YIELD, - - PY_TOKEN_OP_PLUS, // 45 - PY_TOKEN_OP_MINUS, - PY_TOKEN_OP_STAR, - PY_TOKEN_OP_DBL_STAR, - PY_TOKEN_OP_SLASH, - PY_TOKEN_OP_DBL_SLASH, - PY_TOKEN_OP_PERCENT, - PY_TOKEN_OP_LESS, - PY_TOKEN_OP_DBL_LESS, - PY_TOKEN_OP_MORE, - PY_TOKEN_OP_DBL_MORE, // 55 - PY_TOKEN_OP_AMPERSAND, - PY_TOKEN_OP_PIPE, - PY_TOKEN_OP_CARET, - PY_TOKEN_OP_TILDE, - PY_TOKEN_OP_LESS_EQUAL, - PY_TOKEN_OP_MORE_EQUAL, - PY_TOKEN_OP_DBL_EQUAL, - PY_TOKEN_OP_NOT_EQUAL, - - PY_TOKEN_DEL_PAREN_OPEN, // 64 - PY_TOKEN_DEL_PAREN_CLOSE, - PY_TOKEN_DEL_BRACKET_OPEN, - PY_TOKEN_DEL_BRACKET_CLOSE, - PY_TOKEN_DEL_BRACE_OPEN, - PY_TOKEN_DEL_BRACE_CLOSE, - PY_TOKEN_DEL_COMMA, - PY_TOKEN_DEL_COLON, - PY_TOKEN_DEL_PERIOD, - PY_TOKEN_DEL_SEMICOLON, - PY_TOKEN_DEL_AT, // 74 - PY_TOKEN_DEL_EQUAL, - PY_TOKEN_DEL_PLUS_EQUAL, - PY_TOKEN_DEL_MINUS_EQUAL, - PY_TOKEN_DEL_STAR_EQUAL, - PY_TOKEN_DEL_SLASH_EQUAL, - PY_TOKEN_DEL_DBL_SLASH_EQUAL, - PY_TOKEN_DEL_PERCENT_EQUAL, - PY_TOKEN_DEL_AMPERSAND_EQUAL, - PY_TOKEN_DEL_PIPE_EQUAL, - PY_TOKEN_DEL_CARET_EQUAL, // 84 - PY_TOKEN_DEL_DBL_MORE_EQUAL, - PY_TOKEN_DEL_DBL_LESS_EQUAL, - PY_TOKEN_DEL_DBL_STAR_EQUAL, - PY_TOKEN_DEL_MINUS_MORE, -} py_token_kind_t; - -typedef struct _py_token_t { +typedef enum _mp_token_kind_t { + MP_TOKEN_END, // 0 + + MP_TOKEN_INVALID, + MP_TOKEN_DEDENT_MISMATCH, + MP_TOKEN_LONELY_STRING_OPEN, + + MP_TOKEN_NEWLINE, // 4 + MP_TOKEN_INDENT, // 5 + MP_TOKEN_DEDENT, // 6 + + MP_TOKEN_NAME, // 7 + MP_TOKEN_NUMBER, + MP_TOKEN_STRING, + MP_TOKEN_BYTES, + + MP_TOKEN_ELLIPSES, + + MP_TOKEN_KW_FALSE, // 12 + MP_TOKEN_KW_NONE, + MP_TOKEN_KW_TRUE, + MP_TOKEN_KW_AND, + MP_TOKEN_KW_AS, + MP_TOKEN_KW_ASSERT, + MP_TOKEN_KW_BREAK, + MP_TOKEN_KW_CLASS, + MP_TOKEN_KW_CONTINUE, + MP_TOKEN_KW_DEF, // 21 + MP_TOKEN_KW_DEL, + MP_TOKEN_KW_ELIF, + MP_TOKEN_KW_ELSE, + MP_TOKEN_KW_EXCEPT, + MP_TOKEN_KW_FINALLY, + MP_TOKEN_KW_FOR, + MP_TOKEN_KW_FROM, + MP_TOKEN_KW_GLOBAL, + MP_TOKEN_KW_IF, + MP_TOKEN_KW_IMPORT, // 31 + MP_TOKEN_KW_IN, + MP_TOKEN_KW_IS, + MP_TOKEN_KW_LAMBDA, + MP_TOKEN_KW_NONLOCAL, + MP_TOKEN_KW_NOT, + MP_TOKEN_KW_OR, + MP_TOKEN_KW_PASS, + MP_TOKEN_KW_RAISE, + MP_TOKEN_KW_RETURN, + MP_TOKEN_KW_TRY, // 41 + MP_TOKEN_KW_WHILE, + MP_TOKEN_KW_WITH, + MP_TOKEN_KW_YIELD, + + MP_TOKEN_OP_PLUS, // 45 + MP_TOKEN_OP_MINUS, + MP_TOKEN_OP_STAR, + MP_TOKEN_OP_DBL_STAR, + MP_TOKEN_OP_SLASH, + MP_TOKEN_OP_DBL_SLASH, + MP_TOKEN_OP_PERCENT, + MP_TOKEN_OP_LESS, + MP_TOKEN_OP_DBL_LESS, + MP_TOKEN_OP_MORE, + MP_TOKEN_OP_DBL_MORE, // 55 + MP_TOKEN_OP_AMPERSAND, + MP_TOKEN_OP_PIPE, + MP_TOKEN_OP_CARET, + MP_TOKEN_OP_TILDE, + MP_TOKEN_OP_LESS_EQUAL, + MP_TOKEN_OP_MORE_EQUAL, + MP_TOKEN_OP_DBL_EQUAL, + MP_TOKEN_OP_NOT_EQUAL, + + MP_TOKEN_DEL_PAREN_OPEN, // 64 + MP_TOKEN_DEL_PAREN_CLOSE, + MP_TOKEN_DEL_BRACKET_OPEN, + MP_TOKEN_DEL_BRACKET_CLOSE, + MP_TOKEN_DEL_BRACE_OPEN, + MP_TOKEN_DEL_BRACE_CLOSE, + MP_TOKEN_DEL_COMMA, + MP_TOKEN_DEL_COLON, + MP_TOKEN_DEL_PERIOD, + MP_TOKEN_DEL_SEMICOLON, + MP_TOKEN_DEL_AT, // 74 + MP_TOKEN_DEL_EQUAL, + MP_TOKEN_DEL_PLUS_EQUAL, + MP_TOKEN_DEL_MINUS_EQUAL, + MP_TOKEN_DEL_STAR_EQUAL, + MP_TOKEN_DEL_SLASH_EQUAL, + MP_TOKEN_DEL_DBL_SLASH_EQUAL, + MP_TOKEN_DEL_PERCENT_EQUAL, + MP_TOKEN_DEL_AMPERSAND_EQUAL, + MP_TOKEN_DEL_PIPE_EQUAL, + MP_TOKEN_DEL_CARET_EQUAL, // 84 + MP_TOKEN_DEL_DBL_MORE_EQUAL, + MP_TOKEN_DEL_DBL_LESS_EQUAL, + MP_TOKEN_DEL_DBL_STAR_EQUAL, + MP_TOKEN_DEL_MINUS_MORE, +} mp_token_kind_t; + +typedef struct _mp_token_t { const char *src_name; // name of source uint src_line; // source line uint src_column; // source column - py_token_kind_t kind; // kind of token + mp_token_kind_t kind; // kind of token const char *str; // string of token (valid only while this token is current token) uint len; // (byte) length of string of token -} py_token_t; +} mp_token_t; // the next-char function must return the next character in the stream -// it must return PY_LEXER_CHAR_EOF if end of stream -// it can be called again after returning PY_LEXER_CHAR_EOF, and in that case must return PY_LEXER_CHAR_EOF -#define PY_LEXER_CHAR_EOF (-1) -typedef unichar (*py_lexer_stream_next_char_t)(void*); -typedef void (*py_lexer_stream_close_t)(void*); - -typedef struct _py_lexer_t py_lexer_t; - -void py_token_show(const py_token_t *tok); -void py_token_show_error_prefix(const py_token_t *tok); -bool py_token_show_error(const py_token_t *tok, const char *msg); - -py_lexer_t *py_lexer_new(const char *src_name, void *stream_data, py_lexer_stream_next_char_t stream_next_char, py_lexer_stream_close_t stream_close); -void py_lexer_free(py_lexer_t *lex); -void py_lexer_to_next(py_lexer_t *lex); -const py_token_t *py_lexer_cur(const py_lexer_t *lex); -bool py_lexer_is_kind(py_lexer_t *lex, py_token_kind_t kind); +// it must return MP_LEXER_CHAR_EOF if end of stream +// it can be called again after returning MP_LEXER_CHAR_EOF, and in that case must return MP_LEXER_CHAR_EOF +#define MP_LEXER_CHAR_EOF (-1) +typedef unichar (*mp_lexer_stream_next_char_t)(void*); +typedef void (*mp_lexer_stream_close_t)(void*); + +typedef struct _mp_lexer_t mp_lexer_t; + +void mp_token_show(const mp_token_t *tok); +void mp_token_show_error_prefix(const mp_token_t *tok); +bool mp_token_show_error(const mp_token_t *tok, const char *msg); + +mp_lexer_t *mp_lexer_new(const char *src_name, void *stream_data, mp_lexer_stream_next_char_t stream_next_char, mp_lexer_stream_close_t stream_close); +void mp_lexer_free(mp_lexer_t *lex); +void mp_lexer_to_next(mp_lexer_t *lex); +const mp_token_t *mp_lexer_cur(const mp_lexer_t *lex); +bool mp_lexer_is_kind(mp_lexer_t *lex, mp_token_kind_t kind); /* unused -bool py_lexer_is_str(py_lexer_t *lex, const char *str); -bool py_lexer_opt_kind(py_lexer_t *lex, py_token_kind_t kind); -bool py_lexer_opt_str(py_lexer_t *lex, const char *str); +bool mp_lexer_is_str(mp_lexer_t *lex, const char *str); +bool mp_lexer_opt_kind(mp_lexer_t *lex, mp_token_kind_t kind); +bool mp_lexer_opt_str(mp_lexer_t *lex, const char *str); */ -bool py_lexer_show_error(py_lexer_t *lex, const char *msg); -bool py_lexer_show_error_pythonic(py_lexer_t *lex, const char *msg); - -#endif /* INCLUDED_LEXER_H */ +bool mp_lexer_show_error(mp_lexer_t *lex, const char *msg); +bool mp_lexer_show_error_pythonic(mp_lexer_t *lex, const char *msg); diff --git a/py/map.c b/py/map.c index 12753af9f..3c2d1fbb5 100644 --- a/py/map.c +++ b/py/map.c @@ -3,12 +3,10 @@ #include <assert.h> #include "misc.h" -#include "mpyconfig.h" -#include "runtime.h" - -#include "map.h" +#include "mpconfig.h" #include "obj.h" -#include "objprivate.h" +#include "runtime0.h" +#include "map.h" // approximatelly doubling primes; made with Mathematica command: Table[Prime[Floor[(1.7)^n]], {n, 3, 24}] static int doubling_primes[] = {7, 19, 43, 89, 179, 347, 647, 1229, 2297, 4243, 7829, 14347, 26017, 47149, 84947, 152443, 273253, 488399, 869927, 1547173, 2745121, 4861607}; @@ -24,43 +22,46 @@ int get_doubling_prime_greater_or_equal_to(int x) { return x | 1; } -void py_map_init(py_map_t *map, py_map_kind_t kind, int n) { +/******************************************************************************/ +/* map */ + +void mp_map_init(mp_map_t *map, mp_map_kind_t kind, int n) { map->kind = kind; map->used = 0; map->alloc = get_doubling_prime_greater_or_equal_to(n + 1); - map->table = m_new0(py_map_elem_t, map->alloc); + map->table = m_new0(mp_map_elem_t, map->alloc); } -py_map_t *py_map_new(py_map_kind_t kind, int n) { - py_map_t *map = m_new(py_map_t, 1); - py_map_init(map, kind, n); +mp_map_t *mp_map_new(mp_map_kind_t kind, int n) { + mp_map_t *map = m_new(mp_map_t, 1); + mp_map_init(map, kind, n); return map; } -py_map_elem_t* py_map_lookup_helper(py_map_t *map, py_obj_t index, bool add_if_not_found) { - bool is_map_py_obj = (map->kind == MAP_PY_OBJ); +mp_map_elem_t* mp_map_lookup_helper(mp_map_t *map, mp_obj_t index, bool add_if_not_found) { + bool is_map_mp_obj = (map->kind == MP_MAP_OBJ); machine_uint_t hash; - if (is_map_py_obj) { - hash = py_obj_hash(index); + if (is_map_mp_obj) { + hash = mp_obj_hash(index); } else { hash = (machine_uint_t)index; } uint pos = hash % map->alloc; for (;;) { - py_map_elem_t *elem = &map->table[pos]; + mp_map_elem_t *elem = &map->table[pos]; if (elem->key == NULL) { // not in table if (add_if_not_found) { if (map->used + 1 >= map->alloc) { // not enough room in table, rehash it int old_alloc = map->alloc; - py_map_elem_t *old_table = map->table; + mp_map_elem_t *old_table = map->table; map->alloc = get_doubling_prime_greater_or_equal_to(map->alloc + 1); map->used = 0; - map->table = m_new0(py_map_elem_t, map->alloc); + map->table = m_new0(mp_map_elem_t, map->alloc); for (int i = 0; i < old_alloc; i++) { if (old_table[i].key != NULL) { - py_map_lookup_helper(map, old_table[i].key, true)->value = old_table[i].value; + mp_map_lookup_helper(map, old_table[i].key, true)->value = old_table[i].value; } } m_free(old_table); @@ -74,7 +75,7 @@ py_map_elem_t* py_map_lookup_helper(py_map_t *map, py_obj_t index, bool add_if_n } else { return NULL; } - } else if (elem->key == index || (is_map_py_obj && py_obj_equal(elem->key, index))) { + } else if (elem->key == index || (is_map_mp_obj && mp_obj_equal(elem->key, index))) { // found it /* it seems CPython does not replace the index; try x={True:'true'};x[1]='one';x if (add_if_not_found) { @@ -89,55 +90,57 @@ py_map_elem_t* py_map_lookup_helper(py_map_t *map, py_obj_t index, bool add_if_n } } -py_map_elem_t* py_qstr_map_lookup(py_map_t *map, qstr index, bool add_if_not_found) { - py_obj_t o = (py_obj_t)(machine_uint_t)index; - return py_map_lookup_helper(map, o, add_if_not_found); +mp_map_elem_t* mp_qstr_map_lookup(mp_map_t *map, qstr index, bool add_if_not_found) { + mp_obj_t o = (mp_obj_t)(machine_uint_t)index; + return mp_map_lookup_helper(map, o, add_if_not_found); } -py_map_elem_t* py_map_lookup(py_obj_t o, py_obj_t index, bool add_if_not_found) { - assert(IS_O(o, O_MAP)); - return py_map_lookup_helper(&((py_obj_base_t *)o)->u_map, index, add_if_not_found); +/******************************************************************************/ +/* set */ + +void mp_set_init(mp_set_t *set, int n) { + set->alloc = get_doubling_prime_greater_or_equal_to(n + 1); + set->used = 0; + set->table = m_new0(mp_obj_t, set->alloc); } -py_obj_t py_set_lookup(py_obj_t o_in, py_obj_t index, bool add_if_not_found) { - assert(IS_O(o_in, O_SET)); - py_obj_base_t *o = o_in; - int hash = py_obj_hash(index); - int pos = hash % o->u_set.alloc; +mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, bool add_if_not_found) { + int hash = mp_obj_hash(index); + int pos = hash % set->alloc; for (;;) { - py_obj_t elem = o->u_set.table[pos]; - if (elem == NULL) { + mp_obj_t elem = set->table[pos]; + if (elem == MP_OBJ_NULL) { // not in table if (add_if_not_found) { - if (o->u_set.used + 1 >= o->u_set.alloc) { + if (set->used + 1 >= set->alloc) { // not enough room in table, rehash it - int old_alloc = o->u_set.alloc; - py_obj_t *old_table = o->u_set.table; - o->u_set.alloc = get_doubling_prime_greater_or_equal_to(o->u_set.alloc + 1); - o->u_set.used = 0; - o->u_set.table = m_new(py_obj_t, o->u_set.alloc); + int old_alloc = set->alloc; + mp_obj_t *old_table = set->table; + set->alloc = get_doubling_prime_greater_or_equal_to(set->alloc + 1); + set->used = 0; + set->table = m_new(mp_obj_t, set->alloc); for (int i = 0; i < old_alloc; i++) { if (old_table[i] != NULL) { - py_set_lookup(o, old_table[i], true); + mp_set_lookup(set, old_table[i], true); } } m_free(old_table); // restart the search for the new element - pos = hash % o->u_set.alloc; + pos = hash % set->alloc; } else { - o->u_set.used += 1; - o->u_set.table[pos] = index; + set->used += 1; + set->table[pos] = index; return index; } } else { - return NULL; + return MP_OBJ_NULL; } - } else if (py_obj_equal(elem, index)) { + } else if (mp_obj_equal(elem, index)) { // found it return elem; } else { // not yet found, keep searching in this table - pos = (pos + 1) % o->u_set.alloc; + pos = (pos + 1) % set->alloc; } } } diff --git a/py/map.h b/py/map.h index 6c9df9ece..8ee8429b5 100644 --- a/py/map.h +++ b/py/map.h @@ -1,30 +1,37 @@ typedef enum { - MAP_QSTR, - MAP_PY_OBJ, -} py_map_kind_t; + MP_MAP_QSTR, + MP_MAP_OBJ, +} mp_map_kind_t; -typedef struct _py_map_elem_t { - py_obj_t key; - py_obj_t value; -} py_map_elem_t; +typedef struct _mp_map_elem_t { + mp_obj_t key; + mp_obj_t value; +} mp_map_elem_t; -typedef struct _py_map_t { +typedef struct _mp_map_t { struct { - py_map_kind_t kind : 1; + mp_map_kind_t kind : 1; machine_uint_t used : (8 * BYTES_PER_WORD - 1); }; machine_uint_t alloc; - py_map_elem_t *table; -} py_map_t; + mp_map_elem_t *table; +} mp_map_t; + +typedef struct _mp_set_t { + machine_uint_t alloc; + machine_uint_t used; + mp_obj_t *table; +} mp_set_t; // these are defined in runtime.c -py_map_t *rt_get_map_locals(void); -void rt_set_map_locals(py_map_t *m); +mp_map_t *rt_get_map_locals(void); +void rt_set_map_locals(mp_map_t *m); int get_doubling_prime_greater_or_equal_to(int x); -void py_map_init(py_map_t *map, py_map_kind_t kind, int n); -py_map_t *py_map_new(py_map_kind_t kind, int n); -py_map_elem_t* py_map_lookup_helper(py_map_t *map, py_obj_t index, bool add_if_not_found); -py_map_elem_t* py_qstr_map_lookup(py_map_t *map, qstr index, bool add_if_not_found); -py_map_elem_t* py_map_lookup(py_obj_t o, py_obj_t index, bool add_if_not_found); -py_obj_t py_set_lookup(py_obj_t o_in, py_obj_t index, bool add_if_not_found); +void mp_map_init(mp_map_t *map, mp_map_kind_t kind, int n); +mp_map_t *mp_map_new(mp_map_kind_t kind, int n); +mp_map_elem_t* mp_map_lookup_helper(mp_map_t *map, mp_obj_t index, bool add_if_not_found); +mp_map_elem_t* mp_qstr_map_lookup(mp_map_t *map, qstr index, bool add_if_not_found); + +void mp_set_init(mp_set_t *set, int n); +mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, bool add_if_not_found); diff --git a/py/misc.h b/py/misc.h index 4a100af29..6c0e18ca0 100644 --- a/py/misc.h +++ b/py/misc.h @@ -19,6 +19,8 @@ typedef unsigned int uint; #define m_new(type, num) ((type*)(m_malloc(sizeof(type) * (num)))) #define m_new0(type, num) ((type*)(m_malloc0(sizeof(type) * (num)))) #define m_renew(type, ptr, num) ((type*)(m_realloc((ptr), sizeof(type) * (num)))) +#define m_new_obj(type) (m_new(type, 1)) +#define m_new_obj_var(obj_type, var_type, var_num) ((obj_type*)m_malloc(sizeof(obj_type) + sizeof(var_type) * (var_num))) void m_free(void *ptr); void *m_malloc(int num_bytes); diff --git a/py/obj.c b/py/obj.c index 0699d4cde..ff49492bf 100644 --- a/py/obj.c +++ b/py/obj.c @@ -6,166 +6,22 @@ #include "nlr.h" #include "misc.h" -#include "mpyconfig.h" +#include "mpconfig.h" +#include "obj.h" +#include "runtime0.h" #include "runtime.h" - #include "map.h" -#include "obj.h" -#include "objprivate.h" - -py_obj_t py_obj_new_int(machine_int_t value) { - return TO_SMALL_INT(value); -} - -py_obj_t py_obj_new_const(const char *id) { - py_obj_base_t *o = m_new(py_obj_base_t, 1); - o->kind = O_CONST; - o->id = id; - return (py_obj_t)o; -} - -py_obj_t py_obj_new_str(qstr qstr) { - py_obj_base_t *o = m_new(py_obj_base_t, 1); - o->kind = O_STR; - o->u_str = qstr; - return (py_obj_t)o; -} - -#if MICROPY_ENABLE_FLOAT -py_obj_t py_obj_new_float(py_float_t val) { - py_obj_base_t *o = m_new(py_obj_base_t, 1); - o->kind = O_FLOAT; - o->u_float = val; - return (py_obj_t)o; -} - -py_obj_t py_obj_new_complex(py_float_t real, py_float_t imag) { - py_obj_base_t *o = m_new(py_obj_base_t, 1); - o->kind = O_COMPLEX; - o->u_complex.real = real; - o->u_complex.imag = imag; - return (py_obj_t)o; -} -#endif - -py_obj_t py_obj_new_exception_0(qstr id) { - py_obj_base_t *o = m_new(py_obj_base_t, 1); - o->kind = O_EXCEPTION_0; - o->u_exc0.id = id; - return (py_obj_t)o; -} - -py_obj_t py_obj_new_exception_2(qstr id, const char *fmt, const char *s1, const char *s2) { - py_obj_base_t *o = m_new(py_obj_base_t, 1); - o->kind = O_EXCEPTION_N; - o->u_exc_n.id = id; - o->u_exc_n.n_args = 3; - o->u_exc_n.args = m_new(const void*, 3); - o->u_exc_n.args[0] = fmt; - o->u_exc_n.args[1] = s1; - o->u_exc_n.args[2] = s2; - return (py_obj_t)o; -} - -// range is a class and instances are immutable sequence objects -py_obj_t py_obj_new_range(int start, int stop, int step) { - py_obj_base_t *o = m_new(py_obj_base_t, 1); - o->kind = O_RANGE; - o->u_range.start = start; - o->u_range.stop = stop; - o->u_range.step = step; - return o; -} - -py_obj_t py_obj_new_range_iterator(int cur, int stop, int step) { - py_obj_base_t *o = m_new(py_obj_base_t, 1); - o->kind = O_RANGE_IT; - o->u_range_it.cur = cur; - o->u_range_it.stop = stop; - o->u_range_it.step = step; - return o; -} - -py_obj_t py_obj_new_tuple_iterator(py_obj_base_t *tuple, int cur) { - py_obj_base_t *o = m_new(py_obj_base_t, 1); - o->kind = O_TUPLE_IT; - o->u_tuple_list_it.obj = tuple; - o->u_tuple_list_it.cur = cur; - return o; -} -py_obj_t py_obj_new_list_iterator(py_obj_base_t *list, int cur) { - py_obj_base_t *o = m_new(py_obj_base_t, 1); - o->kind = O_LIST_IT; - o->u_tuple_list_it.obj = list; - o->u_tuple_list_it.cur = cur; - return o; +mp_obj_t mp_obj_new_int(machine_int_t value) { + return MP_OBJ_NEW_SMALL_INT(value); } -py_obj_t py_obj_new_user(const py_user_info_t *info, machine_uint_t data1, machine_uint_t data2) { - py_obj_base_t *o = m_new(py_obj_base_t, 1); - o->kind = O_USER; - // TODO should probably parse the info to turn strings to qstr's, and wrap functions in O_FUN_N objects - // that'll take up some memory. maybe we can lazily do the O_FUN_N: leave it a ptr to a C function, and - // only when the method is looked-up do we change that to the O_FUN_N object. - o->u_user.info = info; - o->u_user.data1 = data1; - o->u_user.data2 = data2; - return o; -} - -const char *py_obj_get_type_str(py_obj_t o_in) { - if (IS_SMALL_INT(o_in)) { +const char *mp_obj_get_type_str(mp_obj_t o_in) { + if (MP_OBJ_IS_SMALL_INT(o_in)) { return "int"; } else { - py_obj_base_t *o = o_in; - switch (o->kind) { - case O_CONST: - if (o == py_const_none) { - return "NoneType"; - } else { - return "bool"; - } - case O_STR: - return "str"; -#if MICROPY_ENABLE_FLOAT - case O_FLOAT: - return "float"; -#endif - case O_FUN_0: - case O_FUN_1: - case O_FUN_2: - case O_FUN_N: - case O_FUN_VAR: - case O_FUN_BC: - return "function"; - case O_GEN_INSTANCE: - return "generator"; - case O_TUPLE: - return "tuple"; - case O_LIST: - return "list"; - case O_TUPLE_IT: - return "tuple_iterator"; - case O_LIST_IT: - return "list_iterator"; - case O_SET: - return "set"; - case O_MAP: - return "dict"; - case O_OBJ: - { - py_map_elem_t *qn = py_qstr_map_lookup(o->u_obj.class->u_class.locals, qstr_from_str_static("__qualname__"), false); - assert(qn != NULL); - assert(IS_O(qn->value, O_STR)); - return qstr_str(((py_obj_base_t*)qn->value)->u_str); - } - case O_USER: - return o->u_user.info->type_name; - default: - assert(0); - return "UnknownType"; - } + mp_obj_base_t *o = o_in; + return o->type->name; } } @@ -176,148 +32,43 @@ void printf_wrapper(void *env, const char *fmt, ...) { va_end(args); } -void py_obj_print_helper(void (*print)(void *env, const char *fmt, ...), void *env, py_obj_t o_in) { - if (IS_SMALL_INT(o_in)) { - print(env, "%d", (int)FROM_SMALL_INT(o_in)); +void mp_obj_print_helper(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) { + if (MP_OBJ_IS_SMALL_INT(o_in)) { + print(env, "%d", (int)MP_OBJ_SMALL_INT_VALUE(o_in)); } else { - py_obj_base_t *o = o_in; - switch (o->kind) { - case O_CONST: - print(env, "%s", o->id); - break; - case O_STR: - // TODO need to escape chars etc - print(env, "'%s'", qstr_str(o->u_str)); - break; -#if MICROPY_ENABLE_FLOAT - case O_FLOAT: - print(env, "%.8g", o->u_float); - break; - case O_COMPLEX: - if (o->u_complex.real == 0) { - print(env, "%.8gj", o->u_complex.imag); - } else { - print(env, "(%.8g+%.8gj)", o->u_complex.real, o->u_complex.imag); - } - break; -#endif - case O_EXCEPTION_0: - print(env, "%s", qstr_str(o->u_exc0.id)); - break; - case O_EXCEPTION_N: - print(env, "%s: ", qstr_str(o->u_exc_n.id)); - print(env, o->u_exc_n.args[0], o->u_exc_n.args[1], o->u_exc_n.args[2]); - break; - case O_GEN_INSTANCE: - print(env, "<generator object 'fun-name' at %p>", o); - break; - case O_TUPLE: - print(env, "("); - for (int i = 0; i < o->u_tuple_list.len; i++) { - if (i > 0) { - print(env, ", "); - } - py_obj_print_helper(print, env, o->u_tuple_list.items[i]); - } - if (o->u_tuple_list.len == 1) { - print(env, ","); - } - print(env, ")"); - break; - case O_LIST: - print(env, "["); - for (int i = 0; i < o->u_tuple_list.len; i++) { - if (i > 0) { - print(env, ", "); - } - py_obj_print_helper(print, env, o->u_tuple_list.items[i]); - } - print(env, "]"); - break; - case O_SET: - { - bool first = true; - print(env, "{"); - for (int i = 0; i < o->u_set.alloc; i++) { - if (o->u_set.table[i] != NULL) { - if (!first) { - print(env, ", "); - } - first = false; - py_obj_print_helper(print, env, o->u_set.table[i]); - } - } - print(env, "}"); - break; - } - case O_MAP: - { - bool first = true; - print(env, "{"); - for (int i = 0; i < o->u_map.alloc; i++) { - if (o->u_map.table[i].key != NULL) { - if (!first) { - print(env, ", "); - } - first = false; - py_obj_print_helper(print, env, o->u_map.table[i].key); - print(env, ": "); - py_obj_print_helper(print, env, o->u_map.table[i].value); - } - } - print(env, "}"); - break; - } - case O_USER: - if (o->u_user.info->print == NULL) { - print(env, "<unknown user object>"); - } else { - o->u_user.info->print(o_in); - } - break; - default: - print(env, "<? %d>", o->kind); - assert(0); + mp_obj_base_t *o = o_in; + if (o->type->print != NULL) { + o->type->print(print, env, o_in); + } else { + print(env, "<%s>", o->type->name); } } } -void py_obj_print(py_obj_t o_in) { - py_obj_print_helper(printf_wrapper, NULL, o_in); +void mp_obj_print(mp_obj_t o_in) { + mp_obj_print_helper(printf_wrapper, NULL, o_in); } -bool py_obj_is_callable(py_obj_t o_in) { - if (IS_SMALL_INT(o_in)) { +bool mp_obj_is_callable(mp_obj_t o_in) { + if (MP_OBJ_IS_SMALL_INT(o_in)) { return false; } else { - py_obj_base_t *o = o_in; - switch (o->kind) { - case O_FUN_0: - case O_FUN_1: - case O_FUN_2: - case O_FUN_VAR: - case O_FUN_N: - case O_FUN_BC: - case O_FUN_ASM: - // what about O_CLASS, and an O_OBJ that has a __call__ method? - return true; - default: - return false; - } + mp_obj_base_t *o = o_in; + return o->type->call_n != NULL; } } -machine_int_t py_obj_hash(py_obj_t o_in) { - if (o_in == py_const_false) { +machine_int_t mp_obj_hash(mp_obj_t o_in) { + if (o_in == mp_const_false) { return 0; // needs to hash to same as the integer 0, since False==0 - } else if (o_in == py_const_true) { + } else if (o_in == mp_const_true) { return 1; // needs to hash to same as the integer 1, since True==1 - } else if (IS_SMALL_INT(o_in)) { - return FROM_SMALL_INT(o_in); - } else if (IS_O(o_in, O_CONST)) { + } else if (MP_OBJ_IS_SMALL_INT(o_in)) { + return MP_OBJ_SMALL_INT_VALUE(o_in); + } else if (MP_OBJ_IS_TYPE(o_in, &none_type)) { return (machine_int_t)o_in; - } else if (IS_O(o_in, O_STR)) { - return ((py_obj_base_t*)o_in)->u_str; + } else if (MP_OBJ_IS_TYPE(o_in, &str_type)) { + return mp_obj_str_get(o_in); } else { assert(0); return 0; @@ -330,38 +81,38 @@ machine_int_t py_obj_hash(py_obj_t o_in) { // to a common type. Otherwise, the == and != operators always consider objects of // different types to be unequal." // note also that False==0 and True==1 are true expressions -bool py_obj_equal(py_obj_t o1, py_obj_t o2) { +bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) { if (o1 == o2) { return true; - } else if (IS_SMALL_INT(o1) || IS_SMALL_INT(o2)) { - if (IS_SMALL_INT(o1) && IS_SMALL_INT(o2)) { + } else if (MP_OBJ_IS_SMALL_INT(o1) || MP_OBJ_IS_SMALL_INT(o2)) { + if (MP_OBJ_IS_SMALL_INT(o1) && MP_OBJ_IS_SMALL_INT(o2)) { return false; } else { - if (IS_SMALL_INT(o2)) { - py_obj_t temp = o1; o1 = o2; o2 = temp; + if (MP_OBJ_IS_SMALL_INT(o2)) { + mp_obj_t temp = o1; o1 = o2; o2 = temp; } // o1 is the SMALL_INT, o2 is not - py_small_int_t val = FROM_SMALL_INT(o1); - if (o2 == py_const_false) { + mp_small_int_t val = MP_OBJ_SMALL_INT_VALUE(o1); + if (o2 == mp_const_false) { return val == 0; - } else if (o2 == py_const_true) { + } else if (o2 == mp_const_true) { return val == 1; } else { return false; } } - } else if (IS_O(o1, O_STR) && IS_O(o2, O_STR)) { - return ((py_obj_base_t*)o1)->u_str == ((py_obj_base_t*)o2)->u_str; + } else if (MP_OBJ_IS_TYPE(o1, &str_type) && MP_OBJ_IS_TYPE(o2, &str_type)) { + return mp_obj_str_get(o1) == mp_obj_str_get(o2); } else { assert(0); return false; } } -bool py_obj_less(py_obj_t o1, py_obj_t o2) { - if (IS_SMALL_INT(o1) && IS_SMALL_INT(o2)) { - py_small_int_t i1 = FROM_SMALL_INT(o1); - py_small_int_t i2 = FROM_SMALL_INT(o2); +bool mp_obj_less(mp_obj_t o1, mp_obj_t o2) { + if (MP_OBJ_IS_SMALL_INT(o1) && MP_OBJ_IS_SMALL_INT(o2)) { + mp_small_int_t i1 = MP_OBJ_SMALL_INT_VALUE(o1); + mp_small_int_t i2 = MP_OBJ_SMALL_INT_VALUE(o2); return i1 < i2; } else { assert(0); @@ -369,13 +120,13 @@ bool py_obj_less(py_obj_t o1, py_obj_t o2) { } } -machine_int_t py_obj_get_int(py_obj_t arg) { - if (arg == py_const_false) { +machine_int_t mp_obj_get_int(mp_obj_t arg) { + if (arg == mp_const_false) { return 0; - } else if (arg == py_const_true) { + } else if (arg == mp_const_true) { return 1; - } else if (IS_SMALL_INT(arg)) { - return FROM_SMALL_INT(arg); + } else if (MP_OBJ_IS_SMALL_INT(arg)) { + return MP_OBJ_SMALL_INT_VALUE(arg); } else { assert(0); return 0; @@ -383,37 +134,36 @@ machine_int_t py_obj_get_int(py_obj_t arg) { } #if MICROPY_ENABLE_FLOAT -machine_float_t py_obj_get_float(py_obj_t arg) { - if (arg == py_const_false) { +machine_float_t mp_obj_get_float(mp_obj_t arg) { + if (arg == mp_const_false) { return 0; - } else if (arg == py_const_true) { + } else if (arg == mp_const_true) { return 1; - } else if (IS_SMALL_INT(arg)) { - return FROM_SMALL_INT(arg); - } else if (IS_O(arg, O_FLOAT)) { - return ((py_obj_base_t*)arg)->u_float; + } else if (MP_OBJ_IS_SMALL_INT(arg)) { + return MP_OBJ_SMALL_INT_VALUE(arg); + } else if (MP_OBJ_IS_TYPE(arg, &float_type)) { + return mp_obj_float_get(arg); } else { assert(0); return 0; } } -void py_obj_get_complex(py_obj_t arg, py_float_t *real, py_float_t *imag) { - if (arg == py_const_false) { +void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) { + if (arg == mp_const_false) { *real = 0; *imag = 0; - } else if (arg == py_const_true) { + } else if (arg == mp_const_true) { *real = 1; *imag = 0; - } else if (IS_SMALL_INT(arg)) { - *real = FROM_SMALL_INT(arg); + } else if (MP_OBJ_IS_SMALL_INT(arg)) { + *real = MP_OBJ_SMALL_INT_VALUE(arg); *imag = 0; - } else if (IS_O(arg, O_FLOAT)) { - *real = ((py_obj_base_t*)arg)->u_float; + } else if (MP_OBJ_IS_TYPE(arg, &float_type)) { + *real = mp_obj_float_get(arg); *imag = 0; - } else if (IS_O(arg, O_COMPLEX)) { - *real = ((py_obj_base_t*)arg)->u_complex.real; - *imag = ((py_obj_base_t*)arg)->u_complex.imag; + } else if (MP_OBJ_IS_TYPE(arg, &complex_type)) { + mp_obj_complex_get(arg, real, imag); } else { assert(0); *real = 0; @@ -422,49 +172,45 @@ void py_obj_get_complex(py_obj_t arg, py_float_t *real, py_float_t *imag) { } #endif -qstr py_obj_get_qstr(py_obj_t arg) { - if (IS_O(arg, O_STR)) { - return ((py_obj_base_t*)arg)->u_str; +qstr mp_obj_get_qstr(mp_obj_t arg) { + if (MP_OBJ_IS_TYPE(arg, &str_type)) { + return mp_obj_str_get(arg); } else { assert(0); return 0; } } -py_obj_t *py_obj_get_array_fixed_n(py_obj_t o_in, machine_int_t n) { - if (IS_O(o_in, O_TUPLE) || IS_O(o_in, O_LIST)) { - py_obj_base_t *o = o_in; - if (o->u_tuple_list.len != n) { - nlr_jump(py_obj_new_exception_2(rt_q_IndexError, "requested length %d but object has length %d", (void*)n, (void*)o->u_tuple_list.len)); +mp_obj_t *mp_obj_get_array_fixed_n(mp_obj_t o_in, machine_int_t n) { + if (MP_OBJ_IS_TYPE(o_in, &tuple_type) || MP_OBJ_IS_TYPE(o_in, &list_type)) { + uint seq_len; + mp_obj_t *seq_items; + if (MP_OBJ_IS_TYPE(o_in, &tuple_type)) { + mp_obj_tuple_get(o_in, &seq_len, &seq_items); + } else { + mp_obj_list_get(o_in, &seq_len, &seq_items); + } + if (seq_len != n) { + nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_IndexError, "requested length %d but object has length %d", (void*)n, (void*)(machine_uint_t)seq_len)); } - return o->u_tuple_list.items; + return seq_items; } else { - nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "object '%s' is not a tuple or list", py_obj_get_type_str(o_in), NULL)); + nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "object '%s' is not a tuple or list", mp_obj_get_type_str(o_in))); } } -void py_user_get_data(py_obj_t o, machine_uint_t *data1, machine_uint_t *data2) { - assert(IS_O(o, O_USER)); - if (data1 != NULL) { - *data1 = ((py_obj_base_t*)o)->u_user.data1; - } - if (data2 != NULL) { - *data2 = ((py_obj_base_t*)o)->u_user.data2; +uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index) { + // TODO False and True are considered 0 and 1 for indexing purposes + if (MP_OBJ_IS_SMALL_INT(index)) { + int i = MP_OBJ_SMALL_INT_VALUE(index); + if (i < 0) { + i += len; + } + if (i < 0 || i >= len) { + nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_IndexError, "%s index out of range", type->name)); + } + return i; + } else { + nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_TypeError, "%s indices must be integers, not %s", type->name, mp_obj_get_type_str(index))); } } - -void py_user_set_data(py_obj_t o, machine_uint_t data1, machine_uint_t data2) { - assert(IS_O(o, O_USER)); - ((py_obj_base_t*)o)->u_user.data1 = data1; - ((py_obj_base_t*)o)->u_user.data2 = data2; -} - -// temporary way of making C modules -// hack: use class to mimic a module - -py_obj_t py_module_new(void) { - py_obj_base_t *o = m_new(py_obj_base_t, 1); - o->kind = O_CLASS; - o->u_class.locals = py_map_new(MAP_QSTR, 0); - return o; -} diff --git a/py/obj.h b/py/obj.h index 746c92bba..7d58371db 100644 --- a/py/obj.h +++ b/py/obj.h @@ -1,56 +1,238 @@ -typedef machine_int_t py_small_int_t; // do we need to expose this in the public API? +// All Micro Python objects are at least this type +// It must be of pointer size + +typedef machine_ptr_t mp_obj_t; +typedef machine_const_ptr_t mp_const_obj_t; + +// Integers that fit in a pointer have this type +// (do we need to expose this in the public API?) + +typedef machine_int_t mp_small_int_t; + +// The machine floating-point type used for float and complex numbers #if MICROPY_ENABLE_FLOAT -typedef machine_float_t py_float_t; +typedef machine_float_t mp_float_t; #endif -// user defined objects +// Anything that wants to be a Micro Python object must +// have mp_obj_base_t as its first member (except NULL and small ints) + +typedef struct _mp_obj_base_t mp_obj_base_t; +typedef struct _mp_obj_type_t mp_obj_type_t; + +struct _mp_obj_base_t { + const mp_obj_type_t *type; +}; + +// The NULL object is used to indicate the absence of an object +// It *cannot* be used when an mp_obj_t is expected, except where explicitly allowed + +#define MP_OBJ_NULL ((mp_obj_t)NULL) + +// These macros check for small int or object, and access small int values + +#define MP_OBJ_IS_OBJ(o) ((((mp_small_int_t)(o)) & 1) == 0) +#define MP_OBJ_IS_SMALL_INT(o) ((((mp_small_int_t)(o)) & 1) != 0) +#define MP_OBJ_IS_TYPE(o, t) (((((mp_small_int_t)(o)) & 1) == 0) && (((mp_obj_base_t*)(o))->type == (t))) +#define MP_OBJ_SMALL_INT_VALUE(o) (((mp_small_int_t)(o)) >> 1) +#define MP_OBJ_NEW_SMALL_INT(o) ((mp_obj_t)(((o) << 1) | 1)) + +// These macros are used to declare and define constant function objects +// You can put "static" in front of the definitions to make them local + +#define MP_DECLARE_CONST_FUN_OBJ(obj_name) extern const mp_obj_fun_native_t obj_name -typedef struct _py_user_method_t { +#define MP_DEFINE_CONST_FUN_OBJ_0(obj_name, fun_name) const mp_obj_fun_native_t obj_name = {{&fun_native_type}, 0, 0, fun_name} +#define MP_DEFINE_CONST_FUN_OBJ_1(obj_name, fun_name) const mp_obj_fun_native_t obj_name = {{&fun_native_type}, 1, 1, fun_name} +#define MP_DEFINE_CONST_FUN_OBJ_2(obj_name, fun_name) const mp_obj_fun_native_t obj_name = {{&fun_native_type}, 2, 2, fun_name} +#define MP_DEFINE_CONST_FUN_OBJ_VAR(obj_name, n_args_min, fun_name) const mp_obj_fun_native_t obj_name = {{&fun_native_type}, n_args_min, (~((machine_uint_t)0)), fun_name} +#define MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(obj_name, n_args_min, n_args_max, fun_name) const mp_obj_fun_native_t obj_name = {{&fun_native_type}, n_args_min, n_args_max, fun_name} + +// Type definitions for methods + +typedef mp_obj_t (*mp_fun_0_t)(void); +typedef mp_obj_t (*mp_fun_1_t)(mp_obj_t); +typedef mp_obj_t (*mp_fun_2_t)(mp_obj_t, mp_obj_t); +typedef mp_obj_t (*mp_fun_t)(void); +typedef mp_obj_t (*mp_fun_var_t)(int n, const mp_obj_t *); + +typedef void (*mp_print_fun_t)(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o); +typedef mp_obj_t (*mp_call_n_fun_t)(mp_obj_t fun, int n_args, const mp_obj_t *args); // args are in reverse order in the array +typedef mp_obj_t (*mp_unary_op_fun_t)(int op, mp_obj_t); +typedef mp_obj_t (*mp_binary_op_fun_t)(int op, mp_obj_t, mp_obj_t); + +typedef struct _mp_method_t { const char *name; - machine_uint_t kind; - void *fun; -} py_user_method_t; + mp_const_obj_t fun; +} mp_method_t; + +struct _mp_obj_type_t { + mp_obj_base_t base; + const char *name; + mp_print_fun_t print; + + mp_call_n_fun_t call_n; + mp_unary_op_fun_t unary_op; // can return NULL if op not supported + mp_binary_op_fun_t binary_op; // can return NULL if op not supported + + mp_fun_1_t getiter; + mp_fun_1_t iternext; + + const mp_method_t methods[]; + + /* + What we might need to add here: + + dynamic_type instance -typedef struct _py_user_info_t { - const char *type_name; - void (*print)(py_obj_t); - const py_user_method_t methods[]; -} py_user_info_t; + compare_op + load_attr instance class list + load_method instance str gen list user + store_attr instance class + store_subscr list dict -py_obj_t py_obj_new_int(machine_int_t value); -py_obj_t py_obj_new_const(const char *id); -py_obj_t py_obj_new_str(qstr qstr); + len str tuple list map + abs float complex + hash bool int none str + equal int str + less int + get_array_n tuple list + + unpack seq list tuple + __next__ gen-instance + */ +}; + +// Constant objects, globally accessible + +extern const mp_obj_type_t mp_const_type; +extern const mp_obj_t mp_const_none; +extern const mp_obj_t mp_const_false; +extern const mp_obj_t mp_const_true; +extern const mp_obj_t mp_const_stop_iteration; // special object indicating end of iteration (not StopIteration exception!) + +// Need to declare this here so we are not dependent on map.h + +typedef struct _mp_map_t mp_map_t; + +// General API for objects + +mp_obj_t mp_obj_new_none(void); +mp_obj_t mp_obj_new_bool(bool value); +mp_obj_t mp_obj_new_int(machine_int_t value); +mp_obj_t mp_obj_new_str(qstr qstr); #if MICROPY_ENABLE_FLOAT -py_obj_t py_obj_new_float(py_float_t val); -py_obj_t py_obj_new_complex(py_float_t real, py_float_t imag); +mp_obj_t mp_obj_new_float(mp_float_t val); +mp_obj_t mp_obj_new_complex(mp_float_t real, mp_float_t imag); #endif -py_obj_t py_obj_new_exception_0(qstr id); -py_obj_t py_obj_new_exception_2(qstr id, const char *fmt, const char *s1, const char *s2); -py_obj_t py_obj_new_range(int start, int stop, int step); -py_obj_t py_obj_new_range_iterator(int cur, int stop, int step); -py_obj_t py_obj_new_user(const py_user_info_t *info, machine_uint_t data1, machine_uint_t data2); +mp_obj_t mp_obj_new_exception(qstr id); +mp_obj_t mp_obj_new_exception_msg(qstr id, const char *msg); +mp_obj_t mp_obj_new_exception_msg_1_arg(qstr id, const char *fmt, const char *a1); +mp_obj_t mp_obj_new_exception_msg_2_args(qstr id, const char *fmt, const char *a1, const char *a2); +mp_obj_t mp_obj_new_range(int start, int stop, int step); +mp_obj_t mp_obj_new_range_iterator(int cur, int stop, int step); +mp_obj_t mp_obj_new_fun_bc(int n_args, uint n_state, const byte *code); +mp_obj_t mp_obj_new_fun_asm(uint n_args, void *fun); +mp_obj_t mp_obj_new_gen_wrap(uint n_locals, uint n_cells, uint n_stack, mp_obj_t fun); +mp_obj_t mp_obj_new_gen_instance(mp_obj_t state, const byte *ip, mp_obj_t *sp); +mp_obj_t mp_obj_new_closure(mp_obj_t fun, mp_obj_t closure_tuple); +mp_obj_t mp_obj_new_tuple(uint n, mp_obj_t *items); +mp_obj_t mp_obj_new_tuple_reverse(uint n, mp_obj_t *items); +mp_obj_t mp_obj_new_list(uint n, mp_obj_t *items); +mp_obj_t mp_obj_new_list_reverse(uint n, mp_obj_t *items); +mp_obj_t mp_obj_new_dict(int n_args); +mp_obj_t mp_obj_new_set(int n_args, mp_obj_t *items); +mp_obj_t mp_obj_new_bound_meth(mp_obj_t self, mp_obj_t meth); +mp_obj_t mp_obj_new_class(mp_map_t *class_locals); +mp_obj_t mp_obj_new_instance(mp_obj_t clas); -const char *py_obj_get_type_str(py_obj_t o_in); +const char *mp_obj_get_type_str(mp_obj_t o_in); -void py_obj_print_helper(void (*print)(void *env, const char *fmt, ...), void *env, py_obj_t o_in); -void py_obj_print(py_obj_t o); +void mp_obj_print_helper(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in); +void mp_obj_print(mp_obj_t o); -bool py_obj_is_callable(py_obj_t o_in); -machine_int_t py_obj_hash(py_obj_t o_in); -bool py_obj_equal(py_obj_t o1, py_obj_t o2); -bool py_obj_less(py_obj_t o1, py_obj_t o2); +bool mp_obj_is_callable(mp_obj_t o_in); +machine_int_t mp_obj_hash(mp_obj_t o_in); +bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2); +bool mp_obj_less(mp_obj_t o1, mp_obj_t o2); -machine_int_t py_obj_get_int(py_obj_t arg); +machine_int_t mp_obj_get_int(mp_obj_t arg); #if MICROPY_ENABLE_FLOAT -machine_float_t py_obj_get_float(py_obj_t arg); -void py_obj_get_complex(py_obj_t arg, py_float_t *real, py_float_t *imag); +mp_float_t mp_obj_get_float(mp_obj_t self_in); +void mp_obj_get_complex(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag); #endif -qstr py_obj_get_qstr(py_obj_t arg); -py_obj_t *py_obj_get_array_fixed_n(py_obj_t o, machine_int_t n); +qstr mp_obj_get_qstr(mp_obj_t arg); +mp_obj_t *mp_obj_get_array_fixed_n(mp_obj_t o, machine_int_t n); +uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index); + +// none +extern const mp_obj_type_t none_type; + +// bool +extern const mp_obj_type_t bool_type; + +// cell +mp_obj_t mp_obj_cell_get(mp_obj_t self_in); +void mp_obj_cell_set(mp_obj_t self_in, mp_obj_t obj); + +// str +extern const mp_obj_type_t str_type; +qstr mp_obj_str_get(mp_obj_t self_in); + +#if MICROPY_ENABLE_FLOAT +// float +extern const mp_obj_type_t float_type; +mp_float_t mp_obj_float_get(mp_obj_t self_in); + +// complex +extern const mp_obj_type_t complex_type; +void mp_obj_complex_get(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag); +#endif + +// tuple +extern const mp_obj_type_t tuple_type; +void mp_obj_tuple_get(mp_obj_t self_in, uint *len, mp_obj_t **items); + +// list +extern const mp_obj_type_t list_type; +mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg); +void mp_obj_list_get(mp_obj_t self_in, uint *len, mp_obj_t **items); +void mp_obj_list_store(mp_obj_t self_in, mp_obj_t index, mp_obj_t value); + +// dict +extern const mp_obj_type_t dict_type; +mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value); + +// set +void mp_obj_set_store(mp_obj_t self_in, mp_obj_t item); + +// functions +typedef struct _mp_obj_fun_native_t { // need this so we can define static objects + mp_obj_base_t base; + machine_uint_t n_args_min; // inclusive + machine_uint_t n_args_max; // inclusive + void *fun; +} mp_obj_fun_native_t; +extern const mp_obj_type_t fun_native_type; +extern const mp_obj_type_t fun_bc_type; +void mp_obj_fun_bc_get(mp_obj_t self_in, int *n_args, uint *n_state, const byte **code); + +// generator +extern const mp_obj_type_t gen_instance_type; +mp_obj_t mp_obj_gen_instance_next(mp_obj_t self_in); +MP_DECLARE_CONST_FUN_OBJ(mp_obj_gen_instance_next_obj); + +// class +extern const mp_obj_type_t class_type; +extern const mp_obj_t gen_instance_next_obj; +mp_map_t *mp_obj_class_get_locals(mp_obj_t self_in); -void py_user_get_data(py_obj_t o, machine_uint_t *data1, machine_uint_t *data2); -void py_user_set_data(py_obj_t o, machine_uint_t data1, machine_uint_t data2); +// instance +extern const mp_obj_type_t instance_type; +mp_obj_t mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr); +void mp_obj_instance_load_method(mp_obj_t self_in, qstr attr, mp_obj_t *dest); +void mp_obj_instance_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value); // temporary way of making C modules -py_obj_t py_module_new(void); +mp_obj_t mp_module_new(void); diff --git a/py/objbool.c b/py/objbool.c new file mode 100644 index 000000000..9b53ffae9 --- /dev/null +++ b/py/objbool.c @@ -0,0 +1,39 @@ +#include <stdlib.h> +#include <stdint.h> + +#include "nlr.h" +#include "misc.h" +#include "mpconfig.h" +#include "obj.h" + +typedef struct _mp_obj_bool_t { + mp_obj_base_t base; + bool value; +} mp_obj_bool_t; + +void bool_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) { + mp_obj_bool_t *self = self_in; + if (self->value) { + print(env, "True"); + } else { + print(env, "False"); + } +} + +const mp_obj_type_t bool_type = { + { &mp_const_type }, + "bool", + bool_print, // print + NULL, // call_n + NULL, // unary_op + NULL, // binary_op + NULL, // getiter + NULL, // iternext + {{NULL, NULL},}, // method list +}; + +static const mp_obj_bool_t false_obj = {{&bool_type}, false}; +static const mp_obj_bool_t true_obj = {{&bool_type}, true}; + +const mp_obj_t mp_const_false = (mp_obj_t)&false_obj; +const mp_obj_t mp_const_true = (mp_obj_t)&true_obj; diff --git a/py/objboundmeth.c b/py/objboundmeth.c new file mode 100644 index 000000000..8bd238c65 --- /dev/null +++ b/py/objboundmeth.c @@ -0,0 +1,54 @@ +#include <stdlib.h> +#include <stdint.h> +#include <assert.h> + +#include "nlr.h" +#include "misc.h" +#include "mpconfig.h" +#include "obj.h" +#include "runtime.h" + +typedef struct _mp_obj_bound_meth_t { + mp_obj_base_t base; + mp_obj_t meth; + mp_obj_t self; +} mp_obj_bound_meth_t; + +// args are in reverse order in the array +mp_obj_t bound_meth_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) { + mp_obj_bound_meth_t *self = self_in; + + if (n_args == 0) { + return rt_call_function_n(self->meth, 1, &self->self); + } else if (n_args == 1) { + mp_obj_t args2[2]; + args2[1] = self->self; + args2[0] = args[0]; + return rt_call_function_n(self->meth, 2, args2); + } else { + // TODO not implemented + assert(0); + return mp_const_none; + //return rt_call_function_2(self->meth, n_args + 1, self->self + args); + } +} + +const mp_obj_type_t bound_meth_type = { + { &mp_const_type }, + "bound_method", + NULL, // print + bound_meth_call_n, // call_n + NULL, // unary_op + NULL, // binary_op + NULL, // getiter + NULL, // iternext + {{NULL, NULL},}, // method list +}; + +mp_obj_t mp_obj_new_bound_meth(mp_obj_t self, mp_obj_t meth) { + mp_obj_bound_meth_t *o = m_new_obj(mp_obj_bound_meth_t); + o->base.type = &bound_meth_type; + o->meth = meth; + o->self = self; + return o; +} diff --git a/py/objcell.c b/py/objcell.c new file mode 100644 index 000000000..cba198057 --- /dev/null +++ b/py/objcell.c @@ -0,0 +1,43 @@ +#include <stdlib.h> +#include <stdint.h> +#include <assert.h> + +#include "nlr.h" +#include "misc.h" +#include "mpconfig.h" +#include "obj.h" +#include "runtime.h" + +typedef struct _mp_obj_cell_t { + mp_obj_base_t base; + mp_obj_t obj; +} mp_obj_cell_t; + +mp_obj_t mp_obj_cell_get(mp_obj_t self_in) { + mp_obj_cell_t *self = self_in; + return self->obj; +} + +void mp_obj_cell_set(mp_obj_t self_in, mp_obj_t obj) { + mp_obj_cell_t *self = self_in; + self->obj = obj; +} + +const mp_obj_type_t cell_type = { + { &mp_const_type }, + "cell", + NULL, // print + NULL, // call_n + NULL, // unary_op + NULL, // binary_op + NULL, // getiter + NULL, // iternext + {{NULL, NULL},}, // method list +}; + +mp_obj_t mp_obj_new_cell(mp_obj_t obj) { + mp_obj_cell_t *o = m_new_obj(mp_obj_cell_t); + o->base.type = &cell_type; + o->obj = obj; + return o; +} diff --git a/py/objclass.c b/py/objclass.c new file mode 100644 index 000000000..52e43724f --- /dev/null +++ b/py/objclass.c @@ -0,0 +1,85 @@ +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <assert.h> + +#include "nlr.h" +#include "misc.h" +#include "mpconfig.h" +#include "obj.h" +#include "runtime.h" +#include "map.h" + +typedef struct _mp_obj_class_t { + mp_obj_base_t base; + mp_map_t *locals; +} mp_obj_class_t; + +// args are in reverse order in the array +mp_obj_t class_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) { + // instantiate an instance of a class + + mp_obj_class_t *self = self_in; + + // make instance + mp_obj_t o = mp_obj_new_instance(self_in); + + // look for __init__ function + mp_map_elem_t *init_fn = mp_qstr_map_lookup(self->locals, qstr_from_str_static("__init__"), false); + + if (init_fn != NULL) { + // call __init__ function + mp_obj_t init_ret; + if (n_args == 0) { + init_ret = rt_call_function_n(init_fn->value, 1, (mp_obj_t*)&o); + } else { + mp_obj_t *args2 = m_new(mp_obj_t, n_args + 1); + memcpy(args2, args, n_args * sizeof(mp_obj_t)); + args2[n_args] = o; + init_ret = rt_call_function_n(init_fn->value, n_args + 1, args2); + m_free(args2); + } + if (init_ret != mp_const_none) { + nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "__init__() should return None, not '%s'", mp_obj_get_type_str(init_ret))); + } + + } else { + // TODO + if (n_args != 0) { + nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "function takes 0 positional arguments but %d were given", (void*)(machine_int_t)n_args)); + } + } + + return o; +} + +mp_map_t *mp_obj_class_get_locals(mp_obj_t self_in) { + assert(MP_OBJ_IS_TYPE(self_in, &class_type)); + mp_obj_class_t *self = self_in; + return self->locals; +} + +const mp_obj_type_t class_type = { + { &mp_const_type }, + "class", + NULL, // print + class_call_n, // call_n + NULL, // unary_op + NULL, // binary_op + NULL, // getiter + NULL, // iternext + {{NULL, NULL},}, // method list +}; + +mp_obj_t mp_obj_new_class(mp_map_t *class_locals) { + mp_obj_class_t *o = m_new_obj(mp_obj_class_t); + o->base.type = &class_type; + o->locals = class_locals; + return o; +} + +// temporary way of making C modules +// hack: use class to mimic a module +mp_obj_t mp_module_new(void) { + return mp_obj_new_class(mp_map_new(MP_MAP_QSTR, 0)); +} diff --git a/py/objclosure.c b/py/objclosure.c new file mode 100644 index 000000000..e699c5daa --- /dev/null +++ b/py/objclosure.c @@ -0,0 +1,35 @@ +#include <stdlib.h> +#include <stdint.h> +#include <assert.h> + +#include "nlr.h" +#include "misc.h" +#include "mpconfig.h" +#include "obj.h" +#include "runtime.h" + +typedef struct _mp_obj_closure_t { + mp_obj_base_t base; + mp_obj_t fun; + mp_obj_t vars; +} mp_obj_closure_t; + +const mp_obj_type_t closure_type = { + { &mp_const_type }, + "closure", + NULL, // print + NULL, // call_n + NULL, // unary_op + NULL, // binary_op + NULL, // getiter + NULL, // iternext + {{NULL, NULL},}, // method list +}; + +mp_obj_t mp_obj_new_closure(mp_obj_t fun, mp_obj_t closure_tuple) { + mp_obj_closure_t *o = m_new_obj(mp_obj_closure_t); + o->base.type = &closure_type; + o->fun = fun; + o->vars = closure_tuple; + return o; +} diff --git a/py/objcomplex.c b/py/objcomplex.c new file mode 100644 index 000000000..ab9c14677 --- /dev/null +++ b/py/objcomplex.c @@ -0,0 +1,105 @@ +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <assert.h> + +#include "nlr.h" +#include "misc.h" +#include "mpconfig.h" +#include "obj.h" +#include "runtime0.h" +#include "map.h" + +#if MICROPY_ENABLE_FLOAT + +typedef struct _mp_obj_complex_t { + mp_obj_base_t base; + mp_float_t real; + mp_float_t imag; +} mp_obj_complex_t; + +mp_obj_t mp_obj_new_complex(mp_float_t real, mp_float_t imag); + +void complex_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) { + mp_obj_complex_t *o = o_in; + if (o->real == 0) { + print(env, "%.8gj", o->imag); + } else { + print(env, "(%.8g+%.8gj)", o->real, o->imag); + } +} + +mp_obj_t complex_unary_op(int op, mp_obj_t o_in) { + mp_obj_complex_t *o = o_in; + switch (op) { + case RT_UNARY_OP_NOT: if (o->real != 0 || o->imag != 0) { return mp_const_true;} else { return mp_const_false; } + case RT_UNARY_OP_POSITIVE: return o_in; + case RT_UNARY_OP_NEGATIVE: return mp_obj_new_complex(-o->real, -o->imag); + default: return MP_OBJ_NULL; // op not supported + } +} + +mp_obj_t complex_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { + mp_float_t lhs_real, lhs_imag, rhs_real, rhs_imag; + mp_obj_complex_get(lhs_in, &lhs_real, &lhs_imag); + mp_obj_complex_get(rhs_in, &rhs_real, &rhs_imag); + switch (op) { + case RT_BINARY_OP_ADD: + case RT_BINARY_OP_INPLACE_ADD: + lhs_real += rhs_real; + lhs_imag += rhs_imag; + break; + case RT_BINARY_OP_SUBTRACT: + case RT_BINARY_OP_INPLACE_SUBTRACT: + lhs_real -= rhs_real; + lhs_imag -= rhs_imag; + break; + case RT_BINARY_OP_MULTIPLY: + case RT_BINARY_OP_INPLACE_MULTIPLY: + { + mp_float_t real = lhs_real * rhs_real - lhs_imag * rhs_imag; + lhs_imag = lhs_real * rhs_imag + lhs_imag * rhs_real; + lhs_real = real; + break; + } + /* TODO floor(?) the value + case RT_BINARY_OP_FLOOR_DIVIDE: + case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: val = lhs_val / rhs_val; break; + */ + /* TODO + case RT_BINARY_OP_TRUE_DIVIDE: + case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: val = lhs_val / rhs_val; break; + */ + return NULL; // op not supported + } + return mp_obj_new_complex(lhs_real, lhs_imag); +} + +const mp_obj_type_t complex_type = { + { &mp_const_type }, + "complex", + complex_print, // print + NULL, // call_n + complex_unary_op, // unary_op + complex_binary_op, // binary_op + NULL, // getiter + NULL, // iternext + { { NULL, NULL }, }, // method list +}; + +mp_obj_t mp_obj_new_complex(mp_float_t real, mp_float_t imag) { + mp_obj_complex_t *o = m_new_obj(mp_obj_complex_t); + o->base.type = &complex_type; + o->real = real; + o->imag = imag; + return o; +} + +void mp_obj_complex_get(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag) { + assert(MP_OBJ_IS_TYPE(self_in, &complex_type)); + mp_obj_complex_t *self = self_in; + *real = self->real; + *imag = self->imag; +} + +#endif diff --git a/py/objdict.c b/py/objdict.c new file mode 100644 index 000000000..02753e381 --- /dev/null +++ b/py/objdict.c @@ -0,0 +1,80 @@ +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <assert.h> + +#include "nlr.h" +#include "misc.h" +#include "mpconfig.h" +#include "obj.h" +#include "runtime0.h" +#include "runtime.h" +#include "map.h" + +typedef struct _mp_obj_dict_t { + mp_obj_base_t base; + mp_map_t map; +} mp_obj_dict_t; + +void dict_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) { + mp_obj_dict_t *self = self_in; + bool first = true; + print(env, "{"); + for (int i = 0; i < self->map.alloc; i++) { + if (self->map.table[i].key != NULL) { + if (!first) { + print(env, ", "); + } + first = false; + mp_obj_print_helper(print, env, self->map.table[i].key); + print(env, ": "); + mp_obj_print_helper(print, env, self->map.table[i].value); + } + } + print(env, "}"); +} + +mp_obj_t dict_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { + mp_obj_dict_t *o = lhs_in; + switch (op) { + case RT_BINARY_OP_SUBSCR: + { + // dict load + mp_map_elem_t *elem = mp_map_lookup_helper(&o->map, rhs_in, false); + if (elem == NULL) { + nlr_jump(mp_obj_new_exception_msg(rt_q_KeyError, "<value>")); + } else { + return elem->value; + } + } + default: + // op not supported + return NULL; + } +} + +mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value) { + assert(MP_OBJ_IS_TYPE(self_in, &dict_type)); + mp_obj_dict_t *self = self_in; + mp_map_lookup_helper(&self->map, key, true)->value = value; + return self_in; +} + +const mp_obj_type_t dict_type = { + { &mp_const_type }, + "dict", + dict_print, // print + NULL, // call_n + NULL, // unary_op + dict_binary_op, // binary_op + NULL, // getiter + NULL, // iternext + {{NULL, NULL},}, // method list +}; + +mp_obj_t mp_obj_new_dict(int n_args) { + mp_obj_dict_t *o = m_new_obj(mp_obj_dict_t); + o->base.type = &dict_type; + mp_map_init(&o->map, MP_MAP_OBJ, n_args); + return o; +} diff --git a/py/objexcept.c b/py/objexcept.c new file mode 100644 index 000000000..4abc62437 --- /dev/null +++ b/py/objexcept.c @@ -0,0 +1,86 @@ +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <assert.h> + +#include "nlr.h" +#include "misc.h" +#include "mpconfig.h" +#include "obj.h" + +typedef struct mp_obj_exception_t { + mp_obj_base_t base; + qstr id; + int n_args; + const void *args[]; +} mp_obj_exception_t; + +void exception_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) { + mp_obj_exception_t *o = o_in; + switch (o->n_args) { + case 0: + print(env, "%s", qstr_str(o->id)); + break; + case 1: + print(env, "%s: %s", qstr_str(o->id), (const char*)o->args[0]); + break; + case 2: + print(env, "%s: ", qstr_str(o->id)); + print(env, (const char*)o->args[0], o->args[1]); + break; + default: // here we just assume at least 3 args, but only use first 3 + print(env, "%s: ", qstr_str(o->id)); + print(env, (const char*)o->args[0], o->args[1], o->args[2]); + break; + } +} + +const mp_obj_type_t exception_type = { + { &mp_const_type }, + "exception", + exception_print, // print + NULL, // call_n + NULL, // unary_op + NULL, // binary_op + NULL, // getiter + NULL, // iternext + {{NULL, NULL},}, // method list +}; + +mp_obj_t mp_obj_new_exception(qstr id) { + mp_obj_exception_t *o = m_new_obj(mp_obj_exception_t); + o->base.type = &exception_type; + o->id = id; + o->n_args = 0; + return o; +} + +mp_obj_t mp_obj_new_exception_msg(qstr id, const char *msg) { + mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, void*, 1); + o->base.type = &exception_type; + o->id = id; + o->n_args = 1; + o->args[0] = msg; + return o; +} + +mp_obj_t mp_obj_new_exception_msg_1_arg(qstr id, const char *fmt, const char *a1) { + mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, void*, 2); + o->base.type = &exception_type; + o->id = id; + o->n_args = 2; + o->args[0] = fmt; + o->args[1] = a1; + return o; +} + +mp_obj_t mp_obj_new_exception_msg_2_args(qstr id, const char *fmt, const char *a1, const char *a2) { + mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, void*, 3); + o->base.type = &exception_type; + o->id = id; + o->n_args = 3; + o->args[0] = fmt; + o->args[1] = a1; + o->args[2] = a2; + return o; +} diff --git a/py/objfloat.c b/py/objfloat.c new file mode 100644 index 000000000..f151fe25a --- /dev/null +++ b/py/objfloat.c @@ -0,0 +1,85 @@ +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <assert.h> + +#include "nlr.h" +#include "misc.h" +#include "mpconfig.h" +#include "obj.h" +#include "runtime0.h" + +#if MICROPY_ENABLE_FLOAT + +typedef struct _mp_obj_float_t { + mp_obj_base_t base; + mp_float_t value; +} mp_obj_float_t; + +mp_obj_t mp_obj_new_float(mp_float_t value); + +void float_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) { + mp_obj_float_t *o = o_in; + print(env, "%.8g", o->value); +} + +mp_obj_t float_unary_op(int op, mp_obj_t o_in) { + mp_obj_float_t *o = o_in; + switch (op) { + case RT_UNARY_OP_NOT: if (o->value != 0) { return mp_const_true;} else { return mp_const_false; } + case RT_UNARY_OP_POSITIVE: return o_in; + case RT_UNARY_OP_NEGATIVE: return mp_obj_new_float(-o->value); + default: return NULL; // op not supported + } +} + +mp_obj_t float_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { + if (MP_OBJ_IS_TYPE(rhs_in, &complex_type)) { + return complex_type.binary_op(op, lhs_in, rhs_in); + } + mp_float_t lhs_val = mp_obj_get_float(lhs_in); + mp_float_t rhs_val = mp_obj_get_float(rhs_in); + switch (op) { + case RT_BINARY_OP_ADD: + case RT_BINARY_OP_INPLACE_ADD: lhs_val += rhs_val; break; + case RT_BINARY_OP_SUBTRACT: + case RT_BINARY_OP_INPLACE_SUBTRACT: lhs_val -= rhs_val; break; + case RT_BINARY_OP_MULTIPLY: + case RT_BINARY_OP_INPLACE_MULTIPLY: lhs_val *= rhs_val; break; + /* TODO floor(?) the value + case RT_BINARY_OP_FLOOR_DIVIDE: + case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: val = lhs_val / rhs_val; break; + */ + case RT_BINARY_OP_TRUE_DIVIDE: + case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: lhs_val /= rhs_val; break; + return NULL; // op not supported + } + return mp_obj_new_float(lhs_val); +} + +const mp_obj_type_t float_type = { + { &mp_const_type }, + "float", + float_print, + NULL, // call_n + float_unary_op, + float_binary_op, + NULL, // getiter + NULL, // iternext + { { NULL, NULL }, }, // method list +}; + +mp_obj_t mp_obj_new_float(mp_float_t value) { + mp_obj_float_t *o = m_new(mp_obj_float_t, 1); + o->base.type = &float_type; + o->value = value; + return (mp_obj_t)o; +} + +mp_float_t mp_obj_float_get(mp_obj_t self_in) { + assert(MP_OBJ_IS_TYPE(self_in, &float_type)); + mp_obj_float_t *self = self_in; + return self->value; +} + +#endif diff --git a/py/objfun.c b/py/objfun.c new file mode 100644 index 000000000..bf11b5e6a --- /dev/null +++ b/py/objfun.c @@ -0,0 +1,280 @@ +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <assert.h> + +#include "nlr.h" +#include "misc.h" +#include "mpconfig.h" +#include "obj.h" +#include "runtime.h" +#include "bc.h" + +/******************************************************************************/ +/* native functions */ + +// mp_obj_fun_native_t defined in obj.h + +// args are in reverse order in the array +mp_obj_t fun_native_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) { + mp_obj_fun_native_t *self = self_in; + if (self->n_args_min == self->n_args_max) { + // function requires a fixed number of arguments + + // check number of arguments + if (n_args != self->n_args_min) { + nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)self->n_args_min, (const char*)(machine_int_t)n_args)); + } + + // dispatch function call + switch (self->n_args_min) { + case 0: + return ((mp_fun_0_t)self->fun)(); + + case 1: + return ((mp_fun_1_t)self->fun)(args[0]); + + case 2: + return ((mp_fun_2_t)self->fun)(args[1], args[0]); + + default: + assert(0); + return mp_const_none; + } + + } else { + // function takes a variable number of arguments + + if (n_args < self->n_args_min) { + nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "<fun name>() missing %d required positional arguments: <list of names of params>", (const char*)(machine_int_t)(self->n_args_min - n_args))); + } else if (n_args > self->n_args_max) { + nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_TypeError, "<fun name> expected at most %d arguments, got %d", (void*)(machine_int_t)self->n_args_max, (void*)(machine_int_t)n_args)); + } + + // TODO really the args need to be passed in as a Python tuple, as the form f(*[1,2]) can be used to pass var args + mp_obj_t *args_ordered = m_new(mp_obj_t, n_args); + for (int i = 0; i < n_args; i++) { + args_ordered[i] = args[n_args - i - 1]; + } + + mp_obj_t res = ((mp_fun_var_t)self->fun)(n_args, args_ordered); + m_free(args_ordered); + + return res; + } +} + +const mp_obj_type_t fun_native_type = { + { &mp_const_type }, + "function", + NULL, // print + fun_native_call_n, // call_n + NULL, // unary_op + NULL, // binary_op + NULL, // getiter + NULL, // iternext + { // method list + {NULL, NULL}, // end-of-list sentinel + }, +}; + +mp_obj_t rt_make_function_0(mp_fun_0_t fun) { + mp_obj_fun_native_t *o = m_new_obj(mp_obj_fun_native_t); + o->base.type = &fun_native_type; + o->n_args_min = 0; + o->n_args_max = 0; + o->fun = fun; + return o; +} + +mp_obj_t rt_make_function_1(mp_fun_1_t fun) { + mp_obj_fun_native_t *o = m_new_obj(mp_obj_fun_native_t); + o->base.type = &fun_native_type; + o->n_args_min = 1; + o->n_args_max = 1; + o->fun = fun; + return o; +} + +mp_obj_t rt_make_function_2(mp_fun_2_t fun) { + mp_obj_fun_native_t *o = m_new_obj(mp_obj_fun_native_t); + o->base.type = &fun_native_type; + o->n_args_min = 2; + o->n_args_max = 2; + o->fun = fun; + return o; +} + +mp_obj_t rt_make_function_var(int n_args_min, mp_fun_var_t fun) { + mp_obj_fun_native_t *o = m_new_obj(mp_obj_fun_native_t); + o->base.type = &fun_native_type; + o->n_args_min = n_args_min; + o->n_args_max = ~((machine_uint_t)0); + o->fun = fun; + return o; +} + +// min and max are inclusive +mp_obj_t rt_make_function_var_between(int n_args_min, int n_args_max, mp_fun_var_t fun) { + mp_obj_fun_native_t *o = m_new_obj(mp_obj_fun_native_t); + o->base.type = &fun_native_type; + o->n_args_min = n_args_min; + o->n_args_max = n_args_max; + o->fun = fun; + return o; +} + +/******************************************************************************/ +/* byte code functions */ + +typedef struct _mp_obj_fun_bc_t { + mp_obj_base_t base; + int n_args; + uint n_state; + const byte *code; +} mp_obj_fun_bc_t; + +// args are in reverse order in the array +mp_obj_t fun_bc_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) { + mp_obj_fun_bc_t *self = self_in; + + if (n_args != self->n_args) { + nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)self->n_args, (const char*)(machine_int_t)n_args)); + } + + return mp_execute_byte_code(self->code, args, n_args, self->n_state); +} + +void mp_obj_fun_bc_get(mp_obj_t self_in, int *n_args, uint *n_state, const byte **code) { + assert(MP_OBJ_IS_TYPE(self_in, &fun_bc_type)); + mp_obj_fun_bc_t *self = self_in; + *n_args = self->n_args; + *n_state = self->n_state; + *code = self->code; +} + +const mp_obj_type_t fun_bc_type = { + { &mp_const_type }, + "function", + NULL, // print + fun_bc_call_n, // call_n + NULL, // unary_op + NULL, // binary_op + NULL, // getiter + NULL, // iternext + { // method list + {NULL, NULL}, // end-of-list sentinel + }, +}; + +mp_obj_t mp_obj_new_fun_bc(int n_args, uint n_state, const byte *code) { + mp_obj_fun_bc_t *o = m_new_obj(mp_obj_fun_bc_t); + o->base.type = &fun_bc_type; + o->n_args = n_args; + o->n_state = n_state; + o->code = code; + return o; +} + +/******************************************************************************/ +/* inline assembler functions */ + +typedef struct _mp_obj_fun_asm_t { + mp_obj_base_t base; + int n_args; + void *fun; +} mp_obj_fun_asm_t; + +typedef machine_uint_t (*inline_asm_fun_0_t)(); +typedef machine_uint_t (*inline_asm_fun_1_t)(machine_uint_t); +typedef machine_uint_t (*inline_asm_fun_2_t)(machine_uint_t, machine_uint_t); +typedef machine_uint_t (*inline_asm_fun_3_t)(machine_uint_t, machine_uint_t, machine_uint_t); + +// convert a Micro Python object to a sensible value for inline asm +machine_uint_t convert_obj_for_inline_asm(mp_obj_t obj) { + // TODO for byte_array, pass pointer to the array + if (MP_OBJ_IS_SMALL_INT(obj)) { + return MP_OBJ_SMALL_INT_VALUE(obj); + } else if (obj == mp_const_none) { + return 0; + } else if (obj == mp_const_false) { + return 0; + } else if (obj == mp_const_true) { + return 1; + } else if (MP_OBJ_IS_TYPE(obj, &str_type)) { + // pointer to the string (it's probably constant though!) + return (machine_uint_t)qstr_str(mp_obj_str_get(obj)); +#if MICROPY_ENABLE_FLOAT + } else if (MP_OBJ_IS_TYPE(obj, &float_type)) { + // convert float to int (could also pass in float registers) + return (machine_int_t)mp_obj_float_get(obj); +#endif + } else if (MP_OBJ_IS_TYPE(obj, &tuple_type)) { + // pointer to start of tuple (could pass length, but then could use len(x) for that) + uint len; + mp_obj_t *items; + mp_obj_tuple_get(obj, &len, &items); + return (machine_uint_t)items; + } else if (MP_OBJ_IS_TYPE(obj, &list_type)) { + // pointer to start of list (could pass length, but then could use len(x) for that) + uint len; + mp_obj_t *items; + mp_obj_list_get(obj, &len, &items); + return (machine_uint_t)items; + } else { + // just pass along a pointer to the object + return (machine_uint_t)obj; + } +} + +// convert a return value from inline asm to a sensible Micro Python object +mp_obj_t convert_val_from_inline_asm(machine_uint_t val) { + return MP_OBJ_NEW_SMALL_INT(val); +} + +// args are in reverse order in the array +mp_obj_t fun_asm_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) { + mp_obj_fun_asm_t *self = self_in; + + if (n_args != self->n_args) { + nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)self->n_args, (const char*)(machine_int_t)n_args)); + } + + machine_uint_t ret; + if (n_args == 0) { + ret = ((inline_asm_fun_0_t)self->fun)(); + } else if (n_args == 1) { + ret = ((inline_asm_fun_1_t)self->fun)(convert_obj_for_inline_asm(args[0])); + } else if (n_args == 2) { + ret = ((inline_asm_fun_2_t)self->fun)(convert_obj_for_inline_asm(args[1]), convert_obj_for_inline_asm(args[0])); + } else if (n_args == 3) { + ret = ((inline_asm_fun_3_t)self->fun)(convert_obj_for_inline_asm(args[2]), convert_obj_for_inline_asm(args[1]), convert_obj_for_inline_asm(args[0])); + } else { + assert(0); + ret = 0; + } + + return convert_val_from_inline_asm(ret); +} + +static const mp_obj_type_t fun_asm_type = { + { &mp_const_type }, + "function", + NULL, // print + fun_asm_call_n, // call_n + NULL, // unary_op + NULL, // binary_op + NULL, // getiter + NULL, // iternext + { // method list + {NULL, NULL}, // end-of-list sentinel + }, +}; + +mp_obj_t mp_obj_new_fun_asm(uint n_args, void *fun) { + mp_obj_fun_asm_t *o = m_new_obj(mp_obj_fun_asm_t); + o->base.type = &fun_asm_type; + o->n_args = n_args; + o->fun = fun; + return o; +} diff --git a/py/objgenerator.c b/py/objgenerator.c new file mode 100644 index 000000000..fdb642c1c --- /dev/null +++ b/py/objgenerator.c @@ -0,0 +1,130 @@ +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <assert.h> + +#include "nlr.h" +#include "misc.h" +#include "mpconfig.h" +#include "obj.h" +#include "runtime.h" +#include "bc.h" + +/******************************************************************************/ +/* generator wrapper */ + +typedef struct _mp_obj_gen_wrap_t { + mp_obj_base_t base; + int n_state; + mp_obj_t *fun; +} mp_obj_gen_wrap_t; + +// args are in reverse order in the array +mp_obj_t gen_wrap_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) { + mp_obj_gen_wrap_t *self = self_in; + mp_obj_t self_fun = self->fun; + assert(MP_OBJ_IS_TYPE(self_fun, &fun_bc_type)); + int bc_n_args; + uint bc_n_state; + const byte *bc_code; + mp_obj_fun_bc_get(self_fun, &bc_n_args, &bc_n_state, &bc_code); + if (n_args != bc_n_args) { + nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)bc_n_args, (const char*)(machine_int_t)n_args)); + } + mp_obj_t *state = m_new(mp_obj_t, 1 + self->n_state); + // put function object at first slot in state (to keep u_gen_instance small) + state[0] = self_fun; + // init args + for (int i = 0; i < n_args; i++) { + state[1 + i] = args[n_args - 1 - i]; + } + return mp_obj_new_gen_instance(state, bc_code, state + self->n_state); +} + +const mp_obj_type_t gen_wrap_type = { + { &mp_const_type }, + "generator", + NULL, // print + gen_wrap_call_n, // call_n + NULL, // unary_op + NULL, // binary_op + NULL, // getiter + NULL, // iternext + {{NULL, NULL},}, // method list +}; + +mp_obj_t mp_obj_new_gen_wrap(uint n_locals, uint n_cells, uint n_stack, mp_obj_t fun) { + mp_obj_gen_wrap_t *o = m_new_obj(mp_obj_gen_wrap_t); + o->base.type = &gen_wrap_type; + // we have at least 3 locals so the bc can write back fast[0,1,2] safely; should improve how this is done + o->n_state = ((n_locals + n_cells) < 3 ? 3 : (n_locals + n_cells)) + n_stack; + o->fun = fun; + return o; +} + +/******************************************************************************/ +/* generator instance */ + +typedef struct _mp_obj_gen_instance_t { + mp_obj_base_t base; + mp_obj_t *state; + const byte *ip; + mp_obj_t *sp; +} mp_obj_gen_instance_t; + +void gen_instance_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) { + print(env, "<generator object 'fun-name' at %p>", self_in); +} + +mp_obj_t gen_instance_getiter(mp_obj_t self_in) { + return self_in; +} + +mp_obj_t gen_instance_iternext(mp_obj_t self_in) { + mp_obj_gen_instance_t *self = self_in; + //mp_obj_base_t *fun = self->u_gen_instance.state[0]; + //assert(fun->kind == O_FUN_BC); + bool yield = mp_execute_byte_code_2(&self->ip, &self->state[1], &self->sp); + if (yield) { + return *self->sp; + } else { + if (*self->sp == mp_const_none) { + return mp_const_stop_iteration; + } else { + // TODO return StopIteration with value *self->sp + return mp_const_stop_iteration; + } + } +} + +const mp_obj_type_t gen_instance_type = { + { &mp_const_type }, + "generator", + gen_instance_print, // print + NULL, // call_n + NULL, // unary_op + NULL, // binary_op + gen_instance_getiter, // getiter + gen_instance_iternext, // iternext + {{NULL, NULL},}, // method list +}; + +mp_obj_t mp_obj_new_gen_instance(mp_obj_t state, const byte *ip, mp_obj_t *sp) { + mp_obj_gen_instance_t *o = m_new_obj(mp_obj_gen_instance_t); + o->base.type = &gen_instance_type; + o->state = state; + o->ip = ip; + o->sp = sp; + return o; +} + +mp_obj_t mp_obj_gen_instance_next(mp_obj_t self_in) { + mp_obj_t ret = rt_iternext(self_in); + if (ret == mp_const_stop_iteration) { + nlr_jump(mp_obj_new_exception(qstr_from_str_static("StopIteration"))); + } else { + return ret; + } +} + +MP_DEFINE_CONST_FUN_OBJ_1(mp_obj_gen_instance_next_obj, mp_obj_gen_instance_next); diff --git a/py/objinstance.c b/py/objinstance.c new file mode 100644 index 000000000..e5d23af2d --- /dev/null +++ b/py/objinstance.c @@ -0,0 +1,109 @@ +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <assert.h> + +#include "nlr.h" +#include "misc.h" +#include "mpconfig.h" +#include "obj.h" +#include "runtime.h" +#include "map.h" + +typedef struct _mp_obj_instance_t { + mp_obj_base_t base; + mp_obj_base_t *class; // points to a "class" object + mp_map_t *members; +} mp_obj_instance_t; + +/* +type needs to be specified dynamically + case O_OBJ: + { + py_map_elem_t *qn = py_qstr_map_lookup(o->u_obj.class->u_class.locals, qstr_from_str_static("__qualname__"), false); assert(qn != NULL); + assert(IS_O(qn->value, O_STR)); + return qstr_str(((py_obj_base_t*)qn->value)->u_str); + } + */ + +mp_obj_t mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr) { + // logic: look in obj members then class locals (TODO check this against CPython) + mp_obj_instance_t *self = self_in; + mp_map_elem_t *elem = mp_qstr_map_lookup(self->members, attr, false); + if (elem != NULL) { + // object member, always treated as a value + return elem->value; + } + elem = mp_qstr_map_lookup(mp_obj_class_get_locals(self->class), attr, false); + if (elem != NULL) { + if (mp_obj_is_callable(elem->value)) { + // class member is callable so build a bound method + return mp_obj_new_bound_meth(self_in, elem->value); + } else { + // class member is a value, so just return that value + return elem->value; + } + } + nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(self_in), qstr_str(attr))); +} + +void mp_obj_instance_load_method(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { + // logic: look in obj members then class locals (TODO check this against CPython) + mp_obj_instance_t *self = self_in; + mp_map_elem_t *elem = mp_qstr_map_lookup(self->members, attr, false); + if (elem != NULL) { + // object member, always treated as a value + dest[1] = elem->value; + dest[0] = NULL; + return; + } + elem = mp_qstr_map_lookup(mp_obj_class_get_locals(self->class), attr, false); + if (elem != NULL) { + if (mp_obj_is_callable(elem->value)) { + // class member is callable so build a bound method + dest[1] = elem->value; + dest[0] = self_in; + return; + } else { + // class member is a value, so just return that value + dest[1] = elem->value; + dest[0] = NULL; + return; + } + } + + // no such method, so fall back to load attr + dest[1] = rt_load_attr(self_in, attr); + dest[0] = NULL; +} + +void mp_obj_instance_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) { + // logic: look in class locals (no add) then obj members (add) (TODO check this against CPython) + mp_obj_instance_t *self = self_in; + mp_map_elem_t *elem = mp_qstr_map_lookup(mp_obj_class_get_locals(self->class), attr, false); + if (elem != NULL) { + elem->value = value; + } else { + mp_qstr_map_lookup(self->members, attr, true)->value = value; + } +} + +const mp_obj_type_t instance_type = { + { &mp_const_type }, + "instance", + NULL, // print + NULL, // call_n + NULL, // unary_op + NULL, // binary_op + NULL, // getiter + NULL, // iternext + {{NULL, NULL},}, // method list +}; + +mp_obj_t mp_obj_new_instance(mp_obj_t class) { + mp_obj_instance_t *o = m_new_obj(mp_obj_instance_t); + o->base.type = &instance_type; + o->class = class; + o->members = mp_map_new(MP_MAP_QSTR, 0); + return o; +} diff --git a/py/objlist.c b/py/objlist.c new file mode 100644 index 000000000..4d70c37eb --- /dev/null +++ b/py/objlist.c @@ -0,0 +1,204 @@ +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <assert.h> + +#include "nlr.h" +#include "misc.h" +#include "mpconfig.h" +#include "obj.h" +#include "runtime0.h" +#include "runtime.h" + +typedef struct _mp_obj_list_t { + mp_obj_base_t base; + machine_uint_t alloc; + machine_uint_t len; + mp_obj_t *items; +} mp_obj_list_t; + +static mp_obj_t mp_obj_new_list_iterator(mp_obj_list_t *list, int cur); + +/******************************************************************************/ +/* list */ + +static void list_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) { + mp_obj_list_t *o = o_in; + print(env, "["); + for (int i = 0; i < o->len; i++) { + if (i > 0) { + print(env, ", "); + } + mp_obj_print_helper(print, env, o->items[i]); + } + print(env, "]"); +} + +static mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { + mp_obj_list_t *o = lhs; + switch (op) { + case RT_BINARY_OP_SUBSCR: + { + // list load + uint index = mp_get_index(o->base.type, o->len, rhs); + return o->items[index]; + } + default: + // op not supported + return NULL; + } +} + +static mp_obj_t list_getiter(mp_obj_t o_in) { + return mp_obj_new_list_iterator(o_in, 0); +} + +mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg) { + assert(MP_OBJ_IS_TYPE(self_in, &list_type)); + mp_obj_list_t *self = self_in; + if (self->len >= self->alloc) { + self->alloc *= 2; + self->items = m_renew(mp_obj_t, self->items, self->alloc); + } + self->items[self->len++] = arg; + return mp_const_none; // return None, as per CPython +} + +static mp_obj_t list_pop(mp_obj_t self_in, mp_obj_t arg) { + assert(MP_OBJ_IS_TYPE(self_in, &list_type)); + mp_obj_list_t *self = self_in; + uint index = mp_get_index(self->base.type, self->len, arg); + mp_obj_t ret = self->items[index]; + self->len -= 1; + memcpy(self->items + index, self->items + index + 1, (self->len - index) * sizeof(mp_obj_t)); + return ret; +} + +// TODO make this conform to CPython's definition of sort +static void mp_quicksort(mp_obj_t *head, mp_obj_t *tail, mp_obj_t key_fn) { + while (head < tail) { + mp_obj_t *h = head - 1; + mp_obj_t *t = tail; + mp_obj_t v = rt_call_function_1(key_fn, tail[0]); // get pivot using key_fn + for (;;) { + do ++h; while (rt_compare_op(RT_COMPARE_OP_LESS, rt_call_function_1(key_fn, h[0]), v) == mp_const_true); + do --t; while (h < t && rt_compare_op(RT_COMPARE_OP_LESS, v, rt_call_function_1(key_fn, t[0])) == mp_const_true); + if (h >= t) break; + mp_obj_t x = h[0]; + h[0] = t[0]; + t[0] = x; + } + mp_obj_t x = h[0]; + h[0] = tail[0]; + tail[0] = x; + mp_quicksort(head, t, key_fn); + head = h + 1; + } +} + +static mp_obj_t list_sort(mp_obj_t self_in, mp_obj_t key_fn) { + assert(MP_OBJ_IS_TYPE(self_in, &list_type)); + mp_obj_list_t *self = self_in; + if (self->len > 1) { + mp_quicksort(self->items, self->items + self->len - 1, key_fn); + } + return mp_const_none; // return None, as per CPython +} + +static MP_DEFINE_CONST_FUN_OBJ_2(list_append_obj, mp_obj_list_append); +static MP_DEFINE_CONST_FUN_OBJ_2(list_pop_obj, list_pop); +static MP_DEFINE_CONST_FUN_OBJ_2(list_sort_obj, list_sort); + +const mp_obj_type_t list_type = { + { &mp_const_type }, + "list", + list_print, // print + NULL, // call_n + NULL, // unary_op + list_binary_op, // binary_op + list_getiter, // getiter + NULL, // iternext + { // method list + { "append", &list_append_obj }, + { "pop", &list_pop_obj }, + { "sort", &list_sort_obj }, + { NULL, NULL }, // end-of-list sentinel + }, +}; + +static mp_obj_list_t *list_new(uint n) { + mp_obj_list_t *o = m_new_obj(mp_obj_list_t); + o->base.type = &list_type; + o->alloc = n < 4 ? 4 : n; + o->len = n; + o->items = m_new(mp_obj_t, o->alloc); + return o; +} + +mp_obj_t mp_obj_new_list(uint n, mp_obj_t *items) { + mp_obj_list_t *o = list_new(n); + for (int i = 0; i < n; i++) { + o->items[i] = items[i]; + } + return o; +} + +mp_obj_t mp_obj_new_list_reverse(uint n, mp_obj_t *items) { + mp_obj_list_t *o = list_new(n); + for (int i = 0; i < n; i++) { + o->items[i] = items[n - i - 1]; + } + return o; +} + +void mp_obj_list_get(mp_obj_t self_in, uint *len, mp_obj_t **items) { + mp_obj_list_t *self = self_in; + *len = self->len; + *items = self->items; +} + +void mp_obj_list_store(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { + mp_obj_list_t *self = self_in; + uint i = mp_get_index(self->base.type, self->len, index); + self->items[i] = value; +} + +/******************************************************************************/ +/* list iterator */ + +typedef struct _mp_obj_list_it_t { + mp_obj_base_t base; + mp_obj_list_t *list; + machine_uint_t cur; +} mp_obj_list_it_t; + +mp_obj_t list_it_iternext(mp_obj_t self_in) { + mp_obj_list_it_t *self = self_in; + if (self->cur < self->list->len) { + mp_obj_t o_out = self->list->items[self->cur]; + self->cur += 1; + return o_out; + } else { + return mp_const_stop_iteration; + } +} + +static const mp_obj_type_t list_it_type = { + { &mp_const_type }, + "list_iterator", + NULL, // print + NULL, // call_n + NULL, // unary_op + NULL, // binary_op + NULL, // getiter + list_it_iternext, // iternext + { { NULL, NULL }, }, // method list +}; + +mp_obj_t mp_obj_new_list_iterator(mp_obj_list_t *list, int cur) { + mp_obj_list_it_t *o = m_new_obj(mp_obj_list_it_t); + o->base.type = &list_it_type; + o->list = list; + o->cur = cur; + return o; +} diff --git a/py/objnone.c b/py/objnone.c new file mode 100644 index 000000000..f7b665e99 --- /dev/null +++ b/py/objnone.c @@ -0,0 +1,35 @@ +#include <stdlib.h> +#include <stdint.h> + +#include "nlr.h" +#include "misc.h" +#include "mpconfig.h" +#include "obj.h" + +typedef struct _mp_obj_none_t { + mp_obj_base_t base; +} mp_obj_none_t; + +void none_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) { + print(env, "None"); +} + +const mp_obj_type_t none_type = { + { &mp_const_type }, + "NoneType", + none_print, // print + NULL, // call_n + NULL, // unary_op + NULL, // binary_op + NULL, // getiter + NULL, // iternext + {{NULL, NULL},}, // method list +}; + +static const mp_obj_none_t none_obj = {{&none_type}}; +const mp_obj_t mp_const_none = (mp_obj_t)&none_obj; + +// the stop-iteration object just needs to be something unique +// it's not the StopIteration exception +static const mp_obj_none_t stop_it_obj = {{&none_type}}; +const mp_obj_t mp_const_stop_iteration = (mp_obj_t)&stop_it_obj; diff --git a/py/objprivate.h b/py/objprivate.h deleted file mode 100644 index 70ee6560d..000000000 --- a/py/objprivate.h +++ /dev/null @@ -1,140 +0,0 @@ -// internal py_obj_t representation -// not for general use, instead access using py_obj_xxx functions - -#define IS_O(o, k) (((((py_small_int_t)(o)) & 1) == 0) && (((py_obj_base_t*)(o))->kind == (k))) -#define IS_SMALL_INT(o) (((py_small_int_t)(o)) & 1) -#define FROM_SMALL_INT(o) (((py_small_int_t)(o)) >> 1) -#define TO_SMALL_INT(o) ((py_obj_t)(((o) << 1) | 1)) - -typedef enum { - O_CONST, - O_STR, -#if MICROPY_ENABLE_FLOAT - O_FLOAT, - O_COMPLEX, -#endif - O_CELL, - O_EXCEPTION_0, - O_EXCEPTION_N, - O_RANGE, - O_RANGE_IT, - O_FUN_0, - O_FUN_1, - O_FUN_2, - O_FUN_N, - O_FUN_VAR, - O_FUN_BC, - O_FUN_ASM, - O_GEN_WRAP, - O_GEN_INSTANCE, - O_BOUND_METH, - O_CLOSURE, - O_TUPLE, - O_LIST, - O_TUPLE_IT, - O_LIST_IT, - O_SET, - O_MAP, - O_CLASS, - O_OBJ, - O_USER, -} py_obj_kind_t; - -typedef struct _py_obj_base_t py_obj_base_t; - -struct _py_obj_base_t { - py_obj_kind_t kind; - union { - const char *id; - qstr u_str; -#if MICROPY_ENABLE_FLOAT - py_float_t u_float; // for O_FLOAT - struct { // for O_COMPLEX - py_float_t real; - py_float_t imag; - } u_complex; -#endif - py_obj_t u_cell; // for O_CELL - struct { // for O_EXCEPTION_0 - qstr id; - } u_exc0; - struct { // for O_EXCEPTION_N - // TODO make generic object or something - qstr id; - int n_args; - const void **args; - } u_exc_n; - struct { // for O_RANGE - // TODO make generic object or something - machine_int_t start; - machine_int_t stop; - machine_int_t step; - } u_range; - struct { // for O_RANGE_IT - // TODO make generic object or something - machine_int_t cur; - machine_int_t stop; - machine_int_t step; - } u_range_it; - struct { // for O_FUN_[012N], O_FUN_VAR - int n_args; - void *fun; - } u_fun; - struct { // for O_FUN_BC - int n_args; - uint n_state; - byte *code; - } u_fun_bc; - struct { // for O_FUN_ASM - int n_args; - void *fun; - } u_fun_asm; - struct { // for O_GEN_WRAP - int n_state; - py_obj_base_t *fun; - } u_gen_wrap; - struct { // for O_GEN_INSTANCE - py_obj_t *state; - const byte *ip; - py_obj_t *sp; - } u_gen_instance; - struct { // for O_BOUND_METH - py_obj_t meth; - py_obj_t self; - } u_bound_meth; - struct { // for O_CLOSURE - py_obj_t fun; - py_obj_t vars; - } u_closure; - struct { // for O_TUPLE, O_LIST - machine_uint_t alloc; - machine_uint_t len; - py_obj_t *items; - } u_tuple_list; - struct { // for O_TUPLE_IT, O_LIST_IT - py_obj_base_t *obj; - machine_uint_t cur; - } u_tuple_list_it; - struct { // for O_SET - machine_uint_t alloc; - machine_uint_t used; - py_obj_t *table; - } u_set; - py_map_t u_map; // for O_MAP - struct { // for O_CLASS - py_map_t *locals; - } u_class; - struct { // for O_OBJ - py_obj_base_t *class; // points to a O_CLASS object - py_map_t *members; - } u_obj; - struct { // for O_USER - const py_user_info_t *info; - machine_uint_t data1; - machine_uint_t data2; - } u_user; - }; -}; - -py_obj_t py_obj_new_tuple_iterator(py_obj_base_t *tuple, int cur); -py_obj_t py_obj_new_list_iterator(py_obj_base_t *list, int cur); diff --git a/py/objrange.c b/py/objrange.c new file mode 100644 index 000000000..b7fd17fa0 --- /dev/null +++ b/py/objrange.c @@ -0,0 +1,88 @@ +#include <stdlib.h> +#include <stdint.h> + +#include "nlr.h" +#include "misc.h" +#include "mpconfig.h" +#include "obj.h" + +/******************************************************************************/ +/* range */ + +typedef struct _mp_obj_range_t { + mp_obj_base_t base; + // TODO make these values generic objects or something + machine_int_t start; + machine_int_t stop; + machine_int_t step; +} mp_obj_range_t; + +mp_obj_t range_getiter(mp_obj_t o_in) { + mp_obj_range_t *o = o_in; + return mp_obj_new_range_iterator(o->start, o->stop, o->step); +} + +static const mp_obj_type_t range_type = { + { &mp_const_type} , + "range", + NULL, // print + NULL, // call_n + NULL, // unary_op + NULL, // binary_op + range_getiter, + NULL, // iternext + {{NULL, NULL},}, // method list +}; + +// range is a class and instances are immutable sequence objects +mp_obj_t mp_obj_new_range(int start, int stop, int step) { + mp_obj_range_t *o = m_new_obj(mp_obj_range_t); + o->base.type = &range_type; + o->start = start; + o->stop = stop; + o->step = step; + return o; +} + +/******************************************************************************/ +/* range iterator */ + +typedef struct _mp_obj_range_it_t { + mp_obj_base_t base; + // TODO make these values generic objects or something + machine_int_t cur; + machine_int_t stop; + machine_int_t step; +} mp_obj_range_it_t; + +mp_obj_t range_it_iternext(mp_obj_t o_in) { + mp_obj_range_it_t *o = o_in; + if ((o->step > 0 && o->cur < o->stop) || (o->step < 0 && o->cur > o->stop)) { + mp_obj_t o_out = MP_OBJ_NEW_SMALL_INT(o->cur); + o->cur += o->step; + return o_out; + } else { + return mp_const_stop_iteration; + } +} + +static const mp_obj_type_t range_it_type = { + { &mp_const_type }, + "range_iterator", + NULL, // print + NULL, // call_n + NULL, // unary_op + NULL, // binary_op + NULL, // getiter + range_it_iternext, + {{NULL, NULL},}, // method list +}; + +mp_obj_t mp_obj_new_range_iterator(int cur, int stop, int step) { + mp_obj_range_it_t *o = m_new_obj(mp_obj_range_it_t); + o->base.type = &range_it_type; + o->cur = cur; + o->stop = stop; + o->step = step; + return o; +} diff --git a/py/objset.c b/py/objset.c new file mode 100644 index 000000000..f225ca7f6 --- /dev/null +++ b/py/objset.c @@ -0,0 +1,58 @@ +#include <stdlib.h> +#include <stdint.h> +#include <assert.h> + +#include "nlr.h" +#include "misc.h" +#include "mpconfig.h" +#include "obj.h" +#include "map.h" + +typedef struct _mp_obj_set_t { + mp_obj_base_t base; + mp_set_t set; +} mp_obj_set_t; + +void set_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) { + mp_obj_set_t *self = self_in; + bool first = true; + print(env, "{"); + for (int i = 0; i < self->set.alloc; i++) { + if (self->set.table[i] != MP_OBJ_NULL) { + if (!first) { + print(env, ", "); + } + first = false; + mp_obj_print_helper(print, env, self->set.table[i]); + } + } + print(env, "}"); +} + +static const mp_obj_type_t set_type = { + { &mp_const_type }, + "set", + set_print, // print + NULL, // call_n + NULL, // unary_op + NULL, // binary_op + NULL, // getiter + NULL, // iternext + { { NULL, NULL }, }, // method list +}; + +mp_obj_t mp_obj_new_set(int n_args, mp_obj_t *items) { + mp_obj_set_t *o = m_new_obj(mp_obj_set_t); + o->base.type = &set_type; + mp_set_init(&o->set, n_args); + for (int i = 0; i < n_args; i++) { + mp_set_lookup(&o->set, items[i], true); + } + return o; +} + +void mp_obj_set_store(mp_obj_t self_in, mp_obj_t item) { + assert(MP_OBJ_IS_TYPE(self_in, &set_type)); + mp_obj_set_t *self = self_in; + mp_set_lookup(&self->set, item, true); +} diff --git a/py/objstr.c b/py/objstr.c new file mode 100644 index 000000000..d82ea3d3c --- /dev/null +++ b/py/objstr.c @@ -0,0 +1,151 @@ +#include <stdlib.h> +#include <stdint.h> +#include <stdarg.h> +#include <string.h> +#include <assert.h> + +#include "nlr.h" +#include "misc.h" +#include "mpconfig.h" +#include "obj.h" +#include "runtime0.h" +#include "runtime.h" + +typedef struct _mp_obj_str_t { + mp_obj_base_t base; + qstr qstr; +} mp_obj_str_t; + +void str_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) { + mp_obj_str_t *self = self_in; + // TODO need to escape chars etc + print(env, "'%s'", qstr_str(self->qstr)); +} + +mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { + mp_obj_str_t *lhs = lhs_in; + const char *lhs_str = qstr_str(lhs->qstr); + switch (op) { + case RT_BINARY_OP_SUBSCR: + // string access + // XXX a massive hack! + return mp_obj_new_int(lhs_str[mp_obj_get_int(rhs_in)]); + + case RT_BINARY_OP_ADD: + case RT_BINARY_OP_INPLACE_ADD: + if (MP_OBJ_IS_TYPE(rhs_in, &str_type)) { + // add 2 strings + const char *rhs_str = qstr_str(((mp_obj_str_t*)rhs_in)->qstr); + char *val = m_new(char, strlen(lhs_str) + strlen(rhs_str) + 1); + stpcpy(stpcpy(val, lhs_str), rhs_str); + return mp_obj_new_str(qstr_from_str_take(val)); + } + break; + } + + return MP_OBJ_NULL; // op not supported +} + +mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) { + assert(MP_OBJ_IS_TYPE(self_in, &str_type)); + mp_obj_str_t *self = self_in; + int required_len = strlen(qstr_str(self->qstr)); + + // process arg, count required chars + uint seq_len; + mp_obj_t *seq_items; + if (MP_OBJ_IS_TYPE(arg, &tuple_type)) { + mp_obj_tuple_get(arg, &seq_len, &seq_items); + } else if (MP_OBJ_IS_TYPE(arg, &list_type)) { + mp_obj_list_get(arg, &seq_len, &seq_items); + } else { + goto bad_arg; + } + for (int i = 0; i < seq_len; i++) { + if (!MP_OBJ_IS_TYPE(seq_items[i], &str_type)) { + goto bad_arg; + } + required_len += strlen(qstr_str(mp_obj_str_get(seq_items[i]))); + } + + // make joined string + char *joined_str = m_new(char, required_len + 1); + joined_str[0] = 0; + for (int i = 0; i < seq_len; i++) { + const char *s2 = qstr_str(mp_obj_str_get(seq_items[i])); + if (i > 0) { + strcat(joined_str, qstr_str(self->qstr)); + } + strcat(joined_str, s2); + } + return mp_obj_new_str(qstr_from_str_take(joined_str)); + +bad_arg: + nlr_jump(mp_obj_new_exception_msg(rt_q_TypeError, "?str.join expecting a list of str's")); +} + +void vstr_printf_wrapper(void *env, const char *fmt, ...) { + va_list args; + va_start(args, fmt); + vstr_vprintf(env, fmt, args); + va_end(args); +} + +mp_obj_t str_format(int n_args, const mp_obj_t *args) { + assert(MP_OBJ_IS_TYPE(args[0], &str_type)); + mp_obj_str_t *self = args[0]; + + const char *str = qstr_str(self->qstr); + int arg_i = 1; + vstr_t *vstr = vstr_new(); + for (; *str; str++) { + if (*str == '{') { + str++; + if (*str == '{') { + vstr_add_char(vstr, '{'); + } else if (*str == '}') { + if (arg_i >= n_args) { + nlr_jump(mp_obj_new_exception_msg(rt_q_IndexError, "tuple index out of range")); + } + mp_obj_print_helper(vstr_printf_wrapper, vstr, args[arg_i]); + arg_i++; + } + } else { + vstr_add_char(vstr, *str); + } + } + + return mp_obj_new_str(qstr_from_str_take(vstr->buf)); +} + +static MP_DEFINE_CONST_FUN_OBJ_2(str_join_obj, str_join); +static MP_DEFINE_CONST_FUN_OBJ_VAR(str_format_obj, 1, str_format); + +const mp_obj_type_t str_type = { + { &mp_const_type }, + "str", + str_print, // print + NULL, // call_n + NULL, // unary_op + str_binary_op, // binary_op + NULL, // getiter + NULL, // iternext + { // method list + { "join", &str_join_obj }, + { "format", &str_format_obj }, + { NULL, NULL }, // end-of-list sentinel + }, +}; + +mp_obj_t mp_obj_new_str(qstr qstr) { + mp_obj_str_t *o = m_new_obj(mp_obj_str_t); + o->base.type = &str_type; + o->qstr = qstr; + return o; +} + +qstr mp_obj_str_get(mp_obj_t self_in) { + assert(MP_OBJ_IS_TYPE(self_in, &str_type)); + mp_obj_str_t *self = self_in; + return self->qstr; +} diff --git a/py/objtuple.c b/py/objtuple.c new file mode 100644 index 000000000..b98d6ede7 --- /dev/null +++ b/py/objtuple.c @@ -0,0 +1,133 @@ +#include <stdlib.h> +#include <stdint.h> +//#include <string.h> +#include <assert.h> + +#include "nlr.h" +#include "misc.h" +#include "mpconfig.h" +#include "obj.h" +#include "runtime0.h" + +typedef struct _mp_obj_tuple_t { + mp_obj_base_t base; + machine_uint_t len; + mp_obj_t items[]; +} mp_obj_tuple_t; + +static mp_obj_t mp_obj_new_tuple_iterator(mp_obj_tuple_t *tuple, int cur); + +/******************************************************************************/ +/* tuple */ + +void tuple_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) { + mp_obj_tuple_t *o = o_in; + print(env, "("); + for (int i = 0; i < o->len; i++) { + if (i > 0) { + print(env, ", "); + } + mp_obj_print_helper(print, env, o->items[i]); + } + if (o->len == 1) { + print(env, ","); + } + print(env, ")"); +} + +mp_obj_t tuple_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { + mp_obj_tuple_t *o = lhs; + switch (op) { + case RT_BINARY_OP_SUBSCR: + { + // tuple load + uint index = mp_get_index(o->base.type, o->len, rhs); + return o->items[index]; + } + default: + // op not supported + return NULL; + } +} + +mp_obj_t tuple_getiter(mp_obj_t o_in) { + return mp_obj_new_tuple_iterator(o_in, 0); +} + +void mp_obj_tuple_get(mp_obj_t self_in, uint *len, mp_obj_t **items) { + mp_obj_tuple_t *self = self_in; + *len = self->len; + *items = &self->items[0]; +} + +const mp_obj_type_t tuple_type = { + { &mp_const_type }, + "tuple", + tuple_print, // print + NULL, // call_n + NULL, // unary_op + tuple_binary_op, // binary_op + tuple_getiter, // getiter + NULL, // iternext + {{NULL, NULL},}, // method list +}; + +mp_obj_t mp_obj_new_tuple(uint n, mp_obj_t *items) { + mp_obj_tuple_t *o = m_new_obj_var(mp_obj_tuple_t, mp_obj_t, n); + o->base.type = &tuple_type; + o->len = n; + for (int i = 0; i < n; i++) { + o->items[i] = items[i]; + } + return o; +} + +mp_obj_t mp_obj_new_tuple_reverse(uint n, mp_obj_t *items) { + mp_obj_tuple_t *o = m_new_obj_var(mp_obj_tuple_t, mp_obj_t, n); + o->base.type = &tuple_type; + o->len = n; + for (int i = 0; i < n; i++) { + o->items[i] = items[n - i - 1]; + } + return o; +} + +/******************************************************************************/ +/* tuple iterator */ + +typedef struct _mp_obj_tuple_it_t { + mp_obj_base_t base; + mp_obj_tuple_t *tuple; + machine_uint_t cur; +} mp_obj_tuple_it_t; + +mp_obj_t tuple_it_iternext(mp_obj_t self_in) { + mp_obj_tuple_it_t *self = self_in; + if (self->cur < self->tuple->len) { + mp_obj_t o_out = self->tuple->items[self->cur]; + self->cur += 1; + return o_out; + } else { + return mp_const_stop_iteration; + } +} + +static const mp_obj_type_t tuple_it_type = { + { &mp_const_type }, + "tuple_iterator", + NULL, // print + NULL, // call_n + NULL, // unary_op + NULL, // binary_op + NULL, // getiter + tuple_it_iternext, + {{NULL, NULL},}, // method list +}; + +static mp_obj_t mp_obj_new_tuple_iterator(mp_obj_tuple_t *tuple, int cur) { + mp_obj_tuple_it_t *o = m_new_obj(mp_obj_tuple_it_t); + o->base.type = &tuple_it_type; + o->tuple = tuple; + o->cur = cur; + return o; +} diff --git a/py/objtype.c b/py/objtype.c new file mode 100644 index 000000000..4358148c0 --- /dev/null +++ b/py/objtype.c @@ -0,0 +1,23 @@ +#include <stdlib.h> +#include <stdint.h> + +#include "nlr.h" +#include "misc.h" +#include "mpconfig.h" +#include "obj.h" + +void type_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) { + print(env, "type?"); +} + +const mp_obj_type_t mp_const_type = { + { &mp_const_type }, + "type?", + type_print, // print + NULL, // call_n + NULL, // unary_op + NULL, // binary_op + NULL, // getiter + NULL, // iternext + {{NULL, NULL},}, // method list +}; diff --git a/py/parse.c b/py/parse.c index 632ac4e4f..48c304805 100644 --- a/py/parse.c +++ b/py/parse.c @@ -7,7 +7,7 @@ #include <assert.h> #include "misc.h" -#include "mpyconfig.h" +#include "mpconfig.h" #include "lexer.h" #include "parse.h" @@ -50,9 +50,9 @@ enum { #define one_or_more (RULE_ACT_LIST | 2) #define list (RULE_ACT_LIST | 1) #define list_with_end (RULE_ACT_LIST | 3) -#define tok(t) (RULE_ARG_TOK | PY_TOKEN_##t) +#define tok(t) (RULE_ARG_TOK | MP_TOKEN_##t) #define rule(r) (RULE_ARG_RULE | RULE_##r) -#define opt_tok(t) (RULE_ARG_OPT_TOK | PY_TOKEN_##t) +#define opt_tok(t) (RULE_ARG_OPT_TOK | MP_TOKEN_##t) #define opt_rule(r) (RULE_ARG_OPT_RULE | RULE_##r) #ifdef USE_RULE_NAME #define DEF_RULE(rule, comp, kind, arg...) static const rule_t rule_##rule = { RULE_##rule, kind, #rule, { arg } }; @@ -89,7 +89,7 @@ typedef struct _parser_t { rule_stack_t *rule_stack; uint result_stack_top; - py_parse_node_t *result_stack; + mp_parse_node_t *result_stack; } parser_t; static void push_rule(parser_t *parser, const rule_t *rule, int arg_i) { @@ -115,47 +115,47 @@ static void pop_rule(parser_t *parser, const rule_t **rule, uint *arg_i) { *arg_i = parser->rule_stack[parser->rule_stack_top].arg_i; } -py_parse_node_t py_parse_node_new_leaf(machine_int_t kind, machine_int_t arg) { - return (py_parse_node_t)(kind | (arg << 4)); +mp_parse_node_t mp_parse_node_new_leaf(machine_int_t kind, machine_int_t arg) { + return (mp_parse_node_t)(kind | (arg << 4)); } int num_parse_nodes_allocated = 0; -py_parse_node_struct_t *parse_node_new_struct(int rule_id, int num_args) { - py_parse_node_struct_t *pn = m_malloc(sizeof(py_parse_node_struct_t) + num_args * sizeof(py_parse_node_t)); +mp_parse_node_struct_t *parse_node_new_struct(int rule_id, int num_args) { + mp_parse_node_struct_t *pn = m_malloc(sizeof(mp_parse_node_struct_t) + num_args * sizeof(mp_parse_node_t)); pn->source = 0; // TODO pn->kind_num_nodes = (rule_id & 0xff) | (num_args << 8); num_parse_nodes_allocated += 1; return pn; } -void py_parse_node_show(py_parse_node_t pn, int indent) { +void mp_parse_node_show(mp_parse_node_t pn, int indent) { for (int i = 0; i < indent; i++) { printf(" "); } - if (PY_PARSE_NODE_IS_NULL(pn)) { + if (MP_PARSE_NODE_IS_NULL(pn)) { printf("NULL\n"); - } else if (PY_PARSE_NODE_IS_LEAF(pn)) { - int arg = PY_PARSE_NODE_LEAF_ARG(pn); - switch (PY_PARSE_NODE_LEAF_KIND(pn)) { - case PY_PARSE_NODE_ID: printf("id(%s)\n", qstr_str(arg)); break; - case PY_PARSE_NODE_SMALL_INT: printf("int(%d)\n", arg); break; - case PY_PARSE_NODE_INTEGER: printf("int(%s)\n", qstr_str(arg)); break; - case PY_PARSE_NODE_DECIMAL: printf("dec(%s)\n", qstr_str(arg)); break; - case PY_PARSE_NODE_STRING: printf("str(%s)\n", qstr_str(arg)); break; - case PY_PARSE_NODE_BYTES: printf("bytes(%s)\n", qstr_str(arg)); break; - case PY_PARSE_NODE_TOKEN: printf("tok(%d)\n", arg); break; + } else if (MP_PARSE_NODE_IS_LEAF(pn)) { + int arg = MP_PARSE_NODE_LEAF_ARG(pn); + switch (MP_PARSE_NODE_LEAF_KIND(pn)) { + case MP_PARSE_NODE_ID: printf("id(%s)\n", qstr_str(arg)); break; + case MP_PARSE_NODE_SMALL_INT: printf("int(%d)\n", arg); break; + case MP_PARSE_NODE_INTEGER: printf("int(%s)\n", qstr_str(arg)); break; + case MP_PARSE_NODE_DECIMAL: printf("dec(%s)\n", qstr_str(arg)); break; + case MP_PARSE_NODE_STRING: printf("str(%s)\n", qstr_str(arg)); break; + case MP_PARSE_NODE_BYTES: printf("bytes(%s)\n", qstr_str(arg)); break; + case MP_PARSE_NODE_TOKEN: printf("tok(%d)\n", arg); break; default: assert(0); } } else { - py_parse_node_struct_t *pns2 = (py_parse_node_struct_t*)pn; + mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pn; int n = pns2->kind_num_nodes >> 8; #ifdef USE_RULE_NAME - printf("%s(%d) (n=%d)\n", rules[PY_PARSE_NODE_STRUCT_KIND(pns2)]->rule_name, PY_PARSE_NODE_STRUCT_KIND(pns2), n); + printf("%s(%d) (n=%d)\n", rules[MP_PARSE_NODE_STRUCT_KIND(pns2)]->rule_name, MP_PARSE_NODE_STRUCT_KIND(pns2), n); #else - printf("rule(%u) (n=%d)\n", (uint)PY_PARSE_NODE_STRUCT_KIND(pns2), n); + printf("rule(%u) (n=%d)\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns2), n); #endif for (int i = 0; i < n; i++) { - py_parse_node_show(pns2->nodes[i], indent + 2); + mp_parse_node_show(pns2->nodes[i], indent + 2); } } } @@ -164,31 +164,31 @@ void py_parse_node_show(py_parse_node_t pn, int indent) { static void result_stack_show(parser_t *parser) { printf("result stack, most recent first\n"); for (int i = parser->result_stack_top - 1; i >= 0; i--) { - py_parse_node_show(parser->result_stack[i], 0); + mp_parse_node_show(parser->result_stack[i], 0); } } */ -static py_parse_node_t pop_result(parser_t *parser) { +static mp_parse_node_t pop_result(parser_t *parser) { assert(parser->result_stack_top > 0); return parser->result_stack[--parser->result_stack_top]; } -static py_parse_node_t peek_result(parser_t *parser, int pos) { +static mp_parse_node_t peek_result(parser_t *parser, int pos) { assert(parser->result_stack_top > pos); return parser->result_stack[parser->result_stack_top - 1 - pos]; } -static void push_result_node(parser_t *parser, py_parse_node_t pn) { +static void push_result_node(parser_t *parser, mp_parse_node_t pn) { parser->result_stack[parser->result_stack_top++] = pn; } -static void push_result_token(parser_t *parser, const py_lexer_t *lex) { - const py_token_t *tok = py_lexer_cur(lex); - py_parse_node_t pn; - if (tok->kind == PY_TOKEN_NAME) { - pn = py_parse_node_new_leaf(PY_PARSE_NODE_ID, qstr_from_strn_copy(tok->str, tok->len)); - } else if (tok->kind == PY_TOKEN_NUMBER) { +static void push_result_token(parser_t *parser, const mp_lexer_t *lex) { + const mp_token_t *tok = mp_lexer_cur(lex); + mp_parse_node_t pn; + if (tok->kind == MP_TOKEN_NAME) { + pn = mp_parse_node_new_leaf(MP_PARSE_NODE_ID, qstr_from_strn_copy(tok->str, tok->len)); + } else if (tok->kind == MP_TOKEN_NUMBER) { bool dec = false; bool small_int = true; int int_val = 0; @@ -227,43 +227,43 @@ static void push_result_token(parser_t *parser, const py_lexer_t *lex) { } } if (dec) { - pn = py_parse_node_new_leaf(PY_PARSE_NODE_DECIMAL, qstr_from_strn_copy(str, len)); - } else if (small_int && PY_FIT_SMALL_INT(int_val)) { - pn = py_parse_node_new_leaf(PY_PARSE_NODE_SMALL_INT, int_val); + pn = mp_parse_node_new_leaf(MP_PARSE_NODE_DECIMAL, qstr_from_strn_copy(str, len)); + } else if (small_int && MP_FIT_SMALL_INT(int_val)) { + pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, int_val); } else { - pn = py_parse_node_new_leaf(PY_PARSE_NODE_INTEGER, qstr_from_strn_copy(str, len)); + pn = mp_parse_node_new_leaf(MP_PARSE_NODE_INTEGER, qstr_from_strn_copy(str, len)); } - } else if (tok->kind == PY_TOKEN_STRING) { - pn = py_parse_node_new_leaf(PY_PARSE_NODE_STRING, qstr_from_strn_copy(tok->str, tok->len)); - } else if (tok->kind == PY_TOKEN_BYTES) { - pn = py_parse_node_new_leaf(PY_PARSE_NODE_BYTES, qstr_from_strn_copy(tok->str, tok->len)); + } else if (tok->kind == MP_TOKEN_STRING) { + pn = mp_parse_node_new_leaf(MP_PARSE_NODE_STRING, qstr_from_strn_copy(tok->str, tok->len)); + } else if (tok->kind == MP_TOKEN_BYTES) { + pn = mp_parse_node_new_leaf(MP_PARSE_NODE_BYTES, qstr_from_strn_copy(tok->str, tok->len)); } else { - pn = py_parse_node_new_leaf(PY_PARSE_NODE_TOKEN, tok->kind); + pn = mp_parse_node_new_leaf(MP_PARSE_NODE_TOKEN, tok->kind); } push_result_node(parser, pn); } static void push_result_rule(parser_t *parser, const rule_t *rule, int num_args) { - py_parse_node_struct_t *pn = parse_node_new_struct(rule->rule_id, num_args); + mp_parse_node_struct_t *pn = parse_node_new_struct(rule->rule_id, num_args); for (int i = num_args; i > 0; i--) { pn->nodes[i - 1] = pop_result(parser); } - push_result_node(parser, (py_parse_node_t)pn); + push_result_node(parser, (mp_parse_node_t)pn); } -py_parse_node_t py_parse(py_lexer_t *lex, py_parse_input_kind_t input_kind) { +mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) { parser_t *parser = m_new(parser_t, 1); parser->rule_stack_alloc = 64; parser->rule_stack_top = 0; parser->rule_stack = m_new(rule_stack_t, parser->rule_stack_alloc); - parser->result_stack = m_new(py_parse_node_t, 1000); + parser->result_stack = m_new(mp_parse_node_t, 1000); parser->result_stack_top = 0; int top_level_rule; switch (input_kind) { - case PY_PARSE_SINGLE_INPUT: top_level_rule = RULE_single_input; break; - //case PY_PARSE_EVAL_INPUT: top_level_rule = RULE_eval_input; break; + case MP_PARSE_SINGLE_INPUT: top_level_rule = RULE_single_input; break; + //case MP_PARSE_EVAL_INPUT: top_level_rule = RULE_eval_input; break; default: top_level_rule = RULE_file_input; } push_rule(parser, rules[top_level_rule], 0); @@ -271,7 +271,7 @@ py_parse_node_t py_parse(py_lexer_t *lex, py_parse_input_kind_t input_kind) { uint n, i; bool backtrack = false; const rule_t *rule; - py_token_kind_t tok_kind; + mp_token_kind_t tok_kind; bool emit_rule; bool had_trailing_sep; @@ -303,9 +303,9 @@ py_parse_node_t py_parse(py_lexer_t *lex, py_parse_input_kind_t input_kind) { for (; i < n - 1; ++i) { switch (rule->arg[i] & RULE_ARG_KIND_MASK) { case RULE_ARG_TOK: - if (py_lexer_is_kind(lex, rule->arg[i] & RULE_ARG_ARG_MASK)) { + if (mp_lexer_is_kind(lex, rule->arg[i] & RULE_ARG_ARG_MASK)) { push_result_token(parser, lex); - py_lexer_to_next(lex); + mp_lexer_to_next(lex); goto next_rule; } break; @@ -318,9 +318,9 @@ py_parse_node_t py_parse(py_lexer_t *lex, py_parse_input_kind_t input_kind) { } } if ((rule->arg[i] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) { - if (py_lexer_is_kind(lex, rule->arg[i] & RULE_ARG_ARG_MASK)) { + if (mp_lexer_is_kind(lex, rule->arg[i] & RULE_ARG_ARG_MASK)) { push_result_token(parser, lex); - py_lexer_to_next(lex); + mp_lexer_to_next(lex); } else { backtrack = true; goto next_rule; @@ -337,7 +337,7 @@ py_parse_node_t py_parse(py_lexer_t *lex, py_parse_input_kind_t input_kind) { assert(i > 0); if ((rule->arg[i - 1] & RULE_ARG_KIND_MASK) == RULE_ARG_OPT_RULE) { // an optional rule that failed, so continue with next arg - push_result_node(parser, PY_PARSE_NODE_NULL); + push_result_node(parser, MP_PARSE_NODE_NULL); backtrack = false; } else { // a mandatory rule that failed, so propagate backtrack @@ -356,12 +356,12 @@ py_parse_node_t py_parse(py_lexer_t *lex, py_parse_input_kind_t input_kind) { case RULE_ARG_TOK: // need to match a token tok_kind = rule->arg[i] & RULE_ARG_ARG_MASK; - if (py_lexer_is_kind(lex, tok_kind)) { + if (mp_lexer_is_kind(lex, tok_kind)) { // matched token - if (tok_kind == PY_TOKEN_NAME) { + if (tok_kind == MP_TOKEN_NAME) { push_result_token(parser, lex); } - py_lexer_to_next(lex); + mp_lexer_to_next(lex); } else { // failed to match token if (i > 0) { @@ -399,10 +399,10 @@ py_parse_node_t py_parse(py_lexer_t *lex, py_parse_input_kind_t input_kind) { for (int x = 0; x < n; ++x) { if ((rule->arg[x] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) { tok_kind = rule->arg[x] & RULE_ARG_ARG_MASK; - if (tok_kind >= PY_TOKEN_NAME) { + if (tok_kind >= MP_TOKEN_NAME) { emit_rule = true; } - if (tok_kind == PY_TOKEN_NAME) { + if (tok_kind == MP_TOKEN_NAME) { // only tokens which were names are pushed to stack i += 1; } @@ -427,13 +427,13 @@ py_parse_node_t py_parse(py_lexer_t *lex, py_parse_input_kind_t input_kind) { // always emit these rules, and add an extra blank node at the end (to be used by the compiler to store data) if (rule->rule_id == RULE_funcdef || rule->rule_id == RULE_classdef || rule->rule_id == RULE_comp_for || rule->rule_id == RULE_lambdef || rule->rule_id == RULE_lambdef_nocond) { emit_rule = true; - push_result_node(parser, PY_PARSE_NODE_NULL); + push_result_node(parser, MP_PARSE_NODE_NULL); i += 1; } int num_not_nil = 0; for (int x = 0; x < i; ++x) { - if (peek_result(parser, x) != PY_PARSE_NODE_NULL) { + if (peek_result(parser, x) != MP_PARSE_NODE_NULL) { num_not_nil += 1; } } @@ -446,10 +446,10 @@ py_parse_node_t py_parse(py_lexer_t *lex, py_parse_input_kind_t input_kind) { //assert(0); } else if (num_not_nil == 1) { // single result, leave it on stack - py_parse_node_t pn = PY_PARSE_NODE_NULL; + mp_parse_node_t pn = MP_PARSE_NODE_NULL; for (int x = 0; x < i; ++x) { - py_parse_node_t pn2 = pop_result(parser); - if (pn2 != PY_PARSE_NODE_NULL) { + mp_parse_node_t pn2 = pop_result(parser); + if (pn2 != MP_PARSE_NODE_NULL) { pn = pn2; } } @@ -498,13 +498,13 @@ py_parse_node_t py_parse(py_lexer_t *lex, py_parse_input_kind_t input_kind) { uint arg = rule->arg[i & 1 & n]; switch (arg & RULE_ARG_KIND_MASK) { case RULE_ARG_TOK: - if (py_lexer_is_kind(lex, arg & RULE_ARG_ARG_MASK)) { + if (mp_lexer_is_kind(lex, arg & RULE_ARG_ARG_MASK)) { if (i & 1 & n) { // separators which are tokens are not pushed to result stack } else { push_result_token(parser, lex); } - py_lexer_to_next(lex); + mp_lexer_to_next(lex); // got element of list, so continue parsing list i += 1; } else { @@ -552,7 +552,7 @@ py_parse_node_t py_parse(py_lexer_t *lex, py_parse_input_kind_t input_kind) { } // check we are at the end of the token stream - if (!py_lexer_is_kind(lex, PY_TOKEN_END)) { + if (!mp_lexer_is_kind(lex, MP_TOKEN_END)) { goto syntax_error; } @@ -564,16 +564,16 @@ py_parse_node_t py_parse(py_lexer_t *lex, py_parse_input_kind_t input_kind) { return parser->result_stack[0]; syntax_error: - if (py_lexer_is_kind(lex, PY_TOKEN_INDENT)) { - py_lexer_show_error_pythonic(lex, "IndentationError: unexpected indent"); - } else if (py_lexer_is_kind(lex, PY_TOKEN_DEDENT_MISMATCH)) { - py_lexer_show_error_pythonic(lex, "IndentationError: unindent does not match any outer indentation level"); + if (mp_lexer_is_kind(lex, MP_TOKEN_INDENT)) { + mp_lexer_show_error_pythonic(lex, "IndentationError: unexpected indent"); + } else if (mp_lexer_is_kind(lex, MP_TOKEN_DEDENT_MISMATCH)) { + mp_lexer_show_error_pythonic(lex, "IndentationError: unindent does not match any outer indentation level"); } else { - py_lexer_show_error_pythonic(lex, "syntax error:"); + mp_lexer_show_error_pythonic(lex, "syntax error:"); #ifdef USE_RULE_NAME - py_lexer_show_error(lex, rule->rule_name); + mp_lexer_show_error(lex, rule->rule_name); #endif - py_token_show(py_lexer_cur(lex)); + mp_token_show(mp_lexer_cur(lex)); } - return PY_PARSE_NODE_NULL; + return MP_PARSE_NODE_NULL; } diff --git a/py/parse.h b/py/parse.h index 722d9f6c2..7326243ea 100644 --- a/py/parse.h +++ b/py/parse.h @@ -1,6 +1,6 @@ -struct _py_lexer_t; +struct _mp_lexer_t; -// a py_parse_node_t is: +// a mp_parse_node_t is: // - 0000...0000: no node // - xxxx...0001: an identifier; bits 4 and above are the qstr // - xxxx...0011: a small integer; bits 4 and above are the signed value, 2's complement @@ -8,58 +8,58 @@ struct _py_lexer_t; // - xxxx...0111: a decimal; bits 4 and above are the qstr holding the value // - xxxx...1001: a string; bits 4 and above are the qstr holding the value // - xxxx...1011: a string with triple quotes; bits 4 and above are the qstr holding the value -// - xxxx...1101: a token; bits 4 and above are py_token_kind_t -// - xxxx...xxx0: pointer to py_parse_node_struct_t +// - xxxx...1101: a token; bits 4 and above are mp_token_kind_t +// - xxxx...xxx0: pointer to mp_parse_node_struct_t // makes sure the top 5 bits of x are all cleared (positive number) or all set (negavite number) // these macros can probably go somewhere else because they are used more than just in the parser -#define PY_UINT_HIGH_5_BITS (~((~((machine_uint_t)0)) >> 5)) -#define PY_FIT_SMALL_INT(x) (((((machine_uint_t)(x)) & PY_UINT_HIGH_5_BITS) == 0) || ((((machine_uint_t)(x)) & PY_UINT_HIGH_5_BITS) == PY_UINT_HIGH_5_BITS)) +#define MP_UINT_HIGH_5_BITS (~((~((machine_uint_t)0)) >> 5)) +#define MP_FIT_SMALL_INT(x) (((((machine_uint_t)(x)) & MP_UINT_HIGH_5_BITS) == 0) || ((((machine_uint_t)(x)) & MP_UINT_HIGH_5_BITS) == MP_UINT_HIGH_5_BITS)) -#define PY_PARSE_NODE_NULL (0) -#define PY_PARSE_NODE_ID (0x1) -#define PY_PARSE_NODE_SMALL_INT (0x3) -#define PY_PARSE_NODE_INTEGER (0x5) -#define PY_PARSE_NODE_DECIMAL (0x7) -#define PY_PARSE_NODE_STRING (0x9) -#define PY_PARSE_NODE_BYTES (0xb) -#define PY_PARSE_NODE_TOKEN (0xd) +#define MP_PARSE_NODE_NULL (0) +#define MP_PARSE_NODE_ID (0x1) +#define MP_PARSE_NODE_SMALL_INT (0x3) +#define MP_PARSE_NODE_INTEGER (0x5) +#define MP_PARSE_NODE_DECIMAL (0x7) +#define MP_PARSE_NODE_STRING (0x9) +#define MP_PARSE_NODE_BYTES (0xb) +#define MP_PARSE_NODE_TOKEN (0xd) -typedef machine_uint_t py_parse_node_t; // must be pointer size +typedef machine_uint_t mp_parse_node_t; // must be pointer size -typedef struct _py_parse_node_struct_t { +typedef struct _mp_parse_node_struct_t { uint32_t source; // file identifier, and line number uint32_t kind_num_nodes; // parse node kind, and number of nodes - py_parse_node_t nodes[]; // nodes -} py_parse_node_struct_t; + mp_parse_node_t nodes[]; // nodes +} mp_parse_node_struct_t; -// macros for py_parse_node_t usage +// macros for mp_parse_node_t usage // some of these evaluate their argument more than once -#define PY_PARSE_NODE_IS_NULL(pn) ((pn) == PY_PARSE_NODE_NULL) -#define PY_PARSE_NODE_IS_LEAF(pn) ((pn) & 1) -#define PY_PARSE_NODE_IS_STRUCT(pn) ((pn) != PY_PARSE_NODE_NULL && ((pn) & 1) == 0) -#define PY_PARSE_NODE_IS_STRUCT_KIND(pn, k) ((pn) != PY_PARSE_NODE_NULL && ((pn) & 1) == 0 && PY_PARSE_NODE_STRUCT_KIND((py_parse_node_struct_t*)(pn)) == (k)) +#define MP_PARSE_NODE_IS_NULL(pn) ((pn) == MP_PARSE_NODE_NULL) +#define MP_PARSE_NODE_IS_LEAF(pn) ((pn) & 1) +#define MP_PARSE_NODE_IS_STRUCT(pn) ((pn) != MP_PARSE_NODE_NULL && ((pn) & 1) == 0) +#define MP_PARSE_NODE_IS_STRUCT_KIND(pn, k) ((pn) != MP_PARSE_NODE_NULL && ((pn) & 1) == 0 && MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)(pn)) == (k)) -#define PY_PARSE_NODE_IS_ID(pn) (((pn) & 0xf) == PY_PARSE_NODE_ID) -#define PY_PARSE_NODE_IS_SMALL_INT(pn) (((pn) & 0xf) == PY_PARSE_NODE_SMALL_INT) -#define PY_PARSE_NODE_IS_TOKEN(pn) (((pn) & 0xf) == PY_PARSE_NODE_TOKEN) -#define PY_PARSE_NODE_IS_TOKEN_KIND(pn, k) ((pn) == (PY_PARSE_NODE_TOKEN | (k << 4))) +#define MP_PARSE_NODE_IS_ID(pn) (((pn) & 0xf) == MP_PARSE_NODE_ID) +#define MP_PARSE_NODE_IS_SMALL_INT(pn) (((pn) & 0xf) == MP_PARSE_NODE_SMALL_INT) +#define MP_PARSE_NODE_IS_TOKEN(pn) (((pn) & 0xf) == MP_PARSE_NODE_TOKEN) +#define MP_PARSE_NODE_IS_TOKEN_KIND(pn, k) ((pn) == (MP_PARSE_NODE_TOKEN | (k << 4))) -#define PY_PARSE_NODE_LEAF_KIND(pn) ((pn) & 0xf) +#define MP_PARSE_NODE_LEAF_KIND(pn) ((pn) & 0xf) // TODO should probably have int and uint versions of this macro -#define PY_PARSE_NODE_LEAF_ARG(pn) (((machine_int_t)(pn)) >> 4) -#define PY_PARSE_NODE_STRUCT_KIND(pns) ((pns)->kind_num_nodes & 0xff) -#define PY_PARSE_NODE_STRUCT_NUM_NODES(pns) ((pns)->kind_num_nodes >> 8) +#define MP_PARSE_NODE_LEAF_ARG(pn) (((machine_int_t)(pn)) >> 4) +#define MP_PARSE_NODE_STRUCT_KIND(pns) ((pns)->kind_num_nodes & 0xff) +#define MP_PARSE_NODE_STRUCT_NUM_NODES(pns) ((pns)->kind_num_nodes >> 8) -py_parse_node_t py_parse_node_new_leaf(machine_int_t kind, machine_int_t arg); +mp_parse_node_t mp_parse_node_new_leaf(machine_int_t kind, machine_int_t arg); -void py_parse_node_show(py_parse_node_t pn, int indent); +void mp_parse_node_show(mp_parse_node_t pn, int indent); typedef enum { - PY_PARSE_SINGLE_INPUT, - PY_PARSE_FILE_INPUT, - PY_PARSE_EVAL_INPUT, -} py_parse_input_kind_t; + MP_PARSE_SINGLE_INPUT, + MP_PARSE_FILE_INPUT, + MP_PARSE_EVAL_INPUT, +} mp_parse_input_kind_t; -py_parse_node_t py_parse(struct _py_lexer_t *lex, py_parse_input_kind_t input_kind); +mp_parse_node_t mp_parse(struct _mp_lexer_t *lex, mp_parse_input_kind_t input_kind); diff --git a/py/repl.c b/py/repl.c index f295aff23..ecf6e2d20 100644 --- a/py/repl.c +++ b/py/repl.c @@ -11,7 +11,7 @@ bool str_startswith_word(const char *str, const char *head) { return head[i] == '\0' && (str[i] == '\0' || !g_unichar_isalpha(str[i])); } -bool py_repl_is_compound_stmt(const char *line) { +bool mp_repl_is_compound_stmt(const char *line) { // compound if line starts with a certain keyword if ( str_startswith_word(line, "if") diff --git a/py/repl.h b/py/repl.h index 014e8609b..02fe523ed 100644 --- a/py/repl.h +++ b/py/repl.h @@ -1 +1 @@ -bool py_repl_is_compound_stmt(const char *line); +bool mp_repl_is_compound_stmt(const char *line); diff --git a/py/runtime.c b/py/runtime.c index 35f4f2af2..a3d11f3c6 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -1,23 +1,20 @@ // in principle, rt_xxx functions are called only by vm/native/viper and make assumptions about args -// py_xxx functions are safer and can be called by anyone +// mp_xxx functions are safer and can be called by anyone // note that rt_assign_xxx are called only from emit*, and maybe we can rename them to reflect this #include <stdint.h> #include <stdlib.h> #include <stdio.h> -#include <stdarg.h> #include <string.h> #include <assert.h> #include "nlr.h" #include "misc.h" -#include "mpyconfig.h" +#include "mpconfig.h" +#include "obj.h" +#include "runtime0.h" #include "runtime.h" -#include "bc.h" - #include "map.h" -#include "obj.h" -#include "objprivate.h" #include "builtin.h" #if 0 // print debugging info @@ -46,203 +43,20 @@ qstr rt_q_TypeError; qstr rt_q_SyntaxError; qstr rt_q_ValueError; -py_obj_t py_const_none; -py_obj_t py_const_false; -py_obj_t py_const_true; -py_obj_t py_const_stop_iteration; - // locals and globals need to be pointers because they can be the same in outer module scope -static py_map_t *map_locals; -static py_map_t *map_globals; -static py_map_t map_builtins; - -py_map_t *rt_get_map_locals(void) { - return map_locals; -} - -void rt_set_map_locals(py_map_t *m) { - map_locals = m; -} - -static bool fit_small_int(py_small_int_t o) { - return true; -} - -int rt_is_true(py_obj_t arg) { - DEBUG_OP_printf("is true %p\n", arg); - if (IS_SMALL_INT(arg)) { - if (FROM_SMALL_INT(arg) == 0) { - return 0; - } else { - return 1; - } - } else if (arg == py_const_none) { - return 0; - } else if (arg == py_const_false) { - return 0; - } else if (arg == py_const_true) { - return 1; - } else { - assert(0); - return 0; - } -} - -void vstr_printf_wrapper(void *env, const char *fmt, ...) { - va_list args; - va_start(args, fmt); - vstr_vprintf(env, fmt, args); - va_end(args); -} - -py_obj_t rt_str_join(py_obj_t self_in, py_obj_t arg) { - assert(IS_O(self_in, O_STR)); - py_obj_base_t *self = self_in; - int required_len = strlen(qstr_str(self->u_str)); - - // process arg, count required chars - if (!IS_O(arg, O_TUPLE) && !IS_O(arg, O_LIST)) { - goto bad_arg; - } - py_obj_base_t *tuple_list = arg; - for (int i = 0; i < tuple_list->u_tuple_list.len; i++) { - if (!IS_O(tuple_list->u_tuple_list.items[i], O_STR)) { - goto bad_arg; - } - required_len += strlen(qstr_str(((py_obj_base_t*)tuple_list->u_tuple_list.items[i])->u_str)); - } - - // make joined string - char *joined_str = m_new(char, required_len + 1); - joined_str[0] = 0; - for (int i = 0; i < tuple_list->u_tuple_list.len; i++) { - const char *s2 = qstr_str(((py_obj_base_t*)tuple_list->u_tuple_list.items[i])->u_str); - if (i > 0) { - strcat(joined_str, qstr_str(self->u_str)); - } - strcat(joined_str, s2); - } - return py_obj_new_str(qstr_from_str_take(joined_str)); - -bad_arg: - nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "?str.join expecting a list of str's", NULL, NULL)); -} - -py_obj_t rt_str_format(int n_args, const py_obj_t *args) { - assert(IS_O(args[0], O_STR)); - py_obj_base_t *self = args[0]; - - const char *str = qstr_str(self->u_str); - int arg_i = 1; - vstr_t *vstr = vstr_new(); - for (; *str; str++) { - if (*str == '{') { - str++; - if (*str == '{') { - vstr_add_char(vstr, '{'); - } else if (*str == '}') { - if (arg_i >= n_args) { - nlr_jump(py_obj_new_exception_2(rt_q_IndexError, "tuple index out of range", NULL, NULL)); - } - py_obj_print_helper(vstr_printf_wrapper, vstr, args[arg_i]); - arg_i++; - } - } else { - vstr_add_char(vstr, *str); - } - } - - return py_obj_new_str(qstr_from_str_take(vstr->buf)); -} - -uint get_index(py_obj_base_t *base, py_obj_t index) { - // assumes base is O_TUPLE or O_LIST - // TODO False and True are considered 0 and 1 for indexing purposes - int len = base->u_tuple_list.len; - if (IS_SMALL_INT(index)) { - int i = FROM_SMALL_INT(index); - if (i < 0) { - i += len; - } - if (i < 0 || i >= len) { - nlr_jump(py_obj_new_exception_2(rt_q_IndexError, "%s index out of range", py_obj_get_type_str(base), NULL)); - } - return i; - } else { - nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "%s indices must be integers, not %s", py_obj_get_type_str(base), py_obj_get_type_str(index))); - } -} - -py_obj_t rt_list_append(py_obj_t self_in, py_obj_t arg) { - assert(IS_O(self_in, O_LIST)); - py_obj_base_t *self = self_in; - if (self->u_tuple_list.len >= self->u_tuple_list.alloc) { - self->u_tuple_list.alloc *= 2; - self->u_tuple_list.items = m_renew(py_obj_t, self->u_tuple_list.items, self->u_tuple_list.alloc); - } - self->u_tuple_list.items[self->u_tuple_list.len++] = arg; - return py_const_none; // return None, as per CPython -} - -py_obj_t rt_list_pop(py_obj_t self_in, py_obj_t arg) { - assert(IS_O(self_in, O_LIST)); - py_obj_base_t *self = self_in; - uint index = get_index(self, arg); - py_obj_t ret = self->u_tuple_list.items[index]; - self->u_tuple_list.len -= 1; - memcpy(self->u_tuple_list.items + index, self->u_tuple_list.items + index + 1, (self->u_tuple_list.len - index) * sizeof(py_obj_t)); - return ret; -} - -// TODO make this conform to CPython's definition of sort -static void py_quicksort(py_obj_t *head, py_obj_t *tail, py_obj_t key_fn) { - while (head < tail) { - py_obj_t *h = head - 1; - py_obj_t *t = tail; - py_obj_t v = rt_call_function_1(key_fn, tail[0]); // get pivot using key_fn - for (;;) { - do ++h; while (rt_compare_op(RT_COMPARE_OP_LESS, rt_call_function_1(key_fn, h[0]), v) == py_const_true); - do --t; while (h < t && rt_compare_op(RT_COMPARE_OP_LESS, v, rt_call_function_1(key_fn, t[0])) == py_const_true); - if (h >= t) break; - py_obj_t x = h[0]; - h[0] = t[0]; - t[0] = x; - } - py_obj_t x = h[0]; - h[0] = tail[0]; - tail[0] = x; - py_quicksort(head, t, key_fn); - head = h + 1; - } -} - -py_obj_t rt_list_sort(py_obj_t self_in, py_obj_t key_fn) { - assert(IS_O(self_in, O_LIST)); - py_obj_base_t *self = self_in; - if (self->u_tuple_list.len > 1) { - py_quicksort(self->u_tuple_list.items, self->u_tuple_list.items + self->u_tuple_list.len - 1, key_fn); - } - return py_const_none; // return None, as per CPython -} - -py_obj_t rt_gen_instance_next(py_obj_t self_in) { - py_obj_t ret = rt_iternext(self_in); - if (ret == py_const_stop_iteration) { - nlr_jump(py_obj_new_exception_0(qstr_from_str_static("StopIteration"))); - } else { - return ret; - } -} +static mp_map_t *map_locals; +static mp_map_t *map_globals; +static mp_map_t map_builtins; typedef enum { - PY_CODE_NONE, - PY_CODE_BYTE, - PY_CODE_NATIVE, - PY_CODE_INLINE_ASM, -} py_code_kind_t; - -typedef struct _py_code_t { - py_code_kind_t kind; + MP_CODE_NONE, + MP_CODE_BYTE, + MP_CODE_NATIVE, + MP_CODE_INLINE_ASM, +} mp_code_kind_t; + +typedef struct _mp_code_t { + mp_code_kind_t kind; int n_args; int n_locals; int n_cells; @@ -254,23 +68,16 @@ typedef struct _py_code_t { uint len; } u_byte; struct { - py_fun_t fun; + mp_fun_t fun; } u_native; struct { void *fun; } u_inline_asm; }; -} py_code_t; +} mp_code_t; static int next_unique_code_id; -static py_code_t *unique_codes; - -py_obj_t fun_str_join; -py_obj_t fun_str_format; -py_obj_t fun_list_append; -py_obj_t fun_list_pop; -py_obj_t fun_list_sort; -py_obj_t fun_gen_instance_next; +static mp_code_t *unique_codes; #ifdef WRITE_CODE FILE *fp_write_code = NULL; @@ -292,50 +99,41 @@ void rt_init(void) { rt_q_SyntaxError = qstr_from_str_static("SyntaxError"); rt_q_ValueError = qstr_from_str_static("ValueError"); - py_const_none = py_obj_new_const("None"); - py_const_false = py_obj_new_const("False"); - py_const_true = py_obj_new_const("True"); - py_const_stop_iteration = py_obj_new_const("StopIteration"); - // locals = globals for outer module (see Objects/frameobject.c/PyFrame_New()) - map_locals = map_globals = py_map_new(MAP_QSTR, 1); - py_qstr_map_lookup(map_globals, qstr_from_str_static("__name__"), true)->value = py_obj_new_str(qstr_from_str_static("__main__")); - - py_map_init(&map_builtins, MAP_QSTR, 3); - py_qstr_map_lookup(&map_builtins, rt_q___build_class__, true)->value = rt_make_function_2(py_builtin___build_class__); - py_qstr_map_lookup(&map_builtins, qstr_from_str_static("__repl_print__"), true)->value = rt_make_function_1(py_builtin___repl_print__); - py_qstr_map_lookup(&map_builtins, qstr_from_str_static("abs"), true)->value = rt_make_function_1(py_builtin_abs); - py_qstr_map_lookup(&map_builtins, qstr_from_str_static("all"), true)->value = rt_make_function_1(py_builtin_all); - py_qstr_map_lookup(&map_builtins, qstr_from_str_static("any"), true)->value = rt_make_function_1(py_builtin_any); - py_qstr_map_lookup(&map_builtins, qstr_from_str_static("bool"), true)->value = rt_make_function_var(0, py_builtin_bool); - py_qstr_map_lookup(&map_builtins, qstr_from_str_static("callable"), true)->value = rt_make_function_1(py_builtin_callable); - py_qstr_map_lookup(&map_builtins, qstr_from_str_static("complex"), true)->value = rt_make_function_var(0, py_builtin_complex); - py_qstr_map_lookup(&map_builtins, qstr_from_str_static("chr"), true)->value = rt_make_function_1(py_builtin_chr); - py_qstr_map_lookup(&map_builtins, qstr_from_str_static("dict"), true)->value = rt_make_function_0(py_builtin_dict); - py_qstr_map_lookup(&map_builtins, qstr_from_str_static("divmod"), true)->value = rt_make_function_2(py_builtin_divmod); - py_qstr_map_lookup(&map_builtins, qstr_from_str_static("hash"), true)->value = rt_make_function_1(py_builtin_hash); - py_qstr_map_lookup(&map_builtins, qstr_from_str_static("iter"), true)->value = rt_make_function_1(py_builtin_iter); - py_qstr_map_lookup(&map_builtins, qstr_from_str_static("len"), true)->value = rt_make_function_1(py_builtin_len); - py_qstr_map_lookup(&map_builtins, qstr_from_str_static("list"), true)->value = rt_make_function_var(0, py_builtin_list); - py_qstr_map_lookup(&map_builtins, qstr_from_str_static("max"), true)->value = rt_make_function_var(1, py_builtin_max); - py_qstr_map_lookup(&map_builtins, qstr_from_str_static("min"), true)->value = rt_make_function_var(1, py_builtin_min); - py_qstr_map_lookup(&map_builtins, qstr_from_str_static("next"), true)->value = rt_make_function_1(py_builtin_next); - py_qstr_map_lookup(&map_builtins, qstr_from_str_static("ord"), true)->value = rt_make_function_1(py_builtin_ord); - py_qstr_map_lookup(&map_builtins, qstr_from_str_static("pow"), true)->value = rt_make_function_var(2, py_builtin_pow); - py_qstr_map_lookup(&map_builtins, qstr_from_str_static("print"), true)->value = rt_make_function_var(0, py_builtin_print); - py_qstr_map_lookup(&map_builtins, qstr_from_str_static("range"), true)->value = rt_make_function_var(1, py_builtin_range); - py_qstr_map_lookup(&map_builtins, qstr_from_str_static("sum"), true)->value = rt_make_function_var(1, py_builtin_sum); + map_locals = map_globals = mp_map_new(MP_MAP_QSTR, 1); + mp_qstr_map_lookup(map_globals, qstr_from_str_static("__name__"), true)->value = mp_obj_new_str(qstr_from_str_static("__main__")); + + mp_map_init(&map_builtins, MP_MAP_QSTR, 3); + mp_qstr_map_lookup(&map_builtins, rt_q___build_class__, true)->value = rt_make_function_2(mp_builtin___build_class__); + mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("__repl_print__"), true)->value = rt_make_function_1(mp_builtin___repl_print__); + mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("abs"), true)->value = rt_make_function_1(mp_builtin_abs); + mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("all"), true)->value = rt_make_function_1(mp_builtin_all); + mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("any"), true)->value = rt_make_function_1(mp_builtin_any); + mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("bool"), true)->value = rt_make_function_var(0, mp_builtin_bool); + mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("callable"), true)->value = rt_make_function_1(mp_builtin_callable); +#if MICROPY_ENABLE_FLOAT + mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("complex"), true)->value = rt_make_function_var(0, mp_builtin_complex); +#endif + mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("chr"), true)->value = rt_make_function_1(mp_builtin_chr); + mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("dict"), true)->value = rt_make_function_0(mp_builtin_dict); + mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("divmod"), true)->value = rt_make_function_2(mp_builtin_divmod); + mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("hash"), true)->value = (mp_obj_t)&mp_builtin_hash_obj; + mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("iter"), true)->value = (mp_obj_t)&mp_builtin_iter_obj; + mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("len"), true)->value = rt_make_function_1(mp_builtin_len); + mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("list"), true)->value = rt_make_function_var(0, mp_builtin_list); + mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("max"), true)->value = rt_make_function_var(1, mp_builtin_max); + mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("min"), true)->value = rt_make_function_var(1, mp_builtin_min); + mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("next"), true)->value = (mp_obj_t)&mp_builtin_next_obj; + mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("ord"), true)->value = rt_make_function_1(mp_builtin_ord); + mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("pow"), true)->value = rt_make_function_var(2, mp_builtin_pow); + mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("print"), true)->value = rt_make_function_var(0, mp_builtin_print); + mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("range"), true)->value = rt_make_function_var(1, mp_builtin_range); + mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("set"), true)->value = (mp_obj_t)&mp_builtin_set_obj; + mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("sum"), true)->value = rt_make_function_var(1, mp_builtin_sum); next_unique_code_id = 2; // 1 is reserved for the __main__ module scope unique_codes = NULL; - fun_str_join = rt_make_function_2(rt_str_join); - fun_str_format = rt_make_function_var(1, rt_str_format); - fun_list_append = rt_make_function_2(rt_list_append); - fun_list_pop = rt_make_function_2(rt_list_pop); - fun_list_sort = rt_make_function_2(rt_list_sort); - fun_gen_instance_next = rt_make_function_1(rt_gen_instance_next); - #ifdef WRITE_CODE fp_write_code = fopen("out-code", "wb"); #endif @@ -359,9 +157,9 @@ int rt_get_unique_code_id(bool is_main_module) { static void alloc_unique_codes(void) { if (unique_codes == NULL) { - unique_codes = m_new(py_code_t, next_unique_code_id + 10); // XXX hack until we fix the REPL allocation problem + unique_codes = m_new(mp_code_t, next_unique_code_id + 10); // XXX hack until we fix the REPL allocation problem for (int i = 0; i < next_unique_code_id; i++) { - unique_codes[i].kind = PY_CODE_NONE; + unique_codes[i].kind = MP_CODE_NONE; } } } @@ -370,7 +168,7 @@ void rt_assign_byte_code(int unique_code_id, byte *code, uint len, int n_args, i alloc_unique_codes(); assert(unique_code_id < next_unique_code_id); - unique_codes[unique_code_id].kind = PY_CODE_BYTE; + unique_codes[unique_code_id].kind = MP_CODE_BYTE; unique_codes[unique_code_id].n_args = n_args; unique_codes[unique_code_id].n_locals = n_locals; unique_codes[unique_code_id].n_cells = n_cells; @@ -390,8 +188,8 @@ void rt_assign_byte_code(int unique_code_id, byte *code, uint len, int n_args, i DEBUG_printf(" %02x", code[i]); } DEBUG_printf("\n"); - extern void py_show_byte_code(const byte *code, int len); - py_show_byte_code(code, len); + extern void mp_show_byte_code(const byte *code, int len); + mp_show_byte_code(code, len); #ifdef WRITE_CODE if (fp_write_code != NULL) { @@ -402,11 +200,11 @@ void rt_assign_byte_code(int unique_code_id, byte *code, uint len, int n_args, i #endif } -void rt_assign_native_code(int unique_code_id, py_fun_t fun, uint len, int n_args) { +void rt_assign_native_code(int unique_code_id, void *fun, uint len, int n_args) { alloc_unique_codes(); assert(1 <= unique_code_id && unique_code_id < next_unique_code_id); - unique_codes[unique_code_id].kind = PY_CODE_NATIVE; + unique_codes[unique_code_id].kind = MP_CODE_NATIVE; unique_codes[unique_code_id].n_args = n_args; unique_codes[unique_code_id].n_locals = 0; unique_codes[unique_code_id].n_cells = 0; @@ -436,11 +234,11 @@ void rt_assign_native_code(int unique_code_id, py_fun_t fun, uint len, int n_arg #endif } -void rt_assign_inline_asm_code(int unique_code_id, py_fun_t fun, uint len, int n_args) { +void rt_assign_inline_asm_code(int unique_code_id, void *fun, uint len, int n_args) { alloc_unique_codes(); assert(1 <= unique_code_id && unique_code_id < next_unique_code_id); - unique_codes[unique_code_id].kind = PY_CODE_INLINE_ASM; + unique_codes[unique_code_id].kind = MP_CODE_INLINE_ASM; unique_codes[unique_code_id].n_args = n_args; unique_codes[unique_code_id].n_locals = 0; unique_codes[unique_code_id].n_cells = 0; @@ -467,16 +265,52 @@ void rt_assign_inline_asm_code(int unique_code_id, py_fun_t fun, uint len, int n #endif } +mp_map_t *rt_get_map_locals(void) { + return map_locals; +} + +void rt_set_map_locals(mp_map_t *m) { + map_locals = m; +} + +static bool fit_small_int(mp_small_int_t o) { + return true; +} + +int rt_is_true(mp_obj_t arg) { + DEBUG_OP_printf("is true %p\n", arg); + if (MP_OBJ_IS_SMALL_INT(arg)) { + if (MP_OBJ_SMALL_INT_VALUE(arg) == 0) { + return 0; + } else { + return 1; + } + } else if (arg == mp_const_none) { + return 0; + } else if (arg == mp_const_false) { + return 0; + } else if (arg == mp_const_true) { + return 1; + } else { + assert(0); + return 0; + } +} + +mp_obj_t rt_list_append(mp_obj_t self_in, mp_obj_t arg) { + return mp_obj_list_append(self_in, arg); +} + #define PARSE_DEC_IN_INTG (1) #define PARSE_DEC_IN_FRAC (2) #define PARSE_DEC_IN_EXP (3) -py_obj_t rt_load_const_dec(qstr qstr) { +mp_obj_t rt_load_const_dec(qstr qstr) { #if MICROPY_ENABLE_FLOAT DEBUG_OP_printf("load '%s'\n", qstr_str(qstr)); const char *s = qstr_str(qstr); int in = PARSE_DEC_IN_INTG; - py_float_t dec_val = 0; + mp_float_t dec_val = 0; bool exp_neg = false; int exp_val = 0; int exp_extra = 0; @@ -513,7 +347,7 @@ py_obj_t rt_load_const_dec(qstr qstr) { } } if (*s != 0) { - nlr_jump(py_obj_new_exception_2(rt_q_SyntaxError, "invalid syntax for number", NULL, NULL)); + nlr_jump(mp_obj_new_exception_msg(rt_q_SyntaxError, "invalid syntax for number")); } if (exp_neg) { exp_val = -exp_val; @@ -526,52 +360,52 @@ py_obj_t rt_load_const_dec(qstr qstr) { dec_val *= 0.1; } if (imag) { - return py_obj_new_complex(0, dec_val); + return mp_obj_new_complex(0, dec_val); } else { - return py_obj_new_float(dec_val); + return mp_obj_new_float(dec_val); } #else - nlr_jump(py_obj_new_exception_2(rt_q_SyntaxError, "decimal numbers not supported", NULL, NULL)); + nlr_jump(mp_obj_new_exception_msg(rt_q_SyntaxError, "decimal numbers not supported")); #endif } -py_obj_t rt_load_const_str(qstr qstr) { +mp_obj_t rt_load_const_str(qstr qstr) { DEBUG_OP_printf("load '%s'\n", qstr_str(qstr)); - return py_obj_new_str(qstr); + return mp_obj_new_str(qstr); } -py_obj_t rt_load_name(qstr qstr) { +mp_obj_t rt_load_name(qstr qstr) { // logic: search locals, globals, builtins DEBUG_OP_printf("load name %s\n", qstr_str(qstr)); - py_map_elem_t *elem = py_qstr_map_lookup(map_locals, qstr, false); + mp_map_elem_t *elem = mp_qstr_map_lookup(map_locals, qstr, false); if (elem == NULL) { - elem = py_qstr_map_lookup(map_globals, qstr, false); + elem = mp_qstr_map_lookup(map_globals, qstr, false); if (elem == NULL) { - elem = py_qstr_map_lookup(&map_builtins, qstr, false); + elem = mp_qstr_map_lookup(&map_builtins, qstr, false); if (elem == NULL) { - nlr_jump(py_obj_new_exception_2(rt_q_NameError, "name '%s' is not defined", qstr_str(qstr), NULL)); + nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_NameError, "name '%s' is not defined", qstr_str(qstr))); } } } return elem->value; } -py_obj_t rt_load_global(qstr qstr) { +mp_obj_t rt_load_global(qstr qstr) { // logic: search globals, builtins DEBUG_OP_printf("load global %s\n", qstr_str(qstr)); - py_map_elem_t *elem = py_qstr_map_lookup(map_globals, qstr, false); + mp_map_elem_t *elem = mp_qstr_map_lookup(map_globals, qstr, false); if (elem == NULL) { - elem = py_qstr_map_lookup(&map_builtins, qstr, false); + elem = mp_qstr_map_lookup(&map_builtins, qstr, false); if (elem == NULL) { - nlr_jump(py_obj_new_exception_2(rt_q_NameError, "name '%s' is not defined", qstr_str(qstr), NULL)); + nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_NameError, "name '%s' is not defined", qstr_str(qstr))); } } return elem->value; } -py_obj_t rt_load_build_class(void) { +mp_obj_t rt_load_build_class(void) { DEBUG_OP_printf("load_build_class\n"); - py_map_elem_t *elem = py_qstr_map_lookup(&map_builtins, rt_q___build_class__, false); + mp_map_elem_t *elem = mp_qstr_map_lookup(&map_builtins, rt_q___build_class__, false); if (elem == NULL) { printf("name doesn't exist: __build_class__\n"); assert(0); @@ -579,97 +413,60 @@ py_obj_t rt_load_build_class(void) { return elem->value; } -py_obj_t rt_new_cell(py_obj_t val) { - py_obj_base_t *o = m_new(py_obj_base_t, 1); - o->kind = O_CELL; - o->u_cell = val; - return (py_obj_t)o; -} - -py_obj_t rt_get_cell(py_obj_t cell) { - if (IS_O(cell, O_CELL)) { - return ((py_obj_base_t*)cell)->u_cell; - } else { - assert(0); - return py_const_none; - } +mp_obj_t rt_get_cell(mp_obj_t cell) { + return mp_obj_cell_get(cell); } -void rt_set_cell(py_obj_t cell, py_obj_t val) { - if (IS_O(cell, O_CELL)) { - ((py_obj_base_t*)cell)->u_cell = val; - } else { - assert(0); - } +void rt_set_cell(mp_obj_t cell, mp_obj_t val) { + mp_obj_cell_set(cell, val); } -void rt_store_name(qstr qstr, py_obj_t obj) { +void rt_store_name(qstr qstr, mp_obj_t obj) { DEBUG_OP_printf("store name %s <- %p\n", qstr_str(qstr), obj); - py_qstr_map_lookup(map_locals, qstr, true)->value = obj; + mp_qstr_map_lookup(map_locals, qstr, true)->value = obj; } -void rt_store_global(qstr qstr, py_obj_t obj) { +void rt_store_global(qstr qstr, mp_obj_t obj) { DEBUG_OP_printf("store global %s <- %p\n", qstr_str(qstr), obj); - py_qstr_map_lookup(map_globals, qstr, true)->value = obj; + mp_qstr_map_lookup(map_globals, qstr, true)->value = obj; } -py_obj_t rt_unary_op(int op, py_obj_t arg) { +mp_obj_t rt_unary_op(int op, mp_obj_t arg) { DEBUG_OP_printf("unary %d %p\n", op, arg); - if (IS_SMALL_INT(arg)) { - py_small_int_t val = FROM_SMALL_INT(arg); + if (MP_OBJ_IS_SMALL_INT(arg)) { + mp_small_int_t val = MP_OBJ_SMALL_INT_VALUE(arg); switch (op) { - case RT_UNARY_OP_NOT: if (val != 0) { return py_const_true;} else { return py_const_false; } + case RT_UNARY_OP_NOT: if (val != 0) { return mp_const_true;} else { return mp_const_false; } case RT_UNARY_OP_POSITIVE: break; case RT_UNARY_OP_NEGATIVE: val = -val; break; case RT_UNARY_OP_INVERT: val = ~val; break; default: assert(0); val = 0; } if (fit_small_int(val)) { - return TO_SMALL_INT(val); - } -#if MICROPY_ENABLE_FLOAT - } else if (IS_O(arg, O_FLOAT)) { - py_float_t val = py_obj_get_float(arg); - switch (op) { - case RT_UNARY_OP_NOT: if (val != 0) { return py_const_true;} else { return py_const_false; } - case RT_UNARY_OP_POSITIVE: break; - case RT_UNARY_OP_NEGATIVE: val = -val; break; - case RT_UNARY_OP_INVERT: nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "bad operand type for unary ~: 'float'", NULL, NULL)); - default: assert(0); val = 0; + return MP_OBJ_NEW_SMALL_INT(val); + } else { + // TODO make a bignum + assert(0); + return mp_const_none; + } + } else { // will be an object (small ints are caught in previous if) + mp_obj_base_t *o = arg; + if (o->type->unary_op != NULL) { + mp_obj_t result = o->type->unary_op(op, arg); + if (result != NULL) { + return result; + } } - return py_obj_new_float(val); -#endif + // TODO specify in error message what the operator is + nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "bad operand type for unary operator: '%s'", o->type->name)); } - assert(0); - return py_const_none; } -py_obj_t rt_binary_op(int op, py_obj_t lhs, py_obj_t rhs) { +mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { DEBUG_OP_printf("binary %d %p %p\n", op, lhs, rhs); - if (op == RT_BINARY_OP_SUBSCR) { - if (IS_O(lhs, O_STR)) { - // string access - // XXX a hack! - const char *str = qstr_str(((py_obj_base_t*)lhs)->u_str); - return py_obj_new_int(str[FROM_SMALL_INT(rhs)]); - } else if ((IS_O(lhs, O_TUPLE) || IS_O(lhs, O_LIST))) { - // tuple/list load - uint index = get_index(lhs, rhs); - return ((py_obj_base_t*)lhs)->u_tuple_list.items[index]; - } else if (IS_O(lhs, O_MAP)) { - // map load - py_map_elem_t *elem = py_map_lookup(lhs, rhs, false); - if (elem == NULL) { - nlr_jump(py_obj_new_exception_2(rt_q_KeyError, "<value>", NULL, NULL)); - } else { - return elem->value; - } - } else { - assert(0); - } - } else if (IS_SMALL_INT(lhs) && IS_SMALL_INT(rhs)) { - py_small_int_t lhs_val = FROM_SMALL_INT(lhs); - py_small_int_t rhs_val = FROM_SMALL_INT(rhs); + if (MP_OBJ_IS_SMALL_INT(lhs) && MP_OBJ_IS_SMALL_INT(rhs)) { + mp_small_int_t lhs_val = MP_OBJ_SMALL_INT_VALUE(lhs); + mp_small_int_t rhs_val = MP_OBJ_SMALL_INT_VALUE(rhs); switch (op) { case RT_BINARY_OP_OR: case RT_BINARY_OP_INPLACE_OR: lhs_val |= rhs_val; break; @@ -691,7 +488,7 @@ py_obj_t rt_binary_op(int op, py_obj_t lhs, py_obj_t rhs) { case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: lhs_val /= rhs_val; break; #if MICROPY_ENABLE_FLOAT case RT_BINARY_OP_TRUE_DIVIDE: - case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: return py_obj_new_float((py_float_t)lhs_val / (py_float_t)rhs_val); + case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: return mp_obj_new_float((mp_float_t)lhs_val / (mp_float_t)rhs_val); #endif // TODO implement modulo as specified by Python @@ -717,102 +514,46 @@ py_obj_t rt_binary_op(int op, py_obj_t lhs, py_obj_t rhs) { default: printf("%d\n", op); assert(0); } if (fit_small_int(lhs_val)) { - return TO_SMALL_INT(lhs_val); - } -#if MICROPY_ENABLE_FLOAT - } else if (IS_O(lhs, O_COMPLEX) || IS_O(rhs, O_COMPLEX)) { - py_float_t lhs_real, lhs_imag, rhs_real, rhs_imag; - py_obj_get_complex(lhs, &lhs_real, &lhs_imag); - py_obj_get_complex(rhs, &rhs_real, &rhs_imag); - switch (op) { - case RT_BINARY_OP_ADD: - case RT_BINARY_OP_INPLACE_ADD: - lhs_real += rhs_real; - lhs_imag += rhs_imag; - break; - case RT_BINARY_OP_SUBTRACT: - case RT_BINARY_OP_INPLACE_SUBTRACT: - lhs_real -= rhs_real; - lhs_imag -= rhs_imag; - break; - case RT_BINARY_OP_MULTIPLY: - case RT_BINARY_OP_INPLACE_MULTIPLY: - { - py_float_t real = lhs_real * rhs_real - lhs_imag * rhs_imag; - lhs_imag = lhs_real * rhs_imag + lhs_imag * rhs_real; - lhs_real = real; - break; + return MP_OBJ_NEW_SMALL_INT(lhs_val); + } + } else if (MP_OBJ_IS_OBJ(lhs)) { + mp_obj_base_t *o = lhs; + if (o->type->binary_op != NULL) { + mp_obj_t result = o->type->binary_op(op, lhs, rhs); + if (result != NULL) { + return result; } - /* TODO floor(?) the value - case RT_BINARY_OP_FLOOR_DIVIDE: - case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: val = lhs_val / rhs_val; break; - */ - /* TODO - case RT_BINARY_OP_TRUE_DIVIDE: - case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: val = lhs_val / rhs_val; break; - */ - default: printf("%d\n", op); assert(0); - } - return py_obj_new_complex(lhs_real, lhs_imag); - } else if (IS_O(lhs, O_FLOAT) || IS_O(rhs, O_FLOAT)) { - py_float_t lhs_val = py_obj_get_float(lhs); - py_float_t rhs_val = py_obj_get_float(rhs); - switch (op) { - case RT_BINARY_OP_ADD: - case RT_BINARY_OP_INPLACE_ADD: lhs_val += rhs_val; break; - case RT_BINARY_OP_SUBTRACT: - case RT_BINARY_OP_INPLACE_SUBTRACT: lhs_val -= rhs_val; break; - case RT_BINARY_OP_MULTIPLY: - case RT_BINARY_OP_INPLACE_MULTIPLY: lhs_val *= rhs_val; break; - /* TODO floor(?) the value - case RT_BINARY_OP_FLOOR_DIVIDE: - case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: val = lhs_val / rhs_val; break; - */ - case RT_BINARY_OP_TRUE_DIVIDE: - case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: lhs_val /= rhs_val; break; - default: printf("%d\n", op); assert(0); - } - return py_obj_new_float(lhs_val); -#endif - } else if (IS_O(lhs, O_STR) && IS_O(rhs, O_STR)) { - const char *lhs_str = qstr_str(((py_obj_base_t*)lhs)->u_str); - const char *rhs_str = qstr_str(((py_obj_base_t*)rhs)->u_str); - char *val; - switch (op) { - case RT_BINARY_OP_ADD: - case RT_BINARY_OP_INPLACE_ADD: val = m_new(char, strlen(lhs_str) + strlen(rhs_str) + 1); strcpy(val, lhs_str); strcat(val, rhs_str); break; - default: printf("%d\n", op); assert(0); val = NULL; } - return py_obj_new_str(qstr_from_str_take(val)); } - assert(0); - return py_const_none; + + // TODO specify in error message what the operator is + nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "unsupported operand type for binary operator: '%s'", mp_obj_get_type_str(lhs))); } -py_obj_t rt_compare_op(int op, py_obj_t lhs, py_obj_t rhs) { +mp_obj_t rt_compare_op(int op, mp_obj_t lhs, mp_obj_t rhs) { DEBUG_OP_printf("compare %d %p %p\n", op, lhs, rhs); // deal with == and != if (op == RT_COMPARE_OP_EQUAL || op == RT_COMPARE_OP_NOT_EQUAL) { - if (py_obj_equal(lhs, rhs)) { + if (mp_obj_equal(lhs, rhs)) { if (op == RT_COMPARE_OP_EQUAL) { - return py_const_true; + return mp_const_true; } else { - return py_const_false; + return mp_const_false; } } else { if (op == RT_COMPARE_OP_EQUAL) { - return py_const_false; + return mp_const_false; } else { - return py_const_true; + return mp_const_true; } } } // deal with small ints - if (IS_SMALL_INT(lhs) && IS_SMALL_INT(rhs)) { - py_small_int_t lhs_val = FROM_SMALL_INT(lhs); - py_small_int_t rhs_val = FROM_SMALL_INT(rhs); + if (MP_OBJ_IS_SMALL_INT(lhs) && MP_OBJ_IS_SMALL_INT(rhs)) { + mp_small_int_t lhs_val = MP_OBJ_SMALL_INT_VALUE(lhs); + mp_small_int_t rhs_val = MP_OBJ_SMALL_INT_VALUE(rhs); int cmp; switch (op) { case RT_COMPARE_OP_LESS: cmp = lhs_val < rhs_val; break; @@ -822,17 +563,17 @@ py_obj_t rt_compare_op(int op, py_obj_t lhs, py_obj_t rhs) { default: assert(0); cmp = 0; } if (cmp) { - return py_const_true; + return mp_const_true; } else { - return py_const_false; + return mp_const_false; } } #if MICROPY_ENABLE_FLOAT // deal with floats - if (IS_O(lhs, O_FLOAT) || IS_O(rhs, O_FLOAT)) { - py_float_t lhs_val = py_obj_get_float(lhs); - py_float_t rhs_val = py_obj_get_float(rhs); + if (MP_OBJ_IS_TYPE(lhs, &float_type) || MP_OBJ_IS_TYPE(rhs, &float_type)) { + mp_float_t lhs_val = mp_obj_get_float(lhs); + mp_float_t rhs_val = mp_obj_get_float(rhs); int cmp; switch (op) { case RT_COMPARE_OP_LESS: cmp = lhs_val < rhs_val; break; @@ -842,666 +583,287 @@ py_obj_t rt_compare_op(int op, py_obj_t lhs, py_obj_t rhs) { default: assert(0); cmp = 0; } if (cmp) { - return py_const_true; + return mp_const_true; } else { - return py_const_false; + return mp_const_false; } } #endif // not implemented assert(0); - return py_const_none; + return mp_const_none; } -py_obj_t rt_make_function_from_id(int unique_code_id) { +mp_obj_t rt_make_function_from_id(int unique_code_id) { DEBUG_OP_printf("make_function_from_id %d\n", unique_code_id); if (unique_code_id < 1 || unique_code_id >= next_unique_code_id) { // illegal code id - return py_const_none; + return mp_const_none; } - py_code_t *c = &unique_codes[unique_code_id]; - py_obj_base_t *o = m_new(py_obj_base_t, 1); + + // make the function, depending on the code kind + mp_code_t *c = &unique_codes[unique_code_id]; + mp_obj_t fun; switch (c->kind) { - case PY_CODE_BYTE: - o->kind = O_FUN_BC; - o->u_fun_bc.n_args = c->n_args; - o->u_fun_bc.n_state = c->n_locals + c->n_cells + c->n_stack; - o->u_fun_bc.code = c->u_byte.code; + case MP_CODE_BYTE: + fun = mp_obj_new_fun_bc(c->n_args, c->n_locals + c->n_cells + c->n_stack, c->u_byte.code); break; - case PY_CODE_NATIVE: + case MP_CODE_NATIVE: switch (c->n_args) { - case 0: o->kind = O_FUN_0; break; - case 1: o->kind = O_FUN_1; break; - case 2: o->kind = O_FUN_2; break; - default: assert(0); + case 0: fun = rt_make_function_0(c->u_native.fun); break; + case 1: fun = rt_make_function_1((mp_fun_1_t)c->u_native.fun); break; + case 2: fun = rt_make_function_2((mp_fun_2_t)c->u_native.fun); break; + default: assert(0); fun = mp_const_none; } - o->u_fun.fun = c->u_native.fun; break; - case PY_CODE_INLINE_ASM: - o->kind = O_FUN_ASM; - o->u_fun_asm.n_args = c->n_args; - o->u_fun_asm.fun = c->u_inline_asm.fun; + case MP_CODE_INLINE_ASM: + fun = mp_obj_new_fun_asm(c->n_args, c->u_inline_asm.fun); break; default: assert(0); + fun = mp_const_none; } // check for generator functions and if so wrap in generator object if (c->is_generator) { - py_obj_base_t *o2 = m_new(py_obj_base_t, 1); - o2->kind = O_GEN_WRAP; - // we have at least 3 locals so the bc can write back fast[0,1,2] safely; should improve how this is done - o2->u_gen_wrap.n_state = ((c->n_locals + c->n_cells) < 3 ? 3 : (c->n_locals + c->n_cells)) + c->n_stack; - o2->u_gen_wrap.fun = o; - o = o2; + fun = mp_obj_new_gen_wrap(c->n_locals, c->n_cells, c->n_stack, fun); } - return o; -} - -py_obj_t rt_make_function_0(py_fun_0_t fun) { - py_obj_base_t *o = m_new(py_obj_base_t, 1); - o->kind = O_FUN_0; - o->u_fun.fun = fun; - return o; + return fun; } -py_obj_t rt_make_function_1(py_fun_1_t fun) { - py_obj_base_t *o = m_new(py_obj_base_t, 1); - o->kind = O_FUN_1; - o->u_fun.fun = fun; - return o; -} - -py_obj_t rt_make_function_2(py_fun_2_t fun) { - py_obj_base_t *o = m_new(py_obj_base_t, 1); - o->kind = O_FUN_2; - o->u_fun.fun = fun; - return o; -} - -py_obj_t rt_make_function(int n_args, py_fun_t code) { - // assumes code is a pointer to a py_fun_t (i think this is safe...) - py_obj_base_t *o = m_new(py_obj_base_t, 1); - o->kind = O_FUN_N; - o->u_fun.n_args = n_args; - o->u_fun.fun = code; - return o; -} - -py_obj_t rt_make_function_var(int n_fixed_args, py_fun_var_t f) { - py_obj_base_t *o = m_new(py_obj_base_t, 1); - o->kind = O_FUN_VAR; - o->u_fun.n_args = n_fixed_args; - o->u_fun.fun = f; - return o; -} - -py_obj_t rt_make_closure_from_id(int unique_code_id, py_obj_t closure_tuple) { - py_obj_t f = rt_make_function_from_id(unique_code_id); +mp_obj_t rt_make_closure_from_id(int unique_code_id, mp_obj_t closure_tuple) { + // make function object + mp_obj_t ffun = rt_make_function_from_id(unique_code_id); // wrap function in closure object - py_obj_base_t *f2 = m_new(py_obj_base_t, 1); - f2->kind = O_CLOSURE; - f2->u_closure.fun = f; - f2->u_closure.vars = closure_tuple; - return f2; + return mp_obj_new_closure(ffun, closure_tuple); } -py_obj_t rt_call_function_0(py_obj_t fun) { +mp_obj_t rt_call_function_0(mp_obj_t fun) { return rt_call_function_n(fun, 0, NULL); } -py_obj_t rt_call_function_1(py_obj_t fun, py_obj_t arg) { +mp_obj_t rt_call_function_1(mp_obj_t fun, mp_obj_t arg) { return rt_call_function_n(fun, 1, &arg); } -py_obj_t rt_call_function_2(py_obj_t fun, py_obj_t arg1, py_obj_t arg2) { - py_obj_t args[2]; +mp_obj_t rt_call_function_2(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2) { + mp_obj_t args[2]; args[1] = arg1; args[0] = arg2; return rt_call_function_n(fun, 2, args); } -typedef machine_uint_t (*inline_asm_fun_0_t)(); -typedef machine_uint_t (*inline_asm_fun_1_t)(machine_uint_t); -typedef machine_uint_t (*inline_asm_fun_2_t)(machine_uint_t, machine_uint_t); -typedef machine_uint_t (*inline_asm_fun_3_t)(machine_uint_t, machine_uint_t, machine_uint_t); - -// convert a Python object to a sensible value for inline asm -machine_uint_t rt_convert_obj_for_inline_asm(py_obj_t obj) { - // TODO for byte_array, pass pointer to the array - if (IS_SMALL_INT(obj)) { - return FROM_SMALL_INT(obj); - } else if (obj == py_const_none) { - return 0; - } else if (obj == py_const_false) { - return 0; - } else if (obj == py_const_true) { - return 1; - } else { - py_obj_base_t *o = obj; - switch (o->kind) { - case O_STR: - // pointer to the string (it's probably constant though!) - return (machine_uint_t)qstr_str(o->u_str); - -#if MICROPY_ENABLE_FLOAT - case O_FLOAT: - // convert float to int (could also pass in float registers) - return (machine_int_t)o->u_float; -#endif - - case O_TUPLE: - case O_LIST: - // pointer to start of tuple/list (could pass length, but then could use len(x) for that) - return (machine_uint_t)o->u_tuple_list.items; - - default: - // just pass along a pointer to the object - return (machine_uint_t)obj; - } - } -} - -// convert a return value from inline asm to a sensible Python object -py_obj_t rt_convert_val_from_inline_asm(machine_uint_t val) { - return TO_SMALL_INT(val); -} - // args are in reverse order in the array -py_obj_t rt_call_function_n(py_obj_t fun, int n_args, const py_obj_t *args) { - int n_args_fun = 0; - if (IS_O(fun, O_FUN_0)) { - py_obj_base_t *o = fun; - if (n_args != 0) { - n_args_fun = 0; - goto bad_n_args; - } - DEBUG_OP_printf("calling native %p()\n", o->u_fun.fun); - return ((py_fun_0_t)o->u_fun.fun)(); - - } else if (IS_O(fun, O_FUN_1)) { - py_obj_base_t *o = fun; - if (n_args != 1) { - n_args_fun = 1; - goto bad_n_args; - } - DEBUG_OP_printf("calling native %p(%p)\n", o->u_fun.fun, args[0]); - return ((py_fun_1_t)o->u_fun.fun)(args[0]); - - } else if (IS_O(fun, O_FUN_2)) { - py_obj_base_t *o = fun; - if (n_args != 2) { - n_args_fun = 2; - goto bad_n_args; - } - DEBUG_OP_printf("calling native %p(%p, %p)\n", o->u_fun.fun, args[1], args[0]); - return ((py_fun_2_t)o->u_fun.fun)(args[1], args[0]); - - // TODO O_FUN_N - - } else if (IS_O(fun, O_FUN_VAR)) { - py_obj_base_t *o = fun; - if (n_args < o->u_fun.n_args) { - nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "<fun name>() missing %d required positional arguments: <list of names of params>", (const char*)(machine_int_t)(o->u_fun.n_args - n_args), NULL)); - } - // TODO really the args need to be passed in as a Python tuple, as the form f(*[1,2]) can be used to pass var args - py_obj_t *args_ordered = m_new(py_obj_t, n_args); - for (int i = 0; i < n_args; i++) { - args_ordered[i] = args[n_args - i - 1]; - } - py_obj_t res = ((py_fun_var_t)o->u_fun.fun)(n_args, args_ordered); - m_free(args_ordered); - return res; - - } else if (IS_O(fun, O_FUN_BC)) { - py_obj_base_t *o = fun; - if (n_args != o->u_fun_bc.n_args) { - n_args_fun = o->u_fun_bc.n_args; - goto bad_n_args; - } - DEBUG_OP_printf("calling byte code %p(n_args=%d)\n", o->u_fun_bc.code, n_args); - return py_execute_byte_code(o->u_fun_bc.code, args, n_args, o->u_fun_bc.n_state); - - } else if (IS_O(fun, O_FUN_ASM)) { - py_obj_base_t *o = fun; - if (n_args != o->u_fun_asm.n_args) { - n_args_fun = o->u_fun_asm.n_args; - goto bad_n_args; - } - DEBUG_OP_printf("calling inline asm %p(n_args=%d)\n", o->u_fun_asm.fun, n_args); - machine_uint_t ret; - if (n_args == 0) { - ret = ((inline_asm_fun_0_t)o->u_fun_asm.fun)(); - } else if (n_args == 1) { - ret = ((inline_asm_fun_1_t)o->u_fun_asm.fun)(rt_convert_obj_for_inline_asm(args[0])); - } else if (n_args == 2) { - ret = ((inline_asm_fun_2_t)o->u_fun_asm.fun)(rt_convert_obj_for_inline_asm(args[1]), rt_convert_obj_for_inline_asm(args[0])); - } else if (n_args == 3) { - ret = ((inline_asm_fun_3_t)o->u_fun_asm.fun)(rt_convert_obj_for_inline_asm(args[2]), rt_convert_obj_for_inline_asm(args[1]), rt_convert_obj_for_inline_asm(args[0])); - } else { - assert(0); - ret = 0; - } - return rt_convert_val_from_inline_asm(ret); - - } else if (IS_O(fun, O_GEN_WRAP)) { - py_obj_base_t *o = fun; - py_obj_base_t *o_fun = o->u_gen_wrap.fun; - assert(o_fun->kind == O_FUN_BC); // TODO - if (n_args != o_fun->u_fun_bc.n_args) { - n_args_fun = o_fun->u_fun_bc.n_args; - goto bad_n_args; - } - py_obj_t *state = m_new(py_obj_t, 1 + o->u_gen_wrap.n_state); - // put function object at first slot in state (to keep u_gen_instance small) - state[0] = o_fun; - // init args - for (int i = 0; i < n_args; i++) { - state[1 + i] = args[n_args - 1 - i]; - } - py_obj_base_t *o2 = m_new(py_obj_base_t, 1); - o2->kind = O_GEN_INSTANCE; - o2->u_gen_instance.state = state; - o2->u_gen_instance.ip = o_fun->u_fun_bc.code; - o2->u_gen_instance.sp = state + o->u_gen_wrap.n_state; - return o2; - - } else if (IS_O(fun, O_BOUND_METH)) { - py_obj_base_t *o = fun; - DEBUG_OP_printf("calling bound method %p(self=%p, n_args=%d)\n", o->u_bound_meth.meth, o->u_bound_meth.self, n_args); - if (n_args == 0) { - return rt_call_function_n(o->u_bound_meth.meth, 1, &o->u_bound_meth.self); - } else if (n_args == 1) { - py_obj_t args2[2]; - args2[1] = o->u_bound_meth.self; - args2[0] = args[0]; - return rt_call_function_n(o->u_bound_meth.meth, 2, args2); - } else { - // TODO not implemented - assert(0); - return py_const_none; - //return rt_call_function_2(o->u_bound_meth.meth, n_args + 1, o->u_bound_meth.self + args); - } +mp_obj_t rt_call_function_n(mp_obj_t fun_in, int n_args, const mp_obj_t *args) { + // TODO improve this: fun object can specify its type and we parse here the arguments, + // passing to the function arrays of fixed and keyword arguments - } else if (IS_O(fun, O_CLASS)) { - // instantiate an instance of a class - - DEBUG_OP_printf("instantiate object of class %p with %d args\n", fun, n_args); - py_obj_base_t *o = m_new(py_obj_base_t, 1); - o->kind = O_OBJ; - o->u_obj.class = fun; - o->u_obj.members = py_map_new(MAP_QSTR, 0); - - // look for __init__ function - py_obj_base_t *o_class = fun; - py_map_elem_t *init_fn = py_qstr_map_lookup(o_class->u_class.locals, qstr_from_str_static("__init__"), false); - - if (init_fn != NULL) { - // call __init__ function - py_obj_t init_ret; - if (n_args == 0) { - init_ret = rt_call_function_n(init_fn->value, 1, (py_obj_t*)&o); - } else { - py_obj_t *args2 = m_new(py_obj_t, n_args + 1); - memcpy(args2, args, n_args * sizeof(py_obj_t)); - args2[n_args] = o; - init_ret = rt_call_function_n(init_fn->value, n_args + 1, args2); - m_free(args2); - } - if (init_ret != py_const_none) { - nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "__init__() should return None, not '%s'", py_obj_get_type_str(init_ret), NULL)); - } + DEBUG_OP_printf("calling function %p(n_args=%d, args=%p)\n", fun_in, n_args, args); + if (MP_OBJ_IS_SMALL_INT(fun_in)) { + nlr_jump(mp_obj_new_exception_msg(rt_q_TypeError, "'int' object is not callable")); + } else { + mp_obj_base_t *fun = fun_in; + if (fun->type->call_n != NULL) { + return fun->type->call_n(fun_in, n_args, args); } else { - // TODO - if (n_args != 0) { - n_args_fun = 0; - goto bad_n_args; - } + nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "'%s' object is not callable", fun->type->name)); } - - return o; - - } else { - printf("fun %p %d\n", fun, ((py_obj_base_t*)fun)->kind); - assert(0); - return py_const_none; } - -bad_n_args: - nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)n_args_fun, (const char*)(machine_int_t)n_args)); } // args are in reverse order in the array; keyword arguments come first, value then key // eg: (value1, key1, value0, key0, arg1, arg0) -py_obj_t rt_call_function_n_kw(py_obj_t fun, uint n_args, uint n_kw, const py_obj_t *args) { +mp_obj_t rt_call_function_n_kw(mp_obj_t fun, uint n_args, uint n_kw, const mp_obj_t *args) { // TODO assert(0); - return py_const_none; + return mp_const_none; } // args contains: arg(n_args-1) arg(n_args-2) ... arg(0) self/NULL fun // if n_args==0 then there are only self/NULL and fun -py_obj_t rt_call_method_n(uint n_args, const py_obj_t *args) { +mp_obj_t rt_call_method_n(uint n_args, const mp_obj_t *args) { DEBUG_OP_printf("call method %p(self=%p, n_args=%u)\n", args[n_args + 1], args[n_args], n_args); return rt_call_function_n(args[n_args + 1], n_args + ((args[n_args] == NULL) ? 0 : 1), args); } // args contains: kw_val(n_kw-1) kw_key(n_kw-1) ... kw_val(0) kw_key(0) arg(n_args-1) arg(n_args-2) ... arg(0) self/NULL fun -py_obj_t rt_call_method_n_kw(uint n_args, uint n_kw, const py_obj_t *args) { +mp_obj_t rt_call_method_n_kw(uint n_args, uint n_kw, const mp_obj_t *args) { uint n = n_args + 2 * n_kw; DEBUG_OP_printf("call method %p(self=%p, n_args=%u, n_kw=%u)\n", args[n + 1], args[n], n_args, n_kw); return rt_call_function_n_kw(args[n + 1], n_args + ((args[n] == NULL) ? 0 : 1), n_kw, args); } // items are in reverse order -py_obj_t rt_build_tuple(int n_args, py_obj_t *items) { - py_obj_base_t *o = m_new(py_obj_base_t, 1); - o->kind = O_TUPLE; - o->u_tuple_list.alloc = n_args < 4 ? 4 : n_args; - o->u_tuple_list.len = n_args; - o->u_tuple_list.items = m_new(py_obj_t, o->u_tuple_list.alloc); - for (int i = 0; i < n_args; i++) { - o->u_tuple_list.items[i] = items[n_args - i - 1]; - } - return o; +mp_obj_t rt_build_tuple(int n_args, mp_obj_t *items) { + return mp_obj_new_tuple_reverse(n_args, items); } // items are in reverse order -py_obj_t rt_build_list(int n_args, py_obj_t *items) { - py_obj_base_t *o = m_new(py_obj_base_t, 1); - o->kind = O_LIST; - o->u_tuple_list.alloc = n_args < 4 ? 4 : n_args; - o->u_tuple_list.len = n_args; - o->u_tuple_list.items = m_new(py_obj_t, o->u_tuple_list.alloc); - for (int i = 0; i < n_args; i++) { - o->u_tuple_list.items[i] = items[n_args - i - 1]; - } - return o; +mp_obj_t rt_build_list(int n_args, mp_obj_t *items) { + return mp_obj_new_list_reverse(n_args, items); } -py_obj_t rt_build_set(int n_args, py_obj_t *items) { - py_obj_base_t *o = m_new(py_obj_base_t, 1); - o->kind = O_SET; - o->u_set.alloc = get_doubling_prime_greater_or_equal_to(n_args + 1); - o->u_set.used = 0; - o->u_set.table = m_new(py_obj_t, o->u_set.alloc); - for (int i = 0; i < o->u_set.alloc; i++) { - o->u_set.table[i] = NULL; - } - for (int i = 0; i < n_args; i++) { - py_set_lookup(o, items[i], true); - } - return o; +mp_obj_t rt_build_set(int n_args, mp_obj_t *items) { + return mp_obj_new_set(n_args, items); } -py_obj_t rt_store_set(py_obj_t set, py_obj_t item) { - py_set_lookup(set, item, true); +mp_obj_t rt_store_set(mp_obj_t set, mp_obj_t item) { + mp_set_lookup(set, item, true); return set; } // unpacked items are stored in order into the array pointed to by items -void rt_unpack_sequence(py_obj_t seq_in, uint num, py_obj_t *items) { - if (IS_O(seq_in, O_TUPLE) || IS_O(seq_in, O_LIST)) { - py_obj_base_t *seq = seq_in; - if (seq->u_tuple_list.len < num) { - nlr_jump(py_obj_new_exception_2(rt_q_ValueError, "need more than %d values to unpack", (void*)seq->u_tuple_list.len, NULL)); - } else if (seq->u_tuple_list.len > num) { - nlr_jump(py_obj_new_exception_2(rt_q_ValueError, "too many values to unpack (expected %d)", (void*)(machine_uint_t)num, NULL)); +void rt_unpack_sequence(mp_obj_t seq_in, uint num, mp_obj_t *items) { + if (MP_OBJ_IS_TYPE(seq_in, &tuple_type) || MP_OBJ_IS_TYPE(seq_in, &list_type)) { + uint seq_len; + mp_obj_t *seq_items; + if (MP_OBJ_IS_TYPE(seq_in, &tuple_type)) { + mp_obj_tuple_get(seq_in, &seq_len, &seq_items); + } else { + mp_obj_list_get(seq_in, &seq_len, &seq_items); } - memcpy(items, seq->u_tuple_list.items, num * sizeof(py_obj_t)); + if (seq_len < num) { + nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_ValueError, "need more than %d values to unpack", (void*)(machine_uint_t)seq_len)); + } else if (seq_len > num) { + nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_ValueError, "too many values to unpack (expected %d)", (void*)(machine_uint_t)num)); + } + memcpy(items, seq_items, num * sizeof(mp_obj_t)); } else { // TODO call rt_getiter and extract via rt_iternext - nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "'%s' object is not iterable", py_obj_get_type_str(seq_in), NULL)); + nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "'%s' object is not iterable", mp_obj_get_type_str(seq_in))); } } -py_obj_t rt_build_map(int n_args) { - py_obj_base_t *o = m_new(py_obj_base_t, 1); - o->kind = O_MAP; - py_map_init(&o->u_map, MAP_PY_OBJ, n_args); - return o; -} - -py_obj_t rt_store_map(py_obj_t map, py_obj_t key, py_obj_t value) { - assert(IS_O(map, O_MAP)); // should always be - py_map_lookup(map, key, true)->value = value; - return map; +mp_obj_t rt_build_map(int n_args) { + return mp_obj_new_dict(n_args); } -py_obj_t build_bound_method(py_obj_t self, py_obj_t meth) { - py_obj_base_t *o = m_new(py_obj_base_t, 1); - o->kind = O_BOUND_METH; - o->u_bound_meth.meth = meth; - o->u_bound_meth.self = self; - return o; +mp_obj_t rt_store_map(mp_obj_t map, mp_obj_t key, mp_obj_t value) { + // map should always be a dict + return mp_obj_dict_store(map, key, value); } -py_obj_t rt_load_attr(py_obj_t base, qstr attr) { +mp_obj_t rt_load_attr(mp_obj_t base, qstr attr) { DEBUG_OP_printf("load attr %s\n", qstr_str(attr)); - if (IS_O(base, O_LIST) && attr == rt_q_append) { - return build_bound_method(base, fun_list_append); - } else if (IS_O(base, O_LIST) && attr == rt_q_pop) { - return build_bound_method(base, fun_list_pop); - } else if (IS_O(base, O_LIST) && attr == rt_q_sort) { - return build_bound_method(base, fun_list_sort); - } else if (IS_O(base, O_CLASS)) { - py_obj_base_t *o = base; - py_map_elem_t *elem = py_qstr_map_lookup(o->u_class.locals, attr, false); + if (MP_OBJ_IS_TYPE(base, &class_type)) { + mp_map_elem_t *elem = mp_qstr_map_lookup(mp_obj_class_get_locals(base), attr, false); if (elem == NULL) { - goto no_attr; + nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr))); } return elem->value; - } else if (IS_O(base, O_OBJ)) { - // logic: look in obj members then class locals (TODO check this against CPython) - py_obj_base_t *o = base; - py_map_elem_t *elem = py_qstr_map_lookup(o->u_obj.members, attr, false); - if (elem != NULL) { - // object member, always treated as a value - return elem->value; - } - elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, false); - if (elem != NULL) { - if (py_obj_is_callable(elem->value)) { - // class member is callable so build a bound method - return build_bound_method(base, elem->value); - } else { - // class member is a value, so just return that value - return elem->value; + } else if (MP_OBJ_IS_TYPE(base, &instance_type)) { + return mp_obj_instance_load_attr(base, attr); + } else if (MP_OBJ_IS_OBJ(base)) { + // generic method lookup + mp_obj_base_t *o = base; + const mp_method_t *meth = &o->type->methods[0]; + for (; meth->name != NULL; meth++) { + if (strcmp(meth->name, qstr_str(attr)) == 0) { + return mp_obj_new_bound_meth(base, (mp_obj_t)meth->fun); } } - goto no_attr; } - -no_attr: - nlr_jump(py_obj_new_exception_2(rt_q_AttributeError, "'%s' object has no attribute '%s'", py_obj_get_type_str(base), qstr_str(attr))); + nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr))); } -void rt_load_method(py_obj_t base, qstr attr, py_obj_t *dest) { +void rt_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest) { DEBUG_OP_printf("load method %s\n", qstr_str(attr)); - if (IS_O(base, O_STR)) { - if (attr == rt_q_join) { - dest[1] = fun_str_join; - dest[0] = base; - return; - } else if (attr == rt_q_format) { - dest[1] = fun_str_format; - dest[0] = base; - return; - } - } else if (IS_O(base, O_GEN_INSTANCE) && attr == rt_q___next__) { - dest[1] = fun_gen_instance_next; - dest[0] = base; - return; - } else if (IS_O(base, O_LIST) && attr == rt_q_append) { - dest[1] = fun_list_append; - dest[0] = base; - return; - } else if (IS_O(base, O_LIST) && attr == rt_q_pop) { - dest[1] = fun_list_pop; + if (MP_OBJ_IS_TYPE(base, &gen_instance_type) && attr == rt_q___next__) { + dest[1] = (mp_obj_t)&mp_obj_gen_instance_next_obj; dest[0] = base; return; - } else if (IS_O(base, O_LIST) && attr == rt_q_sort) { - dest[1] = fun_list_sort; - dest[0] = base; + } else if (MP_OBJ_IS_TYPE(base, &instance_type)) { + mp_obj_instance_load_method(base, attr, dest); return; - } else if (IS_O(base, O_OBJ)) { - // logic: look in obj members then class locals (TODO check this against CPython) - py_obj_base_t *o = base; - py_map_elem_t *elem = py_qstr_map_lookup(o->u_obj.members, attr, false); - if (elem != NULL) { - // object member, always treated as a value - dest[1] = elem->value; - dest[0] = NULL; - return; - } - elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, false); - if (elem != NULL) { - if (py_obj_is_callable(elem->value)) { - // class member is callable so build a bound method - dest[1] = elem->value; - dest[0] = base; - return; - } else { - // class member is a value, so just return that value - dest[1] = elem->value; - dest[0] = NULL; - return; - } - } - goto no_attr; - } else if (IS_O(base, O_USER)) { - py_obj_base_t *o = base; - const py_user_method_t *meth = &o->u_user.info->methods[0]; + } else if (MP_OBJ_IS_OBJ(base)) { + // generic method lookup + mp_obj_base_t *o = base; + const mp_method_t *meth = &o->type->methods[0]; for (; meth->name != NULL; meth++) { if (strcmp(meth->name, qstr_str(attr)) == 0) { - if (meth->kind == 0) { - dest[1] = rt_make_function_1(meth->fun); - } else if (meth->kind == 1) { - dest[1] = rt_make_function_2(meth->fun); - } else { - assert(0); - } + dest[1] = (mp_obj_t)meth->fun; dest[0] = base; return; } } } -no_attr: + // no method; fallback to load_attr dest[1] = rt_load_attr(base, attr); dest[0] = NULL; } -void rt_store_attr(py_obj_t base, qstr attr, py_obj_t value) { +void rt_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) { DEBUG_OP_printf("store attr %p.%s <- %p\n", base, qstr_str(attr), value); - if (IS_O(base, O_CLASS)) { + if (MP_OBJ_IS_TYPE(base, &class_type)) { // TODO CPython allows STORE_ATTR to a class, but is this the correct implementation? - py_obj_base_t *o = base; - py_qstr_map_lookup(o->u_class.locals, attr, true)->value = value; - } else if (IS_O(base, O_OBJ)) { - // logic: look in class locals (no add) then obj members (add) (TODO check this against CPython) - py_obj_base_t *o = base; - py_map_elem_t *elem = py_qstr_map_lookup(o->u_obj.class->u_class.locals, attr, false); - if (elem != NULL) { - elem->value = value; - } else { - py_qstr_map_lookup(o->u_obj.members, attr, true)->value = value; - } + mp_map_t *locals = mp_obj_class_get_locals(base); + mp_qstr_map_lookup(locals, attr, true)->value = value; + } else if (MP_OBJ_IS_TYPE(base, &instance_type)) { + mp_obj_instance_store_attr(base, attr, value); } else { - printf("?AttributeError: '%s' object has no attribute '%s'\n", py_obj_get_type_str(base), qstr_str(attr)); + printf("?AttributeError: '%s' object has no attribute '%s'\n", mp_obj_get_type_str(base), qstr_str(attr)); assert(0); } } -void rt_store_subscr(py_obj_t base, py_obj_t index, py_obj_t value) { +void rt_store_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) { DEBUG_OP_printf("store subscr %p[%p] <- %p\n", base, index, value); - if (IS_O(base, O_LIST)) { + if (MP_OBJ_IS_TYPE(base, &list_type)) { // list store - uint i = get_index(base, index); - ((py_obj_base_t*)base)->u_tuple_list.items[i] = value; - } else if (IS_O(base, O_MAP)) { - // map store - py_map_lookup(base, index, true)->value = value; + mp_obj_list_store(base, index, value); + } else if (MP_OBJ_IS_TYPE(base, &dict_type)) { + // dict store + mp_obj_dict_store(base, index, value); } else { assert(0); } } -py_obj_t rt_getiter(py_obj_t o_in) { - if (IS_O(o_in, O_GEN_INSTANCE)) { - return o_in; - } else if (IS_O(o_in, O_RANGE)) { - py_obj_base_t *o = o_in; - return py_obj_new_range_iterator(o->u_range.start, o->u_range.stop, o->u_range.step); - } else if (IS_O(o_in, O_TUPLE)) { - return py_obj_new_tuple_iterator(o_in, 0); - } else if (IS_O(o_in, O_LIST)) { - return py_obj_new_list_iterator(o_in, 0); +mp_obj_t rt_getiter(mp_obj_t o_in) { + if (MP_OBJ_IS_SMALL_INT(o_in)) { + nlr_jump(mp_obj_new_exception_msg(rt_q_TypeError, "'int' object is not iterable")); } else { - nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "'%s' object is not iterable", py_obj_get_type_str(o_in), NULL)); - } -} - -py_obj_t rt_iternext(py_obj_t o_in) { - if (IS_O(o_in, O_GEN_INSTANCE)) { - py_obj_base_t *self = o_in; - //py_obj_base_t *fun = self->u_gen_instance.state[0]; - //assert(fun->kind == O_FUN_BC); - bool yield = py_execute_byte_code_2(&self->u_gen_instance.ip, &self->u_gen_instance.state[1], &self->u_gen_instance.sp); - if (yield) { - return *self->u_gen_instance.sp; + mp_obj_base_t *o = o_in; + if (o->type->getiter != NULL) { + return o->type->getiter(o_in); } else { - if (*self->u_gen_instance.sp == py_const_none) { - return py_const_stop_iteration; - } else { - // TODO return StopIteration with value *self->u_gen_instance.sp - return py_const_stop_iteration; - } - } - - } else if (IS_O(o_in, O_RANGE_IT)) { - py_obj_base_t *o = o_in; - if ((o->u_range_it.step > 0 && o->u_range_it.cur < o->u_range_it.stop) || (o->u_range_it.step < 0 && o->u_range_it.cur > o->u_range_it.stop)) { - py_obj_t o_out = TO_SMALL_INT(o->u_range_it.cur); - o->u_range_it.cur += o->u_range_it.step; - return o_out; - } else { - return py_const_stop_iteration; + nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "'%s' object is not iterable", o->type->name)); } + } +} - } else if (IS_O(o_in, O_TUPLE_IT) || IS_O(o_in, O_LIST_IT)) { - py_obj_base_t *o = o_in; - if (o->u_tuple_list_it.cur < o->u_tuple_list_it.obj->u_tuple_list.len) { - py_obj_t o_out = o->u_tuple_list_it.obj->u_tuple_list.items[o->u_tuple_list_it.cur]; - o->u_tuple_list_it.cur += 1; - return o_out; +mp_obj_t rt_iternext(mp_obj_t o_in) { + if (MP_OBJ_IS_SMALL_INT(o_in)) { + nlr_jump(mp_obj_new_exception_msg(rt_q_TypeError, "? 'int' object is not iterable")); + } else { + mp_obj_base_t *o = o_in; + if (o->type->iternext != NULL) { + return o->type->iternext(o_in); } else { - return py_const_stop_iteration; + nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "? '%s' object is not iterable", o->type->name)); } - - } else { - nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "? '%s' object is not iterable", py_obj_get_type_str(o_in), NULL)); } } -py_obj_t rt_import_name(qstr name, py_obj_t fromlist, py_obj_t level) { +mp_obj_t rt_import_name(qstr name, mp_obj_t fromlist, mp_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 + mp_obj_t args[5]; + args[0] = mp_obj_new_str(name); + args[1] = mp_const_none; // TODO should be globals + args[2] = mp_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); + return mp_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); +mp_obj_t rt_import_from(mp_obj_t module, qstr name) { + mp_obj_t x = rt_load_attr(module, name); /* TODO convert AttributeError to ImportError if (fail) { (ImportError, "cannot import name %s", qstr_str(name), NULL) diff --git a/py/runtime.h b/py/runtime.h index d5d160535..37b036852 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -1,91 +1,3 @@ -typedef enum { - RT_UNARY_OP_NOT, - RT_UNARY_OP_POSITIVE, - RT_UNARY_OP_NEGATIVE, - RT_UNARY_OP_INVERT, -} rt_unary_op_t; - -typedef enum { - RT_BINARY_OP_SUBSCR, - RT_BINARY_OP_OR, - RT_BINARY_OP_XOR, - RT_BINARY_OP_AND, - RT_BINARY_OP_LSHIFT, - RT_BINARY_OP_RSHIFT, - RT_BINARY_OP_ADD, - RT_BINARY_OP_SUBTRACT, - RT_BINARY_OP_MULTIPLY, - RT_BINARY_OP_FLOOR_DIVIDE, - RT_BINARY_OP_TRUE_DIVIDE, - RT_BINARY_OP_MODULO, - RT_BINARY_OP_POWER, - RT_BINARY_OP_INPLACE_OR, - RT_BINARY_OP_INPLACE_XOR, - RT_BINARY_OP_INPLACE_AND, - RT_BINARY_OP_INPLACE_LSHIFT, - RT_BINARY_OP_INPLACE_RSHIFT, - RT_BINARY_OP_INPLACE_ADD, - RT_BINARY_OP_INPLACE_SUBTRACT, - RT_BINARY_OP_INPLACE_MULTIPLY, - RT_BINARY_OP_INPLACE_FLOOR_DIVIDE, - RT_BINARY_OP_INPLACE_TRUE_DIVIDE, - RT_BINARY_OP_INPLACE_MODULO, - RT_BINARY_OP_INPLACE_POWER, -} rt_binary_op_t; - -typedef enum { - RT_COMPARE_OP_LESS, - RT_COMPARE_OP_MORE, - RT_COMPARE_OP_EQUAL, - RT_COMPARE_OP_LESS_EQUAL, - RT_COMPARE_OP_MORE_EQUAL, - RT_COMPARE_OP_NOT_EQUAL, - RT_COMPARE_OP_IN, - RT_COMPARE_OP_NOT_IN, - RT_COMPARE_OP_IS, - RT_COMPARE_OP_IS_NOT, - RT_COMPARE_OP_EXCEPTION_MATCH, -} rt_compare_op_t; - -typedef enum { - RT_F_LOAD_CONST_DEC = 0, - RT_F_LOAD_CONST_STR, - RT_F_LOAD_NAME, - RT_F_LOAD_GLOBAL, - RT_F_LOAD_BUILD_CLASS, - RT_F_LOAD_ATTR, - RT_F_LOAD_METHOD, - RT_F_STORE_NAME, - RT_F_STORE_ATTR, - RT_F_STORE_SUBSCR, - RT_F_IS_TRUE, - RT_F_UNARY_OP, - RT_F_BUILD_TUPLE, - RT_F_BUILD_LIST, - RT_F_LIST_APPEND, - RT_F_BUILD_MAP, - RT_F_STORE_MAP, - RT_F_BUILD_SET, - RT_F_STORE_SET, - RT_F_MAKE_FUNCTION_FROM_ID, - RT_F_CALL_FUNCTION_N, - RT_F_CALL_METHOD_N, - RT_F_BINARY_OP, - RT_F_COMPARE_OP, - RT_F_GETITER, - RT_F_ITERNEXT, - RT_F_NUMBER_OF, -} rt_fun_kind_t; - -extern void *const rt_fun_table[RT_F_NUMBER_OF]; - -typedef machine_ptr_t py_obj_t; // must be of pointer size -typedef py_obj_t (*py_fun_0_t)(void); -typedef py_obj_t (*py_fun_1_t)(py_obj_t); -typedef py_obj_t (*py_fun_2_t)(py_obj_t, py_obj_t); -typedef py_obj_t (*py_fun_t)(void); -typedef py_obj_t (*py_fun_var_t)(int n, const py_obj_t *); - extern qstr rt_q_append; extern qstr rt_q_pop; extern qstr rt_q_sort; @@ -101,61 +13,47 @@ extern qstr rt_q_TypeError; extern qstr rt_q_SyntaxError; extern qstr rt_q_ValueError; -extern py_obj_t py_const_none; -extern py_obj_t py_const_false; -extern py_obj_t py_const_true; -extern py_obj_t py_const_stop_iteration; // special object indicating end of iteration (not StopIteration exception!) - -void rt_init(void); -void rt_deinit(void); -int rt_get_unique_code_id(bool is_main_module); -void rt_assign_byte_code(int unique_code_id, byte *code, uint len, int n_args, int n_locals, int n_cells, int n_stack, bool is_generator); -void rt_assign_native_code(int unique_code_id, py_fun_t f, uint len, int n_args); -void rt_assign_inline_asm_code(int unique_code_id, py_fun_t f, uint len, int n_args); - -int rt_is_true(py_obj_t arg); - -py_obj_t rt_load_const_dec(qstr qstr); -py_obj_t rt_load_const_str(qstr qstr); -py_obj_t rt_load_name(qstr qstr); -py_obj_t rt_load_global(qstr qstr); -py_obj_t rt_load_build_class(void); -py_obj_t rt_get_cell(py_obj_t cell); -void rt_set_cell(py_obj_t cell, py_obj_t val); -void rt_store_name(qstr qstr, py_obj_t obj); -void rt_store_global(qstr qstr, py_obj_t obj); -py_obj_t rt_unary_op(int op, py_obj_t arg); -py_obj_t rt_binary_op(int op, py_obj_t lhs, py_obj_t rhs); -py_obj_t rt_compare_op(int op, py_obj_t lhs, py_obj_t rhs); -py_obj_t rt_make_function_from_id(int unique_code_id); -py_obj_t rt_make_function_0(py_fun_0_t f); -py_obj_t rt_make_function_1(py_fun_1_t f); -py_obj_t rt_make_function_2(py_fun_2_t f); -py_obj_t rt_make_function(int n_args, py_fun_t code); -py_obj_t rt_make_function_var(int n_fixed_args, py_fun_var_t f); -py_obj_t rt_make_closure_from_id(int unique_code_id, py_obj_t closure_tuple); -py_obj_t rt_call_function_0(py_obj_t fun); -py_obj_t rt_call_function_1(py_obj_t fun, py_obj_t arg); -py_obj_t rt_call_function_2(py_obj_t fun, py_obj_t arg1, py_obj_t arg2); -py_obj_t rt_call_function_n(py_obj_t fun, int n_args, const py_obj_t *args); -py_obj_t rt_call_function_n_kw(py_obj_t fun, uint n_args, uint n_kw, const py_obj_t *args); -py_obj_t rt_call_method_n(uint n_args, const py_obj_t *args); -py_obj_t rt_call_method_n_kw(uint n_args, uint n_kw, const py_obj_t *args); -py_obj_t rt_build_tuple(int n_args, py_obj_t *items); -py_obj_t rt_build_list(int n_args, py_obj_t *items); -py_obj_t rt_list_append(py_obj_t list, py_obj_t arg); -py_obj_t rt_build_set(int n_args, py_obj_t *items); -py_obj_t rt_store_set(py_obj_t set, py_obj_t item); -void rt_unpack_sequence(py_obj_t seq, uint num, py_obj_t *items); -py_obj_t rt_build_map(int n_args); -py_obj_t rt_store_map(py_obj_t map, py_obj_t key, py_obj_t value); -py_obj_t rt_load_attr(py_obj_t base, qstr attr); -void rt_load_method(py_obj_t base, qstr attr, py_obj_t *dest); -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); - -py_obj_t rt_gen_instance_next(py_obj_t self_in); +int rt_is_true(mp_obj_t arg); + +mp_obj_t rt_load_const_dec(qstr qstr); +mp_obj_t rt_load_const_str(qstr qstr); +mp_obj_t rt_load_name(qstr qstr); +mp_obj_t rt_load_global(qstr qstr); +mp_obj_t rt_load_build_class(void); +mp_obj_t rt_get_cell(mp_obj_t cell); +void rt_set_cell(mp_obj_t cell, mp_obj_t val); +void rt_store_name(qstr qstr, mp_obj_t obj); +void rt_store_global(qstr qstr, mp_obj_t obj); +mp_obj_t rt_unary_op(int op, mp_obj_t arg); +mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs); +mp_obj_t rt_compare_op(int op, mp_obj_t lhs, mp_obj_t rhs); +mp_obj_t rt_make_function_from_id(int unique_code_id); +mp_obj_t rt_make_function_0(mp_fun_0_t f); +mp_obj_t rt_make_function_1(mp_fun_1_t f); +mp_obj_t rt_make_function_2(mp_fun_2_t f); +mp_obj_t rt_make_function_var(int n_args_min, mp_fun_var_t f); +mp_obj_t rt_make_function_var_between(int n_args_min, int n_args_max, mp_fun_var_t fun); // min and max are inclusive +mp_obj_t rt_make_closure_from_id(int unique_code_id, mp_obj_t closure_tuple); +mp_obj_t rt_call_function_0(mp_obj_t fun); +mp_obj_t rt_call_function_1(mp_obj_t fun, mp_obj_t arg); +mp_obj_t rt_call_function_2(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2); +mp_obj_t rt_call_function_n(mp_obj_t fun, int n_args, const mp_obj_t *args); +mp_obj_t rt_call_function_n_kw(mp_obj_t fun, uint n_args, uint n_kw, const mp_obj_t *args); +mp_obj_t rt_call_method_n(uint n_args, const mp_obj_t *args); +mp_obj_t rt_call_method_n_kw(uint n_args, uint n_kw, const mp_obj_t *args); +mp_obj_t rt_build_tuple(int n_args, mp_obj_t *items); +mp_obj_t rt_build_list(int n_args, mp_obj_t *items); +mp_obj_t rt_list_append(mp_obj_t list, mp_obj_t arg); +mp_obj_t rt_build_set(int n_args, mp_obj_t *items); +mp_obj_t rt_store_set(mp_obj_t set, mp_obj_t item); +void rt_unpack_sequence(mp_obj_t seq, uint num, mp_obj_t *items); +mp_obj_t rt_build_map(int n_args); +mp_obj_t rt_store_map(mp_obj_t map, mp_obj_t key, mp_obj_t value); +mp_obj_t rt_load_attr(mp_obj_t base, qstr attr); +void rt_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest); +void rt_store_attr(mp_obj_t base, qstr attr, mp_obj_t val); +void rt_store_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t val); +mp_obj_t rt_getiter(mp_obj_t o); +mp_obj_t rt_iternext(mp_obj_t o); +mp_obj_t rt_import_name(qstr name, mp_obj_t fromlist, mp_obj_t level); +mp_obj_t rt_import_from(mp_obj_t module, qstr name); diff --git a/py/runtime0.h b/py/runtime0.h new file mode 100644 index 000000000..f68b7b961 --- /dev/null +++ b/py/runtime0.h @@ -0,0 +1,87 @@ +typedef enum { + RT_UNARY_OP_NOT, + RT_UNARY_OP_POSITIVE, + RT_UNARY_OP_NEGATIVE, + RT_UNARY_OP_INVERT, +} rt_unary_op_t; + +typedef enum { + RT_BINARY_OP_SUBSCR, + RT_BINARY_OP_OR, + RT_BINARY_OP_XOR, + RT_BINARY_OP_AND, + RT_BINARY_OP_LSHIFT, + RT_BINARY_OP_RSHIFT, + RT_BINARY_OP_ADD, + RT_BINARY_OP_SUBTRACT, + RT_BINARY_OP_MULTIPLY, + RT_BINARY_OP_FLOOR_DIVIDE, + RT_BINARY_OP_TRUE_DIVIDE, + RT_BINARY_OP_MODULO, + RT_BINARY_OP_POWER, + RT_BINARY_OP_INPLACE_OR, + RT_BINARY_OP_INPLACE_XOR, + RT_BINARY_OP_INPLACE_AND, + RT_BINARY_OP_INPLACE_LSHIFT, + RT_BINARY_OP_INPLACE_RSHIFT, + RT_BINARY_OP_INPLACE_ADD, + RT_BINARY_OP_INPLACE_SUBTRACT, + RT_BINARY_OP_INPLACE_MULTIPLY, + RT_BINARY_OP_INPLACE_FLOOR_DIVIDE, + RT_BINARY_OP_INPLACE_TRUE_DIVIDE, + RT_BINARY_OP_INPLACE_MODULO, + RT_BINARY_OP_INPLACE_POWER, +} rt_binary_op_t; + +typedef enum { + RT_COMPARE_OP_LESS, + RT_COMPARE_OP_MORE, + RT_COMPARE_OP_EQUAL, + RT_COMPARE_OP_LESS_EQUAL, + RT_COMPARE_OP_MORE_EQUAL, + RT_COMPARE_OP_NOT_EQUAL, + RT_COMPARE_OP_IN, + RT_COMPARE_OP_NOT_IN, + RT_COMPARE_OP_IS, + RT_COMPARE_OP_IS_NOT, + RT_COMPARE_OP_EXCEPTION_MATCH, +} rt_compare_op_t; + +typedef enum { + RT_F_LOAD_CONST_DEC = 0, + RT_F_LOAD_CONST_STR, + RT_F_LOAD_NAME, + RT_F_LOAD_GLOBAL, + RT_F_LOAD_BUILD_CLASS, + RT_F_LOAD_ATTR, + RT_F_LOAD_METHOD, + RT_F_STORE_NAME, + RT_F_STORE_ATTR, + RT_F_STORE_SUBSCR, + RT_F_IS_TRUE, + RT_F_UNARY_OP, + RT_F_BUILD_TUPLE, + RT_F_BUILD_LIST, + RT_F_LIST_APPEND, + RT_F_BUILD_MAP, + RT_F_STORE_MAP, + RT_F_BUILD_SET, + RT_F_STORE_SET, + RT_F_MAKE_FUNCTION_FROM_ID, + RT_F_CALL_FUNCTION_N, + RT_F_CALL_METHOD_N, + RT_F_BINARY_OP, + RT_F_COMPARE_OP, + RT_F_GETITER, + RT_F_ITERNEXT, + RT_F_NUMBER_OF, +} rt_fun_kind_t; + +extern void *const rt_fun_table[RT_F_NUMBER_OF]; + +void rt_init(void); +void rt_deinit(void); +int rt_get_unique_code_id(bool is_main_module); +void rt_assign_byte_code(int unique_code_id, byte *code, uint len, int n_args, int n_locals, int n_cells, int n_stack, bool is_generator); +void rt_assign_native_code(int unique_code_id, void *f, uint len, int n_args); +void rt_assign_inline_asm_code(int unique_code_id, void *f, uint len, int n_args); diff --git a/py/scope.c b/py/scope.c index d72d130f2..7d55d3923 100644 --- a/py/scope.c +++ b/py/scope.c @@ -4,11 +4,11 @@ #include <assert.h> #include "misc.h" -#include "mpyconfig.h" +#include "mpconfig.h" #include "parse.h" #include "scope.h" -scope_t *scope_new(scope_kind_t kind, py_parse_node_t pn, uint unique_code_id, uint emit_options) { +scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, uint unique_code_id, uint emit_options) { scope_t *scope = m_new(scope_t, 1); scope->kind = kind; scope->parent = NULL; @@ -20,8 +20,8 @@ scope_t *scope_new(scope_kind_t kind, py_parse_node_t pn, uint unique_code_id, u break; case SCOPE_FUNCTION: case SCOPE_CLASS: - assert(PY_PARSE_NODE_IS_STRUCT(pn)); - scope->simple_name = PY_PARSE_NODE_LEAF_ARG(((py_parse_node_struct_t*)pn)->nodes[0]); + assert(MP_PARSE_NODE_IS_STRUCT(pn)); + scope->simple_name = MP_PARSE_NODE_LEAF_ARG(((mp_parse_node_struct_t*)pn)->nodes[0]); break; case SCOPE_LAMBDA: scope->simple_name = qstr_from_str_static("<lambda>"); diff --git a/py/scope.h b/py/scope.h index f560e3d21..1231b3cc5 100644 --- a/py/scope.h +++ b/py/scope.h @@ -37,7 +37,7 @@ typedef struct _scope_t { scope_kind_t kind; struct _scope_t *parent; struct _scope_t *next; - py_parse_node_t pn; + mp_parse_node_t pn; qstr simple_name; int id_info_alloc; int id_info_len; @@ -55,7 +55,7 @@ typedef struct _scope_t { uint emit_options; } scope_t; -scope_t *scope_new(scope_kind_t kind, py_parse_node_t pn, uint unique_code_id, uint emit_options); +scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, uint unique_code_id, uint emit_options); id_info_t *scope_find_or_add_id(scope_t *scope, qstr qstr, bool *added); id_info_t *scope_find(scope_t *scope, qstr qstr); id_info_t *scope_find_global(scope_t *scope, qstr qstr); diff --git a/py/showbc.c b/py/showbc.c index bd8a50515..fd1d51203 100644 --- a/py/showbc.c +++ b/py/showbc.c @@ -5,16 +5,15 @@ #include <assert.h> #include "misc.h" -#include "mpyconfig.h" -#include "runtime.h" -#include "bc.h" +#include "mpconfig.h" +#include "bc0.h" #define DECODE_UINT do { unum = *ip++; if (unum > 127) { unum = ((unum & 0x3f) << 8) | (*ip++); } } while (0) #define DECODE_ULABEL do { unum = (ip[0] | (ip[1] << 8)); ip += 2; } while (0) #define DECODE_SLABEL do { unum = (ip[0] | (ip[1] << 8)) - 0x8000; ip += 2; } while (0) #define DECODE_QSTR do { qstr = *ip++; if (qstr > 127) { qstr = ((qstr & 0x3f) << 8) | (*ip++); } } while (0) -void py_show_byte_code(const byte *ip, int len) { +void mp_show_byte_code(const byte *ip, int len) { const byte *ip_start = ip; machine_uint_t unum; qstr qstr; @@ -22,164 +21,164 @@ void py_show_byte_code(const byte *ip, int len) { printf("%02u ", (uint)(ip - ip_start)); int op = *ip++; switch (op) { - case PYBC_LOAD_CONST_FALSE: + case MP_BC_LOAD_CONST_FALSE: printf("LOAD_CONST_FALSE"); break; - case PYBC_LOAD_CONST_NONE: + case MP_BC_LOAD_CONST_NONE: printf("LOAD_CONST_NONE"); break; - case PYBC_LOAD_CONST_TRUE: + case MP_BC_LOAD_CONST_TRUE: printf("LOAD_CONST_TRUE"); break; - case PYBC_LOAD_CONST_SMALL_INT: + case MP_BC_LOAD_CONST_SMALL_INT: unum = (ip[0] | (ip[1] << 8) | (ip[2] << 16)) - 0x800000; ip += 3; printf("LOAD_CONST_SMALL_INT %d", (int)unum); break; /* - case PYBC_LOAD_CONST_DEC: + case MP_BC_LOAD_CONST_DEC: DECODE_QSTR; PUSH(rt_load_const_dec(qstr)); break; */ - case PYBC_LOAD_CONST_ID: + case MP_BC_LOAD_CONST_ID: DECODE_QSTR; printf("LOAD_CONST_ID %s", qstr_str(qstr)); break; - case PYBC_LOAD_CONST_STRING: + case MP_BC_LOAD_CONST_STRING: DECODE_QSTR; printf("LOAD_CONST_STRING %s", qstr_str(qstr)); break; - case PYBC_LOAD_FAST_0: + case MP_BC_LOAD_FAST_0: printf("LOAD_FAST_0"); break; - case PYBC_LOAD_FAST_1: + case MP_BC_LOAD_FAST_1: printf("LOAD_FAST_1"); break; - case PYBC_LOAD_FAST_2: + case MP_BC_LOAD_FAST_2: printf("LOAD_FAST_2"); break; - case PYBC_LOAD_FAST_N: + case MP_BC_LOAD_FAST_N: DECODE_UINT; printf("LOAD_FAST_N %lu", unum); break; - case PYBC_LOAD_NAME: + case MP_BC_LOAD_NAME: DECODE_QSTR; printf("LOAD_NAME %s", qstr_str(qstr)); break; - case PYBC_LOAD_GLOBAL: + case MP_BC_LOAD_GLOBAL: DECODE_QSTR; printf("LOAD_GLOBAL %s", qstr_str(qstr)); break; - case PYBC_LOAD_ATTR: + case MP_BC_LOAD_ATTR: DECODE_QSTR; printf("LOAD_ATTR %s", qstr_str(qstr)); break; - case PYBC_LOAD_METHOD: + case MP_BC_LOAD_METHOD: DECODE_QSTR; printf("LOAD_METHOD %s", qstr_str(qstr)); break; - case PYBC_LOAD_BUILD_CLASS: + case MP_BC_LOAD_BUILD_CLASS: printf("LOAD_BUILD_CLASS"); break; - case PYBC_STORE_FAST_0: + case MP_BC_STORE_FAST_0: printf("STORE_FAST_0"); break; - case PYBC_STORE_FAST_1: + case MP_BC_STORE_FAST_1: printf("STORE_FAST_1"); break; - case PYBC_STORE_FAST_2: + case MP_BC_STORE_FAST_2: printf("STORE_FAST_2"); break; - case PYBC_STORE_FAST_N: + case MP_BC_STORE_FAST_N: DECODE_UINT; printf("STORE_FAST_N %lu", unum); break; - case PYBC_STORE_NAME: + case MP_BC_STORE_NAME: DECODE_QSTR; printf("STORE_NAME %s", qstr_str(qstr)); break; /* - case PYBC_STORE_GLOBAL: + case MP_BC_STORE_GLOBAL: DECODE_QSTR; rt_store_global(qstr, POP()); break; */ - case PYBC_STORE_ATTR: + case MP_BC_STORE_ATTR: DECODE_QSTR; printf("STORE_ATTR %s", qstr_str(qstr)); break; - case PYBC_STORE_SUBSCR: + case MP_BC_STORE_SUBSCR: printf("STORE_SUBSCR"); break; /* - case PYBC_DUP_TOP: + case MP_BC_DUP_TOP: obj1 = *sp; PUSH(obj1); break; */ - case PYBC_DUP_TOP_TWO: + case MP_BC_DUP_TOP_TWO: printf("DUP_TOP_TWO"); break; - case PYBC_POP_TOP: + case MP_BC_POP_TOP: printf("POP_TOP"); break; /* - case PYBC_ROT_TWO: + case MP_BC_ROT_TWO: obj1 = sp[0]; sp[0] = sp[1]; sp[1] = obj1; break; */ - case PYBC_ROT_THREE: + case MP_BC_ROT_THREE: printf("ROT_THREE"); break; - case PYBC_JUMP: + case MP_BC_JUMP: DECODE_SLABEL; printf("JUMP %lu", ip + unum - ip_start); break; - case PYBC_POP_JUMP_IF_TRUE: + case MP_BC_POP_JUMP_IF_TRUE: DECODE_SLABEL; printf("POP_JUMP_IF_TRUE %lu", ip + unum - ip_start); break; - case PYBC_POP_JUMP_IF_FALSE: + case MP_BC_POP_JUMP_IF_FALSE: DECODE_SLABEL; printf("POP_JUMP_IF_FALSE %lu", ip + unum - ip_start); break; /* - case PYBC_JUMP_IF_TRUE_OR_POP: + case MP_BC_JUMP_IF_TRUE_OR_POP: DECODE_SLABEL; if (rt_is_true(*sp)) { ip += unum; @@ -188,7 +187,7 @@ void py_show_byte_code(const byte *ip, int len) { } break; - case PYBC_JUMP_IF_FALSE_OR_POP: + case MP_BC_JUMP_IF_FALSE_OR_POP: DECODE_SLABEL; if (rt_is_true(*sp)) { sp++; @@ -197,13 +196,13 @@ void py_show_byte_code(const byte *ip, int len) { } break; - case PYBC_SETUP_EXCEPT: + case MP_BC_SETUP_EXCEPT: DECODE_ULABEL; // except labels are always forward *++exc_sp = (machine_uint_t)ip + unum; *++exc_sp = (machine_uint_t)sp; break; - case PYBC_END_FINALLY: + case MP_BC_END_FINALLY: // not implemented // if TOS is an exception, reraises the exception (3 values on TOS) // if TOS is an integer, does something else @@ -213,90 +212,90 @@ void py_show_byte_code(const byte *ip, int len) { break; */ - case PYBC_GET_ITER: + case MP_BC_GET_ITER: printf("GET_ITER"); break; - case PYBC_FOR_ITER: + case MP_BC_FOR_ITER: DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward printf("FOR_ITER %lu", ip + unum - ip_start); break; /* - case PYBC_POP_BLOCK: + case MP_BC_POP_BLOCK: // pops block and restores the stack assert(0); break; - case PYBC_POP_EXCEPT: + case MP_BC_POP_EXCEPT: // TODO need to work out how blocks work etc // pops block, checks it's an exception block, and restores the stack, saving the 3 exception values to local threadstate assert(exc_sp >= &exc_stack[0]); - //sp = (py_obj_t*)(*exc_sp--); + //sp = (mp_obj_t*)(*exc_sp--); //exc_sp--; // discard ip exc_sp -= 2; //sp += 3; // pop 3 exception values break; - case PYBC_UNARY_OP: + case MP_BC_UNARY_OP: unum = *ip++; *sp = rt_unary_op(unum, *sp); break; */ - case PYBC_BINARY_OP: + case MP_BC_BINARY_OP: unum = *ip++; printf("BINARY_OP %lu", unum); break; - case PYBC_COMPARE_OP: + case MP_BC_COMPARE_OP: unum = *ip++; printf("COMPARE_OP %lu", unum); break; - case PYBC_BUILD_TUPLE: + case MP_BC_BUILD_TUPLE: DECODE_UINT; printf("BUILD_TUPLE %lu", unum); break; - case PYBC_BUILD_LIST: + case MP_BC_BUILD_LIST: DECODE_UINT; printf("BUILD_LIST %lu", unum); break; /* - case PYBC_LIST_APPEND: + case MP_BC_LIST_APPEND: DECODE_UINT; // I think it's guaranteed by the compiler that sp[unum] is a list rt_list_append(sp[unum], sp[0]); sp++; break; - case PYBC_BUILD_MAP: + case MP_BC_BUILD_MAP: DECODE_UINT; PUSH(rt_build_map(unum)); break; - case PYBC_STORE_MAP: + case MP_BC_STORE_MAP: sp += 2; rt_store_map(sp[0], sp[-2], sp[-1]); break; - case PYBC_MAP_ADD: + case MP_BC_MAP_ADD: DECODE_UINT; // I think it's guaranteed by the compiler that sp[unum + 1] is a map rt_store_map(sp[unum + 1], sp[0], sp[1]); sp += 2; break; - case PYBC_BUILD_SET: + case MP_BC_BUILD_SET: DECODE_UINT; obj1 = rt_build_set(unum, sp); sp += unum - 1; *sp = obj1; break; - case PYBC_SET_ADD: + case MP_BC_SET_ADD: DECODE_UINT; // I think it's guaranteed by the compiler that sp[unum] is a set rt_store_set(sp[unum], sp[0]); @@ -304,32 +303,32 @@ void py_show_byte_code(const byte *ip, int len) { break; */ - case PYBC_UNPACK_SEQUENCE: + case MP_BC_UNPACK_SEQUENCE: DECODE_UINT; printf("UNPACK_SEQUENCE %lu", unum); break; - case PYBC_MAKE_FUNCTION: + case MP_BC_MAKE_FUNCTION: DECODE_UINT; printf("MAKE_FUNCTION %lu", unum); break; - case PYBC_CALL_FUNCTION: + case MP_BC_CALL_FUNCTION: DECODE_UINT; printf("CALL_FUNCTION n=%lu nkw=%lu", unum & 0xff, (unum >> 8) & 0xff); break; - case PYBC_CALL_METHOD: + case MP_BC_CALL_METHOD: DECODE_UINT; printf("CALL_METHOD n=%lu nkw=%lu", unum & 0xff, (unum >> 8) & 0xff); break; - case PYBC_RETURN_VALUE: + case MP_BC_RETURN_VALUE: printf("RETURN_VALUE"); break; /* - case PYBC_YIELD_VALUE: + case MP_BC_YIELD_VALUE: nlr_pop(); *ip_in_out = ip; fastn[0] = fast0; diff --git a/py/vm.c b/py/vm.c index 7db6a7d9c..b10d641ca 100644 --- a/py/vm.c +++ b/py/vm.c @@ -6,8 +6,10 @@ #include "nlr.h" #include "misc.h" -#include "mpyconfig.h" +#include "mpconfig.h" +#include "obj.h" #include "runtime.h" +#include "bc0.h" #include "bc.h" // (value) stack grows down (to be compatible with native code when passing pointers to the stack), top element is pointed to @@ -23,12 +25,12 @@ #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) { - py_obj_t temp_state[10]; // TODO allocate properly - py_obj_t *state = &temp_state[0]; - py_obj_t *sp = &state[10]; +mp_obj_t mp_execute_byte_code(const byte *code, const mp_obj_t *args, uint n_args, uint n_state) { + mp_obj_t temp_state[10]; // TODO allocate properly + mp_obj_t *state = &temp_state[0]; + mp_obj_t *sp = &state[10]; if (n_state > 10) { - state = m_new(py_obj_t, n_state); + state = m_new(mp_obj_t, n_state); sp = &state[n_state]; } // init args @@ -37,7 +39,7 @@ py_obj_t py_execute_byte_code(const byte *code, const py_obj_t *args, uint n_arg state[i] = args[n_args - 1 - i]; } const byte *ip = code; - if (py_execute_byte_code_2(&ip, &state[0], &sp)) { + if (mp_execute_byte_code_2(&ip, &state[0], &sp)) { // it shouldn't yield assert(0); } @@ -48,15 +50,15 @@ py_obj_t py_execute_byte_code(const byte *code, const py_obj_t *args, uint n_arg // fastn has items in normal order // sp points to top of stack which grows down -bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t **sp_in_out) { +bool mp_execute_byte_code_2(const byte **ip_in_out, mp_obj_t *fastn, mp_obj_t **sp_in_out) { // careful: be sure to declare volatile any variables read in the exception handler (written is ok, I think) const byte *ip = *ip_in_out; - py_obj_t *sp = *sp_in_out; + mp_obj_t *sp = *sp_in_out; machine_uint_t unum; qstr qstr; - py_obj_t obj1, obj2; - py_obj_t fast0 = fastn[0], fast1 = fastn[1], fast2 = fastn[2]; + mp_obj_t obj1, obj2; + mp_obj_t fast0 = fastn[0], fast1 = fastn[1], fast2 = fastn[2]; nlr_buf_t nlr; // on the exception stack we store (ip, sp) for each block @@ -70,182 +72,182 @@ bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t ** for (;;) { int op = *ip++; switch (op) { - case PYBC_LOAD_CONST_FALSE: - PUSH(py_const_false); + case MP_BC_LOAD_CONST_FALSE: + PUSH(mp_const_false); break; - case PYBC_LOAD_CONST_NONE: - PUSH(py_const_none); + case MP_BC_LOAD_CONST_NONE: + PUSH(mp_const_none); break; - case PYBC_LOAD_CONST_TRUE: - PUSH(py_const_true); + case MP_BC_LOAD_CONST_TRUE: + PUSH(mp_const_true); break; - case PYBC_LOAD_CONST_SMALL_INT: + case MP_BC_LOAD_CONST_SMALL_INT: unum = (ip[0] | (ip[1] << 8) | (ip[2] << 16)) - 0x800000; ip += 3; - PUSH((py_obj_t)(unum << 1 | 1)); + PUSH((mp_obj_t)(unum << 1 | 1)); break; - case PYBC_LOAD_CONST_DEC: + case MP_BC_LOAD_CONST_DEC: DECODE_QSTR; PUSH(rt_load_const_dec(qstr)); break; - case PYBC_LOAD_CONST_ID: + case MP_BC_LOAD_CONST_ID: DECODE_QSTR; PUSH(rt_load_const_str(qstr)); // TODO break; - case PYBC_LOAD_CONST_STRING: + case MP_BC_LOAD_CONST_STRING: DECODE_QSTR; PUSH(rt_load_const_str(qstr)); break; - case PYBC_LOAD_FAST_0: + case MP_BC_LOAD_FAST_0: PUSH(fast0); break; - case PYBC_LOAD_FAST_1: + case MP_BC_LOAD_FAST_1: PUSH(fast1); break; - case PYBC_LOAD_FAST_2: + case MP_BC_LOAD_FAST_2: PUSH(fast2); break; - case PYBC_LOAD_FAST_N: + case MP_BC_LOAD_FAST_N: DECODE_UINT; PUSH(fastn[unum]); break; - case PYBC_LOAD_DEREF: + case MP_BC_LOAD_DEREF: DECODE_UINT; PUSH(rt_get_cell(fastn[unum])); break; - case PYBC_LOAD_CLOSURE: + case MP_BC_LOAD_CLOSURE: DECODE_UINT; PUSH(fastn[unum]); break; - case PYBC_LOAD_NAME: + case MP_BC_LOAD_NAME: DECODE_QSTR; PUSH(rt_load_name(qstr)); break; - case PYBC_LOAD_GLOBAL: + case MP_BC_LOAD_GLOBAL: DECODE_QSTR; PUSH(rt_load_global(qstr)); break; - case PYBC_LOAD_ATTR: + case MP_BC_LOAD_ATTR: DECODE_QSTR; SET_TOP(rt_load_attr(TOP(), qstr)); break; - case PYBC_LOAD_METHOD: + case MP_BC_LOAD_METHOD: DECODE_QSTR; sp -= 1; rt_load_method(sp[1], qstr, sp); break; - case PYBC_LOAD_BUILD_CLASS: + case MP_BC_LOAD_BUILD_CLASS: PUSH(rt_load_build_class()); break; - case PYBC_STORE_FAST_0: + case MP_BC_STORE_FAST_0: fast0 = POP(); break; - case PYBC_STORE_FAST_1: + case MP_BC_STORE_FAST_1: fast1 = POP(); break; - case PYBC_STORE_FAST_2: + case MP_BC_STORE_FAST_2: fast2 = POP(); break; - case PYBC_STORE_FAST_N: + case MP_BC_STORE_FAST_N: DECODE_UINT; fastn[unum] = POP(); break; - case PYBC_STORE_DEREF: + case MP_BC_STORE_DEREF: DECODE_UINT; rt_set_cell(fastn[unum], POP()); break; - case PYBC_STORE_NAME: + case MP_BC_STORE_NAME: DECODE_QSTR; rt_store_name(qstr, POP()); break; - case PYBC_STORE_GLOBAL: + case MP_BC_STORE_GLOBAL: DECODE_QSTR; rt_store_global(qstr, POP()); break; - case PYBC_STORE_ATTR: + case MP_BC_STORE_ATTR: DECODE_QSTR; rt_store_attr(sp[0], qstr, sp[1]); sp += 2; break; - case PYBC_STORE_SUBSCR: + case MP_BC_STORE_SUBSCR: rt_store_subscr(sp[1], sp[0], sp[2]); sp += 3; break; - case PYBC_DUP_TOP: + case MP_BC_DUP_TOP: obj1 = TOP(); PUSH(obj1); break; - case PYBC_DUP_TOP_TWO: + case MP_BC_DUP_TOP_TWO: sp -= 2; sp[0] = sp[2]; sp[1] = sp[3]; break; - case PYBC_POP_TOP: + case MP_BC_POP_TOP: ++sp; break; - case PYBC_ROT_TWO: + case MP_BC_ROT_TWO: obj1 = sp[0]; sp[0] = sp[1]; sp[1] = obj1; break; - case PYBC_ROT_THREE: + case MP_BC_ROT_THREE: obj1 = sp[0]; sp[0] = sp[1]; sp[1] = sp[2]; sp[2] = obj1; break; - case PYBC_JUMP: + case MP_BC_JUMP: DECODE_SLABEL; ip += unum; break; - case PYBC_POP_JUMP_IF_TRUE: + case MP_BC_POP_JUMP_IF_TRUE: DECODE_SLABEL; if (rt_is_true(POP())) { ip += unum; } break; - case PYBC_POP_JUMP_IF_FALSE: + case MP_BC_POP_JUMP_IF_FALSE: DECODE_SLABEL; if (!rt_is_true(POP())) { ip += unum; } break; - case PYBC_JUMP_IF_TRUE_OR_POP: + case MP_BC_JUMP_IF_TRUE_OR_POP: DECODE_SLABEL; if (rt_is_true(TOP())) { ip += unum; @@ -254,7 +256,7 @@ bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t ** } break; - case PYBC_JUMP_IF_FALSE_OR_POP: + case MP_BC_JUMP_IF_FALSE_OR_POP: DECODE_SLABEL; if (rt_is_true(TOP())) { sp++; @@ -264,19 +266,19 @@ bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t ** break; /* we are trying to get away without using this opcode - case PYBC_SETUP_LOOP: + case MP_BC_SETUP_LOOP: DECODE_UINT; - // push_block(PYBC_SETUP_LOOP, ip + unum, sp) + // push_block(MP_BC_SETUP_LOOP, ip + unum, sp) break; */ - case PYBC_SETUP_EXCEPT: + case MP_BC_SETUP_EXCEPT: DECODE_ULABEL; // except labels are always forward *++exc_sp = (machine_uint_t)ip + unum; *++exc_sp = (machine_uint_t)sp; break; - case PYBC_END_FINALLY: + case MP_BC_END_FINALLY: // not implemented // if TOS is an exception, reraises the exception (3 values on TOS) // if TOS is an integer, does something else @@ -285,14 +287,14 @@ bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t ** assert(0); break; - case PYBC_GET_ITER: + case MP_BC_GET_ITER: SET_TOP(rt_getiter(TOP())); break; - case PYBC_FOR_ITER: + case MP_BC_FOR_ITER: DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward obj1 = rt_iternext(TOP()); - if (obj1 == py_const_stop_iteration) { + if (obj1 == mp_const_stop_iteration) { ++sp; // pop the exhausted iterator ip += unum; // jump to after for-block } else { @@ -300,110 +302,110 @@ bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t ** } break; - case PYBC_POP_BLOCK: + case MP_BC_POP_BLOCK: // pops block and restores the stack assert(0); break; - case PYBC_POP_EXCEPT: + case MP_BC_POP_EXCEPT: // TODO need to work out how blocks work etc // pops block, checks it's an exception block, and restores the stack, saving the 3 exception values to local threadstate assert(exc_sp >= &exc_stack[0]); - //sp = (py_obj_t*)(*exc_sp--); + //sp = (mp_obj_t*)(*exc_sp--); //exc_sp--; // discard ip exc_sp -= 2; //sp += 3; // pop 3 exception values break; - case PYBC_UNARY_OP: + case MP_BC_UNARY_OP: unum = *ip++; SET_TOP(rt_unary_op(unum, TOP())); break; - case PYBC_BINARY_OP: + case MP_BC_BINARY_OP: unum = *ip++; obj2 = POP(); obj1 = TOP(); SET_TOP(rt_binary_op(unum, obj1, obj2)); break; - case PYBC_COMPARE_OP: + case MP_BC_COMPARE_OP: unum = *ip++; obj2 = POP(); obj1 = TOP(); SET_TOP(rt_compare_op(unum, obj1, obj2)); break; - case PYBC_BUILD_TUPLE: + case MP_BC_BUILD_TUPLE: DECODE_UINT; obj1 = rt_build_tuple(unum, sp); sp += unum - 1; SET_TOP(obj1); break; - case PYBC_BUILD_LIST: + case MP_BC_BUILD_LIST: DECODE_UINT; obj1 = rt_build_list(unum, sp); sp += unum - 1; SET_TOP(obj1); break; - case PYBC_LIST_APPEND: + case MP_BC_LIST_APPEND: DECODE_UINT; // I think it's guaranteed by the compiler that sp[unum] is a list rt_list_append(sp[unum], sp[0]); sp++; break; - case PYBC_BUILD_MAP: + case MP_BC_BUILD_MAP: DECODE_UINT; PUSH(rt_build_map(unum)); break; - case PYBC_STORE_MAP: + case MP_BC_STORE_MAP: sp += 2; rt_store_map(sp[0], sp[-2], sp[-1]); break; - case PYBC_MAP_ADD: + case MP_BC_MAP_ADD: DECODE_UINT; // I think it's guaranteed by the compiler that sp[unum + 1] is a map rt_store_map(sp[unum + 1], sp[0], sp[1]); sp += 2; break; - case PYBC_BUILD_SET: + case MP_BC_BUILD_SET: DECODE_UINT; obj1 = rt_build_set(unum, sp); sp += unum - 1; SET_TOP(obj1); break; - case PYBC_SET_ADD: + case MP_BC_SET_ADD: DECODE_UINT; // I think it's guaranteed by the compiler that sp[unum] is a set rt_store_set(sp[unum], sp[0]); sp++; break; - case PYBC_UNPACK_SEQUENCE: + case MP_BC_UNPACK_SEQUENCE: DECODE_UINT; rt_unpack_sequence(sp[0], unum, sp - unum + 1); sp -= unum - 1; break; - case PYBC_MAKE_FUNCTION: + case MP_BC_MAKE_FUNCTION: DECODE_UINT; PUSH(rt_make_function_from_id(unum)); break; - case PYBC_MAKE_CLOSURE: + case MP_BC_MAKE_CLOSURE: DECODE_UINT; obj1 = POP(); PUSH(rt_make_closure_from_id(unum, obj1)); break; - case PYBC_CALL_FUNCTION: + case MP_BC_CALL_FUNCTION: DECODE_UINT; assert((unum & 0xff00) == 0); // n_keyword unum &= 0xff; // n_positional @@ -411,7 +413,7 @@ bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t ** *sp = rt_call_function_n(*sp, unum, sp - unum); break; - case PYBC_CALL_METHOD: + case MP_BC_CALL_METHOD: DECODE_UINT; if ((unum & 0xff00) == 0) { // no keywords @@ -426,13 +428,13 @@ bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t ** SET_TOP(obj1); break; - case PYBC_RETURN_VALUE: + case MP_BC_RETURN_VALUE: nlr_pop(); *sp_in_out = sp; assert(exc_sp == &exc_stack[-1]); return false; - case PYBC_YIELD_VALUE: + case MP_BC_YIELD_VALUE: nlr_pop(); *ip_in_out = ip; fastn[0] = fast0; @@ -441,13 +443,13 @@ 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: + case MP_BC_IMPORT_NAME: DECODE_QSTR; obj1 = POP(); SET_TOP(rt_import_name(qstr, obj1, TOP())); break; - case PYBC_IMPORT_FROM: + case MP_BC_IMPORT_FROM: DECODE_QSTR; obj1 = rt_import_from(TOP(), qstr); PUSH(obj1); @@ -466,12 +468,12 @@ bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t ** if (exc_sp >= &exc_stack[0]) { // catch exception and pass to byte code - sp = (py_obj_t*)(exc_sp[0]); + sp = (mp_obj_t*)(exc_sp[0]); ip = (const byte*)(exc_sp[-1]); // push(traceback, exc-val, exc-type) - PUSH(py_const_none); + PUSH(mp_const_none); PUSH(nlr.ret_val); - PUSH(py_const_none); + PUSH(mp_const_none); } else { // re-raise exception // TODO what to do if this is a generator?? diff --git a/stm/Makefile b/stm/Makefile index 881771795..1e0831159 100644 --- a/stm/Makefile +++ b/stm/Makefile @@ -23,6 +23,7 @@ SRC_C = \ lexerstm.c \ led.c \ lcd.c \ + servo.c \ flash.c \ storage.c \ mma.c \ @@ -57,6 +58,25 @@ PY_O = \ runtime.o \ map.o \ obj.o \ + objbool.o \ + objboundmeth.o \ + objcell.o \ + objclass.o \ + objclosure.o \ + objcomplex.o \ + objdict.o \ + objexcept.o \ + objfloat.o \ + objfun.o \ + objgenerator.o \ + objinstance.o \ + objlist.o \ + objnone.o \ + objrange.o \ + objset.o \ + objstr.o \ + objtuple.o \ + objtype.o \ builtin.o \ vm.o \ repl.o \ @@ -150,7 +170,7 @@ $(BUILD)/%.o: $(CC3KSRC)/%.c $(BUILD)/%.o: $(PYSRC)/%.s $(AS) -o $@ $< -$(BUILD)/%.o: $(PYSRC)/%.c mpyconfig.h +$(BUILD)/%.o: $(PYSRC)/%.c mpconfig.h $(CC) $(CFLAGS) -c -o $@ $< $(BUILD)/emitnthumb.o: $(PYSRC)/emitnative.c $(PYSRC)/emit.h diff --git a/stm/audio.c b/stm/audio.c index 41614416e..62d2ff2f8 100644 --- a/stm/audio.c +++ b/stm/audio.c @@ -6,9 +6,10 @@ #include "nlr.h" #include "misc.h" -#include "mpyconfig.h" +#include "mpconfig.h" #include "parse.h" #include "compile.h" +#include "obj.h" #include "runtime.h" #include "audio.h" @@ -44,22 +45,22 @@ void audio_drain(void) { } // direct access to DAC -py_obj_t pyb_audio_dac(py_obj_t val) { - DAC_SetChannel2Data(DAC_Align_8b_R, py_obj_get_int(val)); - return py_const_none; +mp_obj_t pyb_audio_dac(mp_obj_t val) { + DAC_SetChannel2Data(DAC_Align_8b_R, mp_obj_get_int(val)); + return mp_const_none; } -py_obj_t pyb_audio_is_full(void) { +mp_obj_t pyb_audio_is_full(void) { if (audio_is_full()) { - return py_const_true; + return mp_const_true; } else { - return py_const_false; + return mp_const_false; } } -py_obj_t pyb_audio_fill(py_obj_t val) { - audio_fill(py_obj_get_int(val)); - return py_const_none; +mp_obj_t pyb_audio_fill(mp_obj_t val) { + audio_fill(mp_obj_get_int(val)); + return mp_const_none; } void audio_init(void) { @@ -90,7 +91,7 @@ void audio_init(void) { // enable interrupt // Python interface - py_obj_t m = py_module_new(); + mp_obj_t m = mp_module_new(); rt_store_attr(m, qstr_from_str_static("dac"), rt_make_function_1(pyb_audio_dac)); rt_store_attr(m, qstr_from_str_static("is_full"), rt_make_function_0(pyb_audio_is_full)); rt_store_attr(m, qstr_from_str_static("fill"), rt_make_function_1(pyb_audio_fill)); diff --git a/stm/lcd.c b/stm/lcd.c index 5d2c67734..cec5bf548 100644 --- a/stm/lcd.c +++ b/stm/lcd.c @@ -3,9 +3,10 @@ #include "nlr.h" #include "misc.h" -#include "mpyconfig.h" +#include "mpconfig.h" #include "parse.h" #include "compile.h" +#include "obj.h" #include "runtime.h" #include "systick.h" @@ -88,16 +89,16 @@ static void lcd_data_out(uint8_t i) { // writes 8 vertical pixels // pos 0 is upper left, pos 1 is 8 pixels to right of that, pos 128 is 8 pixels below that -py_obj_t lcd_draw_pixel_8(py_obj_t py_pos, py_obj_t py_val) { - int pos = py_obj_get_int(py_pos); - int val = py_obj_get_int(py_val); +mp_obj_t lcd_draw_pixel_8(mp_obj_t mp_pos, mp_obj_t mp_val) { + int pos = mp_obj_get_int(mp_pos); + int val = mp_obj_get_int(mp_val); int page = pos / 128; int offset = pos - (page * 128); lcd_out(LCD_INSTR, 0xb0 | page); // page address set lcd_out(LCD_INSTR, 0x10 | ((offset >> 4) & 0x0f)); // column address set upper lcd_out(LCD_INSTR, 0x00 | (offset & 0x0f)); // column address set lower lcd_out(LCD_DATA, val); // write data - return py_const_none; + return mp_const_none; } #define LCD_BUF_W (16) @@ -112,45 +113,45 @@ int lcd_next_line; byte lcd_pix_buf[LCD_PIX_BUF_SIZE]; byte lcd_pix_buf2[LCD_PIX_BUF_SIZE]; -py_obj_t lcd_pix_clear(void) { +mp_obj_t lcd_pix_clear(void) { memset(lcd_pix_buf, 0, LCD_PIX_BUF_SIZE); memset(lcd_pix_buf2, 0, LCD_PIX_BUF_SIZE); - return py_const_none; + return mp_const_none; } -py_obj_t lcd_pix_get(py_obj_t py_x, py_obj_t py_y) { - int x = py_obj_get_int(py_x); - int y = py_obj_get_int(py_y); +mp_obj_t lcd_pix_get(mp_obj_t mp_x, mp_obj_t mp_y) { + int x = mp_obj_get_int(mp_x); + int y = mp_obj_get_int(mp_y); if (0 <= x && x <= 127 && 0 <= y && y <= 31) { uint byte_pos = x + 128 * ((uint)y >> 3); if (lcd_pix_buf[byte_pos] & (1 << (y & 7))) { - return py_obj_new_int(1); + return mp_obj_new_int(1); } } - return py_obj_new_int(0); + return mp_obj_new_int(0); } -py_obj_t lcd_pix_set(py_obj_t py_x, py_obj_t py_y) { - int x = py_obj_get_int(py_x); - int y = py_obj_get_int(py_y); +mp_obj_t lcd_pix_set(mp_obj_t mp_x, mp_obj_t mp_y) { + int x = mp_obj_get_int(mp_x); + int y = mp_obj_get_int(mp_y); if (0 <= x && x <= 127 && 0 <= y && y <= 31) { uint byte_pos = x + 128 * ((uint)y >> 3); lcd_pix_buf2[byte_pos] |= 1 << (y & 7); } - return py_const_none; + return mp_const_none; } -py_obj_t lcd_pix_reset(py_obj_t py_x, py_obj_t py_y) { - int x = py_obj_get_int(py_x); - int y = py_obj_get_int(py_y); +mp_obj_t lcd_pix_reset(mp_obj_t mp_x, mp_obj_t mp_y) { + int x = mp_obj_get_int(mp_x); + int y = mp_obj_get_int(mp_y); if (0 <= x && x <= 127 && 0 <= y && y <= 31) { uint byte_pos = x + 128 * ((uint)y >> 3); lcd_pix_buf2[byte_pos] &= ~(1 << (y & 7)); } - return py_const_none; + return mp_const_none; } -py_obj_t lcd_pix_show(void) { +mp_obj_t lcd_pix_show(void) { memcpy(lcd_pix_buf, lcd_pix_buf2, LCD_PIX_BUF_SIZE); for (uint page = 0; page < 4; page++) { lcd_out(LCD_INSTR, 0xb0 | page); // page address set @@ -160,12 +161,12 @@ py_obj_t lcd_pix_show(void) { lcd_out(LCD_DATA, lcd_pix_buf[i + 128 * page]); } } - return py_const_none; + return mp_const_none; } -py_obj_t lcd_print(py_obj_t text) { - lcd_print_str(qstr_str(py_obj_get_qstr(text))); - return py_const_none; +mp_obj_t lcd_print(mp_obj_t text) { + lcd_print_str(qstr_str(mp_obj_get_qstr(text))); + return mp_const_none; } void lcd_init(void) { @@ -219,7 +220,7 @@ void lcd_init(void) { lcd_next_line = 0; // Python interface - py_obj_t m = py_module_new(); + mp_obj_t m = mp_module_new(); rt_store_attr(m, qstr_from_str_static("lcd8"), rt_make_function_2(lcd_draw_pixel_8)); rt_store_attr(m, qstr_from_str_static("clear"), rt_make_function_0(lcd_pix_clear)); rt_store_attr(m, qstr_from_str_static("get"), rt_make_function_2(lcd_pix_get)); diff --git a/stm/led.c b/stm/led.c index a48ccf5f0..08077641a 100644 --- a/stm/led.c +++ b/stm/led.c @@ -1,5 +1,10 @@ +#include <stdio.h> #include <stm32f4xx.h> #include <stm32f4xx_gpio.h> + +#include "misc.h" +#include "mpconfig.h" +#include "obj.h" #include "led.h" #define PYB_LED_R_PORT (GPIOA) @@ -64,3 +69,60 @@ void led_toggle(pyb_led_t led) { port->BSRRH = pin; } } + +/******************************************************************************/ +/* Micro Python bindings */ + +typedef struct _pyb_led_obj_t { + mp_obj_base_t base; + uint led_id; +} pyb_led_obj_t; + +void led_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) { + pyb_led_obj_t *self = self_in; + print(env, "<LED %lu>", self->led_id); +} + +mp_obj_t led_obj_on(mp_obj_t self_in) { + pyb_led_obj_t *self = self_in; + switch (self->led_id) { + case 1: led_state(PYB_LED_G1, 1); break; + case 2: led_state(PYB_LED_G2, 1); break; + } + return mp_const_none; +} + +mp_obj_t led_obj_off(mp_obj_t self_in) { + pyb_led_obj_t *self = self_in; + switch (self->led_id) { + case 1: led_state(PYB_LED_G1, 0); break; + case 2: led_state(PYB_LED_G2, 0); break; + } + return mp_const_none; +} + +static MP_DEFINE_CONST_FUN_OBJ_1(led_obj_on_obj, led_obj_on); +static MP_DEFINE_CONST_FUN_OBJ_1(led_obj_off_obj, led_obj_off); + +static const mp_obj_type_t led_obj_type = { + { &mp_const_type }, + "Led", + led_obj_print, // print + NULL, // call_n + NULL, // unary_op + NULL, // binary_op + NULL, // getiter + NULL, // iternext + { // method list + { "on", &led_obj_on_obj }, + { "off", &led_obj_off_obj }, + { NULL, NULL }, + } +}; + +mp_obj_t pyb_Led(mp_obj_t led_id) { + pyb_led_obj_t *o = m_new_obj(pyb_led_obj_t); + o->base.type = &led_obj_type; + o->led_id = mp_obj_get_int(led_id); + return o; +} diff --git a/stm/led.h b/stm/led.h index c4b68196b..e6d0c30bc 100644 --- a/stm/led.h +++ b/stm/led.h @@ -8,3 +8,5 @@ typedef enum { void led_init(void); void led_state(pyb_led_t led, int state); void led_toggle(pyb_led_t led); + +mp_obj_t pyb_Led(mp_obj_t led_id); diff --git a/stm/lexerstm.c b/stm/lexerstm.c index 06ea04d1b..4e9905224 100644 --- a/stm/lexerstm.c +++ b/stm/lexerstm.c @@ -7,37 +7,37 @@ #include "lexer.h" #include "lexerstm.h" -unichar str_buf_next_char(py_lexer_str_buf_t *sb) { +unichar str_buf_next_char(mp_lexer_str_buf_t *sb) { if (sb->src_cur < sb->src_end) { return *sb->src_cur++; } else { - return PY_LEXER_CHAR_EOF; + return MP_LEXER_CHAR_EOF; } } -void str_buf_free(py_lexer_str_buf_t *sb) { +void str_buf_free(mp_lexer_str_buf_t *sb) { if (sb->free) { m_free((char*)sb->src_beg); } } -py_lexer_t *py_lexer_new_from_str_len(const char *src_name, const char *str, uint len, bool free_str, py_lexer_str_buf_t *sb) { +mp_lexer_t *mp_lexer_new_from_str_len(const char *src_name, const char *str, uint len, bool free_str, mp_lexer_str_buf_t *sb) { sb->free = free_str; sb->src_beg = str; sb->src_cur = str; sb->src_end = str + len; - return py_lexer_new(src_name, sb, (py_lexer_stream_next_char_t)str_buf_next_char, (py_lexer_stream_close_t)str_buf_free); + return mp_lexer_new(src_name, sb, (mp_lexer_stream_next_char_t)str_buf_next_char, (mp_lexer_stream_close_t)str_buf_free); } -unichar file_buf_next_char(py_lexer_file_buf_t *fb) { +unichar file_buf_next_char(mp_lexer_file_buf_t *fb) { if (fb->pos >= fb->len) { if (fb->len < sizeof(fb->buf)) { - return PY_LEXER_CHAR_EOF; + return MP_LEXER_CHAR_EOF; } else { UINT n; f_read(&fb->fp, fb->buf, sizeof(fb->buf), &n); if (n == 0) { - return PY_LEXER_CHAR_EOF; + return MP_LEXER_CHAR_EOF; } fb->len = n; fb->pos = 0; @@ -46,11 +46,11 @@ unichar file_buf_next_char(py_lexer_file_buf_t *fb) { return fb->buf[fb->pos++]; } -void file_buf_close(py_lexer_file_buf_t *fb) { +void file_buf_close(mp_lexer_file_buf_t *fb) { f_close(&fb->fp); } -py_lexer_t *py_lexer_new_from_file(const char *filename, py_lexer_file_buf_t *fb) { +mp_lexer_t *mp_lexer_new_from_file(const char *filename, mp_lexer_file_buf_t *fb) { FRESULT res = f_open(&fb->fp, filename, FA_READ); if (res != FR_OK) { return NULL; @@ -59,5 +59,5 @@ py_lexer_t *py_lexer_new_from_file(const char *filename, py_lexer_file_buf_t *fb f_read(&fb->fp, fb->buf, sizeof(fb->buf), &n); fb->len = n; fb->pos = 0; - return py_lexer_new(filename, fb, (py_lexer_stream_next_char_t)file_buf_next_char, (py_lexer_stream_close_t)file_buf_close); + return mp_lexer_new(filename, fb, (mp_lexer_stream_next_char_t)file_buf_next_char, (mp_lexer_stream_close_t)file_buf_close); } diff --git a/stm/lexerstm.h b/stm/lexerstm.h index f57d1faa9..7e090898a 100644 --- a/stm/lexerstm.h +++ b/stm/lexerstm.h @@ -3,14 +3,14 @@ typedef struct _py_lexer_str_buf_t { const char *src_beg; // beginning of source const char *src_cur; // current location in source const char *src_end; // end (exclusive) of source -} py_lexer_str_buf_t; +} mp_lexer_str_buf_t; typedef struct _py_lexer_file_buf_t { FIL fp; char buf[20]; uint16_t len; uint16_t pos; -} py_lexer_file_buf_t; +} mp_lexer_file_buf_t; -py_lexer_t *py_lexer_new_from_str_len(const char *src_name, const char *str, uint len, bool free_str, py_lexer_str_buf_t *sb); -py_lexer_t *py_lexer_new_from_file(const char *filename, py_lexer_file_buf_t *fb); +mp_lexer_t *mp_lexer_new_from_str_len(const char *src_name, const char *str, uint len, bool free_str, mp_lexer_str_buf_t *sb); +mp_lexer_t *mp_lexer_new_from_file(const char *filename, mp_lexer_file_buf_t *fb); diff --git a/stm/main.c b/stm/main.c index a262a917e..f45e89985 100644 --- a/stm/main.c +++ b/stm/main.c @@ -13,16 +13,27 @@ #include "std.h" #include "misc.h" -#include "mpyconfig.h" +#include "ff.h" +#include "mpconfig.h" +#include "nlr.h" +#include "misc.h" +#include "lexer.h" +#include "lexerstm.h" +#include "parse.h" +#include "compile.h" +#include "obj.h" +#include "runtime0.h" +#include "runtime.h" +#include "repl.h" #include "gc.h" #include "systick.h" #include "led.h" +#include "servo.h" #include "lcd.h" #include "storage.h" #include "mma.h" #include "usart.h" #include "usb.h" -#include "ff.h" #include "timer.h" #include "audio.h" #include "pybwlan.h" @@ -114,128 +125,43 @@ void __fatal_error(const char *msg) { } } -#include "nlr.h" -#include "misc.h" -#include "lexer.h" -#include "lexerstm.h" -#include "mpyconfig.h" -#include "parse.h" -#include "compile.h" -#include "runtime.h" -#include "obj.h" -#include "repl.h" - static qstr pyb_config_source_dir = 0; static qstr pyb_config_main = 0; -py_obj_t pyb_source_dir(py_obj_t source_dir) { - pyb_config_source_dir = py_obj_get_qstr(source_dir); - return py_const_none; +mp_obj_t pyb_source_dir(mp_obj_t source_dir) { + pyb_config_source_dir = mp_obj_get_qstr(source_dir); + return mp_const_none; } -py_obj_t pyb_main(py_obj_t main) { - pyb_config_main = py_obj_get_qstr(main); - return py_const_none; +mp_obj_t pyb_main(mp_obj_t main) { + pyb_config_main = mp_obj_get_qstr(main); + return mp_const_none; } // sync all file systems -py_obj_t pyb_sync(void) { +mp_obj_t pyb_sync(void) { storage_flush(); - return py_const_none; + return mp_const_none; } -py_obj_t pyb_delay(py_obj_t count) { - sys_tick_delay_ms(py_obj_get_int(count)); - return py_const_none; +mp_obj_t pyb_delay(mp_obj_t count) { + sys_tick_delay_ms(mp_obj_get_int(count)); + return mp_const_none; } -py_obj_t pyb_led(py_obj_t state) { +mp_obj_t pyb_led(mp_obj_t state) { led_state(PYB_LED_G1, rt_is_true(state)); return state; } -void led_obj_print(py_obj_t self) { - machine_uint_t led_id; - py_user_get_data(self, &led_id, NULL); - printf("<LED %lu>", led_id); -} - -py_obj_t led_obj_on(py_obj_t self) { - machine_uint_t led_id; - py_user_get_data(self, &led_id, NULL); - switch (led_id) { - case 1: led_state(PYB_LED_G1, 1); break; - case 2: led_state(PYB_LED_G2, 1); break; - } - return py_const_none; -} - -py_obj_t led_obj_off(py_obj_t self) { - machine_uint_t led_id; - py_user_get_data(self, &led_id, NULL); - switch (led_id) { - case 1: led_state(PYB_LED_G1, 0); break; - case 2: led_state(PYB_LED_G2, 0); break; - } - return py_const_none; -} - -const py_user_info_t led_obj_info = { - "Led", - led_obj_print, - { - {"on", 0, led_obj_on}, - {"off", 0, led_obj_off}, - {NULL, 0, NULL}, - } -}; - -py_obj_t pyb_Led(py_obj_t led_id) { - return py_obj_new_user(&led_obj_info, (machine_uint_t)py_obj_get_int(led_id), 0); -} - -py_obj_t pyb_sw(void) { +mp_obj_t pyb_sw(void) { if (sw_get()) { - return py_const_true; + return mp_const_true; } else { - return py_const_false; + return mp_const_false; } } -void servo_obj_print(py_obj_t self) { - machine_uint_t servo_id; - py_user_get_data(self, &servo_id, NULL); - printf("<Servo %lu>", servo_id); -} - -py_obj_t servo_obj_angle(py_obj_t self, py_obj_t angle) { - machine_uint_t servo_id; - py_user_get_data(self, &servo_id, NULL); - machine_int_t v = 152 + 85.0 * py_obj_get_float(angle) / 90.0; - if (v < 65) { v = 65; } - if (v > 210) { v = 210; } - switch (servo_id) { - case 1: TIM2->CCR1 = v; break; - case 2: TIM2->CCR2 = v; break; - case 3: TIM2->CCR3 = v; break; - case 4: TIM2->CCR4 = v; break; - } - return py_const_none; -} - -const py_user_info_t servo_obj_info = { - "Servo", - servo_obj_print, - { - {"angle", 1, servo_obj_angle}, - {NULL, 0, NULL}, - } -}; - -py_obj_t pyb_Servo(py_obj_t servo_id) { - return py_obj_new_user(&servo_obj_info, (machine_uint_t)py_obj_get_int(servo_id), 0); -} - /* void g(uint i) { printf("g:%d\n", i); @@ -306,13 +232,13 @@ static const char *help_text = ; // get some help about available functions -static py_obj_t pyb_help(void) { +static mp_obj_t pyb_help(void) { printf("%s", help_text); - return py_const_none; + return mp_const_none; } // get lots of info about the board -static py_obj_t pyb_info(void) { +static mp_obj_t pyb_info(void) { // get and print unique id; 96 bits { byte *id = (byte*)0x1fff7a10; @@ -364,14 +290,14 @@ static py_obj_t pyb_info(void) { printf("LFS free: %u bytes\n", (uint)(nclst * fatfs->csize * 512)); } - return py_const_none; + return mp_const_none; } // SD card test -static py_obj_t pyb_sd_test(void) { +static mp_obj_t pyb_sd_test(void) { extern void sdio_init(void); sdio_init(); - return py_const_none; + return mp_const_none; } static void SYSCLKConfig_STOP(void) { @@ -398,7 +324,7 @@ static void SYSCLKConfig_STOP(void) { } } -static py_obj_t pyb_stop(void) { +static mp_obj_t pyb_stop(void) { PWR_EnterSTANDBYMode(); //PWR_FlashPowerDownCmd(ENABLE); don't know what the logic is with this @@ -411,28 +337,28 @@ static py_obj_t pyb_stop(void) { //PWR_FlashPowerDownCmd(DISABLE); - return py_const_none; + return mp_const_none; } -static py_obj_t pyb_standby(void) { +static mp_obj_t pyb_standby(void) { PWR_EnterSTANDBYMode(); - return py_const_none; + return mp_const_none; } -py_obj_t pyb_usart_send(py_obj_t data) { - usart_tx_char(py_obj_get_int(data)); - return py_const_none; +mp_obj_t pyb_usart_send(mp_obj_t data) { + usart_tx_char(mp_obj_get_int(data)); + return mp_const_none; } -py_obj_t pyb_usart_receive(void) { - return py_obj_new_int(usart_rx_char()); +mp_obj_t pyb_usart_receive(void) { + return mp_obj_new_int(usart_rx_char()); } -py_obj_t pyb_usart_status(void) { +mp_obj_t pyb_usart_status(void) { if (usart_rx_any()) { - return py_const_true; + return mp_const_true; } else { - return py_const_false; + return mp_const_false; } } @@ -544,7 +470,7 @@ void do_repl(void) { continue; } - if (py_repl_is_compound_stmt(vstr_str(&line))) { + if (mp_repl_is_compound_stmt(vstr_str(&line))) { for (;;) { vstr_add_char(&line, '\n'); int len = vstr_len(&line); @@ -556,16 +482,16 @@ void do_repl(void) { } } - py_lexer_str_buf_t sb; - py_lexer_t *lex = py_lexer_new_from_str_len("<stdin>", vstr_str(&line), vstr_len(&line), false, &sb); - py_parse_node_t pn = py_parse(lex, PY_PARSE_SINGLE_INPUT); - py_lexer_free(lex); + mp_lexer_str_buf_t sb; + mp_lexer_t *lex = mp_lexer_new_from_str_len("<stdin>", vstr_str(&line), vstr_len(&line), false, &sb); + mp_parse_node_t pn = mp_parse(lex, MP_PARSE_SINGLE_INPUT); + mp_lexer_free(lex); - if (pn != PY_PARSE_NODE_NULL) { - bool comp_ok = py_compile(pn, true); + if (pn != MP_PARSE_NODE_NULL) { + bool comp_ok = mp_compile(pn, true); if (comp_ok) { - py_obj_t module_fun = rt_make_function_from_id(1); - if (module_fun != py_const_none) { + mp_obj_t module_fun = rt_make_function_from_id(1); + if (module_fun != mp_const_none) { nlr_buf_t nlr; uint32_t start = sys_tick_counter; if (nlr_push(&nlr) == 0) { @@ -578,7 +504,7 @@ void do_repl(void) { } } else { // uncaught exception - py_obj_print((py_obj_t)nlr.ret_val); + mp_obj_print((mp_obj_t)nlr.ret_val); printf("\n"); } } @@ -590,28 +516,28 @@ void do_repl(void) { } bool do_file(const char *filename) { - py_lexer_file_buf_t fb; - py_lexer_t *lex = py_lexer_new_from_file(filename, &fb); + mp_lexer_file_buf_t fb; + mp_lexer_t *lex = mp_lexer_new_from_file(filename, &fb); if (lex == NULL) { printf("could not open file '%s' for reading\n", filename); return false; } - py_parse_node_t pn = py_parse(lex, PY_PARSE_FILE_INPUT); - py_lexer_free(lex); + mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT); + mp_lexer_free(lex); - if (pn == PY_PARSE_NODE_NULL) { + if (pn == MP_PARSE_NODE_NULL) { return false; } - bool comp_ok = py_compile(pn, false); + bool comp_ok = mp_compile(pn, false); if (!comp_ok) { return false; } - py_obj_t module_fun = rt_make_function_from_id(1); - if (module_fun == py_const_none) { + mp_obj_t module_fun = rt_make_function_from_id(1); + if (module_fun == mp_const_none) { return false; } @@ -622,7 +548,7 @@ bool do_file(const char *filename) { return true; } else { // uncaught exception - py_obj_print((py_obj_t)nlr.ret_val); + mp_obj_print((mp_obj_t)nlr.ret_val); printf("\n"); return false; } @@ -655,115 +581,16 @@ void gc_collect(void) { } } -py_obj_t pyb_gc(void) { +mp_obj_t pyb_gc(void) { gc_collect(); - return py_const_none; -} - -// PWM -// TIM2 and TIM5 have CH1, CH2, CH3, CH4 on PA0-PA3 respectively -// they are both 32-bit counters -// 16-bit prescaler -// TIM2_CH3 also on PB10 (used below) -void servo_init(void) { - // TIM2 clock enable - RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); - - // for PB10 - /* - // GPIOB Configuration: TIM2_CH3 (PB10) - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; - GPIO_Init(GPIOB, &GPIO_InitStructure); - - // Connect TIM2 pins to AF1 - GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_TIM2); - */ - - // for PA0, PA1, PA2, PA3 - { - // GPIOA Configuration: TIM2_CH0, TIM2_CH1 (PA0, PA1) - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; - GPIO_Init(GPIOA, &GPIO_InitStructure); - - // Connect TIM2 pins to AF1 - GPIO_PinAFConfig(GPIOA, GPIO_PinSource0, GPIO_AF_TIM2); - GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_TIM2); - GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_TIM2); - GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_TIM2); - } - - // Compute the prescaler value so TIM2 runs at 100kHz - uint16_t PrescalerValue = (uint16_t) ((SystemCoreClock / 2) / 100000) - 1; - - // Time base configuration - TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; - TIM_TimeBaseStructure.TIM_Period = 2000; // timer cycles at 50Hz - TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue; - TIM_TimeBaseStructure.TIM_ClockDivision = 0; - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; - TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); - - // PWM Mode configuration - TIM_OCInitTypeDef TIM_OCInitStructure; - TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; - TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; - TIM_OCInitStructure.TIM_Pulse = 150; // units of 10us - TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; - TIM_OC1Init(TIM2, &TIM_OCInitStructure); // channel 1 - TIM_OC2Init(TIM2, &TIM_OCInitStructure); // channel 2 - TIM_OC3Init(TIM2, &TIM_OCInitStructure); // channel 3 - TIM_OC4Init(TIM2, &TIM_OCInitStructure); // channel 4 - - // ? - TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable); // channel 1 - TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable); // channel 2 - TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable); // channel 3 - TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Enable); // channel 4 - - // ? - TIM_ARRPreloadConfig(TIM2, ENABLE); - - // TIM2 enable counter - TIM_Cmd(TIM2, ENABLE); -} - -py_obj_t pyb_servo_set(py_obj_t port, py_obj_t value) { - int p = py_obj_get_int(port); - int v = py_obj_get_int(value); - if (v < 50) { v = 50; } - if (v > 250) { v = 250; } - switch (p) { - case 1: TIM2->CCR1 = v; break; - case 2: TIM2->CCR2 = v; break; - case 3: TIM2->CCR3 = v; break; - case 4: TIM2->CCR4 = v; break; - } - return py_const_none; -} - -py_obj_t pyb_pwm_set(py_obj_t period, py_obj_t pulse) { - int pe = py_obj_get_int(period); - int pu = py_obj_get_int(pulse); - TIM2->ARR = pe; - TIM2->CCR3 = pu; - return py_const_none; + return mp_const_none; } #define MMA_ADDR (0x4c) int mma_buf[12]; -py_obj_t pyb_mma_read(void) { +mp_obj_t pyb_mma_read(void) { for (int i = 0; i <= 6; i += 3) { mma_buf[0 + i] = mma_buf[0 + i + 3]; mma_buf[1 + i] = mma_buf[1 + i + 3]; @@ -782,24 +609,24 @@ py_obj_t pyb_mma_read(void) { } int jolt_info = mma_read_nack(); - py_obj_t data[4]; - data[0] = py_obj_new_int(jolt_info); - data[1] = py_obj_new_int(mma_buf[2] + mma_buf[5] + mma_buf[8] + mma_buf[11]); - data[2] = py_obj_new_int(mma_buf[1] + mma_buf[4] + mma_buf[7] + mma_buf[10]); - data[3] = py_obj_new_int(mma_buf[0] + mma_buf[3] + mma_buf[6] + mma_buf[9]); + mp_obj_t data[4]; + data[0] = mp_obj_new_int(jolt_info); + data[1] = mp_obj_new_int(mma_buf[2] + mma_buf[5] + mma_buf[8] + mma_buf[11]); + data[2] = mp_obj_new_int(mma_buf[1] + mma_buf[4] + mma_buf[7] + mma_buf[10]); + data[3] = mp_obj_new_int(mma_buf[0] + mma_buf[3] + mma_buf[6] + mma_buf[9]); return rt_build_tuple(4, data); // items in reverse order in data } -py_obj_t pyb_hid_send_report(py_obj_t arg) { - py_obj_t *items = py_obj_get_array_fixed_n(arg, 4); +mp_obj_t pyb_hid_send_report(mp_obj_t arg) { + mp_obj_t *items = mp_obj_get_array_fixed_n(arg, 4); uint8_t data[4]; - data[0] = py_obj_get_int(items[0]); - data[1] = py_obj_get_int(items[1]); - data[2] = py_obj_get_int(items[2]); - data[3] = py_obj_get_int(items[3]); + data[0] = mp_obj_get_int(items[0]); + data[1] = mp_obj_get_int(items[1]); + data[2] = mp_obj_get_int(items[2]); + data[3] = mp_obj_get_int(items[3]); usb_hid_send_report(data); - return py_const_none; + return mp_const_none; } static void rtc_init(void) { @@ -855,90 +682,102 @@ static void rtc_init(void) { //RTC_WriteBackupRegister(RTC_BKP_DR0, 0x32F2); } -py_obj_t pyb_rtc_read(void) { +mp_obj_t pyb_rtc_read(void) { RTC_TimeTypeDef RTC_TimeStructure; RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure); printf("%02d:%02d:%02d\n", RTC_TimeStructure.RTC_Hours, RTC_TimeStructure.RTC_Minutes, RTC_TimeStructure.RTC_Seconds); - return py_const_none; + return mp_const_none; } -void file_obj_print(py_obj_t o) { - FIL *fp; - py_user_get_data(o, (machine_uint_t*)&fp, NULL); - printf("<file %p>", fp); +typedef struct _pyb_file_obj_t { + mp_obj_base_t base; + FIL fp; +} pyb_file_obj_t; + +void file_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) { + printf("<file %p>", self_in); } -py_obj_t file_obj_read(py_obj_t self, py_obj_t arg) { - FIL *fp; - py_user_get_data(self, (machine_uint_t*)&fp, NULL); - int n = py_obj_get_int(arg); +mp_obj_t file_obj_read(mp_obj_t self_in, mp_obj_t arg) { + pyb_file_obj_t *self = self_in; + int n = mp_obj_get_int(arg); char *buf = m_new(char, n + 1); UINT n_out; - f_read(fp, buf, n, &n_out); + f_read(&self->fp, buf, n, &n_out); buf[n_out] = 0; - return py_obj_new_str(qstr_from_str_take(buf)); + return mp_obj_new_str(qstr_from_str_take(buf)); } -py_obj_t file_obj_write(py_obj_t self, py_obj_t arg) { - FIL *fp; - py_user_get_data(self, (machine_uint_t*)&fp, NULL); - const char *s = qstr_str(py_obj_get_qstr(arg)); +mp_obj_t file_obj_write(mp_obj_t self_in, mp_obj_t arg) { + pyb_file_obj_t *self = self_in; + const char *s = qstr_str(mp_obj_get_qstr(arg)); UINT n_out; - FRESULT res = f_write(fp, s, strlen(s), &n_out); + FRESULT res = f_write(&self->fp, s, strlen(s), &n_out); if (res != FR_OK) { printf("File error: could not write to file; error code %d\n", res); } else if (n_out != strlen(s)) { printf("File error: could not write all data to file; wrote %d / %d bytes\n", n_out, strlen(s)); } - return py_const_none; + return mp_const_none; } -py_obj_t file_obj_close(py_obj_t self) { - FIL *fp; - py_user_get_data(self, (machine_uint_t*)&fp, NULL); - f_close(fp); - return py_const_none; +mp_obj_t file_obj_close(mp_obj_t self_in) { + pyb_file_obj_t *self = self_in; + f_close(&self->fp); + return mp_const_none; } +static MP_DEFINE_CONST_FUN_OBJ_2(file_obj_read_obj, file_obj_read); +static MP_DEFINE_CONST_FUN_OBJ_2(file_obj_write_obj, file_obj_write); +static MP_DEFINE_CONST_FUN_OBJ_1(file_obj_close_obj, file_obj_close); + // TODO gc hook to close the file if not already closed -const py_user_info_t file_obj_info = { + +static const mp_obj_type_t file_obj_type = { + { &mp_const_type }, "File", - file_obj_print, - { - {"read", 1, file_obj_read}, - {"write", 1, file_obj_write}, - {"close", 0, file_obj_close}, - {NULL, 0, NULL}, + file_obj_print, // print + NULL, // call_n + NULL, // unary_op + NULL, // binary_op + NULL, // getiter + NULL, // iternext + { // method list + { "read", &file_obj_read_obj }, + { "write", &file_obj_write_obj }, + { "close", &file_obj_close_obj }, + {NULL, NULL}, } }; -py_obj_t pyb_io_open(py_obj_t o_filename, py_obj_t o_mode) { - const char *filename = qstr_str(py_obj_get_qstr(o_filename)); - const char *mode = qstr_str(py_obj_get_qstr(o_mode)); - FIL *fp = m_new(FIL, 1); +mp_obj_t pyb_io_open(mp_obj_t o_filename, mp_obj_t o_mode) { + const char *filename = qstr_str(mp_obj_get_qstr(o_filename)); + const char *mode = qstr_str(mp_obj_get_qstr(o_mode)); + pyb_file_obj_t *self = m_new_obj(pyb_file_obj_t); + self->base.type = &file_obj_type; if (mode[0] == 'r') { // open for reading - FRESULT res = f_open(fp, filename, FA_READ); + FRESULT res = f_open(&self->fp, filename, FA_READ); if (res != FR_OK) { printf("FileNotFoundError: [Errno 2] No such file or directory: '%s'\n", filename); - return py_const_none; + return mp_const_none; } } else if (mode[0] == 'w') { // open for writing, truncate the file first - FRESULT res = f_open(fp, filename, FA_WRITE | FA_CREATE_ALWAYS); + FRESULT res = f_open(&self->fp, filename, FA_WRITE | FA_CREATE_ALWAYS); if (res != FR_OK) { printf("?FileError: could not create file: '%s'\n", filename); - return py_const_none; + return mp_const_none; } } else { printf("ValueError: invalid mode: '%s'\n", mode); - return py_const_none; + return mp_const_none; } - return py_obj_new_user(&file_obj_info, (machine_uint_t)fp, 0); + return self; } -py_obj_t pyb_rng_get(void) { - return py_obj_new_int(RNG_GetRandomNumber() >> 16); +mp_obj_t pyb_rng_get(void) { + return mp_obj_new_int(RNG_GetRandomNumber() >> 16); } int main(void) { @@ -1015,7 +854,7 @@ soft_reset: { rt_store_name(qstr_from_str_static("help"), rt_make_function_0(pyb_help)); - py_obj_t m = py_module_new(); + mp_obj_t m = mp_module_new(); rt_store_attr(m, qstr_from_str_static("info"), rt_make_function_0(pyb_info)); rt_store_attr(m, qstr_from_str_static("sd_test"), rt_make_function_0(pyb_sd_test)); rt_store_attr(m, qstr_from_str_static("stop"), rt_make_function_0(pyb_stop)); @@ -1312,19 +1151,19 @@ soft_reset: " pass\n" "f()\n"; - py_lexer_str_buf_t py_lexer_str_buf; - py_lexer_t *lex = py_lexer_new_from_str_len("<stdin>", pysrc, strlen(pysrc), false, &py_lexer_str_buf); + mp_lexer_str_buf_t mp_lexer_str_buf; + mp_lexer_t *lex = mp_lexer_new_from_str_len("<stdin>", pysrc, strlen(pysrc), false, &mp_lexer_str_buf); // nalloc=1740;6340;6836 -> 140;4600;496 bytes for lexer, parser, compiler printf("lex; al=%u\n", m_get_total_bytes_allocated()); sys_tick_delay_ms(1000); - py_parse_node_t pn = py_parse(lex, PY_PARSE_FILE_INPUT); - py_lexer_free(lex); - if (pn != PY_PARSE_NODE_NULL) { + mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT); + mp_lexer_free(lex); + if (pn != MP_PARSE_NODE_NULL) { printf("pars;al=%u\n", m_get_total_bytes_allocated()); sys_tick_delay_ms(1000); //parse_node_show(pn, 0); - bool comp_ok = py_compile(pn, false); + bool comp_ok = mp_compile(pn, false); printf("comp;al=%u\n", m_get_total_bytes_allocated()); sys_tick_delay_ms(1000); @@ -1333,7 +1172,7 @@ soft_reset: } else { // execute it! - py_obj_t module_fun = rt_make_function_from_id(1); + mp_obj_t module_fun = rt_make_function_from_id(1); // flash once led_state(PYB_LED_G1, 1); @@ -1342,15 +1181,15 @@ soft_reset: nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { - py_obj_t ret = rt_call_function_0(module_fun); + mp_obj_t ret = rt_call_function_0(module_fun); printf("done! got: "); - py_obj_print(ret); + mp_obj_print(ret); printf("\n"); nlr_pop(); } else { // uncaught exception printf("exception: "); - py_obj_print((py_obj_t)nlr.ret_val); + mp_obj_print((mp_obj_t)nlr.ret_val); printf("\n"); } diff --git a/stm/malloc0.c b/stm/malloc0.c index 7157252ed..7e3f620db 100644 --- a/stm/malloc0.c +++ b/stm/malloc0.c @@ -1,6 +1,6 @@ #include <stdint.h> #include "std.h" -#include "mpyconfig.h" +#include "mpconfig.h" #include "gc.h" #if 0 diff --git a/stm/mpyconfig.h b/stm/mpconfig.h similarity index 89% rename from stm/mpyconfig.h rename to stm/mpconfig.h index 3fa3ac652..1f9529e11 100644 --- a/stm/mpyconfig.h +++ b/stm/mpconfig.h @@ -13,6 +13,7 @@ typedef int32_t machine_int_t; // must be pointer size typedef uint32_t machine_uint_t; // must be pointer size typedef void *machine_ptr_t; // must be of pointer size +typedef const void *machine_const_ptr_t; // must be of pointer size typedef float machine_float_t; machine_float_t machine_sqrt(machine_float_t x); diff --git a/stm/pybwlan.c b/stm/pybwlan.c index 3d1f216f8..863c241b6 100644 --- a/stm/pybwlan.c +++ b/stm/pybwlan.c @@ -11,7 +11,7 @@ #include "std.h" #include "misc.h" -#include "mpyconfig.h" +#include "mpconfig.h" #include "systick.h" #include "nlr.h" @@ -19,6 +19,7 @@ #include "lexer.h" #include "parse.h" #include "compile.h" +#include "obj.h" #include "runtime.h" #include "cc3k/ccspi.h" @@ -28,27 +29,27 @@ #include "cc3k/wlan.h" #include "cc3k/nvmem.h" -py_obj_t pyb_wlan_connect(int n_args, const py_obj_t *args) { +mp_obj_t pyb_wlan_connect(int n_args, const mp_obj_t *args) { const char *ap; const char *key; if (n_args == 2) { - ap = qstr_str(py_obj_get_qstr(args[0])); - key = qstr_str(py_obj_get_qstr(args[1])); + ap = qstr_str(mp_obj_get_qstr(args[0])); + key = qstr_str(mp_obj_get_qstr(args[1])); } else { - ap = "Rama3"; - key = "underthechristmastree"; + ap = "your-ssid"; + key = "your-password"; } // might want to set wlan_ioctl_set_connection_policy int ret = wlan_connect(WLAN_SEC_WPA2, ap, strlen(ap), NULL, (byte*)key, strlen(key)); - return py_obj_new_int(ret); + return mp_obj_new_int(ret); } -py_obj_t pyb_wlan_disconnect(void) { +mp_obj_t pyb_wlan_disconnect(void) { int ret = wlan_disconnect(); - return py_obj_new_int(ret); + return mp_obj_new_int(ret); } -py_obj_t decode_addr(unsigned char *ip, int nBytes) { +mp_obj_t decode_addr(unsigned char *ip, int nBytes) { char data[64] = ""; if (nBytes == 4) { snprintf(data, 64, "%u.%u.%u.%u", ip[3], ip[2], ip[1], ip[0]); @@ -57,21 +58,21 @@ py_obj_t decode_addr(unsigned char *ip, int nBytes) { } else if (nBytes == 32) { snprintf(data, 64, "%s", ip); } - return py_obj_new_str(qstr_from_strn_copy(data, strlen(data))); + return mp_obj_new_str(qstr_from_strn_copy(data, strlen(data))); } -void _wlan_getIP_get_address(py_obj_t object, qstr q_attr, unsigned char *ip, int nBytes) { +void _wlan_getIP_get_address(mp_obj_t object, qstr q_attr, unsigned char *ip, int nBytes) { rt_store_attr(object, q_attr, decode_addr(ip, nBytes)); } -py_obj_t pyb_wlan_get_ip(void) { +mp_obj_t pyb_wlan_get_ip(void) { tNetappIpconfigRetArgs ipconfig; netapp_ipconfig(&ipconfig); /* If byte 1 is 0 we don't have a valid address */ - if (ipconfig.aucIP[3] == 0) return py_const_none; + if (ipconfig.aucIP[3] == 0) return mp_const_none; - py_obj_t data = py_module_new(); // TODO should really be a class + mp_obj_t data = mp_module_new(); // TODO should really be a class _wlan_getIP_get_address(data, qstr_from_str_static("ip"), &ipconfig.aucIP[0], 4); _wlan_getIP_get_address(data, qstr_from_str_static("subnet"), &ipconfig.aucSubnetMask[0], 4); _wlan_getIP_get_address(data, qstr_from_str_static("gateway"), &ipconfig.aucDefaultGateway[0], 4); @@ -84,16 +85,16 @@ py_obj_t pyb_wlan_get_ip(void) { } uint32_t last_ip = 0; // XXX such a hack! -py_obj_t pyb_wlan_get_host(py_obj_t host_name) { - const char *host = qstr_str(py_obj_get_qstr(host_name)); +mp_obj_t pyb_wlan_get_host(mp_obj_t host_name) { + const char *host = qstr_str(mp_obj_get_qstr(host_name)); uint32_t ip; if (gethostbyname(host, strlen(host), &ip) < 0) { printf("gethostbyname failed\n"); - return py_const_none; + return mp_const_none; } if (ip == 0) { // unknown host - return py_const_none; + return mp_const_none; } last_ip = ip; byte ip_data[4]; @@ -104,19 +105,17 @@ py_obj_t pyb_wlan_get_host(py_obj_t host_name) { return decode_addr(ip_data, 4); } -py_obj_t py_obj_new_exception_2(qstr, const char *, void*, void*); - -py_obj_t pyb_wlan_http_get(py_obj_t host_name, py_obj_t host_path) { - if (host_name == py_const_none) { +mp_obj_t pyb_wlan_http_get(mp_obj_t host_name, mp_obj_t host_path) { + if (host_name == mp_const_none) { last_ip = (192 << 24) | (168 << 16) | (0 << 8) | (3); } else { - if (pyb_wlan_get_host(host_name) == py_const_none) { - nlr_jump(py_obj_new_exception_2(qstr_from_str_static("WlanError"), "unknown host", NULL, NULL)); + if (pyb_wlan_get_host(host_name) == mp_const_none) { + nlr_jump(mp_obj_new_exception_msg(qstr_from_str_static("WlanError"), "unknown host")); } } int sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sd < 0) { - nlr_jump(py_obj_new_exception_2(qstr_from_str_static("WlanError"), "socket failed: %d", (void*)sd, NULL)); + nlr_jump(mp_obj_new_exception_msg_1_arg(qstr_from_str_static("WlanError"), "socket failed: %d", (void*)sd)); } //printf("socket seemed to work\n"); //sys_tick_delay_ms(200); @@ -127,13 +126,13 @@ py_obj_t pyb_wlan_http_get(py_obj_t host_name, py_obj_t host_path) { remote.sin_addr.s_addr = htonl(last_ip); int ret = connect(sd, (sockaddr*)&remote, sizeof(sockaddr)); if (ret != 0) { - nlr_jump(py_obj_new_exception_2(qstr_from_str_static("WlanError"), "connect failed: %d", (void*)ret, NULL)); + nlr_jump(mp_obj_new_exception_msg_1_arg(qstr_from_str_static("WlanError"), "connect failed: %d", (void*)ret)); } //printf("connect seemed to work\n"); //sys_tick_delay_ms(200); vstr_t *vstr = vstr_new(); - vstr_printf(vstr, "GET %s HTTP/1.1\r\nHost: %s\r\nUser-Agent: PYBv2\r\n\r\n", qstr_str(py_obj_get_qstr(host_path)), qstr_str(py_obj_get_qstr(host_name))); + vstr_printf(vstr, "GET %s HTTP/1.1\r\nHost: %s\r\nUser-Agent: PYBv2\r\n\r\n", qstr_str(mp_obj_get_qstr(host_path)), qstr_str(mp_obj_get_qstr(host_name))); const char *query = vstr_str(vstr); // send query @@ -148,7 +147,7 @@ py_obj_t pyb_wlan_http_get(py_obj_t host_name, py_obj_t host_path) { ret = send(sd, query + sent, strlen(query + sent), 0); //printf("sent %d bytes\n", ret); if (ret < 0) { - nlr_jump(py_obj_new_exception_2(qstr_from_str_static("WlanError"), "send failed", NULL, NULL)); + nlr_jump(mp_obj_new_exception_msg(qstr_from_str_static("WlanError"), "send failed")); } sent += ret; //sys_tick_delay_ms(200); @@ -159,7 +158,7 @@ py_obj_t pyb_wlan_http_get(py_obj_t host_name, py_obj_t host_path) { //sys_tick_delay_ms(5000); // receive reply - py_obj_t py_ret = py_const_none; + mp_obj_t mp_ret = mp_const_none; { //printf("doing receive\n"); char buf[64]; @@ -185,33 +184,33 @@ py_obj_t pyb_wlan_http_get(py_obj_t host_name, py_obj_t host_path) { // read data ret = recv(sd, buf, 64, 0); if (ret < 0) { - nlr_jump(py_obj_new_exception_2(qstr_from_str_static("WlanError"), "recv failed %d", (void*)ret, NULL)); + nlr_jump(mp_obj_new_exception_msg_1_arg(qstr_from_str_static("WlanError"), "recv failed %d", (void*)ret)); } vstr_add_strn(vstr, buf, ret); } - py_ret = py_obj_new_str(qstr_from_str_take(vstr_str(vstr))); + mp_ret = mp_obj_new_str(qstr_from_str_take(vstr_str(vstr))); } closesocket(sd); - return py_ret; + return mp_ret; } -py_obj_t pyb_wlan_serve(void) { +mp_obj_t pyb_wlan_serve(void) { printf("serve socket\n"); int sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); printf("serve socket got %d\n", sd); sys_tick_delay_ms(500); if (sd < 0) { printf("socket fail\n"); - nlr_jump(py_obj_new_exception_2(qstr_from_str_static("WlanError"), "socket failed: %d", (void*)sd, NULL)); + nlr_jump(mp_obj_new_exception_msg_1_arg(qstr_from_str_static("WlanError"), "socket failed: %d", (void*)sd)); } /* if (setsockopt(sd, SOL_SOCKET, SOCKOPT_ACCEPT_NONBLOCK, SOCK_ON, sizeof(SOCK_ON)) < 0) { printf("couldn't set socket as non-blocking\n"); - return py_const_none; + return mp_const_none; } */ @@ -226,7 +225,7 @@ py_obj_t pyb_wlan_serve(void) { sys_tick_delay_ms(100); if (ret != 0) { printf("bind fail\n"); - nlr_jump(py_obj_new_exception_2(qstr_from_str_static("WlanError"), "bind failed: %d", (void*)ret, NULL)); + nlr_jump(mp_obj_new_exception_msg_1_arg(qstr_from_str_static("WlanError"), "bind failed: %d", (void*)ret)); } printf("bind seemed to work\n"); @@ -268,7 +267,7 @@ py_obj_t pyb_wlan_serve(void) { closesocket(fd); closesocket(sd); - return py_const_none; + return mp_const_none; } //***************************************************************************** @@ -344,7 +343,7 @@ void pyb_wlan_init(void) { SpiInit(); wlan_init(CC3000_UsynchCallback, sendWLFWPatch, sendDriverPatch, sendBootLoaderPatch, ReadWlanInterruptPin, WlanInterruptEnable, WlanInterruptDisable, WriteWlanPin); - py_obj_t m = py_module_new(); + mp_obj_t m = mp_module_new(); rt_store_attr(m, qstr_from_str_static("connect"), rt_make_function_var(0, pyb_wlan_connect)); rt_store_attr(m, qstr_from_str_static("disconnect"), rt_make_function_0(pyb_wlan_disconnect)); rt_store_attr(m, qstr_from_str_static("ip"), rt_make_function_0(pyb_wlan_get_ip)); diff --git a/stm/servo.c b/stm/servo.c new file mode 100644 index 000000000..ae421048b --- /dev/null +++ b/stm/servo.c @@ -0,0 +1,160 @@ +#include <stdio.h> +#include <stm32f4xx.h> +#include <stm32f4xx_rcc.h> +#include <stm32f4xx_gpio.h> +#include <stm32f4xx_tim.h> + +#include "misc.h" +#include "mpconfig.h" +#include "obj.h" +#include "servo.h" + +// PWM +// TIM2 and TIM5 have CH1, CH2, CH3, CH4 on PA0-PA3 respectively +// they are both 32-bit counters +// 16-bit prescaler +// TIM2_CH3 also on PB10 (used below) +void servo_init(void) { + // TIM2 clock enable + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); + + // for PB10 + /* + // GPIOB Configuration: TIM2_CH3 (PB10) + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(GPIOB, &GPIO_InitStructure); + + // Connect TIM2 pins to AF1 + GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_TIM2); + */ + + // for PA0, PA1, PA2, PA3 + { + // GPIOA Configuration: TIM2_CH0, TIM2_CH1 (PA0, PA1) + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + // Connect TIM2 pins to AF1 + GPIO_PinAFConfig(GPIOA, GPIO_PinSource0, GPIO_AF_TIM2); + GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_TIM2); + GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_TIM2); + GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_TIM2); + } + + // Compute the prescaler value so TIM2 runs at 100kHz + uint16_t PrescalerValue = (uint16_t) ((SystemCoreClock / 2) / 100000) - 1; + + // Time base configuration + TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; + TIM_TimeBaseStructure.TIM_Period = 2000; // timer cycles at 50Hz + TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue; + TIM_TimeBaseStructure.TIM_ClockDivision = 0; + TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; + TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); + + // PWM Mode configuration + TIM_OCInitTypeDef TIM_OCInitStructure; + TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; + TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; + TIM_OCInitStructure.TIM_Pulse = 150; // units of 10us + TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; + TIM_OC1Init(TIM2, &TIM_OCInitStructure); // channel 1 + TIM_OC2Init(TIM2, &TIM_OCInitStructure); // channel 2 + TIM_OC3Init(TIM2, &TIM_OCInitStructure); // channel 3 + TIM_OC4Init(TIM2, &TIM_OCInitStructure); // channel 4 + + // ? + TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable); // channel 1 + TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable); // channel 2 + TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable); // channel 3 + TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Enable); // channel 4 + + // ? + TIM_ARRPreloadConfig(TIM2, ENABLE); + + // TIM2 enable counter + TIM_Cmd(TIM2, ENABLE); +} + +/******************************************************************************/ +/* Micro Python bindings */ + +mp_obj_t pyb_servo_set(mp_obj_t port, mp_obj_t value) { + int p = mp_obj_get_int(port); + int v = mp_obj_get_int(value); + if (v < 50) { v = 50; } + if (v > 250) { v = 250; } + switch (p) { + case 1: TIM2->CCR1 = v; break; + case 2: TIM2->CCR2 = v; break; + case 3: TIM2->CCR3 = v; break; + case 4: TIM2->CCR4 = v; break; + } + return mp_const_none; +} + +mp_obj_t pyb_pwm_set(mp_obj_t period, mp_obj_t pulse) { + int pe = mp_obj_get_int(period); + int pu = mp_obj_get_int(pulse); + TIM2->ARR = pe; + TIM2->CCR3 = pu; + return mp_const_none; +} + +typedef struct _pyb_servo_obj_t { + mp_obj_base_t base; + uint servo_id; +} pyb_servo_obj_t; + +static void servo_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) { + pyb_servo_obj_t *self = self_in; + print(env, "<Servo %lu>", self->servo_id); +} + +static mp_obj_t servo_obj_angle(mp_obj_t self_in, mp_obj_t angle) { + pyb_servo_obj_t *self = self_in; + machine_int_t v = 152 + 85.0 * mp_obj_get_float(angle) / 90.0; + if (v < 65) { v = 65; } + if (v > 210) { v = 210; } + switch (self->servo_id) { + case 1: TIM2->CCR1 = v; break; + case 2: TIM2->CCR2 = v; break; + case 3: TIM2->CCR3 = v; break; + case 4: TIM2->CCR4 = v; break; + } + return mp_const_none; +} + +static MP_DEFINE_CONST_FUN_OBJ_2(servo_obj_angle_obj, servo_obj_angle); + +static const mp_obj_type_t servo_obj_type = { + { &mp_const_type }, + "Servo", + servo_obj_print, // print + NULL, // call_n + NULL, // unary_op + NULL, // binary_op + NULL, // getiter + NULL, // iternext + { // method list + { "angle", &servo_obj_angle_obj }, + { NULL, NULL }, + } +}; + +mp_obj_t pyb_Servo(mp_obj_t servo_id) { + pyb_servo_obj_t *o = m_new_obj(pyb_servo_obj_t); + o->base.type = &servo_obj_type; + o->servo_id = mp_obj_get_int(servo_id); + return o; +} diff --git a/stm/servo.h b/stm/servo.h new file mode 100644 index 000000000..02702e067 --- /dev/null +++ b/stm/servo.h @@ -0,0 +1,5 @@ +void servo_init(void); + +mp_obj_t pyb_servo_set(mp_obj_t port, mp_obj_t value); +mp_obj_t pyb_pwm_set(mp_obj_t period, mp_obj_t pulse); +mp_obj_t pyb_Servo(mp_obj_t servo_id); diff --git a/stm/stm32fxxx_it.c b/stm/stm32fxxx_it.c index 0f17681e5..4c185d034 100644 --- a/stm/stm32fxxx_it.c +++ b/stm/stm32fxxx_it.c @@ -267,6 +267,9 @@ void TIM6_DAC_IRQHandler(void) { } #include "std.h" +#include "misc.h" +#include "mpconfig.h" +#include "obj.h" #include "led.h" // EXTI // for USRSW on A13 diff --git a/stm/storage.c b/stm/storage.c index ac0458d13..6878de22e 100644 --- a/stm/storage.c +++ b/stm/storage.c @@ -3,6 +3,8 @@ #include "misc.h" #include "systick.h" +#include "mpconfig.h" +#include "obj.h" #include "led.h" #include "flash.h" #include "storage.h" diff --git a/stm/timer.c b/stm/timer.c index ecfc2bb28..2236bbce4 100644 --- a/stm/timer.c +++ b/stm/timer.c @@ -7,37 +7,38 @@ #include "nlr.h" #include "misc.h" -#include "mpyconfig.h" +#include "mpconfig.h" #include "parse.h" #include "compile.h" +#include "obj.h" #include "runtime.h" #include "timer.h" // TIM6 is used as an internal interrup to schedule something at a specific rate -py_obj_t timer_py_callback; +mp_obj_t timer_py_callback; -py_obj_t timer_py_set_callback(py_obj_t f) { +mp_obj_t timer_py_set_callback(mp_obj_t f) { timer_py_callback = f; - return py_const_none; + return mp_const_none; } -py_obj_t timer_py_set_period(py_obj_t period) { - TIM6->ARR = py_obj_get_int(period) & 0xffff; - return py_const_none; +mp_obj_t timer_py_set_period(mp_obj_t period) { + TIM6->ARR = mp_obj_get_int(period) & 0xffff; + return mp_const_none; } -py_obj_t timer_py_set_prescaler(py_obj_t prescaler) { - TIM6->PSC = py_obj_get_int(prescaler) & 0xffff; - return py_const_none; +mp_obj_t timer_py_set_prescaler(mp_obj_t prescaler) { + TIM6->PSC = mp_obj_get_int(prescaler) & 0xffff; + return mp_const_none; } -py_obj_t timer_py_get_value(void) { - return py_obj_new_int(TIM6->CNT & 0xfffff); +mp_obj_t timer_py_get_value(void) { + return mp_obj_new_int(TIM6->CNT & 0xfffff); } void timer_init(void) { - timer_py_callback = py_const_none; + timer_py_callback = mp_const_none; // TIM6 clock enable RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); @@ -71,7 +72,7 @@ void timer_init(void) { TIM_Cmd(TIM6, ENABLE); // Python interface - py_obj_t m = py_module_new(); + mp_obj_t m = mp_module_new(); rt_store_attr(m, qstr_from_str_static("callback"), rt_make_function_1(timer_py_set_callback)); rt_store_attr(m, qstr_from_str_static("period"), rt_make_function_1(timer_py_set_period)); rt_store_attr(m, qstr_from_str_static("prescaler"), rt_make_function_1(timer_py_set_prescaler)); @@ -80,7 +81,7 @@ void timer_init(void) { } void timer_interrupt(void) { - if (timer_py_callback != py_const_none) { + if (timer_py_callback != mp_const_none) { nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { // XXX what to do if the GC is in the middle of running?? @@ -89,7 +90,7 @@ void timer_interrupt(void) { } else { // uncaught exception printf("exception in timer interrupt\n"); - py_obj_print((py_obj_t)nlr.ret_val); + mp_obj_print((mp_obj_t)nlr.ret_val); printf("\n"); } } diff --git a/unix/Makefile b/unix/Makefile index 76cc0a385..463f6b170 100644 --- a/unix/Makefile +++ b/unix/Makefile @@ -31,6 +31,25 @@ PY_O = \ runtime.o \ map.o \ obj.o \ + objbool.o \ + objboundmeth.o \ + objcell.o \ + objclass.o \ + objclosure.o \ + objcomplex.o \ + objdict.o \ + objexcept.o \ + objfloat.o \ + objfun.o \ + objgenerator.o \ + objinstance.o \ + objlist.o \ + objnone.o \ + objrange.o \ + objset.o \ + objstr.o \ + objtuple.o \ + objtype.o \ builtin.o \ vm.o \ showbc.o \ @@ -42,6 +61,8 @@ PROG = py $(PROG): $(BUILD) $(OBJ) $(CC) -o $@ $(OBJ) $(LIB) $(LDFLAGS) + strip $(PROG) + size $(PROG) $(BUILD): mkdir $@ @@ -52,7 +73,7 @@ $(BUILD)/%.o: %.c $(BUILD)/%.o: $(PYSRC)/%.s $(AS) -o $@ $< -$(BUILD)/%.o: $(PYSRC)/%.c mpyconfig.h +$(BUILD)/%.o: $(PYSRC)/%.c mpconfig.h $(CC) $(CFLAGS) -c -o $@ $< $(BUILD)/emitnx64.o: $(PYSRC)/emitnative.c $(PYSRC)/emit.h @@ -65,7 +86,7 @@ $(BUILD)/emitnthumb.o: $(PYSRC)/emitnative.c $(PYSRC)/emit.h $(BUILD)/vm.o: $(PYSRC)/vm.c $(CC) $(CFLAGS) -O3 -c -o $@ $< -$(BUILD)/main.o: mpyconfig.h +$(BUILD)/main.o: mpconfig.h $(BUILD)/parse.o: $(PYSRC)/grammar.h $(BUILD)/compile.o: $(PYSRC)/grammar.h $(BUILD)/emitcpy.o: $(PYSRC)/emit.h diff --git a/unix/lexerunix.c b/unix/lexerunix.c index e76d7f2c2..ac07781b5 100644 --- a/unix/lexerunix.c +++ b/unix/lexerunix.c @@ -17,7 +17,7 @@ unichar str_buf_next_char(str_buf_t *sb) { if (sb->src_cur < sb->src_end) { return *sb->src_cur++; } else { - return PY_LEXER_CHAR_EOF; + return MP_LEXER_CHAR_EOF; } } @@ -30,16 +30,16 @@ void str_buf_free(str_buf_t *sb) { } } -py_lexer_t *py_lexer_new_from_str_len(const char *src_name, const char *str, uint len, bool free_str) { +mp_lexer_t *mp_lexer_new_from_str_len(const char *src_name, const char *str, uint len, bool free_str) { str_buf_t *sb = m_new(str_buf_t, 1); sb->free = free_str; sb->src_beg = str; sb->src_cur = str; sb->src_end = str + len; - return py_lexer_new(src_name, sb, (py_lexer_stream_next_char_t)str_buf_next_char, (py_lexer_stream_close_t)str_buf_free); + return mp_lexer_new(src_name, sb, (mp_lexer_stream_next_char_t)str_buf_next_char, (mp_lexer_stream_close_t)str_buf_free); } -py_lexer_t *py_lexer_new_from_file(const char *filename) { +mp_lexer_t *mp_lexer_new_from_file(const char *filename) { int fd = open(filename, O_RDONLY); if (fd < 0) { printf("cannot open file %s\n", filename); @@ -51,5 +51,5 @@ py_lexer_t *py_lexer_new_from_file(const char *filename) { read(fd, data, size); close(fd); - return py_lexer_new_from_str_len(filename, data, size, true); + return mp_lexer_new_from_str_len(filename, data, size, true); } diff --git a/unix/lexerunix.h b/unix/lexerunix.h index aa7631cb0..d86f202d5 100644 --- a/unix/lexerunix.h +++ b/unix/lexerunix.h @@ -1,2 +1,2 @@ -py_lexer_t *py_lexer_new_from_str_len(const char *src_name, const char *str, uint len, bool free_str); -py_lexer_t *py_lexer_new_from_file(const char *filename); +mp_lexer_t *mp_lexer_new_from_str_len(const char *src_name, const char *str, uint len, bool free_str); +mp_lexer_t *mp_lexer_new_from_file(const char *filename); diff --git a/unix/main.c b/unix/main.c index e5aa9de15..295e82d26 100644 --- a/unix/main.c +++ b/unix/main.c @@ -4,18 +4,19 @@ #include "nlr.h" #include "misc.h" -#include "mpyconfig.h" +#include "mpconfig.h" #include "lexer.h" #include "lexerunix.h" #include "parse.h" #include "compile.h" -#include "runtime.h" #include "obj.h" +#include "runtime0.h" +#include "runtime.h" #include "repl.h" #include <readline/readline.h> -char *str_join(const char *s1, int sep_char, const char *s2) { +static char *str_join(const char *s1, int sep_char, const char *s2) { int l1 = strlen(s1); int l2 = strlen(s2); char *s = m_new(char, l1 + l2 + 2); @@ -29,14 +30,14 @@ char *str_join(const char *s1, int sep_char, const char *s2) { return s; } -void do_repl(void) { +static void do_repl(void) { for (;;) { char *line = readline(">>> "); if (line == NULL) { // EOF return; } - if (py_repl_is_compound_stmt(line)) { + if (mp_repl_is_compound_stmt(line)) { for (;;) { char *line2 = readline("... "); if (line2 == NULL || strlen(line2) == 0) { @@ -49,23 +50,23 @@ void do_repl(void) { } } - py_lexer_t *lex = py_lexer_new_from_str_len("<stdin>", line, strlen(line), false); - py_parse_node_t pn = py_parse(lex, PY_PARSE_SINGLE_INPUT); - py_lexer_free(lex); + mp_lexer_t *lex = mp_lexer_new_from_str_len("<stdin>", line, strlen(line), false); + mp_parse_node_t pn = mp_parse(lex, MP_PARSE_SINGLE_INPUT); + mp_lexer_free(lex); - if (pn != PY_PARSE_NODE_NULL) { - //py_parse_node_show(pn, 0); - bool comp_ok = py_compile(pn, true); + if (pn != MP_PARSE_NODE_NULL) { + //mp_parse_node_show(pn, 0); + bool comp_ok = mp_compile(pn, true); if (comp_ok) { - py_obj_t module_fun = rt_make_function_from_id(1); - if (module_fun != py_const_none) { + mp_obj_t module_fun = rt_make_function_from_id(1); + if (module_fun != mp_const_none) { nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { rt_call_function_0(module_fun); nlr_pop(); } else { // uncaught exception - py_obj_print((py_obj_t)nlr.ret_val); + mp_obj_print((mp_obj_t)nlr.ret_val); printf("\n"); } } @@ -75,32 +76,32 @@ void do_repl(void) { } void do_file(const char *file) { - py_lexer_t *lex = py_lexer_new_from_file(file); + mp_lexer_t *lex = mp_lexer_new_from_file(file); //const char *pysrc = "def f():\n x=x+1\n print(42)\n"; - //py_lexer_t *lex = py_lexer_from_str_len("<>", pysrc, strlen(pysrc), false); + //mp_lexer_t *lex = mp_lexer_from_str_len("<>", pysrc, strlen(pysrc), false); if (lex == NULL) { return; } if (0) { // just tokenise - while (!py_lexer_is_kind(lex, PY_TOKEN_END)) { - py_token_show(py_lexer_cur(lex)); - py_lexer_to_next(lex); + while (!mp_lexer_is_kind(lex, MP_TOKEN_END)) { + mp_token_show(mp_lexer_cur(lex)); + mp_lexer_to_next(lex); } - py_lexer_free(lex); + mp_lexer_free(lex); } else { // compile - py_parse_node_t pn = py_parse(lex, PY_PARSE_FILE_INPUT); - py_lexer_free(lex); + mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT); + mp_lexer_free(lex); - if (pn != PY_PARSE_NODE_NULL) { + if (pn != MP_PARSE_NODE_NULL) { //printf("----------------\n"); //parse_node_show(pn, 0); //printf("----------------\n"); - bool comp_ok = py_compile(pn, false); + bool comp_ok = mp_compile(pn, false); //printf("----------------\n"); #if MICROPY_EMIT_CPYTHON @@ -110,19 +111,19 @@ void do_file(const char *file) { #else if (1 && comp_ok) { // execute it - py_obj_t module_fun = rt_make_function_from_id(1); - if (module_fun != py_const_none) { + mp_obj_t module_fun = rt_make_function_from_id(1); + if (module_fun != mp_const_none) { nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { - py_obj_t ret = rt_call_function_0(module_fun); + mp_obj_t ret = rt_call_function_0(module_fun); printf("done! got: "); - py_obj_print(ret); + mp_obj_print(ret); printf("\n"); nlr_pop(); } else { // uncaught exception printf("exception: "); - py_obj_print((py_obj_t)nlr.ret_val); + mp_obj_print((mp_obj_t)nlr.ret_val); printf("\n"); } } @@ -132,37 +133,58 @@ void do_file(const char *file) { } } -void test_print(py_obj_t o_in) { - printf("<test>"); +typedef struct _test_obj_t { + mp_obj_base_t base; + bool value; +} test_obj_t; + +static void test_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) { + test_obj_t *self = self_in; + print(env, "<test %d>", self->value); } -py_obj_t test_get(py_obj_t o_in) { - py_obj_t d1; - py_obj_t d2; - py_user_get_data(o_in, (machine_uint_t*)&d1, (machine_uint_t*)&d2); - return d1; +static mp_obj_t test_get(mp_obj_t self_in) { + test_obj_t *self = self_in; + return mp_obj_new_int(self->value); } -py_obj_t test_set(py_obj_t o_in, py_obj_t arg) { - py_user_set_data(o_in, (machine_uint_t)arg, (machine_uint_t)arg); - return py_const_none; +static mp_obj_t test_set(mp_obj_t self_in, mp_obj_t arg) { + test_obj_t *self = self_in; + self->value = mp_obj_get_int(arg); + return mp_const_none; } -const py_user_info_t test_obj_info = { +static MP_DEFINE_CONST_FUN_OBJ_1(test_get_obj, test_get); +static MP_DEFINE_CONST_FUN_OBJ_2(test_set_obj, test_set); + +static const mp_obj_type_t test_type = { + { &mp_const_type }, "Test", - test_print, - { - { "get", 0, test_get }, - { "set", 1, test_set }, - { NULL, 0, NULL }, + test_print, // print + NULL, // call_n + NULL, // unary_op + NULL, // binary_op + NULL, // getiter + NULL, // iternext + { // method list + { "get", &test_get_obj }, + { "set", &test_set_obj }, + { NULL, NULL }, } }; +mp_obj_t test_obj_new(int value) { + test_obj_t *o = m_new_obj(test_obj_t); + o->base.type = &test_type; + o->value = value; + return o; +} + int main(int argc, char **argv) { qstr_init(); rt_init(); - rt_store_name(qstr_from_str_static("test"), py_obj_new_user(&test_obj_info, (machine_uint_t)py_obj_new_int(42), 0)); + rt_store_name(qstr_from_str_static("test"), test_obj_new(42)); if (argc == 1) { do_repl(); diff --git a/unix/mpyconfig.h b/unix/mpconfig.h similarity index 89% rename from unix/mpyconfig.h rename to unix/mpconfig.h index f187cbb4e..a358d7db8 100644 --- a/unix/mpyconfig.h +++ b/unix/mpconfig.h @@ -13,6 +13,7 @@ typedef int64_t machine_int_t; // must be pointer size typedef uint64_t machine_uint_t; // must be pointer size typedef void *machine_ptr_t; // must be of pointer size +typedef const void *machine_const_ptr_t; // must be of pointer size typedef double machine_float_t; machine_float_t machine_sqrt(machine_float_t x); -- GitLab