diff --git a/py/emitglue.c b/py/emitglue.c index 0ab9090924..ed816a5161 100644 --- a/py/emitglue.c +++ b/py/emitglue.c @@ -1,6 +1,6 @@ // This code glues the code emitters to the runtime. -#include +#include #include #include "misc.h" @@ -10,6 +10,7 @@ #include "runtime0.h" #include "runtime.h" #include "emitglue.h" +#include "bc.h" #if 0 // print debugging info #define DEBUG_PRINT (1) @@ -51,13 +52,27 @@ STATIC machine_uint_t unique_codes_alloc = 0; STATIC mp_code_t *unique_codes = NULL; STATIC uint next_unique_code_id; +#ifdef WRITE_CODE +FILE *fp_write_code = NULL; +#endif + void mp_emit_glue_init(void) { next_unique_code_id = 0; unique_codes_alloc = 0; unique_codes = NULL; + +#ifdef WRITE_CODE + fp_write_code = fopen("out-code", "wb"); +#endif } void mp_emit_glue_deinit(void) { +#ifdef WRITE_CODE + if (fp_write_code != NULL) { + fclose(fp_write_code); + } +#endif + m_del(mp_code_t, unique_codes, unique_codes_alloc); } diff --git a/py/obj.h b/py/obj.h index af38253c56..500ffbdc04 100644 --- a/py/obj.h +++ b/py/obj.h @@ -231,6 +231,7 @@ extern const mp_obj_t mp_const_false; extern const mp_obj_t mp_const_true; extern const mp_obj_t mp_const_empty_tuple; extern const mp_obj_t mp_const_ellipsis; +extern const mp_obj_t mp_const_GeneratorExit; // General API for objects diff --git a/py/objexcept.c b/py/objexcept.c index 71874751b2..d4c4b12492 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -21,6 +21,12 @@ typedef struct mp_obj_exception_t { mp_obj_tuple_t args; } mp_obj_exception_t; +// Instance of GeneratorExit exception - needed by generator.close() +// This would belong to objgenerator.c, but to keep mp_obj_exception_t +// definition module-private so far, have it here. +STATIC mp_obj_exception_t GeneratorExit_obj = {{&mp_type_GeneratorExit}, MP_OBJ_NULL, NULL, {{&tuple_type}, 0}}; +const mp_obj_t mp_const_GeneratorExit = (mp_obj_t)&GeneratorExit_obj; + STATIC void mp_obj_exception_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) { mp_obj_exception_t *o = o_in; if (o->msg != NULL) { diff --git a/py/objgenerator.c b/py/objgenerator.c index aeb5f6219a..f6c7007a02 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -171,7 +171,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(gen_instance_throw_obj, 2, 4, gen_ins STATIC mp_obj_t gen_instance_close(mp_obj_t self_in) { mp_obj_t ret; - switch (mp_obj_gen_resume(self_in, mp_const_none, (mp_obj_t)&mp_type_GeneratorExit, &ret)) { + switch (mp_obj_gen_resume(self_in, mp_const_none, mp_const_GeneratorExit, &ret)) { case MP_VM_RETURN_YIELD: nlr_jump(mp_obj_new_exception_msg(&mp_type_RuntimeError, "generator ignored GeneratorExit")); diff --git a/py/runtime.c b/py/runtime.c index 762924c20a..3f637a16f9 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -20,7 +20,6 @@ #if 0 // print debugging info #define DEBUG_PRINT (1) -#define WRITE_CODE (1) #define DEBUG_printf DEBUG_printf #define DEBUG_OP_printf(...) DEBUG_printf(__VA_ARGS__) #else // don't print debugging info @@ -33,10 +32,6 @@ STATIC mp_map_t *map_locals; STATIC mp_map_t *map_globals; STATIC mp_map_t map_builtins; -#ifdef WRITE_CODE -FILE *fp_write_code = NULL; -#endif - // a good optimising compiler will inline this if necessary STATIC void mp_map_add_qstr(mp_map_t *map, qstr qstr, mp_obj_t value) { mp_map_lookup(map, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value; @@ -68,18 +63,9 @@ void rt_init(void) { // for efficiency, left to platform-specific startup code //sys_path = mp_obj_new_list(0, NULL); //rt_store_attr(m_sys, MP_QSTR_path, sys_path); - -#ifdef WRITE_CODE - fp_write_code = fopen("out-code", "wb"); -#endif } void rt_deinit(void) { -#ifdef WRITE_CODE - if (fp_write_code != NULL) { - fclose(fp_write_code); - } -#endif mp_map_free(map_globals); mp_map_deinit(&map_builtins); mp_module_deinit(); diff --git a/py/showbc.c b/py/showbc.c index eb743bd29e..12bd901185 100644 --- a/py/showbc.c +++ b/py/showbc.c @@ -30,7 +30,16 @@ void mp_byte_code_print(const byte *ip, int len) { machine_uint_t code_info_size = ip[0] | (ip[1] << 8) | (ip[2] << 16) | (ip[3] << 24); ip += code_info_size; - // decode prelude + // bytecode prelude: state size and exception stack size; 16 bit uints + { + uint n_state = ip[0] | (ip[1] << 8); + uint n_exc_stack = ip[2] | (ip[3] << 8); + ip += 4; + printf("(N_STATE %u)\n", n_state); + printf("(N_EXC_STACK %u)\n", n_exc_stack); + } + + // bytecode prelude: initialise closed over variables { uint n_local = *ip++; printf("(NUM_LOCAL %u)\n", n_local); @@ -244,6 +253,15 @@ void mp_byte_code_print(const byte *ip, int len) { printf("SETUP_LOOP " UINT_FMT, ip + unum - ip_start); break; + case MP_BC_SETUP_WITH: + DECODE_ULABEL; // loop-like labels are always forward + printf("SETUP_WITH " UINT_FMT, ip + unum - ip_start); + break; + + case MP_BC_WITH_CLEANUP: + printf("WITH_CLEANUP"); + break; + case MP_BC_UNWIND_JUMP: DECODE_SLABEL; printf("UNWIND_JUMP " UINT_FMT " %d", ip + unum - ip_start, *ip);