diff options
Diffstat (limited to 'py')
-rw-r--r-- | py/builtin.h | 6 | ||||
-rw-r--r-- | py/builtinimport.c | 9 | ||||
-rw-r--r-- | py/builtintables.c | 150 | ||||
-rw-r--r-- | py/builtintables.h | 2 | ||||
-rw-r--r-- | py/makeqstrdata.py | 4 | ||||
-rw-r--r-- | py/modarray.c | 25 | ||||
-rw-r--r-- | py/modcollections.c | 25 | ||||
-rw-r--r-- | py/modmath.c (renamed from py/builtinmath.c) | 0 | ||||
-rw-r--r-- | py/modmicropython.c (renamed from py/builtinmp.c) | 1 | ||||
-rw-r--r-- | py/mpconfig.h | 8 | ||||
-rw-r--r-- | py/obj.c | 28 | ||||
-rw-r--r-- | py/obj.h | 42 | ||||
-rw-r--r-- | py/objarray.c | 12 | ||||
-rw-r--r-- | py/objexcept.c | 24 | ||||
-rw-r--r-- | py/objmodule.c | 45 | ||||
-rw-r--r-- | py/objmodule.h | 4 | ||||
-rw-r--r-- | py/py.mk | 7 | ||||
-rw-r--r-- | py/qstr.c | 8 | ||||
-rw-r--r-- | py/qstrdefs.h | 7 | ||||
-rw-r--r-- | py/runtime.c | 154 |
20 files changed, 327 insertions, 234 deletions
diff --git a/py/builtin.h b/py/builtin.h index d9414045de..45da172d10 100644 --- a/py/builtin.h +++ b/py/builtin.h @@ -1,4 +1,4 @@ -mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args); +mp_obj_t mp_builtin___import__(uint n_args, mp_obj_t *args); MP_DECLARE_CONST_FUN_OBJ(mp_builtin___build_class___obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin___import___obj); @@ -6,7 +6,6 @@ MP_DECLARE_CONST_FUN_OBJ(mp_builtin___repl_print___obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_abs_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_all_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_any_obj); -MP_DECLARE_CONST_FUN_OBJ(mp_builtin_bytes_obj); // Temporary hack MP_DECLARE_CONST_FUN_OBJ(mp_builtin_callable_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_chr_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_dir_obj); @@ -30,9 +29,10 @@ MP_DECLARE_CONST_FUN_OBJ(mp_builtin_range_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_repr_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_sorted_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_sum_obj); -MP_DECLARE_CONST_FUN_OBJ(mp_builtin_str_obj); MP_DECLARE_CONST_FUN_OBJ(mp_namedtuple_obj); +extern const mp_obj_module_t mp_module_array; +extern const mp_obj_module_t mp_module_collections; extern const mp_obj_module_t mp_module_math; extern const mp_obj_module_t mp_module_micropython; diff --git a/py/builtinimport.c b/py/builtinimport.c index 2b9b3a30b9..882b128df1 100644 --- a/py/builtinimport.c +++ b/py/builtinimport.c @@ -12,6 +12,7 @@ #include "lexerunix.h" #include "parse.h" #include "obj.h" +#include "objmodule.h" #include "parsehelper.h" #include "compile.h" #include "runtime0.h" @@ -128,7 +129,7 @@ void do_load(mp_obj_t module_obj, vstr_t *file) { rt_globals_set(old_globals); } -mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) { +mp_obj_t mp_builtin___import__(uint n_args, mp_obj_t *args) { /* printf("import:\n"); for (int i = 0; i < n_args; i++) { @@ -156,7 +157,7 @@ mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) { const char *mod_str = (const char*)mp_obj_str_get_data(args[0], &mod_len); // check if module already exists - mp_obj_t module_obj = mp_obj_module_get(mp_obj_str_get_qstr(args[0])); + mp_obj_t module_obj = mp_module_get(mp_obj_str_get_qstr(args[0])); if (module_obj != MP_OBJ_NULL) { // If it's not a package, return module right away char *p = strchr(mod_str, '.'); @@ -169,7 +170,7 @@ mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) { } // Otherwise, we need to return top-level package qstr pkg_name = qstr_from_strn(mod_str, p - mod_str); - return mp_obj_module_get(pkg_name); + return mp_module_get(pkg_name); } uint last = 0; @@ -200,7 +201,7 @@ mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) { nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ImportError, "ImportError: No module named '%s'", qstr_str(mod_name))); } - module_obj = mp_obj_module_get(mod_name); + module_obj = mp_module_get(mod_name); if (module_obj == MP_OBJ_NULL) { // module not already loaded, so load it! diff --git a/py/builtintables.c b/py/builtintables.c new file mode 100644 index 0000000000..0aa0b66a72 --- /dev/null +++ b/py/builtintables.c @@ -0,0 +1,150 @@ +#include <stdlib.h> + +#include "misc.h" +#include "mpconfig.h" +#include "qstr.h" +#include "obj.h" +#include "builtin.h" +#include "builtintables.h" +#include "objarray.h" + +// builtins +// we put these tables in ROM because they're always needed and take up quite a bit of room in RAM +// in fact, it uses less ROM here in table form than the equivalent in code form initialising a dynamic mp_map_t object in RAM +// at the moment it's a linear table, but we could convert it to a const mp_map_t table with a simple preprocessing script + +typedef struct _mp_builtin_elem_t { + qstr qstr; + mp_obj_t elem; +} mp_builtin_elem_t; + +STATIC const mp_builtin_elem_t builtin_object_table[] = { + // built-in core functions + { MP_QSTR___build_class__, (mp_obj_t)&mp_builtin___build_class___obj }, + { MP_QSTR___import__, (mp_obj_t)&mp_builtin___import___obj }, + { MP_QSTR___repl_print__, (mp_obj_t)&mp_builtin___repl_print___obj }, + + // built-in types + { MP_QSTR_bool, (mp_obj_t)&bool_type }, + { MP_QSTR_bytes, (mp_obj_t)&bytes_type }, +#if MICROPY_ENABLE_FLOAT + { MP_QSTR_complex, (mp_obj_t)&mp_type_complex }, +#endif + { MP_QSTR_dict, (mp_obj_t)&dict_type }, + { MP_QSTR_enumerate, (mp_obj_t)&enumerate_type }, + { MP_QSTR_filter, (mp_obj_t)&filter_type }, +#if MICROPY_ENABLE_FLOAT + { MP_QSTR_float, (mp_obj_t)&mp_type_float }, +#endif + { MP_QSTR_int, (mp_obj_t)&int_type }, + { MP_QSTR_list, (mp_obj_t)&list_type }, + { MP_QSTR_map, (mp_obj_t)&map_type }, + { MP_QSTR_object, (mp_obj_t)&mp_type_object }, + { MP_QSTR_set, (mp_obj_t)&set_type }, + { MP_QSTR_str, (mp_obj_t)&str_type }, + { MP_QSTR_super, (mp_obj_t)&super_type }, + { MP_QSTR_tuple, (mp_obj_t)&tuple_type }, + { MP_QSTR_type, (mp_obj_t)&mp_type_type }, + { MP_QSTR_zip, (mp_obj_t)&zip_type }, + + { MP_QSTR_classmethod, (mp_obj_t)&mp_type_classmethod }, + { MP_QSTR_staticmethod, (mp_obj_t)&mp_type_staticmethod }, + + // built-in user functions + { MP_QSTR_abs, (mp_obj_t)&mp_builtin_abs_obj }, + { MP_QSTR_all, (mp_obj_t)&mp_builtin_all_obj }, + { MP_QSTR_any, (mp_obj_t)&mp_builtin_any_obj }, + { MP_QSTR_callable, (mp_obj_t)&mp_builtin_callable_obj }, + { MP_QSTR_chr, (mp_obj_t)&mp_builtin_chr_obj }, + { MP_QSTR_dir, (mp_obj_t)&mp_builtin_dir_obj }, + { MP_QSTR_divmod, (mp_obj_t)&mp_builtin_divmod_obj }, + { MP_QSTR_eval, (mp_obj_t)&mp_builtin_eval_obj }, + { MP_QSTR_exec, (mp_obj_t)&mp_builtin_exec_obj }, + { MP_QSTR_hash, (mp_obj_t)&mp_builtin_hash_obj }, + { MP_QSTR_id, (mp_obj_t)&mp_builtin_id_obj }, + { MP_QSTR_isinstance, (mp_obj_t)&mp_builtin_isinstance_obj }, + { MP_QSTR_issubclass, (mp_obj_t)&mp_builtin_issubclass_obj }, + { MP_QSTR_iter, (mp_obj_t)&mp_builtin_iter_obj }, + { MP_QSTR_len, (mp_obj_t)&mp_builtin_len_obj }, + { MP_QSTR_max, (mp_obj_t)&mp_builtin_max_obj }, + { MP_QSTR_min, (mp_obj_t)&mp_builtin_min_obj }, + { MP_QSTR_next, (mp_obj_t)&mp_builtin_next_obj }, + { MP_QSTR_ord, (mp_obj_t)&mp_builtin_ord_obj }, + { MP_QSTR_pow, (mp_obj_t)&mp_builtin_pow_obj }, + { MP_QSTR_print, (mp_obj_t)&mp_builtin_print_obj }, + { MP_QSTR_range, (mp_obj_t)&mp_builtin_range_obj }, + { MP_QSTR_repr, (mp_obj_t)&mp_builtin_repr_obj }, + { MP_QSTR_sorted, (mp_obj_t)&mp_builtin_sorted_obj }, + { MP_QSTR_sum, (mp_obj_t)&mp_builtin_sum_obj }, + { MP_QSTR_bytearray, (mp_obj_t)&mp_builtin_bytearray_obj }, + + // built-in exceptions + { MP_QSTR_BaseException, (mp_obj_t)&mp_type_BaseException }, + { MP_QSTR_ArithmeticError, (mp_obj_t)&mp_type_ArithmeticError }, + { MP_QSTR_AssertionError, (mp_obj_t)&mp_type_AssertionError }, + { MP_QSTR_AttributeError, (mp_obj_t)&mp_type_AttributeError }, + { MP_QSTR_BufferError, (mp_obj_t)&mp_type_BufferError }, + { MP_QSTR_EOFError, (mp_obj_t)&mp_type_EOFError }, + { MP_QSTR_Exception, (mp_obj_t)&mp_type_Exception }, + { MP_QSTR_FloatingPointError, (mp_obj_t)&mp_type_FloatingPointError }, + { MP_QSTR_GeneratorExit, (mp_obj_t)&mp_type_GeneratorExit }, + { MP_QSTR_IOError, (mp_obj_t)&mp_type_IOError }, + { MP_QSTR_ImportError, (mp_obj_t)&mp_type_ImportError }, + { MP_QSTR_IndentationError, (mp_obj_t)&mp_type_IndentationError }, + { MP_QSTR_IndexError, (mp_obj_t)&mp_type_IndexError }, + { MP_QSTR_KeyError, (mp_obj_t)&mp_type_KeyError }, + { MP_QSTR_LookupError, (mp_obj_t)&mp_type_LookupError }, + { MP_QSTR_MemoryError, (mp_obj_t)&mp_type_MemoryError }, + { MP_QSTR_NameError, (mp_obj_t)&mp_type_NameError }, + { MP_QSTR_NotImplementedError, (mp_obj_t)&mp_type_NotImplementedError }, + { MP_QSTR_OSError, (mp_obj_t)&mp_type_OSError }, + { MP_QSTR_OverflowError, (mp_obj_t)&mp_type_OverflowError }, + { MP_QSTR_RuntimeError, (mp_obj_t)&mp_type_RuntimeError }, + { MP_QSTR_StopIteration, (mp_obj_t)&mp_type_StopIteration }, + { MP_QSTR_SyntaxError, (mp_obj_t)&mp_type_SyntaxError }, + { MP_QSTR_SystemError, (mp_obj_t)&mp_type_SystemError }, + { MP_QSTR_TypeError, (mp_obj_t)&mp_type_TypeError }, + { MP_QSTR_UnboundLocalError, (mp_obj_t)&mp_type_UnboundLocalError }, + { MP_QSTR_ValueError, (mp_obj_t)&mp_type_ValueError }, + { MP_QSTR_ZeroDivisionError, (mp_obj_t)&mp_type_ZeroDivisionError }, + // Somehow CPython managed to have OverflowError not inherit from ValueError ;-/ + // TODO: For MICROPY_CPYTHON_COMPAT==0 use ValueError to avoid exc proliferation + + // Extra builtins as defined by a port + MICROPY_EXTRA_BUILTINS + + { MP_QSTR_, MP_OBJ_NULL }, // end of list sentinel +}; + +STATIC const mp_builtin_elem_t builtin_module_table[] = { + { MP_QSTR_micropython, (mp_obj_t)&mp_module_micropython }, + + { MP_QSTR_array, (mp_obj_t)&mp_module_array }, + { MP_QSTR_collections, (mp_obj_t)&mp_module_collections }, + +#if MICROPY_ENABLE_FLOAT + { MP_QSTR_math, (mp_obj_t)&mp_module_math }, +#endif + + // extra builtin modules as defined by a port + MICROPY_EXTRA_BUILTIN_MODULES + + { MP_QSTR_, MP_OBJ_NULL }, // end of list sentinel +}; + +STATIC mp_obj_t mp_builtin_tables_lookup(const mp_builtin_elem_t *table, qstr q) { + for (; table->qstr != MP_QSTR_; table++) { + if (table->qstr == q) { + return table->elem; + } + } + return MP_OBJ_NULL; +} + +mp_obj_t mp_builtin_tables_lookup_object(qstr q) { + return mp_builtin_tables_lookup(&builtin_object_table[0], q); +} + +mp_obj_t mp_builtin_tables_lookup_module(qstr q) { + return mp_builtin_tables_lookup(&builtin_module_table[0], q); +} diff --git a/py/builtintables.h b/py/builtintables.h new file mode 100644 index 0000000000..9b22b66e03 --- /dev/null +++ b/py/builtintables.h @@ -0,0 +1,2 @@ +mp_obj_t mp_builtin_tables_lookup_object(qstr q); +mp_obj_t mp_builtin_tables_lookup_module(qstr q); diff --git a/py/makeqstrdata.py b/py/makeqstrdata.py index 934bc43beb..7413365712 100644 --- a/py/makeqstrdata.py +++ b/py/makeqstrdata.py @@ -18,9 +18,9 @@ codepoint2name[ord('/')] = 'slash' # this must match the equivalent function in qstr.c def compute_hash(qstr): - hash = 0 + hash = 5381 for char in qstr: - hash += ord(char) + hash = (hash * 33) ^ ord(char) return hash & 0xffff def do_work(infiles): diff --git a/py/modarray.c b/py/modarray.c new file mode 100644 index 0000000000..2544f7ed59 --- /dev/null +++ b/py/modarray.c @@ -0,0 +1,25 @@ +#include "misc.h" +#include "mpconfig.h" +#include "qstr.h" +#include "obj.h" +#include "map.h" +#include "builtin.h" + +STATIC const mp_map_elem_t mp_module_array_globals_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_array) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_array), (mp_obj_t)&mp_type_array }, +}; + +STATIC const mp_map_t mp_module_array_globals = { + .all_keys_are_qstrs = 1, + .table_is_fixed_array = 1, + .used = sizeof(mp_module_array_globals_table) / sizeof(mp_map_elem_t), + .alloc = sizeof(mp_module_array_globals_table) / sizeof(mp_map_elem_t), + .table = (mp_map_elem_t*)mp_module_array_globals_table, +}; + +const mp_obj_module_t mp_module_array = { + .base = { &mp_type_module }, + .name = MP_QSTR_array, + .globals = (mp_map_t*)&mp_module_array_globals, +}; diff --git a/py/modcollections.c b/py/modcollections.c new file mode 100644 index 0000000000..ad951d5e9e --- /dev/null +++ b/py/modcollections.c @@ -0,0 +1,25 @@ +#include "misc.h" +#include "mpconfig.h" +#include "qstr.h" +#include "obj.h" +#include "map.h" +#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_namedtuple), (mp_obj_t)&mp_namedtuple_obj }, +}; + +STATIC const mp_map_t mp_module_collections_globals = { + .all_keys_are_qstrs = 1, + .table_is_fixed_array = 1, + .used = sizeof(mp_module_collections_globals_table) / sizeof(mp_map_elem_t), + .alloc = sizeof(mp_module_collections_globals_table) / sizeof(mp_map_elem_t), + .table = (mp_map_elem_t*)mp_module_collections_globals_table, +}; + +const mp_obj_module_t mp_module_collections = { + .base = { &mp_type_module }, + .name = MP_QSTR_collections, + .globals = (mp_map_t*)&mp_module_collections_globals, +}; diff --git a/py/builtinmath.c b/py/modmath.c index b814822531..b814822531 100644 --- a/py/builtinmath.c +++ b/py/modmath.c diff --git a/py/builtinmp.c b/py/modmicropython.c index 3b73517963..96ceb811c9 100644 --- a/py/builtinmp.c +++ b/py/modmicropython.c @@ -1,4 +1,3 @@ - #include "misc.h" #include "mpconfig.h" #include "qstr.h" diff --git a/py/mpconfig.h b/py/mpconfig.h index 5b13c46480..09cc37913a 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -125,10 +125,16 @@ typedef double mp_float_t; #define MICROPY_PATH_MAX (512) #endif -// Additional builtin function definitions - see runtime.c:builtin_table for format. +// Additional builtin function definitions - see builtintables.c:builtin_object_table for format. #ifndef MICROPY_EXTRA_BUILTINS #define MICROPY_EXTRA_BUILTINS #endif + +// Additional builtin module definitions - see builtintables.c:builtin_module_table for format. +#ifndef MICROPY_EXTRA_BUILTIN_MODULES +#define MICROPY_EXTRA_BUILTIN_MODULES +#endif + /*****************************************************************************/ /* Miscellaneous settings */ @@ -206,21 +206,29 @@ void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) { } #endif -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)) { +void mp_obj_get_array(mp_obj_t o, uint *len, mp_obj_t **items) { + if (MP_OBJ_IS_TYPE(o, &tuple_type)) { + mp_obj_tuple_get(o, len, items); + } else if (MP_OBJ_IS_TYPE(o, &list_type)) { + mp_obj_list_get(o, len, items); + } else { + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "object '%s' is not a tuple or list", mp_obj_get_type_str(o))); + } +} + +void mp_obj_get_array_fixed_n(mp_obj_t o, uint len, mp_obj_t **items) { + if (MP_OBJ_IS_TYPE(o, &tuple_type) || MP_OBJ_IS_TYPE(o, &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); + if (MP_OBJ_IS_TYPE(o, &tuple_type)) { + mp_obj_tuple_get(o, &seq_len, items); } else { - mp_obj_list_get(o_in, &seq_len, &seq_items); + mp_obj_list_get(o, &seq_len, items); } - if (seq_len != n) { - nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_IndexError, "requested length %d but object has length %d", n, seq_len)); + if (seq_len != len) { + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_IndexError, "requested length %d but object has length %d", len, seq_len)); } - return seq_items; } else { - nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "object '%s' is not a tuple or list", mp_obj_get_type_str(o_in))); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "object '%s' is not a tuple or list", mp_obj_get_type_str(o))); } } @@ -175,7 +175,6 @@ struct _mp_obj_type_t { abs float complex hash bool int none str equal int str - get_array_n tuple list unpack seq list tuple */ @@ -192,17 +191,12 @@ extern const mp_obj_type_t mp_type_ArithmeticError; extern const mp_obj_type_t mp_type_AssertionError; extern const mp_obj_type_t mp_type_AttributeError; extern const mp_obj_type_t mp_type_BufferError; -extern const mp_obj_type_t mp_type_BytesWarning; -extern const mp_obj_type_t mp_type_DeprecationWarning; extern const mp_obj_type_t mp_type_EOFError; -extern const mp_obj_type_t mp_type_EnvironmentError; extern const mp_obj_type_t mp_type_Exception; extern const mp_obj_type_t mp_type_FloatingPointError; -extern const mp_obj_type_t mp_type_FutureWarning; extern const mp_obj_type_t mp_type_GeneratorExit; extern const mp_obj_type_t mp_type_IOError; extern const mp_obj_type_t mp_type_ImportError; -extern const mp_obj_type_t mp_type_ImportWarning; extern const mp_obj_type_t mp_type_IndentationError; extern const mp_obj_type_t mp_type_IndexError; extern const mp_obj_type_t mp_type_KeyError; @@ -212,43 +206,16 @@ extern const mp_obj_type_t mp_type_NameError; extern const mp_obj_type_t mp_type_NotImplementedError; extern const mp_obj_type_t mp_type_OSError; extern const mp_obj_type_t mp_type_OverflowError; -extern const mp_obj_type_t mp_type_PendingDeprecationWarning; -extern const mp_obj_type_t mp_type_ReferenceError; -extern const mp_obj_type_t mp_type_ResourceWarning; extern const mp_obj_type_t mp_type_RuntimeError; -extern const mp_obj_type_t mp_type_RuntimeWarning; +extern const mp_obj_type_t mp_type_StopIteration; extern const mp_obj_type_t mp_type_SyntaxError; -extern const mp_obj_type_t mp_type_SyntaxWarning; extern const mp_obj_type_t mp_type_SystemError; -extern const mp_obj_type_t mp_type_SystemExit; -extern const mp_obj_type_t mp_type_TabError; extern const mp_obj_type_t mp_type_TypeError; extern const mp_obj_type_t mp_type_UnboundLocalError; -extern const mp_obj_type_t mp_type_UserWarning; extern const mp_obj_type_t mp_type_ValueError; -extern const mp_obj_type_t mp_type_Warning; extern const mp_obj_type_t mp_type_ZeroDivisionError; -extern const mp_obj_type_t mp_type_StopIteration; -/*extern const mp_obj_type_t mp_type_BaseException; -extern const mp_obj_type_t mp_type_AssertionError; -extern const mp_obj_type_t mp_type_AttributeError; -extern const mp_obj_type_t mp_type_ImportError; -extern const mp_obj_type_t mp_type_IndentationError; -extern const mp_obj_type_t mp_type_IndexError; -extern const mp_obj_type_t mp_type_KeyError; -extern const mp_obj_type_t mp_type_NameError; -extern const mp_obj_type_t mp_type_SyntaxError; -extern const mp_obj_type_t mp_type_TypeError; -extern const mp_obj_type_t mp_type_ValueError; -extern const mp_obj_type_t mp_type_OverflowError; -extern const mp_obj_type_t mp_type_OSError; -extern const mp_obj_type_t mp_type_NotImplementedError; -extern const mp_obj_type_t mp_type_StopIteration; -extern const mp_obj_type_t mp_type_ZeroDivisionError;*/ - // Constant objects, globally accessible - extern const mp_obj_t mp_const_none; extern const mp_obj_t mp_const_false; extern const mp_obj_t mp_const_true; @@ -311,7 +278,8 @@ 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 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); +void mp_obj_get_array(mp_obj_t o, uint *len, mp_obj_t **items); +void mp_obj_get_array_fixed_n(mp_obj_t o, uint len, mp_obj_t **items); uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index, bool is_slice); mp_obj_t mp_obj_len_maybe(mp_obj_t o_in); /* may return NULL */ @@ -417,7 +385,7 @@ void mp_obj_slice_get(mp_obj_t self_in, machine_int_t *start, machine_int_t *sto extern const mp_obj_type_t zip_type; // array -extern const mp_obj_type_t array_type; +extern const mp_obj_type_t mp_type_array; uint mp_obj_array_len(mp_obj_t self_in); mp_obj_t mp_obj_new_bytearray_by_ref(uint n, void *items); @@ -454,8 +422,6 @@ typedef struct _mp_obj_module_t { struct _mp_map_t *globals; } mp_obj_module_t; extern const mp_obj_type_t mp_type_module; -mp_obj_t mp_obj_new_module(qstr module_name); -mp_obj_t mp_obj_module_get(qstr module_name); struct _mp_map_t *mp_obj_module_get_globals(mp_obj_t self_in); // staticmethod and classmethod types; defined here so we can make const versions diff --git a/py/objarray.c b/py/objarray.c index ee43bde960..69f60e000a 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -121,7 +121,7 @@ STATIC mp_obj_t array_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { } STATIC mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg) { - assert(MP_OBJ_IS_TYPE(self_in, &array_type)); + assert(MP_OBJ_IS_TYPE(self_in, &mp_type_array)); mp_obj_array_t *self = self_in; if (self->free == 0) { int item_sz = mp_binary_get_size(self->typecode); @@ -154,7 +154,7 @@ STATIC const mp_method_t array_type_methods[] = { { NULL, NULL }, }; -const mp_obj_type_t array_type = { +const mp_obj_type_t mp_type_array = { { &mp_type_type }, .name = MP_QSTR_array, .print = array_print, @@ -169,7 +169,7 @@ const mp_obj_type_t array_type = { STATIC mp_obj_array_t *array_new(char typecode, uint n) { mp_obj_array_t *o = m_new_obj(mp_obj_array_t); - o->base.type = &array_type; + o->base.type = &mp_type_array; o->typecode = typecode; o->free = 0; o->len = n; @@ -190,7 +190,7 @@ mp_obj_t mp_obj_new_bytearray(uint n, void *items) { // Create bytearray which references specified memory area mp_obj_t mp_obj_new_bytearray_by_ref(uint n, void *items) { mp_obj_array_t *o = m_new_obj(mp_obj_array_t); - o->base.type = &array_type; + o->base.type = &mp_type_array; o->typecode = BYTEARRAY_TYPECODE; o->free = 0; o->len = n; @@ -207,7 +207,7 @@ typedef struct _mp_obj_array_it_t { machine_uint_t cur; } mp_obj_array_it_t; -mp_obj_t array_it_iternext(mp_obj_t self_in) { +STATIC mp_obj_t array_it_iternext(mp_obj_t self_in) { mp_obj_array_it_t *self = self_in; if (self->cur < self->array->len) { return mp_binary_get_val(self->array->typecode, self->array->items, self->cur++); @@ -222,7 +222,7 @@ STATIC const mp_obj_type_t array_it_type = { .iternext = array_it_iternext, }; -mp_obj_t array_iterator_new(mp_obj_t array_in) { +STATIC mp_obj_t array_iterator_new(mp_obj_t array_in) { mp_obj_array_t *array = array_in; mp_obj_array_it_t *o = m_new_obj(mp_obj_array_it_t); o->base.type = &array_it_type; diff --git a/py/objexcept.c b/py/objexcept.c index de9bf1694f..0650920e7d 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -53,16 +53,31 @@ STATIC mp_obj_t mp_obj_exception_make_new(mp_obj_t type_in, uint n_args, uint n_ o->base.type = type; o->traceback = MP_OBJ_NULL; o->msg = NULL; + o->args.base.type = &tuple_type; o->args.len = n_args; memcpy(o->args.items, args, n_args * sizeof(mp_obj_t)); return o; } +STATIC void exception_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { + mp_obj_exception_t *self = self_in; + if (attr == MP_QSTR_args) { + dest[0] = &self->args; + } else if (self->base.type == &mp_type_StopIteration && attr == MP_QSTR_value) { + if (self->args.len == 0) { + dest[0] = mp_const_none; + } else { + dest[0] = self->args.items[0]; + } + } +} + const mp_obj_type_t mp_type_BaseException = { { &mp_type_type }, .name = MP_QSTR_BaseException, .print = mp_obj_exception_print, .make_new = mp_obj_exception_make_new, + .load_attr = exception_load_attr, }; #define MP_DEFINE_EXCEPTION_BASE(base_name) \ @@ -74,13 +89,14 @@ const mp_obj_type_t mp_type_ ## exc_name = { \ .name = MP_QSTR_ ## exc_name, \ .print = mp_obj_exception_print, \ .make_new = mp_obj_exception_make_new, \ + .load_attr = exception_load_attr, \ .bases_tuple = (mp_obj_t)&mp_type_ ## base_name ## _base_tuple, \ }; // List of all exceptions, arranged as in the table at: // http://docs.python.org/3.3/library/exceptions.html MP_DEFINE_EXCEPTION_BASE(BaseException) -MP_DEFINE_EXCEPTION(SystemExit, BaseException) +//MP_DEFINE_EXCEPTION(SystemExit, BaseException) //MP_DEFINE_EXCEPTION(KeyboardInterrupt, BaseException) MP_DEFINE_EXCEPTION(GeneratorExit, BaseException) MP_DEFINE_EXCEPTION(Exception, BaseException) @@ -94,7 +110,7 @@ MP_DEFINE_EXCEPTION(Exception, BaseException) MP_DEFINE_EXCEPTION(AssertionError, Exception) MP_DEFINE_EXCEPTION(AttributeError, Exception) MP_DEFINE_EXCEPTION(BufferError, Exception) - MP_DEFINE_EXCEPTION(EnvironmentError, Exception) + //MP_DEFINE_EXCEPTION(EnvironmentError, Exception) MP_DEFINE_EXCEPTION(EOFError, Exception) MP_DEFINE_EXCEPTION(ImportError, Exception) MP_DEFINE_EXCEPTION(IOError, Exception) @@ -124,7 +140,7 @@ MP_DEFINE_EXCEPTION(Exception, BaseException) MP_DEFINE_EXCEPTION(TimeoutError, OSError)*/ MP_DEFINE_EXCEPTION(FileExistsError, OSError) MP_DEFINE_EXCEPTION(FileNotFoundError, OSError) - MP_DEFINE_EXCEPTION(ReferenceError, Exception) + //MP_DEFINE_EXCEPTION(ReferenceError, Exception) MP_DEFINE_EXCEPTION(RuntimeError, Exception) MP_DEFINE_EXCEPTION_BASE(RuntimeError) MP_DEFINE_EXCEPTION(NotImplementedError, RuntimeError) @@ -132,7 +148,7 @@ MP_DEFINE_EXCEPTION(Exception, BaseException) MP_DEFINE_EXCEPTION_BASE(SyntaxError) MP_DEFINE_EXCEPTION(IndentationError, SyntaxError) MP_DEFINE_EXCEPTION_BASE(IndentationError) - MP_DEFINE_EXCEPTION(TabError, IndentationError) + //MP_DEFINE_EXCEPTION(TabError, IndentationError) MP_DEFINE_EXCEPTION(SystemError, Exception) MP_DEFINE_EXCEPTION(TypeError, Exception) MP_DEFINE_EXCEPTION(ValueError, Exception) diff --git a/py/objmodule.c b/py/objmodule.c index e0778b4cf2..a388ca3f37 100644 --- a/py/objmodule.c +++ b/py/objmodule.c @@ -6,9 +6,12 @@ #include "mpconfig.h" #include "qstr.h" #include "obj.h" +#include "objmodule.h" #include "runtime.h" #include "map.h" -#include "builtin.h" +#include "builtintables.h" + +STATIC mp_map_t mp_loaded_modules_map; // TODO: expose as sys.modules STATIC void module_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { mp_obj_module_t *self = self_in; @@ -39,7 +42,7 @@ const mp_obj_type_t mp_type_module = { }; mp_obj_t mp_obj_new_module(qstr module_name) { - mp_map_elem_t *el = mp_map_lookup(rt_loaded_modules_get(), MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); + mp_map_elem_t *el = mp_map_lookup(&mp_loaded_modules_map, MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); // We could error out if module already exists, but let C extensions // add new members to existing modules. if (el->value != MP_OBJ_NULL) { @@ -62,9 +65,27 @@ mp_obj_t mp_obj_new_module(qstr module_name) { return o; } -mp_obj_t mp_obj_module_get(qstr module_name) { +mp_map_t *mp_obj_module_get_globals(mp_obj_t self_in) { + assert(MP_OBJ_IS_TYPE(self_in, &mp_type_module)); + mp_obj_module_t *self = self_in; + return self->globals; +} + +/******************************************************************************/ +// Global module table and related functions + +void mp_module_init(void) { + mp_map_init(&mp_loaded_modules_map, 3); +} + +void mp_module_deinit(void) { + mp_map_deinit(&mp_loaded_modules_map); +} + +// returns MP_OBJ_NULL if not found +mp_obj_t mp_module_get(qstr module_name) { // lookup module - mp_map_elem_t *el = mp_map_lookup(rt_loaded_modules_get(), MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP); + mp_map_elem_t *el = mp_map_lookup(&mp_loaded_modules_map, MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP); // module found, return it if (el != NULL) { @@ -72,18 +93,10 @@ mp_obj_t mp_obj_module_get(qstr module_name) { } // module not found, look for builtin module names -#if MICROPY_ENABLE_FLOAT - if (module_name == MP_QSTR_math) { - return (mp_obj_t)&mp_module_math; - } -#endif - - // no module found, return NULL object - return MP_OBJ_NULL; + // it will return MP_OBJ_NULL if nothing found + return mp_builtin_tables_lookup_module(module_name); } -mp_map_t *mp_obj_module_get_globals(mp_obj_t self_in) { - assert(MP_OBJ_IS_TYPE(self_in, &mp_type_module)); - mp_obj_module_t *self = self_in; - return self->globals; +void mp_module_register(qstr qstr, mp_obj_t module) { + mp_map_lookup(&mp_loaded_modules_map, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = module; } diff --git a/py/objmodule.h b/py/objmodule.h new file mode 100644 index 0000000000..270551da4f --- /dev/null +++ b/py/objmodule.h @@ -0,0 +1,4 @@ +void mp_module_init(void); +void mp_module_deinit(void); +mp_obj_t mp_module_get(qstr module_name); +void mp_module_register(qstr qstr, mp_obj_t module); @@ -74,8 +74,11 @@ PY_O_BASENAME = \ builtin.o \ builtinimport.o \ builtinevex.o \ - builtinmp.o \ - builtinmath.o \ + builtintables.o \ + modarray.o \ + modcollections.o \ + modmath.o \ + modmicropython.o \ vm.o \ showbc.o \ repl.o \ @@ -18,7 +18,7 @@ // A qstr is an index into the qstr pool. // The data for a qstr contains (hash, length, data). // For now we use very simple encoding, just to get the framework correct: -// - hash is 2 bytes (simply the sum of data bytes) +// - hash is 2 bytes (see function below) // - length is 2 bytes // - data follows // - \0 terminated (for now, so they can be printed using printf) @@ -28,10 +28,12 @@ #define Q_GET_LENGTH(q) ((q)[2] | ((q)[3] << 8)) #define Q_GET_DATA(q) ((q) + 4) +// this must match the equivalent function in makeqstrdata.py machine_uint_t qstr_compute_hash(const byte *data, uint len) { - machine_uint_t hash = 0; + // djb2 algorithm; see http://www.cse.yorku.ca/~oz/hash.html + machine_uint_t hash = 5381; for (const byte *top = data + len; data < top; data++) { - hash += *data; + hash = ((hash << 5) + hash) ^ (*data); // hash * 33 ^ data } return hash & 0xffff; } diff --git a/py/qstrdefs.h b/py/qstrdefs.h index 898e67582f..44c61002a6 100644 --- a/py/qstrdefs.h +++ b/py/qstrdefs.h @@ -39,7 +39,6 @@ Q(AssertionError) Q(AttributeError) Q(BufferError) Q(EOFError) -Q(EnvironmentError) Q(Exception) Q(FileExistsError) Q(FileNotFoundError) @@ -56,16 +55,12 @@ Q(NameError) Q(NotImplementedError) Q(OSError) Q(OverflowError) -Q(ReferenceError) Q(RuntimeError) Q(SyntaxError) Q(SystemError) -Q(SystemExit) -Q(TabError) Q(TypeError) Q(UnboundLocalError) Q(ValueError) -Q(Warning) Q(ZeroDivisionError) Q(None) @@ -78,6 +73,7 @@ Q(NoneType) Q(abs) Q(all) Q(any) +Q(args) Q(array) Q(bool) Q(bytearray) @@ -123,6 +119,7 @@ Q(str) Q(sys) Q(tuple) Q(type) +Q(value) Q(zip) Q(append) diff --git a/py/runtime.c b/py/runtime.c index 58c6620085..0f5d1229f2 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -12,12 +12,13 @@ #include "mpconfig.h" #include "qstr.h" #include "obj.h" +#include "objmodule.h" #include "parsenum.h" #include "runtime0.h" #include "runtime.h" #include "map.h" #include "builtin.h" -#include "objarray.h" +#include "builtintables.h" #include "bc.h" #include "intdivmod.h" @@ -35,7 +36,6 @@ STATIC mp_map_t *map_locals; STATIC mp_map_t *map_globals; STATIC mp_map_t map_builtins; -STATIC mp_map_t map_loaded_modules; // TODO: expose as sys.modules typedef enum { MP_CODE_NONE, @@ -72,119 +72,6 @@ STATIC mp_code_t *unique_codes = NULL; FILE *fp_write_code = NULL; #endif -// builtins -// we put this table in ROM because it's always needed and takes up quite a bit of room in RAM -// in fact, it uses less ROM here in table form than the equivalent in code form initialising a dynamic mp_map_t object in RAM -// at the moment it's a linear table, but we could convert it to a const mp_map_t table with a simple preprocessing script -// if we wanted to allow dynamic modification of the builtins, we could provide an mp_map_t object which is searched before this one - -typedef struct _mp_builtin_elem_t { - qstr qstr; - mp_obj_t fun; -} mp_builtin_elem_t; - -STATIC const mp_builtin_elem_t builtin_table[] = { - // built-in core functions - { MP_QSTR___build_class__, (mp_obj_t)&mp_builtin___build_class___obj }, - { MP_QSTR___import__, (mp_obj_t)&mp_builtin___import___obj }, - { MP_QSTR___repl_print__, (mp_obj_t)&mp_builtin___repl_print___obj }, - - // built-in types - { MP_QSTR_bool, (mp_obj_t)&bool_type }, - { MP_QSTR_bytes, (mp_obj_t)&bytes_type }, -#if MICROPY_ENABLE_FLOAT - { MP_QSTR_complex, (mp_obj_t)&mp_type_complex }, -#endif - { MP_QSTR_dict, (mp_obj_t)&dict_type }, - { MP_QSTR_enumerate, (mp_obj_t)&enumerate_type }, - { MP_QSTR_filter, (mp_obj_t)&filter_type }, -#if MICROPY_ENABLE_FLOAT - { MP_QSTR_float, (mp_obj_t)&mp_type_float }, -#endif - { MP_QSTR_int, (mp_obj_t)&int_type }, - { MP_QSTR_list, (mp_obj_t)&list_type }, - { MP_QSTR_map, (mp_obj_t)&map_type }, - { MP_QSTR_object, (mp_obj_t)&mp_type_object }, - { MP_QSTR_set, (mp_obj_t)&set_type }, - { MP_QSTR_str, (mp_obj_t)&str_type }, - { MP_QSTR_super, (mp_obj_t)&super_type }, - { MP_QSTR_tuple, (mp_obj_t)&tuple_type }, - { MP_QSTR_type, (mp_obj_t)&mp_type_type }, - { MP_QSTR_zip, (mp_obj_t)&zip_type }, - - { MP_QSTR_classmethod, (mp_obj_t)&mp_type_classmethod }, - { MP_QSTR_staticmethod, (mp_obj_t)&mp_type_staticmethod }, - - // built-in user functions - { MP_QSTR_abs, (mp_obj_t)&mp_builtin_abs_obj }, - { MP_QSTR_all, (mp_obj_t)&mp_builtin_all_obj }, - { MP_QSTR_any, (mp_obj_t)&mp_builtin_any_obj }, - { MP_QSTR_callable, (mp_obj_t)&mp_builtin_callable_obj }, - { MP_QSTR_chr, (mp_obj_t)&mp_builtin_chr_obj }, - { MP_QSTR_dir, (mp_obj_t)&mp_builtin_dir_obj }, - { MP_QSTR_divmod, (mp_obj_t)&mp_builtin_divmod_obj }, - { MP_QSTR_eval, (mp_obj_t)&mp_builtin_eval_obj }, - { MP_QSTR_exec, (mp_obj_t)&mp_builtin_exec_obj }, - { MP_QSTR_hash, (mp_obj_t)&mp_builtin_hash_obj }, - { MP_QSTR_id, (mp_obj_t)&mp_builtin_id_obj }, - { MP_QSTR_isinstance, (mp_obj_t)&mp_builtin_isinstance_obj }, - { MP_QSTR_issubclass, (mp_obj_t)&mp_builtin_issubclass_obj }, - { MP_QSTR_iter, (mp_obj_t)&mp_builtin_iter_obj }, - { MP_QSTR_len, (mp_obj_t)&mp_builtin_len_obj }, - { MP_QSTR_max, (mp_obj_t)&mp_builtin_max_obj }, - { MP_QSTR_min, (mp_obj_t)&mp_builtin_min_obj }, - { MP_QSTR_next, (mp_obj_t)&mp_builtin_next_obj }, - { MP_QSTR_ord, (mp_obj_t)&mp_builtin_ord_obj }, - { MP_QSTR_pow, (mp_obj_t)&mp_builtin_pow_obj }, - { MP_QSTR_print, (mp_obj_t)&mp_builtin_print_obj }, - { MP_QSTR_range, (mp_obj_t)&mp_builtin_range_obj }, - { MP_QSTR_repr, (mp_obj_t)&mp_builtin_repr_obj }, - { MP_QSTR_sorted, (mp_obj_t)&mp_builtin_sorted_obj }, - { MP_QSTR_sum, (mp_obj_t)&mp_builtin_sum_obj }, - { MP_QSTR_bytearray, (mp_obj_t)&mp_builtin_bytearray_obj }, - - // built-in exceptions - { MP_QSTR_BaseException, (mp_obj_t)&mp_type_BaseException }, - { MP_QSTR_ArithmeticError, (mp_obj_t)&mp_type_ArithmeticError }, - { MP_QSTR_AssertionError, (mp_obj_t)&mp_type_AssertionError }, - { MP_QSTR_AttributeError, (mp_obj_t)&mp_type_AttributeError }, - { MP_QSTR_BufferError, (mp_obj_t)&mp_type_BufferError }, - { MP_QSTR_EOFError, (mp_obj_t)&mp_type_EOFError }, - { MP_QSTR_EnvironmentError, (mp_obj_t)&mp_type_EnvironmentError }, - { MP_QSTR_Exception, (mp_obj_t)&mp_type_Exception }, - { MP_QSTR_FloatingPointError, (mp_obj_t)&mp_type_FloatingPointError }, - { MP_QSTR_GeneratorExit, (mp_obj_t)&mp_type_GeneratorExit }, - { MP_QSTR_IOError, (mp_obj_t)&mp_type_IOError }, - { MP_QSTR_ImportError, (mp_obj_t)&mp_type_ImportError }, - { MP_QSTR_IndentationError, (mp_obj_t)&mp_type_IndentationError }, - { MP_QSTR_IndexError, (mp_obj_t)&mp_type_IndexError }, - { MP_QSTR_KeyError, (mp_obj_t)&mp_type_KeyError }, - { MP_QSTR_LookupError, (mp_obj_t)&mp_type_LookupError }, - { MP_QSTR_MemoryError, (mp_obj_t)&mp_type_MemoryError }, - { MP_QSTR_NameError, (mp_obj_t)&mp_type_NameError }, - { MP_QSTR_NotImplementedError, (mp_obj_t)&mp_type_NotImplementedError }, - { MP_QSTR_OSError, (mp_obj_t)&mp_type_OSError }, - { MP_QSTR_OverflowError, (mp_obj_t)&mp_type_OverflowError }, - { MP_QSTR_ReferenceError, (mp_obj_t)&mp_type_ReferenceError }, - { MP_QSTR_RuntimeError, (mp_obj_t)&mp_type_RuntimeError }, - { MP_QSTR_SyntaxError, (mp_obj_t)&mp_type_SyntaxError }, - { MP_QSTR_SystemError, (mp_obj_t)&mp_type_SystemError }, - { MP_QSTR_SystemExit, (mp_obj_t)&mp_type_SystemExit }, - { MP_QSTR_TabError, (mp_obj_t)&mp_type_TabError }, - { MP_QSTR_TypeError, (mp_obj_t)&mp_type_TypeError }, - { MP_QSTR_UnboundLocalError, (mp_obj_t)&mp_type_UnboundLocalError }, - { MP_QSTR_ValueError, (mp_obj_t)&mp_type_ValueError }, - { MP_QSTR_ZeroDivisionError, (mp_obj_t)&mp_type_ZeroDivisionError }, - { MP_QSTR_StopIteration, (mp_obj_t)&mp_type_StopIteration }, - // Somehow CPython managed to have OverflowError not inherit from ValueError ;-/ - // TODO: For MICROPY_CPYTHON_COMPAT==0 use ValueError to avoid exc proliferation - - // Extra builtins as defined by a port - MICROPY_EXTRA_BUILTINS - - { MP_QSTR_, MP_OBJ_NULL }, // end of list sentinel -}; - // 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; @@ -193,23 +80,17 @@ STATIC void mp_map_add_qstr(mp_map_t *map, qstr qstr, mp_obj_t value) { void rt_init(void) { // locals = globals for outer module (see Objects/frameobject.c/PyFrame_New()) map_locals = map_globals = mp_map_new(1); - mp_map_add_qstr(map_globals, MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR___main__)); // init built-in hash table mp_map_init(&map_builtins, 3); - // init loaded modules table - mp_map_init(&map_loaded_modules, 3); + // init global module stuff + mp_module_init(); - // built-in objects + // add some builtins that can't be done in ROM + mp_map_add_qstr(map_globals, MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR___main__)); mp_map_add_qstr(&map_builtins, MP_QSTR_Ellipsis, mp_const_ellipsis); - mp_obj_t m_array = mp_obj_new_module(MP_QSTR_array); - rt_store_attr(m_array, MP_QSTR_array, (mp_obj_t)&array_type); - - mp_obj_t m_collections = mp_obj_new_module(MP_QSTR_collections); - rt_store_attr(m_collections, MP_QSTR_namedtuple, (mp_obj_t)&mp_namedtuple_obj); - #if MICROPY_CPYTHON_COMPAT // Precreate sys module, so "import sys" didn't throw exceptions. mp_obj_t m_sys = mp_obj_new_module(MP_QSTR_sys); @@ -221,10 +102,6 @@ void rt_init(void) { //sys_path = mp_obj_new_list(0, NULL); //rt_store_attr(m_sys, MP_QSTR_path, sys_path); - // we pre-import the micropython module - // probably shouldn't do this, so we are compatible with CPython - rt_store_name(MP_QSTR_micropython, (mp_obj_t)&mp_module_micropython); - // TODO: wastes one mp_code_t structure in mem next_unique_code_id = 1; // 0 indicates "no code" unique_codes_alloc = 0; @@ -238,8 +115,8 @@ void rt_init(void) { void rt_deinit(void) { m_del(mp_code_t, unique_codes, unique_codes_alloc); mp_map_free(map_globals); - mp_map_deinit(&map_loaded_modules); mp_map_deinit(&map_builtins); + mp_module_deinit(); #ifdef WRITE_CODE if (fp_write_code != NULL) { fclose(fp_write_code); @@ -428,10 +305,9 @@ mp_obj_t rt_load_global(qstr qstr) { if (elem == NULL) { elem = mp_map_lookup(&map_builtins, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP); if (elem == NULL) { - for (const mp_builtin_elem_t *e = &builtin_table[0]; e->qstr != MP_QSTR_; e++) { - if (e->qstr == qstr) { - return e->fun; - } + mp_obj_t o = mp_builtin_tables_lookup_object(qstr); + if (o != MP_OBJ_NULL) { + return o; } nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_NameError, "name '%s' is not defined", qstr_str(qstr))); } @@ -441,10 +317,13 @@ mp_obj_t rt_load_global(qstr qstr) { mp_obj_t rt_load_build_class(void) { DEBUG_OP_printf("load_build_class\n"); + // lookup __build_class__ in dynamic table of builtins first mp_map_elem_t *elem = mp_map_lookup(&map_builtins, MP_OBJ_NEW_QSTR(MP_QSTR___build_class__), MP_MAP_LOOKUP); if (elem != NULL) { + // found user-defined __build_class__, return it return elem->value; } else { + // no user-defined __build_class__, return builtin one return (mp_obj_t)&mp_builtin___build_class___obj; } } @@ -1001,7 +880,8 @@ void rt_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest) { // no attribute/method called attr // following CPython, we give a more detailed error message for type objects if (MP_OBJ_IS_TYPE(base, &mp_type_type)) { - nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_AttributeError, "type object '%s' has no attribute '%s'", ((mp_obj_type_t*)base)->name, qstr_str(attr))); + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_AttributeError, + "type object '%s' has no attribute '%s'", qstr_str(((mp_obj_type_t*)base)->name), qstr_str(attr))); } else { nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr))); } @@ -1140,10 +1020,6 @@ void rt_globals_set(mp_map_t *m) { map_globals = m; } -mp_map_t *rt_loaded_modules_get(void) { - return &map_loaded_modules; -} - // these must correspond to the respective enum void *const rt_fun_table[RT_F_NUMBER_OF] = { rt_load_const_dec, |