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->globals = rt_globals_get(); o->n_args = n_args; o->n_state = n_state; o->bytecode = code; return o; }
// 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)); } // optimisation: allow the compiler to optimise this tail call for // the common case when the globals don't need to be changed mp_map_t *old_globals = rt_globals_get(); if (self->globals == old_globals) { return mp_execute_byte_code(self->bytecode, args, n_args, self->n_state); } else { rt_globals_set(self->globals); mp_obj_t result = mp_execute_byte_code(self->bytecode, args, n_args, self->n_state); rt_globals_set(old_globals); return result; } }
STATIC mp_obj_t mp_builtin_exec(uint n_args, const mp_obj_t *args) { // Unconditional getting/setting assumes that these operations // are cheap, which is the case when this comment was written. mp_map_t *old_globals = rt_globals_get(); mp_map_t *old_locals = rt_locals_get(); if (n_args > 1) { mp_obj_t globals = args[1]; mp_obj_t locals; if (n_args > 2) { locals = args[2]; } else { locals = globals; } rt_globals_set(mp_obj_dict_get_map(globals)); rt_locals_set(mp_obj_dict_get_map(locals)); } mp_obj_t res = parse_compile_execute(args[0], MP_PARSE_FILE_INPUT); // TODO if the above call throws an exception, then we never get to reset the globals/locals rt_globals_set(old_globals); rt_locals_set(old_locals); return res; }