summaryrefslogtreecommitdiffstatshomepage
path: root/py
diff options
context:
space:
mode:
Diffstat (limited to 'py')
-rw-r--r--py/builtin.h3
-rw-r--r--py/builtinevex.c7
-rw-r--r--py/builtinimport.c7
-rw-r--r--py/builtintables.c2
-rw-r--r--py/compile.c15
-rw-r--r--py/emitbc.c34
-rw-r--r--py/emitcommon.c4
-rw-r--r--py/emitcpy.c2
-rw-r--r--py/emitglue.c159
-rw-r--r--py/emitglue.h40
-rw-r--r--py/emitinlinethumb.c5
-rw-r--r--py/emitnative.c12
-rw-r--r--py/emitpass1.c2
-rw-r--r--py/modcollections.c4
-rw-r--r--py/obj.c6
-rw-r--r--py/objdict.c9
-rw-r--r--py/objfun.c25
-rw-r--r--py/objint.c23
-rw-r--r--py/objlist.c40
-rw-r--r--py/objset.c2
-rw-r--r--py/opmethods.c20
-rw-r--r--py/parsehelper.c22
-rw-r--r--py/parsehelper.h2
-rw-r--r--py/py.mk1
-rw-r--r--py/qstrdefs.h3
-rw-r--r--py/runtime.c2
-rw-r--r--py/runtime.h3
-rw-r--r--py/runtime0.h2
-rw-r--r--py/scope.c6
-rw-r--r--py/scope.h4
-rw-r--r--py/showbc.c13
-rw-r--r--py/vm.c30
32 files changed, 274 insertions, 235 deletions
diff --git a/py/builtin.h b/py/builtin.h
index bf65b48329..743f748da0 100644
--- a/py/builtin.h
+++ b/py/builtin.h
@@ -35,6 +35,9 @@ MP_DECLARE_CONST_FUN_OBJ(mp_builtin_sum_obj);
MP_DECLARE_CONST_FUN_OBJ(mp_namedtuple_obj);
+MP_DECLARE_CONST_FUN_OBJ(mp_op_contains_obj);
+MP_DECLARE_CONST_FUN_OBJ(mp_op_getitem_obj);
+
extern const mp_obj_module_t mp_module___main__;
extern const mp_obj_module_t mp_module_array;
extern const mp_obj_module_t mp_module_collections;
diff --git a/py/builtinevex.c b/py/builtinevex.c
index fc3a60182e..ae82537374 100644
--- a/py/builtinevex.c
+++ b/py/builtinevex.c
@@ -25,13 +25,16 @@ STATIC mp_obj_t parse_compile_execute(mp_obj_t o_in, mp_parse_input_kind_t parse
// parse the string
mp_parse_error_kind_t parse_error_kind;
mp_parse_node_t pn = mp_parse(lex, parse_input_kind, &parse_error_kind);
- mp_lexer_free(lex);
if (pn == MP_PARSE_NODE_NULL) {
// parse error; raise exception
- nlr_raise(mp_parse_make_exception(parse_error_kind));
+ mp_obj_t exc = mp_parse_make_exception(lex, parse_error_kind);
+ mp_lexer_free(lex);
+ nlr_raise(exc);
}
+ mp_lexer_free(lex);
+
// compile the string
mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, false);
mp_parse_node_free(pn);
diff --git a/py/builtinimport.c b/py/builtinimport.c
index 578e73feb6..4af7dd7ed3 100644
--- a/py/builtinimport.c
+++ b/py/builtinimport.c
@@ -96,15 +96,18 @@ void do_load(mp_obj_t module_obj, vstr_t *file) {
// parse the imported script
mp_parse_error_kind_t parse_error_kind;
mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT, &parse_error_kind);
- mp_lexer_free(lex);
if (pn == MP_PARSE_NODE_NULL) {
// parse error; clean up and raise exception
+ mp_obj_t exc = mp_parse_make_exception(lex, parse_error_kind);
+ mp_lexer_free(lex);
mp_locals_set(old_locals);
mp_globals_set(old_globals);
- nlr_raise(mp_parse_make_exception(parse_error_kind));
+ nlr_raise(exc);
}
+ mp_lexer_free(lex);
+
// compile the imported script
mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, false);
mp_parse_node_free(pn);
diff --git a/py/builtintables.c b/py/builtintables.c
index 23c34eda11..0115ea04b5 100644
--- a/py/builtintables.c
+++ b/py/builtintables.c
@@ -126,7 +126,7 @@ STATIC const mp_map_elem_t mp_builtin_module_table[] = {
#if MICROPY_ENABLE_MOD_IO
{ MP_OBJ_NEW_QSTR(MP_QSTR_io), (mp_obj_t)&mp_module_io },
#endif
- { MP_OBJ_NEW_QSTR(MP_QSTR_collections), (mp_obj_t)&mp_module_collections },
+ { MP_OBJ_NEW_QSTR(MP_QSTR__collections), (mp_obj_t)&mp_module_collections },
#if MICROPY_ENABLE_MOD_STRUCT
{ MP_OBJ_NEW_QSTR(MP_QSTR_struct), (mp_obj_t)&mp_module_struct },
#endif
diff --git a/py/compile.c b/py/compile.c
index f397501f17..7a3d810f9d 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -10,11 +10,11 @@
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
-#include "scope.h"
#include "runtime0.h"
-#include "emit.h"
-#include "emitglue.h"
#include "obj.h"
+#include "emitglue.h"
+#include "scope.h"
+#include "emit.h"
#include "compile.h"
#include "runtime.h"
#include "builtin.h"
@@ -283,7 +283,7 @@ STATIC void compile_decrease_except_level(compiler_t *comp) {
}
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, comp->source_file, mp_emit_glue_get_unique_code_id(), emit_options);
+ scope_t *scope = scope_new(kind, pn, comp->source_file, emit_options);
scope->parent = comp->scope_cur;
scope->next = NULL;
if (comp->scope_head == NULL) {
@@ -3454,7 +3454,7 @@ mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, uint emit_opt, bool is
#endif // !MICROPY_EMIT_CPYTHON
// free the scopes
- uint unique_code_id = module_scope->unique_code_id;
+ mp_raw_code_t *outer_raw_code = module_scope->raw_code;
for (scope_t *s = module_scope; s;) {
scope_t *next = s->next;
scope_free(s);
@@ -3471,12 +3471,11 @@ mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, uint emit_opt, bool is
} else {
#if MICROPY_EMIT_CPYTHON
// can't create code, so just return true
- (void)unique_code_id; // to suppress warning that unique_code_id is unused
+ (void)outer_raw_code; // to suppress warning that outer_raw_code is unused
return mp_const_true;
#else
// return function that executes the outer module
- // we can free the unique_code slot because no-one has reference to this unique_code_id anymore
- return mp_make_function_from_id_and_free(unique_code_id, MP_OBJ_NULL, MP_OBJ_NULL);
+ return mp_make_function_from_raw_code(outer_raw_code, MP_OBJ_NULL, MP_OBJ_NULL);
#endif
}
}
diff --git a/py/emitbc.c b/py/emitbc.c
index d1d59ef4a5..2d71d86855 100644
--- a/py/emitbc.c
+++ b/py/emitbc.c
@@ -9,10 +9,11 @@
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
+#include "obj.h"
+#include "emitglue.h"
#include "scope.h"
#include "runtime0.h"
#include "emit.h"
-#include "emitglue.h"
#include "bc0.h"
struct _emit_t {
@@ -65,6 +66,10 @@ STATIC byte* emit_get_cur_to_write_code_info(emit_t* emit, int num_bytes_to_writ
}
}
+STATIC void emit_align_code_info_to_machine_word(emit_t* emit) {
+ emit->code_info_offset = (emit->code_info_offset + sizeof(machine_uint_t) - 1) & (~(sizeof(machine_uint_t) - 1));
+}
+
STATIC void emit_write_code_info_qstr(emit_t* emit, qstr qstr) {
byte* c = emit_get_cur_to_write_code_info(emit, 4);
// TODO variable length encoding for qstr
@@ -98,6 +103,10 @@ STATIC byte* emit_get_cur_to_write_byte_code(emit_t* emit, int num_bytes_to_writ
}
}
+STATIC void emit_align_byte_code_to_machine_word(emit_t* emit) {
+ emit->byte_code_offset = (emit->byte_code_offset + sizeof(machine_uint_t) - 1) & (~(sizeof(machine_uint_t) - 1));
+}
+
STATIC void emit_write_byte_code_byte(emit_t* emit, byte b1) {
byte* c = emit_get_cur_to_write_byte_code(emit, 1);
c[0] = b1;
@@ -158,6 +167,14 @@ STATIC void emit_write_byte_code_byte_uint(emit_t* emit, byte b, uint num) {
emit_write_byte_code_uint(emit, num);
}
+// aligns the pointer so it is friendly to GC
+STATIC void emit_write_byte_code_byte_ptr(emit_t* emit, byte b, void *ptr) {
+ emit_write_byte_code_byte(emit, b);
+ emit_align_byte_code_to_machine_word(emit);
+ machine_uint_t *c = (machine_uint_t*)emit_get_cur_to_write_byte_code(emit, sizeof(machine_uint_t));
+ *c = (machine_uint_t)ptr;
+}
+
/* currently unused
STATIC void emit_write_byte_code_byte_uint_uint(emit_t* emit, byte b, uint num1, uint num2) {
emit_write_byte_code_byte(emit, b);
@@ -178,7 +195,7 @@ STATIC void emit_write_byte_code_byte_unsigned_label(emit_t* emit, byte b1, uint
} else {
byte_code_offset = emit->label_offsets[label] - emit->byte_code_offset - 3;
}
- byte* c = emit_get_cur_to_write_byte_code(emit, 3);
+ byte *c = emit_get_cur_to_write_byte_code(emit, 3);
c[0] = b1;
c[1] = byte_code_offset;
c[2] = byte_code_offset >> 8;
@@ -269,19 +286,20 @@ STATIC void emit_bc_end_pass(emit_t *emit) {
}
emit_write_code_info_bytes_lines(emit, 0, 0); // end of line number info
+ emit_align_code_info_to_machine_word(emit); // align so that following byte_code is aligned
if (emit->pass == PASS_2) {
// calculate size of code in bytes
emit->code_info_size = emit->code_info_offset;
emit->byte_code_size = emit->byte_code_offset;
- emit->code_base = m_new(byte, emit->code_info_size + emit->byte_code_size);
+ emit->code_base = m_new0(byte, emit->code_info_size + emit->byte_code_size);
} else if (emit->pass == PASS_3) {
qstr *arg_names = m_new(qstr, emit->scope->num_params);
for (int i = 0; i < emit->scope->num_params; i++) {
arg_names[i] = emit->scope->id_info[i].qstr;
}
- mp_emit_glue_assign_byte_code(emit->scope->unique_code_id, emit->code_base,
+ mp_emit_glue_assign_byte_code(emit->scope->raw_code, emit->code_base,
emit->code_info_size + emit->byte_code_size,
emit->scope->num_params, emit->scope->num_locals,
emit->scope->scope_flags, arg_names);
@@ -733,7 +751,7 @@ STATIC void emit_bc_unpack_ex(emit_t *emit, int n_left, int n_right) {
STATIC void emit_bc_make_function(emit_t *emit, scope_t *scope, uint n_pos_defaults, uint n_kw_defaults) {
if (n_pos_defaults == 0 && n_kw_defaults == 0) {
emit_bc_pre(emit, 1);
- emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_FUNCTION, scope->unique_code_id);
+ emit_write_byte_code_byte_ptr(emit, MP_BC_MAKE_FUNCTION, scope->raw_code);
} else {
if (n_pos_defaults == 0) {
// load dummy entry for non-existent positional default tuple
@@ -744,14 +762,14 @@ STATIC void emit_bc_make_function(emit_t *emit, scope_t *scope, uint n_pos_defau
emit_bc_load_null(emit);
}
emit_bc_pre(emit, -1);
- emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_FUNCTION_DEFARGS, scope->unique_code_id);
+ emit_write_byte_code_byte_ptr(emit, MP_BC_MAKE_FUNCTION_DEFARGS, scope->raw_code);
}
}
STATIC void emit_bc_make_closure(emit_t *emit, scope_t *scope, uint n_pos_defaults, uint n_kw_defaults) {
if (n_pos_defaults == 0 && n_kw_defaults == 0) {
emit_bc_pre(emit, 0);
- emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_CLOSURE, scope->unique_code_id);
+ emit_write_byte_code_byte_ptr(emit, MP_BC_MAKE_CLOSURE, scope->raw_code);
} else {
if (n_pos_defaults == 0) {
// load dummy entry for non-existent positional default tuple
@@ -763,7 +781,7 @@ STATIC void emit_bc_make_closure(emit_t *emit, scope_t *scope, uint n_pos_defaul
emit_bc_rot_two(emit);
}
emit_bc_pre(emit, -2);
- emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_CLOSURE_DEFARGS, scope->unique_code_id);
+ emit_write_byte_code_byte_ptr(emit, MP_BC_MAKE_CLOSURE_DEFARGS, scope->raw_code);
}
}
diff --git a/py/emitcommon.c b/py/emitcommon.c
index 30f5ace923..454ec9c5e5 100644
--- a/py/emitcommon.c
+++ b/py/emitcommon.c
@@ -7,8 +7,10 @@
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
-#include "scope.h"
#include "runtime0.h"
+#include "obj.h"
+#include "emitglue.h"
+#include "scope.h"
#include "emit.h"
#define EMIT(fun, ...) (emit_method_table->fun(emit, __VA_ARGS__))
diff --git a/py/emitcpy.c b/py/emitcpy.c
index 5866d474e9..010219d12f 100644
--- a/py/emitcpy.c
+++ b/py/emitcpy.c
@@ -9,6 +9,8 @@
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
+#include "obj.h"
+#include "emitglue.h"
#include "scope.h"
#include "runtime0.h"
#include "emit.h"
diff --git a/py/emitglue.c b/py/emitglue.c
index bcc9b2cca1..ce296f4321 100644
--- a/py/emitglue.c
+++ b/py/emitglue.c
@@ -23,46 +23,11 @@
#define DEBUG_OP_printf(...) (void)0
#endif
-typedef enum {
- MP_CODE_UNUSED,
- MP_CODE_RESERVED,
- MP_CODE_BYTE,
- MP_CODE_NATIVE,
- MP_CODE_INLINE_ASM,
-} mp_code_kind_t;
-
-typedef struct _mp_code_t {
- mp_code_kind_t kind : 8;
- uint scope_flags : 8;
- uint n_args : 16;
- union {
- struct {
- byte *code;
- uint len;
- } u_byte;
- struct {
- mp_fun_t fun;
- } u_native;
- struct {
- void *fun;
- } u_inline_asm;
- };
- qstr *arg_names;
-} mp_code_t;
-
-STATIC machine_uint_t unique_codes_alloc = 0;
-STATIC machine_uint_t unique_codes_total = 0; // always >= unique_codes_alloc
-STATIC mp_code_t *unique_codes = NULL;
-
#ifdef WRITE_CODE
FILE *fp_write_code = NULL;
#endif
void mp_emit_glue_init(void) {
- unique_codes_alloc = 0;
- unique_codes_total = 0;
- unique_codes = NULL;
-
#ifdef WRITE_CODE
fp_write_code = fopen("out-code", "wb");
#endif
@@ -74,50 +39,24 @@ void mp_emit_glue_deinit(void) {
fclose(fp_write_code);
}
#endif
-
- m_del(mp_code_t, unique_codes, unique_codes_alloc);
-}
-
-uint mp_emit_glue_get_unique_code_id(void) {
- // look for an existing unused slot
- for (uint i = 0; i < unique_codes_alloc; i++) {
- if (unique_codes[i].kind == MP_CODE_UNUSED) {
- unique_codes[i].kind = MP_CODE_RESERVED;
- return i;
- }
- }
- // no existing slot
- // return next available id, memory will be allocated later
- return unique_codes_total++;
}
-STATIC void mp_emit_glue_alloc_unique_codes(void) {
- if (unique_codes_total > unique_codes_alloc) {
- DEBUG_printf("allocate more unique codes: " UINT_FMT " -> %u\n", unique_codes_alloc, unique_codes_total);
- // increase size of unique_codes table (all new entries are already reserved)
- unique_codes = m_renew(mp_code_t, unique_codes, unique_codes_alloc, unique_codes_total);
- for (uint i = unique_codes_alloc; i < unique_codes_total; i++) {
- unique_codes[i].kind = MP_CODE_RESERVED;
- }
- unique_codes_alloc = unique_codes_total;
- }
+mp_raw_code_t *mp_emit_glue_new_raw_code(void) {
+ mp_raw_code_t *rc = m_new0(mp_raw_code_t, 1);
+ rc->kind = MP_CODE_RESERVED;
+ return rc;
}
-void mp_emit_glue_assign_byte_code(uint unique_code_id, byte *code, uint len, int n_args, int n_locals, uint scope_flags, qstr *arg_names) {
- mp_emit_glue_alloc_unique_codes();
-
- assert(unique_code_id < unique_codes_alloc && unique_codes[unique_code_id].kind == MP_CODE_RESERVED);
- unique_codes[unique_code_id].kind = MP_CODE_BYTE;
- unique_codes[unique_code_id].scope_flags = scope_flags;
- unique_codes[unique_code_id].n_args = n_args;
- unique_codes[unique_code_id].u_byte.code = code;
- unique_codes[unique_code_id].u_byte.len = len;
- unique_codes[unique_code_id].arg_names = arg_names;
-
- //printf("byte code: %d bytes\n", len);
+void mp_emit_glue_assign_byte_code(mp_raw_code_t *rc, byte *code, uint len, int n_args, int n_locals, uint scope_flags, qstr *arg_names) {
+ rc->kind = MP_CODE_BYTE;
+ rc->scope_flags = scope_flags;
+ rc->n_args = n_args;
+ rc->u_byte.code = code;
+ rc->u_byte.len = len;
+ rc->arg_names = arg_names;
#ifdef DEBUG_PRINT
- DEBUG_printf("assign byte code: id=%d code=%p len=%u n_args=%d n_locals=%d\n", unique_code_id, code, len, n_args, n_locals);
+ DEBUG_printf("assign byte code: code=%p len=%u n_args=%d n_locals=%d\n", code, len, n_args, n_locals);
for (int i = 0; i < 128 && i < len; i++) {
if (i > 0 && i % 16 == 0) {
DEBUG_printf("\n");
@@ -131,19 +70,14 @@ void mp_emit_glue_assign_byte_code(uint unique_code_id, byte *code, uint len, in
#endif
}
-void mp_emit_glue_assign_native_code(uint unique_code_id, void *fun, uint len, int n_args) {
- mp_emit_glue_alloc_unique_codes();
-
- assert(unique_code_id < unique_codes_alloc && unique_codes[unique_code_id].kind == MP_CODE_RESERVED);
- unique_codes[unique_code_id].kind = MP_CODE_NATIVE;
- unique_codes[unique_code_id].scope_flags = 0;
- unique_codes[unique_code_id].n_args = n_args;
- unique_codes[unique_code_id].u_native.fun = fun;
-
- //printf("native code: %d bytes\n", len);
+void mp_emit_glue_assign_native_code(mp_raw_code_t *rc, void *fun, uint len, int n_args) {
+ rc->kind = MP_CODE_NATIVE;
+ rc->scope_flags = 0;
+ rc->n_args = n_args;
+ rc->u_native.fun = fun;
#ifdef DEBUG_PRINT
- DEBUG_printf("assign native code: id=%d fun=%p len=%u n_args=%d\n", unique_code_id, fun, len, n_args);
+ DEBUG_printf("assign native code: fun=%p len=%u n_args=%d\n", fun, len, n_args);
byte *fun_data = (byte*)(((machine_uint_t)fun) & (~1)); // need to clear lower bit in case it's thumb code
for (int i = 0; i < 128 && i < len; i++) {
if (i > 0 && i % 16 == 0) {
@@ -162,17 +96,14 @@ void mp_emit_glue_assign_native_code(uint unique_code_id, void *fun, uint len, i
#endif
}
-void mp_emit_glue_assign_inline_asm_code(uint unique_code_id, void *fun, uint len, int n_args) {
- mp_emit_glue_alloc_unique_codes();
-
- assert(unique_code_id < unique_codes_alloc && unique_codes[unique_code_id].kind == MP_CODE_RESERVED);
- unique_codes[unique_code_id].kind = MP_CODE_INLINE_ASM;
- unique_codes[unique_code_id].scope_flags = 0;
- unique_codes[unique_code_id].n_args = n_args;
- unique_codes[unique_code_id].u_inline_asm.fun = fun;
+void mp_emit_glue_assign_inline_asm_code(mp_raw_code_t *rc, void *fun, uint len, int n_args) {
+ rc->kind = MP_CODE_INLINE_ASM;
+ rc->scope_flags = 0;
+ rc->n_args = n_args;
+ rc->u_inline_asm.fun = fun;
#ifdef DEBUG_PRINT
- DEBUG_printf("assign inline asm code: id=%d fun=%p len=%u n_args=%d\n", unique_code_id, fun, len, n_args);
+ DEBUG_printf("assign inline asm code: fun=%p len=%u n_args=%d\n", fun, len, n_args);
byte *fun_data = (byte*)(((machine_uint_t)fun) & (~1)); // need to clear lower bit in case it's thumb code
for (int i = 0; i < 128 && i < len; i++) {
if (i > 0 && i % 16 == 0) {
@@ -191,12 +122,9 @@ void mp_emit_glue_assign_inline_asm_code(uint unique_code_id, void *fun, uint le
#endif
}
-mp_obj_t mp_make_function_from_id(uint unique_code_id, mp_obj_t def_args, mp_obj_t def_kw_args) {
- DEBUG_OP_printf("make_function_from_id %d\n", unique_code_id);
- if (unique_code_id >= unique_codes_total) {
- // illegal code id
- return mp_const_none;
- }
+mp_obj_t mp_make_function_from_raw_code(mp_raw_code_t *rc, mp_obj_t def_args, mp_obj_t def_kw_args) {
+ DEBUG_OP_printf("make_function_from_raw_code %p\n", rc);
+ assert(rc != NULL);
// def_args must be MP_OBJ_NULL or a tuple
assert(def_args == MP_OBJ_NULL || MP_OBJ_IS_TYPE(def_args, &mp_type_tuple));
@@ -204,49 +132,36 @@ mp_obj_t mp_make_function_from_id(uint unique_code_id, mp_obj_t def_args, mp_obj
// TODO implement default kw args
assert(def_kw_args == MP_OBJ_NULL);
- // make the function, depending on the code kind
- mp_code_t *c = &unique_codes[unique_code_id];
+ // make the function, depending on the raw code kind
mp_obj_t fun;
- switch (c->kind) {
+ switch (rc->kind) {
case MP_CODE_BYTE:
- fun = mp_obj_new_fun_bc(c->scope_flags, c->arg_names, c->n_args, def_args, c->u_byte.code);
+ fun = mp_obj_new_fun_bc(rc->scope_flags, rc->arg_names, rc->n_args, def_args, rc->u_byte.code);
break;
case MP_CODE_NATIVE:
- fun = mp_make_function_n(c->n_args, c->u_native.fun);
+ fun = mp_make_function_n(rc->n_args, rc->u_native.fun);
break;
case MP_CODE_INLINE_ASM:
- fun = mp_obj_new_fun_asm(c->n_args, c->u_inline_asm.fun);
+ fun = mp_obj_new_fun_asm(rc->n_args, rc->u_inline_asm.fun);
break;
default:
- // code id was never assigned (this should not happen)
+ // raw code was never set (this should not happen)
assert(0);
return mp_const_none;
}
// check for generator functions and if so wrap in generator object
- if ((c->scope_flags & MP_SCOPE_FLAG_GENERATOR) != 0) {
+ if ((rc->scope_flags & MP_SCOPE_FLAG_GENERATOR) != 0) {
fun = mp_obj_new_gen_wrap(fun);
}
return fun;
}
-mp_obj_t mp_make_function_from_id_and_free(uint unique_code_id, mp_obj_t def_args, mp_obj_t def_kw_args) {
- mp_obj_t f = mp_make_function_from_id(unique_code_id, def_args, def_kw_args);
-
- // in some cases we can free the unique_code slot
- // any dynamically allocated memory is now owned by the fun object
- mp_code_t *c = &unique_codes[unique_code_id];
- memset(c, 0, sizeof *c); // make sure all pointers are zeroed
- c->kind = MP_CODE_UNUSED;
-
- return f;
-}
-
-mp_obj_t mp_make_closure_from_id(uint unique_code_id, mp_obj_t closure_tuple, mp_obj_t def_args, mp_obj_t def_kw_args) {
- DEBUG_OP_printf("make_closure_from_id %d\n", unique_code_id);
+mp_obj_t mp_make_closure_from_raw_code(mp_raw_code_t *rc, mp_obj_t closure_tuple, mp_obj_t def_args, mp_obj_t def_kw_args) {
+ DEBUG_OP_printf("make_closure_from_raw_code %p\n", rc);
// make function object
- mp_obj_t ffun = mp_make_function_from_id(unique_code_id, def_args, def_kw_args);
+ mp_obj_t ffun = mp_make_function_from_raw_code(rc, def_args, def_kw_args);
// wrap function in closure object
return mp_obj_new_closure(ffun, closure_tuple);
}
diff --git a/py/emitglue.h b/py/emitglue.h
index 8f69951c21..2f9960bfa1 100644
--- a/py/emitglue.h
+++ b/py/emitglue.h
@@ -1,8 +1,40 @@
// These variables and functions glue the code emitters to the runtime.
+typedef enum {
+ MP_CODE_UNUSED,
+ MP_CODE_RESERVED,
+ MP_CODE_BYTE,
+ MP_CODE_NATIVE,
+ MP_CODE_INLINE_ASM,
+} mp_raw_code_kind_t;
+
+typedef struct _mp_code_t {
+ mp_raw_code_kind_t kind : 8;
+ uint scope_flags : 8;
+ uint n_args : 16;
+ union {
+ struct {
+ byte *code;
+ uint len;
+ } u_byte;
+ struct {
+ mp_fun_t fun;
+ } u_native;
+ struct {
+ void *fun;
+ } u_inline_asm;
+ };
+ qstr *arg_names;
+} mp_raw_code_t;
+
void mp_emit_glue_init(void);
void mp_emit_glue_deinit(void);
-uint mp_emit_glue_get_unique_code_id(void);
-void mp_emit_glue_assign_byte_code(uint unique_code_id, byte *code, uint len, int n_args, int n_locals, uint scope_flags, qstr *arg_names);
-void mp_emit_glue_assign_native_code(uint unique_code_id, void *f, uint len, int n_args);
-void mp_emit_glue_assign_inline_asm_code(uint unique_code_id, void *f, uint len, int n_args);
+
+mp_raw_code_t *mp_emit_glue_new_raw_code(void);
+
+void mp_emit_glue_assign_byte_code(mp_raw_code_t *rc, byte *code, uint len, int n_args, int n_locals, uint scope_flags, qstr *arg_names);
+void mp_emit_glue_assign_native_code(mp_raw_code_t *rc, void *f, uint len, int n_args);
+void mp_emit_glue_assign_inline_asm_code(mp_raw_code_t *rc, void *f, uint len, int n_args);
+
+mp_obj_t mp_make_function_from_raw_code(mp_raw_code_t *rc, mp_obj_t def_args, mp_obj_t def_kw_args);
+mp_obj_t mp_make_closure_from_raw_code(mp_raw_code_t *rc, mp_obj_t closure_tuple, mp_obj_t def_args, mp_obj_t def_kw_args);
diff --git a/py/emitinlinethumb.c b/py/emitinlinethumb.c
index fc881f3d18..812e702af6 100644
--- a/py/emitinlinethumb.c
+++ b/py/emitinlinethumb.c
@@ -9,10 +9,11 @@
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
+#include "obj.h"
+#include "emitglue.h"
#include "scope.h"
#include "runtime0.h"
#include "emit.h"
-#include "emitglue.h"
#include "asmthumb.h"
#if MICROPY_EMIT_INLINE_THUMB
@@ -72,7 +73,7 @@ STATIC bool emit_inline_thumb_end_pass(emit_inline_asm_t *emit) {
if (emit->pass == PASS_3) {
void *f = asm_thumb_get_code(emit->as);
- mp_emit_glue_assign_inline_asm_code(emit->scope->unique_code_id, f, asm_thumb_get_code_size(emit->as), emit->scope->num_params);
+ mp_emit_glue_assign_inline_asm_code(emit->scope->raw_code, f, asm_thumb_get_code_size(emit->as), emit->scope->num_params);
}
return emit->success;
diff --git a/py/emitnative.c b/py/emitnative.c
index b5a3acc231..3046aef4d6 100644
--- a/py/emitnative.c
+++ b/py/emitnative.c
@@ -27,11 +27,11 @@
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
+#include "obj.h"
+#include "emitglue.h"
#include "scope.h"
#include "runtime0.h"
#include "emit.h"
-#include "emitglue.h"
-#include "obj.h"
#include "runtime.h"
#if 0 // print debugging info
@@ -283,10 +283,10 @@ STATIC void emit_native_end_pass(emit_t *emit) {
if (emit->pass == PASS_3) {
#if N_X64
void *f = asm_x64_get_code(emit->as);
- mp_emit_glue_assign_native_code(emit->scope->unique_code_id, f, asm_x64_get_code_size(emit->as), emit->scope->num_params);
+ mp_emit_glue_assign_native_code(emit->scope->raw_code, f, asm_x64_get_code_size(emit->as), emit->scope->num_params);
#elif N_THUMB
void *f = asm_thumb_get_code(emit->as);
- mp_emit_glue_assign_native_code(emit->scope->unique_code_id, f, asm_thumb_get_code_size(emit->as), emit->scope->num_params);
+ mp_emit_glue_assign_native_code(emit->scope->raw_code, f, asm_thumb_get_code_size(emit->as), emit->scope->num_params);
#endif
}
}
@@ -1188,7 +1188,9 @@ STATIC void emit_native_make_function(emit_t *emit, scope_t *scope, uint n_pos_d
// call runtime, with type info for args, or don't support dict/default params, or only support Python objects for them
assert(n_pos_defaults == 0 && n_kw_defaults == 0);
emit_native_pre(emit);
- emit_call_with_3_imm_args(emit, MP_F_MAKE_FUNCTION_FROM_ID, mp_make_function_from_id, scope->unique_code_id, REG_ARG_1, (machine_uint_t)MP_OBJ_NULL, REG_ARG_2, (machine_uint_t)MP_OBJ_NULL, REG_ARG_3);
+ assert(0);
+ // TODO we need to store the raw_code ptr aligned within the code for the GC
+ emit_call_with_3_imm_args(emit, MP_F_MAKE_FUNCTION_FROM_RAW_CODE, mp_make_function_from_raw_code, (machine_uint_t)scope->raw_code, REG_ARG_1, (machine_uint_t)MP_OBJ_NULL, REG_ARG_2, (machine_uint_t)MP_OBJ_NULL, REG_ARG_3);
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
}
diff --git a/py/emitpass1.c b/py/emitpass1.c
index ad86588e20..01156bfbe6 100644
--- a/py/emitpass1.c
+++ b/py/emitpass1.c
@@ -7,6 +7,8 @@
#include "qstr.h"
#include "lexer.h"
#include "parse.h"
+#include "obj.h"
+#include "emitglue.h"
#include "scope.h"
#include "runtime0.h"
#include "emit.h"
diff --git a/py/modcollections.c b/py/modcollections.c
index dbd1896f20..11845a00ce 100644
--- a/py/modcollections.c
+++ b/py/modcollections.c
@@ -5,7 +5,7 @@
#include "builtin.h"
STATIC const mp_map_elem_t mp_module_collections_globals_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_collections) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR__collections) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_namedtuple), (mp_obj_t)&mp_namedtuple_obj },
};
@@ -22,6 +22,6 @@ STATIC const mp_obj_dict_t mp_module_collections_globals = {
const mp_obj_module_t mp_module_collections = {
.base = { &mp_type_module },
- .name = MP_QSTR_collections,
+ .name = MP_QSTR__collections,
.globals = (mp_obj_dict_t*)&mp_module_collections_globals,
};
diff --git a/py/obj.c b/py/obj.c
index 6eaedb3a7f..bdafc72476 100644
--- a/py/obj.c
+++ b/py/obj.c
@@ -333,11 +333,11 @@ mp_obj_t mp_identity(mp_obj_t self) {
MP_DEFINE_CONST_FUN_OBJ_1(mp_identity_obj, mp_identity);
bool mp_get_buffer(mp_obj_t obj, buffer_info_t *bufinfo) {
- mp_obj_base_t *o = (mp_obj_base_t *)obj;
- if (o->type->buffer_p.get_buffer == NULL) {
+ mp_obj_type_t *type = mp_obj_get_type(obj);
+ if (type->buffer_p.get_buffer == NULL) {
return false;
}
- o->type->buffer_p.get_buffer(o, bufinfo, BUFFER_READ);
+ type->buffer_p.get_buffer(obj, bufinfo, BUFFER_READ);
if (bufinfo->buf == NULL) {
return false;
}
diff --git a/py/objdict.c b/py/objdict.c
index 8bdd0026a5..2c56540d15 100644
--- a/py/objdict.c
+++ b/py/objdict.c
@@ -10,6 +10,7 @@
#include "objtuple.h"
#include "runtime0.h"
#include "runtime.h"
+#include "builtin.h"
STATIC mp_obj_t mp_obj_new_dict_iterator(mp_obj_dict_t *dict, int cur);
STATIC mp_map_elem_t *dict_it_iternext_elem(mp_obj_t self_in);
@@ -137,12 +138,6 @@ STATIC bool dict_store_item(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
return true;
}
-STATIC mp_obj_t dict_getitem(mp_obj_t lhs_in, mp_obj_t rhs_in) {
- return dict_binary_op(MP_BINARY_OP_SUBSCR, lhs_in, rhs_in);
-}
-
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(dict_getitem_obj, dict_getitem);
-
/******************************************************************************/
/* dict iterator */
@@ -501,7 +496,7 @@ STATIC const mp_map_elem_t dict_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_setdefault), (mp_obj_t)&dict_setdefault_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_update), (mp_obj_t)&dict_update_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_values), (mp_obj_t)&dict_values_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR___getitem__), (mp_obj_t)&dict_getitem_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR___getitem__), (mp_obj_t)&mp_op_getitem_obj },
};
STATIC MP_DEFINE_CONST_DICT(dict_locals_dict, dict_locals_dict_table);
diff --git a/py/objfun.c b/py/objfun.c
index 4ef92c0256..8fadbc6119 100644
--- a/py/objfun.c
+++ b/py/objfun.c
@@ -229,7 +229,8 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_o
if (n_args > self->n_args) {
// given more than enough arguments
if (!self->takes_var_args) {
- goto arg_error;
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+ "function takes %d positional arguments but %d were given", self->n_args, n_args));
}
// put extra arguments in varargs tuple
*extra_args = mp_obj_new_tuple(n_args - self->n_args, args + self->n_args);
@@ -249,7 +250,9 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_o
extra_args -= self->n_args - n_args;
n_extra_args += self->n_args - n_args;
} else {
- goto arg_error;
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+ "function takes at least %d positional arguments but %d were given",
+ self->n_args - self->n_def_args, n_args));
}
}
}
@@ -344,9 +347,6 @@ continue2:;
} else { // MP_VM_RETURN_EXCEPTION
nlr_raise(result);
}
-
-arg_error:
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function takes %d positional arguments but %d were given", self->n_args, n_args));
}
const mp_obj_type_t mp_type_fun_bc = {
@@ -442,14 +442,15 @@ STATIC machine_uint_t convert_obj_for_inline_asm(mp_obj_t obj) {
mp_obj_t *items;
mp_obj_list_get(obj, &len, &items);
return (machine_uint_t)items;
- } else if (type->buffer_p.get_buffer != NULL) {
- // supports the buffer protocol, get a pointer to the data
- buffer_info_t bufinfo;
- type->buffer_p.get_buffer(obj, &bufinfo, BUFFER_READ);
- return (machine_uint_t)bufinfo.buf;
} else {
- // just pass along a pointer to the object
- return (machine_uint_t)obj;
+ buffer_info_t bufinfo;
+ if (mp_get_buffer(obj, &bufinfo)) {
+ // supports the buffer protocol, return a pointer to the data
+ return (machine_uint_t)bufinfo.buf;
+ } else {
+ // just pass along a pointer to the object
+ return (machine_uint_t)obj;
+ }
}
}
}
diff --git a/py/objint.c b/py/objint.c
index 69954168de..2eabff8d4e 100644
--- a/py/objint.c
+++ b/py/objint.c
@@ -265,18 +265,27 @@ mp_obj_t mp_obj_int_binary_op_extra_cases(int op, mp_obj_t lhs_in, mp_obj_t rhs_
return MP_OBJ_NULL;
}
+// this is a classmethod
STATIC mp_obj_t int_from_bytes(uint n_args, const mp_obj_t *args) {
+ // TODO: Support long ints
+ // TODO: Support byteorder param (assumes 'little' at the moment)
+ // TODO: Support signed param (assumes signed=False at the moment)
+
+ // get the buffer info
buffer_info_t bufinfo;
- mp_get_buffer_raise(args[0], &bufinfo);
+ mp_get_buffer_raise(args[1], &bufinfo);
- assert(bufinfo.len >= sizeof(machine_int_t));
- // TODO: Support long ints
- // TODO: Support byteorder param
- // TODO: Support signed param
- return mp_obj_new_int_from_uint(*(machine_uint_t*)bufinfo.buf);
+ // convert the bytes to an integer
+ machine_uint_t value = 0;
+ for (const byte* buf = bufinfo.buf + bufinfo.len - 1; buf >= (byte*)bufinfo.buf; buf--) {
+ value = (value << 8) | *buf;
+ }
+
+ return mp_obj_new_int_from_uint(value);
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(int_from_bytes_obj, 1, 3, int_from_bytes);
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(int_from_bytes_fun_obj, 2, 3, int_from_bytes);
+STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(int_from_bytes_obj, (const mp_obj_t)&int_from_bytes_fun_obj);
STATIC mp_obj_t int_to_bytes(uint n_args, const mp_obj_t *args) {
machine_int_t val = mp_obj_int_get_checked(args[0]);
diff --git a/py/objlist.c b/py/objlist.c
index 538cba71fd..fa7d2bc1c7 100644
--- a/py/objlist.c
+++ b/py/objlist.c
@@ -33,6 +33,15 @@ STATIC void list_print(void (*print)(void *env, const char *fmt, ...), void *env
print(env, "]");
}
+STATIC mp_obj_t list_extend_from_iter(mp_obj_t list, mp_obj_t iterable) {
+ mp_obj_t iter = mp_getiter(iterable);
+ mp_obj_t item;
+ while ((item = mp_iternext(iter)) != MP_OBJ_NULL) {
+ mp_obj_list_append(list, item);
+ }
+ return list;
+}
+
STATIC mp_obj_t list_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
// TODO check n_kw == 0
@@ -44,13 +53,9 @@ STATIC mp_obj_t list_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp
case 1:
{
// make list from iterable
- mp_obj_t iterable = mp_getiter(args[0]);
+ // TODO: optimize list/tuple
mp_obj_t list = mp_obj_new_list(0, NULL);
- mp_obj_t item;
- while ((item = mp_iternext(iterable)) != MP_OBJ_NULL) {
- mp_obj_list_append(list, item);
- }
- return list;
+ return list_extend_from_iter(list, args[0]);
}
default:
@@ -167,18 +172,21 @@ mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg) {
STATIC mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in) {
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
- assert(MP_OBJ_IS_TYPE(arg_in, &mp_type_list));
- mp_obj_list_t *self = self_in;
- mp_obj_list_t *arg = arg_in;
+ if (MP_OBJ_IS_TYPE(arg_in, &mp_type_list)) {
+ mp_obj_list_t *self = self_in;
+ mp_obj_list_t *arg = arg_in;
+
+ if (self->len + arg->len > self->alloc) {
+ // TODO: use alloc policy for "4"
+ self->items = m_renew(mp_obj_t, self->items, self->alloc, self->len + arg->len + 4);
+ self->alloc = self->len + arg->len + 4;
+ }
- if (self->len + arg->len > self->alloc) {
- // TODO: use alloc policy for "4"
- self->items = m_renew(mp_obj_t, self->items, self->alloc, self->len + arg->len + 4);
- self->alloc = self->len + arg->len + 4;
+ memcpy(self->items + self->len, arg->items, sizeof(mp_obj_t) * arg->len);
+ self->len += arg->len;
+ } else {
+ list_extend_from_iter(self_in, arg_in);
}
-
- memcpy(self->items + self->len, arg->items, sizeof(mp_obj_t) * arg->len);
- self->len += arg->len;
return mp_const_none; // return None, as per CPython
}
diff --git a/py/objset.c b/py/objset.c
index 05d064a047..bdc8d7f382 100644
--- a/py/objset.c
+++ b/py/objset.c
@@ -9,6 +9,7 @@
#include "obj.h"
#include "runtime.h"
#include "runtime0.h"
+#include "builtin.h"
typedef struct _mp_obj_set_t {
mp_obj_base_t base;
@@ -445,6 +446,7 @@ STATIC const mp_map_elem_t set_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_symmetric_difference_update), (mp_obj_t)&set_symmetric_difference_update_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_union), (mp_obj_t)&set_union_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_update), (mp_obj_t)&set_update_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR___contains__), (mp_obj_t)&mp_op_contains_obj },
};
STATIC MP_DEFINE_CONST_DICT(set_locals_dict, set_locals_dict_table);
diff --git a/py/opmethods.c b/py/opmethods.c
new file mode 100644
index 0000000000..af2524cf20
--- /dev/null
+++ b/py/opmethods.c
@@ -0,0 +1,20 @@
+#include "nlr.h"
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "obj.h"
+#include "runtime.h"
+#include "runtime0.h"
+#include "builtin.h"
+
+STATIC mp_obj_t op_getitem(mp_obj_t lhs_in, mp_obj_t rhs_in) {
+ mp_obj_type_t *type = mp_obj_get_type(lhs_in);
+ return type->binary_op(MP_BINARY_OP_SUBSCR, lhs_in, rhs_in);
+}
+MP_DEFINE_CONST_FUN_OBJ_2(mp_op_getitem_obj, op_getitem);
+
+STATIC mp_obj_t op_contains(mp_obj_t lhs_in, mp_obj_t rhs_in) {
+ mp_obj_type_t *type = mp_obj_get_type(lhs_in);
+ return type->binary_op(MP_BINARY_OP_IN, lhs_in, rhs_in);
+}
+MP_DEFINE_CONST_FUN_OBJ_2(mp_op_contains_obj, op_contains);
diff --git a/py/parsehelper.c b/py/parsehelper.c
index e069657b1d..d467399a17 100644
--- a/py/parsehelper.c
+++ b/py/parsehelper.c
@@ -38,20 +38,30 @@ void mp_parse_show_exception(mp_lexer_t *lex, mp_parse_error_kind_t parse_error_
}
}
-mp_obj_t mp_parse_make_exception(mp_parse_error_kind_t parse_error_kind) {
- // TODO add source file and line number to exception?
+mp_obj_t mp_parse_make_exception(mp_lexer_t *lex, mp_parse_error_kind_t parse_error_kind) {
+ // make exception object
+ mp_obj_t exc;
switch (parse_error_kind) {
case MP_PARSE_ERROR_MEMORY:
- return mp_obj_new_exception_msg(&mp_type_MemoryError, STR_MEMORY);
+ exc = mp_obj_new_exception_msg(&mp_type_MemoryError, STR_MEMORY);
+ break;
case MP_PARSE_ERROR_UNEXPECTED_INDENT:
- return mp_obj_new_exception_msg(&mp_type_IndentationError, STR_UNEXPECTED_INDENT);
+ exc = mp_obj_new_exception_msg(&mp_type_IndentationError, STR_UNEXPECTED_INDENT);
+ break;
case MP_PARSE_ERROR_UNMATCHED_UNINDENT:
- return mp_obj_new_exception_msg(&mp_type_IndentationError, STR_UNMATCHED_UNINDENT);
+ exc = mp_obj_new_exception_msg(&mp_type_IndentationError, STR_UNMATCHED_UNINDENT);
+ break;
case MP_PARSE_ERROR_INVALID_SYNTAX:
default:
- return mp_obj_new_exception_msg(&mp_type_SyntaxError, STR_INVALID_SYNTAX);
+ exc = mp_obj_new_exception_msg(&mp_type_SyntaxError, STR_INVALID_SYNTAX);
+ break;
}
+
+ // add traceback to give info about file name and location
+ mp_obj_exception_add_traceback(exc, mp_lexer_source_name(lex), mp_lexer_cur(lex)->src_line, mp_lexer_cur(lex)->src_column);
+
+ return exc;
}
diff --git a/py/parsehelper.h b/py/parsehelper.h
index 1de70d19d6..b8f8c106dd 100644
--- a/py/parsehelper.h
+++ b/py/parsehelper.h
@@ -1,2 +1,2 @@
void mp_parse_show_exception(mp_lexer_t *lex, mp_parse_error_kind_t parse_error_kind);
-mp_obj_t mp_parse_make_exception(mp_parse_error_kind_t parse_error_kind);
+mp_obj_t mp_parse_make_exception(mp_lexer_t *lex, mp_parse_error_kind_t parse_error_kind);
diff --git a/py/py.mk b/py/py.mk
index 09b40566d5..741d4438f8 100644
--- a/py/py.mk
+++ b/py/py.mk
@@ -69,6 +69,7 @@ PY_O_BASENAME = \
objtuple.o \
objtype.o \
objzip.o \
+ opmethods.o \
sequence.o \
stream.o \
binary.o \
diff --git a/py/qstrdefs.h b/py/qstrdefs.h
index 6075000166..b332e22fa2 100644
--- a/py/qstrdefs.h
+++ b/py/qstrdefs.h
@@ -17,6 +17,7 @@ Q(__path__)
Q(__repl_print__)
Q(__bool__)
+Q(__contains__)
Q(__enter__)
Q(__exit__)
Q(__len__)
@@ -90,7 +91,7 @@ Q(calcsize)
#endif
Q(chr)
Q(classmethod)
-Q(collections)
+Q(_collections)
Q(complex)
Q(dict)
Q(dir)
diff --git a/py/runtime.c b/py/runtime.c
index ed01193628..a507f97f36 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -1132,7 +1132,7 @@ void *const mp_fun_table[MP_F_NUMBER_OF] = {
mp_obj_dict_store,
mp_obj_new_set,
mp_obj_set_store,
- mp_make_function_from_id,
+ mp_make_function_from_raw_code,
mp_call_function_n_kw_for_native,
mp_call_method_n_kw,
mp_getiter,
diff --git a/py/runtime.h b/py/runtime.h
index bf3d3da3ca..1d60181e7f 100644
--- a/py/runtime.h
+++ b/py/runtime.h
@@ -29,12 +29,9 @@ mp_obj_t mp_load_const_dec(qstr qstr);
mp_obj_t mp_load_const_str(qstr qstr);
mp_obj_t mp_load_const_bytes(qstr qstr);
-mp_obj_t mp_make_function_from_id(uint unique_code_id, mp_obj_t def_args, mp_obj_t def_kw_args);
-mp_obj_t mp_make_function_from_id_and_free(uint unique_code_id, mp_obj_t def_args, mp_obj_t def_kw_args);
mp_obj_t mp_make_function_n(int n_args, void *fun); // fun must have the correct signature for n_args fixed arguments
mp_obj_t mp_make_function_var(int n_args_min, mp_fun_var_t fun);
mp_obj_t mp_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 mp_make_closure_from_id(uint unique_code_id, mp_obj_t closure_tuple, mp_obj_t def_args, mp_obj_t def_kw_args);
mp_obj_t mp_call_function_0(mp_obj_t fun);
mp_obj_t mp_call_function_1(mp_obj_t fun, mp_obj_t arg);
diff --git a/py/runtime0.h b/py/runtime0.h
index 6ee70aa01d..eef3706794 100644
--- a/py/runtime0.h
+++ b/py/runtime0.h
@@ -86,7 +86,7 @@ typedef enum {
MP_F_STORE_MAP,
MP_F_BUILD_SET,
MP_F_STORE_SET,
- MP_F_MAKE_FUNCTION_FROM_ID,
+ MP_F_MAKE_FUNCTION_FROM_RAW_CODE,
MP_F_CALL_FUNCTION_N_KW_FOR_NATIVE,
MP_F_CALL_METHOD_N_KW,
MP_F_GETITER,
diff --git a/py/scope.c b/py/scope.c
index 51701727e6..391ad5da87 100644
--- a/py/scope.c
+++ b/py/scope.c
@@ -6,10 +6,12 @@
#include "misc.h"
#include "mpconfig.h"
#include "qstr.h"
+#include "obj.h"
#include "parse.h"
+#include "emitglue.h"
#include "scope.h"
-scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, uint unique_code_id, uint emit_options) {
+scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, uint emit_options) {
scope_t *scope = m_new0(scope_t, 1);
scope->kind = kind;
scope->pn = pn;
@@ -41,7 +43,7 @@ scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, uint
default:
assert(0);
}
- scope->unique_code_id = unique_code_id;
+ scope->raw_code = mp_emit_glue_new_raw_code();
scope->emit_options = emit_options;
scope->id_info_alloc = 8;
scope->id_info = m_new(id_info_t, scope->id_info_alloc);
diff --git a/py/scope.h b/py/scope.h
index 07b41fe721..6e0990ea9c 100644
--- a/py/scope.h
+++ b/py/scope.h
@@ -29,7 +29,7 @@ typedef struct _scope_t {
mp_parse_node_t pn;
qstr source_file;
qstr simple_name;
- uint unique_code_id;
+ mp_raw_code_t *raw_code;
uint8_t scope_flags; // see runtime0.h
uint8_t emit_options; // see compile.h
uint16_t num_params;
@@ -41,7 +41,7 @@ typedef struct _scope_t {
id_info_t *id_info;
} scope_t;
-scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, uint unique_code_id, uint emit_options);
+scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, uint emit_options);
void scope_free(scope_t *scope);
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);
diff --git a/py/showbc.c b/py/showbc.c
index 615d1fe0de..25b1b2ffb6 100644
--- a/py/showbc.c
+++ b/py/showbc.c
@@ -22,6 +22,11 @@
qstr = (qstr << 7) + (*ip & 0x7f); \
} while ((*ip++ & 0x80) != 0); \
}
+#define DECODE_PTR do { \
+ ip = (byte*)(((machine_uint_t)ip + sizeof(machine_uint_t) - 1) & (~(sizeof(machine_uint_t) - 1))); /* align ip */ \
+ unum = *(machine_uint_t*)ip; \
+ ip += sizeof(machine_uint_t); \
+} while (0)
void mp_byte_code_print(const byte *ip, int len) {
const byte *ip_start = ip;
@@ -389,22 +394,22 @@ void mp_byte_code_print(const byte *ip, int len) {
break;
case MP_BC_MAKE_FUNCTION:
- DECODE_UINT;
+ DECODE_PTR;
printf("MAKE_FUNCTION " UINT_FMT, unum);
break;
case MP_BC_MAKE_FUNCTION_DEFARGS:
- DECODE_UINT;
+ DECODE_PTR;
printf("MAKE_FUNCTION_DEFARGS " UINT_FMT, unum);
break;
case MP_BC_MAKE_CLOSURE:
- DECODE_UINT;
+ DECODE_PTR;
printf("MAKE_CLOSURE " UINT_FMT, unum);
break;
case MP_BC_MAKE_CLOSURE_DEFARGS:
- DECODE_UINT;
+ DECODE_PTR;
printf("MAKE_CLOSURE_DEFARGS " UINT_FMT, unum);
break;
diff --git a/py/vm.c b/py/vm.c
index f62cb2d7b1..be7cf01f00 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -7,6 +7,7 @@
#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
+#include "emitglue.h"
#include "runtime.h"
#include "bc0.h"
#include "bc.h"
@@ -29,20 +30,25 @@ typedef enum {
UNWIND_JUMP,
} mp_unwind_reason_t;
-#define DECODE_UINT { \
+#define DECODE_UINT do { \
unum = 0; \
do { \
unum = (unum << 7) + (*ip & 0x7f); \
} while ((*ip++ & 0x80) != 0); \
-}
+} 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 { \
+#define DECODE_QSTR do { \
qst = 0; \
do { \
qst = (qst << 7) + (*ip & 0x7f); \
} while ((*ip++ & 0x80) != 0); \
-}
+} while (0)
+#define DECODE_PTR do { \
+ ip = (byte*)(((machine_uint_t)ip + sizeof(machine_uint_t) - 1) & (~(sizeof(machine_uint_t) - 1))); /* align ip */ \
+ unum = *(machine_uint_t*)ip; \
+ ip += sizeof(machine_uint_t); \
+} while (0)
#define PUSH(val) *++sp = (val)
#define POP() (*sp--)
#define TOP() (*sp)
@@ -704,29 +710,29 @@ unwind_jump:
break;
case MP_BC_MAKE_FUNCTION:
- DECODE_UINT;
- PUSH(mp_make_function_from_id(unum, MP_OBJ_NULL, MP_OBJ_NULL));
+ DECODE_PTR;
+ PUSH(mp_make_function_from_raw_code((mp_raw_code_t*)unum, MP_OBJ_NULL, MP_OBJ_NULL));
break;
case MP_BC_MAKE_FUNCTION_DEFARGS:
- DECODE_UINT;
+ DECODE_PTR;
// Stack layout: def_tuple def_dict <- TOS
obj1 = POP();
- SET_TOP(mp_make_function_from_id(unum, TOP(), obj1));
+ SET_TOP(mp_make_function_from_raw_code((mp_raw_code_t*)unum, TOP(), obj1));
break;
case MP_BC_MAKE_CLOSURE:
- DECODE_UINT;
+ DECODE_PTR;
// Stack layout: closure_tuple <- TOS
- SET_TOP(mp_make_closure_from_id(unum, TOP(), MP_OBJ_NULL, MP_OBJ_NULL));
+ SET_TOP(mp_make_closure_from_raw_code((mp_raw_code_t*)unum, TOP(), MP_OBJ_NULL, MP_OBJ_NULL));
break;
case MP_BC_MAKE_CLOSURE_DEFARGS:
- DECODE_UINT;
+ DECODE_PTR;
// Stack layout: def_tuple def_dict closure_tuple <- TOS
obj1 = POP();
obj2 = POP();
- SET_TOP(mp_make_closure_from_id(unum, obj1, TOP(), obj2));
+ SET_TOP(mp_make_closure_from_raw_code((mp_raw_code_t*)unum, obj1, TOP(), obj2));
break;
case MP_BC_CALL_FUNCTION: