aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md6
-rw-r--r--py/builtin.c36
-rw-r--r--py/builtin.h2
-rw-r--r--py/builtinevex.c2
-rw-r--r--py/builtinimport.c12
-rw-r--r--py/builtintables.c4
-rw-r--r--py/compile.c30
-rw-r--r--py/gc.c1
-rw-r--r--py/intdivmod.c24
-rw-r--r--py/intdivmod.h4
-rw-r--r--py/malloc.c6
-rw-r--r--py/map.c202
-rw-r--r--py/misc.h1
-rw-r--r--py/modio.c30
-rw-r--r--py/mpconfig.h5
-rw-r--r--py/mpz.c36
-rw-r--r--py/mpz.h1
-rw-r--r--py/nlr.h17
-rw-r--r--py/nlrx64.S63
-rw-r--r--py/obj.c54
-rw-r--r--py/obj.h13
-rw-r--r--py/objarray.c2
-rw-r--r--py/objbool.c12
-rw-r--r--py/objcomplex.c2
-rw-r--r--py/objdict.c39
-rw-r--r--py/objexcept.c5
-rw-r--r--py/objfilter.c2
-rw-r--r--py/objfloat.c4
-rw-r--r--py/objfun.c37
-rw-r--r--py/objgenerator.c16
-rw-r--r--py/objgetitemiter.c2
-rw-r--r--py/objint.c55
-rw-r--r--py/objint.h7
-rw-r--r--py/objint_longlong.c18
-rw-r--r--py/objint_mpz.c40
-rw-r--r--py/objlist.c13
-rw-r--r--py/objmap.c2
-rw-r--r--py/objnamedtuple.c4
-rw-r--r--py/objobject.c2
-rw-r--r--py/objset.c25
-rw-r--r--py/objstr.c233
-rw-r--r--py/objtuple.c2
-rw-r--r--py/objtype.c27
-rw-r--r--py/parsenum.c10
-rw-r--r--py/pfenv.c4
-rw-r--r--py/pfenv.h2
-rwxr-xr-xpy/py-version.sh16
-rw-r--r--py/py.mk13
-rw-r--r--py/qstrdefs.h1
-rw-r--r--py/runtime.c180
-rw-r--r--py/runtime.h2
-rw-r--r--py/sequence.c2
-rw-r--r--py/smallint.c53
-rw-r--r--py/smallint.h5
-rw-r--r--py/stream.c20
-rw-r--r--py/vm.c21
-rw-r--r--stm/adc.c4
-rw-r--r--stm/audio.c2
-rw-r--r--stm/exti.c10
-rw-r--r--stm/file.c2
-rw-r--r--stm/mpconfigport.h2
-rw-r--r--stm/pin_map.c4
-rw-r--r--stm/pybwlan.c14
-rw-r--r--stmhal/adc.c8
-rwxr-xr-xstmhal/autoflash23
-rw-r--r--stmhal/dac.c4
-rw-r--r--stmhal/exti.c10
-rw-r--r--stmhal/file.c70
-rw-r--r--stmhal/i2c.c8
-rw-r--r--stmhal/input.c2
-rw-r--r--stmhal/led.c2
-rw-r--r--stmhal/main.c2
-rw-r--r--stmhal/math.c402
-rw-r--r--stmhal/modos.c10
-rw-r--r--stmhal/pin_map.c4
-rw-r--r--stmhal/pyexec.c8
-rw-r--r--stmhal/qstrdefsport.h2
-rw-r--r--stmhal/readline.c151
-rw-r--r--stmhal/servo.c6
-rw-r--r--stmhal/timer.c2
-rw-r--r--stmhal/usart.c2
-rw-r--r--stmhal/usb.h1
-rw-r--r--teensy/main.c2
-rw-r--r--teensy/servo.c4
-rw-r--r--tests/basics/dict-del.py21
-rw-r--r--tests/basics/getattr1.py2
-rw-r--r--tests/basics/globals-del.py27
-rw-r--r--tests/basics/math-fun.py4
-rw-r--r--tests/basics/memoryerror.py6
-rw-r--r--tests/basics/set_remove.py24
-rw-r--r--tests/basics/string-format-modulo.py41
-rw-r--r--tests/basics/string-format.py3
-rw-r--r--tests/basics/types2.py12
-rw-r--r--tests/io/file-with.py21
-rw-r--r--tests/misc/rge-sm.py2
-rwxr-xr-xtests/run-tests27
-rw-r--r--tools/pyboard.py39
-rw-r--r--unix-cpy/mpconfigport.h1
-rw-r--r--unix/Makefile6
-rw-r--r--unix/file.c31
-rw-r--r--unix/gccollect.c11
-rw-r--r--unix/main.c75
-rw-r--r--unix/modffi.c (renamed from unix/ffi.c)14
-rw-r--r--unix/modsocket.c (renamed from unix/socket.c)82
-rw-r--r--unix/modtime.c (renamed from unix/time.c)12
-rw-r--r--unix/mpconfigport.h1
106 files changed, 1962 insertions, 688 deletions
diff --git a/README.md b/README.md
index 411d274a4..52fd2f9c0 100644
--- a/README.md
+++ b/README.md
@@ -38,9 +38,9 @@ The Unix version
----------------
The "unix" port requires a standard Unix environment with gcc and GNU make.
-x86 and x64 architectures are supported (i.e. x86 32- and 64-bit). ARM to
-be confirmed. Porting to other architectures require writing some assembly
-code for the exception handling.
+x86 and x64 architectures are supported (i.e. x86 32- and 64-bit), as well
+as ARM. Porting to other architectures require writing some assembly code
+for the exception handling.
To build:
diff --git a/py/builtin.c b/py/builtin.c
index 67b0e46a6..22c5ecfde 100644
--- a/py/builtin.c
+++ b/py/builtin.c
@@ -141,7 +141,7 @@ STATIC mp_obj_t mp_builtin_chr(mp_obj_t o_in) {
byte str[1] = {ord};
return mp_obj_new_str(str, 1, true);
} else {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "chr() arg not in range(0x110000)"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "chr() arg not in range(0x110000)"));
}
}
@@ -194,7 +194,7 @@ STATIC mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) {
args[1] = MP_OBJ_NEW_SMALL_INT(i1 % i2);
return mp_obj_new_tuple(2, args);
} else {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "unsupported operand type(s) for divmod(): '%s' and '%s'", mp_obj_get_type_str(o1_in), mp_obj_get_type_str(o2_in)));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "unsupported operand type(s) for divmod(): '%s' and '%s'", mp_obj_get_type_str(o1_in), mp_obj_get_type_str(o2_in)));
}
}
@@ -216,7 +216,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_iter_obj, mp_builtin_iter);
STATIC mp_obj_t mp_builtin_len(mp_obj_t o_in) {
mp_obj_t len = mp_obj_len_maybe(o_in);
if (len == NULL) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "object of type '%s' has no len()", mp_obj_get_type_str(o_in)));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "object of type '%s' has no len()", mp_obj_get_type_str(o_in)));
} else {
return len;
}
@@ -231,19 +231,19 @@ STATIC mp_obj_t mp_builtin_max(uint n_args, const mp_obj_t *args) {
mp_obj_t max_obj = NULL;
mp_obj_t item;
while ((item = mp_iternext(iterable)) != MP_OBJ_NULL) {
- if (max_obj == NULL || mp_obj_less(max_obj, item)) {
+ if (max_obj == NULL || mp_binary_op(MP_BINARY_OP_LESS, max_obj, item)) {
max_obj = item;
}
}
if (max_obj == NULL) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "max() arg is an empty sequence"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "max() arg is an empty sequence"));
}
return max_obj;
} else {
// given many args
mp_obj_t max_obj = args[0];
for (int i = 1; i < n_args; i++) {
- if (mp_obj_less(max_obj, args[i])) {
+ if (mp_binary_op(MP_BINARY_OP_LESS, max_obj, args[i])) {
max_obj = args[i];
}
}
@@ -260,19 +260,19 @@ STATIC mp_obj_t mp_builtin_min(uint n_args, const mp_obj_t *args) {
mp_obj_t min_obj = NULL;
mp_obj_t item;
while ((item = mp_iternext(iterable)) != MP_OBJ_NULL) {
- if (min_obj == NULL || mp_obj_less(item, min_obj)) {
+ if (min_obj == NULL || mp_binary_op(MP_BINARY_OP_LESS, item, min_obj)) {
min_obj = item;
}
}
if (min_obj == NULL) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "min() arg is an empty sequence"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "min() arg is an empty sequence"));
}
return min_obj;
} else {
// given many args
mp_obj_t min_obj = args[0];
for (int i = 1; i < n_args; i++) {
- if (mp_obj_less(args[i], min_obj)) {
+ if (mp_binary_op(MP_BINARY_OP_LESS, args[i], min_obj)) {
min_obj = args[i];
}
}
@@ -285,7 +285,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR(mp_builtin_min_obj, 1, mp_builtin_min);
STATIC mp_obj_t mp_builtin_next(mp_obj_t o) {
mp_obj_t ret = mp_iternext_allow_raise(o);
if (ret == MP_OBJ_NULL) {
- nlr_jump(mp_obj_new_exception(&mp_type_StopIteration));
+ nlr_raise(mp_obj_new_exception(&mp_type_StopIteration));
} else {
return ret;
}
@@ -301,7 +301,7 @@ STATIC mp_obj_t mp_builtin_ord(mp_obj_t o_in) {
// TODO unicode
return mp_obj_new_int(((const byte*)str)[0]);
} else {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "ord() expected a character, but string of length %d found", len));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "ord() expected a character, but string of length %d found", len));
}
}
@@ -383,7 +383,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_sum_obj, 1, 2, mp_builtin_sum);
STATIC mp_obj_t mp_builtin_sorted(uint n_args, const mp_obj_t *args, mp_map_t *kwargs) {
assert(n_args >= 1);
if (n_args > 1) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError,
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
"must use keyword argument for key function"));
}
mp_obj_t self = mp_type_list.make_new((mp_obj_t)&mp_type_list, 1, 0, args);
@@ -400,9 +400,13 @@ STATIC mp_obj_t mp_builtin_id(mp_obj_t o_in) {
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_id_obj, mp_builtin_id);
-STATIC mp_obj_t mp_builtin_getattr(mp_obj_t o_in, mp_obj_t attr) {
- assert(MP_OBJ_IS_QSTR(attr));
- return mp_load_attr(o_in, MP_OBJ_QSTR_VALUE(attr));
+STATIC mp_obj_t mp_builtin_getattr(uint n_args, const mp_obj_t *args) {
+ assert(MP_OBJ_IS_QSTR(args[1]));
+ mp_obj_t defval = MP_OBJ_NULL;
+ if (n_args > 2) {
+ defval = args[2];
+ }
+ return mp_load_attr_default(args[0], MP_OBJ_QSTR_VALUE(args[1]), defval);
}
-MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_getattr_obj, mp_builtin_getattr);
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_getattr_obj, 2, 3, mp_builtin_getattr);
diff --git a/py/builtin.h b/py/builtin.h
index 50269dfe1..60b7c85b8 100644
--- a/py/builtin.h
+++ b/py/builtin.h
@@ -33,7 +33,9 @@ MP_DECLARE_CONST_FUN_OBJ(mp_builtin_sum_obj);
MP_DECLARE_CONST_FUN_OBJ(mp_namedtuple_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;
+extern const mp_obj_module_t mp_module_io;
extern const mp_obj_module_t mp_module_math;
extern const mp_obj_module_t mp_module_micropython;
diff --git a/py/builtinevex.c b/py/builtinevex.c
index 264aa77f3..4aafbdbe6 100644
--- a/py/builtinevex.c
+++ b/py/builtinevex.c
@@ -29,7 +29,7 @@ STATIC mp_obj_t parse_compile_execute(mp_obj_t o_in, mp_parse_input_kind_t parse
if (pn == MP_PARSE_NODE_NULL) {
// parse error; raise exception
- nlr_jump(mp_parse_make_exception(parse_error_kind));
+ nlr_raise(mp_parse_make_exception(parse_error_kind));
}
// compile the string
diff --git a/py/builtinimport.c b/py/builtinimport.c
index 8feb2a01b..ae59ea795 100644
--- a/py/builtinimport.c
+++ b/py/builtinimport.c
@@ -77,7 +77,7 @@ void do_load(mp_obj_t module_obj, vstr_t *file) {
if (lex == NULL) {
// we verified the file exists using stat, but lexer could still fail
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ImportError, "ImportError: No module named '%s'", vstr_str(file)));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError, "ImportError: No module named '%s'", vstr_str(file)));
}
qstr source_name = mp_lexer_source_name(lex);
@@ -99,7 +99,7 @@ void do_load(mp_obj_t module_obj, vstr_t *file) {
// parse error; clean up and raise exception
mp_locals_set(old_locals);
mp_globals_set(old_globals);
- nlr_jump(mp_parse_make_exception(parse_error_kind));
+ nlr_raise(mp_parse_make_exception(parse_error_kind));
}
// compile the imported script
@@ -122,7 +122,7 @@ void do_load(mp_obj_t module_obj, vstr_t *file) {
// exception; restore context and re-raise same exception
mp_locals_set(old_locals);
mp_globals_set(old_globals);
- nlr_jump(nlr.ret_val);
+ nlr_raise(nlr.ret_val);
}
mp_locals_set(old_locals);
mp_globals_set(old_globals);
@@ -148,7 +148,7 @@ mp_obj_t mp_builtin___import__(uint n_args, mp_obj_t *args) {
}
if (level != 0) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_NotImplementedError,
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_NotImplementedError,
"Relative import is not implemented"));
}
@@ -197,7 +197,7 @@ mp_obj_t mp_builtin___import__(uint n_args, mp_obj_t *args) {
// fail if we couldn't find the file
if (stat == MP_IMPORT_STAT_NO_EXIST) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ImportError, "ImportError: No module named '%s'", qstr_str(mod_name)));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError, "ImportError: No module named '%s'", qstr_str(mod_name)));
}
module_obj = mp_module_get(mod_name);
@@ -211,7 +211,7 @@ mp_obj_t mp_builtin___import__(uint n_args, mp_obj_t *args) {
vstr_add_str(&path, "__init__.py");
if (mp_import_stat(vstr_str(&path)) != MP_IMPORT_STAT_FILE) {
vstr_cut_tail_bytes(&path, sizeof("/__init__.py") - 1); // cut off /__init__.py
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ImportError,
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError,
"Per PEP-420 a dir without __init__.py (%s) is a namespace package; "
"namespace packages are not supported", vstr_str(&path)));
}
diff --git a/py/builtintables.c b/py/builtintables.c
index 2cb9240bb..1edeefa44 100644
--- a/py/builtintables.c
+++ b/py/builtintables.c
@@ -118,9 +118,13 @@ STATIC const mp_builtin_elem_t builtin_object_table[] = {
};
STATIC const mp_builtin_elem_t builtin_module_table[] = {
+ { MP_QSTR___main__, (mp_obj_t)&mp_module___main__ },
{ MP_QSTR_micropython, (mp_obj_t)&mp_module_micropython },
{ MP_QSTR_array, (mp_obj_t)&mp_module_array },
+#if MICROPY_ENABLE_MOD_IO
+ { MP_QSTR_io, (mp_obj_t)&mp_module_io },
+#endif
{ MP_QSTR_collections, (mp_obj_t)&mp_module_collections },
#if MICROPY_ENABLE_FLOAT
diff --git a/py/compile.c b/py/compile.c
index 3273abe40..6ede84239 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -17,7 +17,7 @@
#include "obj.h"
#include "compile.h"
#include "runtime.h"
-#include "intdivmod.h"
+#include "smallint.h"
// TODO need to mangle __attr names
@@ -115,38 +115,38 @@ mp_parse_node_t fold_constants(mp_parse_node_t pn) {
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_SMALL_INT(pns->nodes[0]);
machine_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[2]);
- machine_int_t res;
if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PLUS)) {
- res = arg0 + arg1;
+ arg0 += arg1;
} else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_MINUS)) {
- res = arg0 - arg1;
+ arg0 -= arg1;
} else {
// shouldn't happen
assert(0);
- res = 0;
}
- if (MP_PARSE_FITS_SMALL_INT(res)) {
- pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, res);
+ if (MP_PARSE_FITS_SMALL_INT(arg0)) {
+ pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0);
}
}
break;
case PN_term:
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_SMALL_INT(pns->nodes[0]);
- int arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[2]);
+ machine_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
+ machine_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(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 = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 * arg1);
-#endif
+ if (!mp_small_int_mul_overflow(arg0, arg1)) {
+ arg0 *= arg1;
+ if (MP_PARSE_FITS_SMALL_INT(arg0)) {
+ pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0);
+ }
+ }
} else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_SLASH)) {
; // pass
} else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PERCENT)) {
- pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, python_modulo(arg0, arg1));
+ pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, mp_small_int_modulo(arg0, arg1));
} else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_SLASH)) {
if (arg1 != 0) {
- pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, python_floor_divide(arg0, arg1));
+ pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, mp_small_int_floor_divide(arg0, arg1));
}
} else {
// shouldn't happen
diff --git a/py/gc.c b/py/gc.c
index e330e5c4a..1eb859cbf 100644
--- a/py/gc.c
+++ b/py/gc.c
@@ -3,6 +3,7 @@
#include <stdbool.h>
#include "mpconfig.h"
+#include "misc.h"
#include "gc.h"
#include "misc.h"
diff --git a/py/intdivmod.c b/py/intdivmod.c
deleted file mode 100644
index 4cb363b51..000000000
--- a/py/intdivmod.c
+++ /dev/null
@@ -1,24 +0,0 @@
-#include "mpconfig.h"
-
-machine_int_t python_modulo(machine_int_t dividend, machine_int_t divisor) {
- machine_int_t lsign = (dividend >= 0) ? 1 :-1;
- machine_int_t rsign = (divisor >= 0) ? 1 :-1;
- dividend %= divisor;
- if (lsign != rsign) {
- dividend += divisor;
- }
- return dividend;
-}
-
-
-machine_int_t python_floor_divide(machine_int_t num, machine_int_t denom) {
- machine_int_t lsign = num > 0 ? 1 : -1;
- machine_int_t rsign = denom > 0 ? 1 : -1;
- if (lsign == -1) {num *= -1;}
- if (rsign == -1) {denom *= -1;}
- if (lsign != rsign){
- return - ( num + denom - 1) / denom;
- } else {
- return num / denom;
- }
-}
diff --git a/py/intdivmod.h b/py/intdivmod.h
deleted file mode 100644
index 7716bd21e..000000000
--- a/py/intdivmod.h
+++ /dev/null
@@ -1,4 +0,0 @@
-// Functions for integer modulo and floor division
-
-machine_int_t python_modulo(machine_int_t dividend, machine_int_t divisor);
-machine_int_t python_floor_divide(machine_int_t num, machine_int_t denom);
diff --git a/py/malloc.c b/py/malloc.c
index b0094a254..a07d36002 100644
--- a/py/malloc.c
+++ b/py/malloc.c
@@ -42,8 +42,7 @@ void *m_malloc(int num_bytes) {
}
void *ptr = malloc(num_bytes);
if (ptr == NULL) {
- printf("could not allocate memory, allocating %d bytes\n", num_bytes);
- return NULL;
+ return m_malloc_fail(num_bytes);
}
#if MICROPY_MEM_STATS
total_bytes_allocated += num_bytes;
@@ -87,8 +86,7 @@ void *m_realloc(void *ptr, int old_num_bytes, int new_num_bytes) {
}
void *new_ptr = realloc(ptr, new_num_bytes);
if (new_ptr == NULL) {
- printf("could not allocate memory, reallocating %d bytes\n", new_num_bytes);
- return NULL;
+ return m_malloc_fail(new_num_bytes);
}
#if MICROPY_MEM_STATS
// At first thought, "Total bytes allocated" should only grow,
diff --git a/py/map.c b/py/map.c
index d424c277c..933b5f8e2 100644
--- a/py/map.c
+++ b/py/map.c
@@ -83,7 +83,7 @@ STATIC void mp_map_rehash(mp_map_t *map) {
map->all_keys_are_qstrs = 1;
map->table = m_new0(mp_map_elem_t, map->alloc);
for (int i = 0; i < old_alloc; i++) {
- if (old_table[i].key != NULL) {
+ if (old_table[i].key != MP_OBJ_NULL && old_table[i].key != MP_OBJ_SENTINEL) {
mp_map_lookup(map, old_table[i].key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = old_table[i].value;
}
}
@@ -106,8 +106,6 @@ mp_map_elem_t* mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t
// map is a hash table (not a fixed array), so do a hash lookup
- machine_uint_t hash;
- hash = mp_obj_hash(index);
if (map->alloc == 0) {
if (lookup_kind & MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) {
mp_map_rehash(map);
@@ -116,49 +114,78 @@ mp_map_elem_t* mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t
}
}
+ machine_uint_t hash = mp_obj_hash(index);
uint pos = hash % map->alloc;
+ uint start_pos = pos;
+ mp_map_elem_t *avail_slot = NULL;
for (;;) {
- mp_map_elem_t *elem = &map->table[pos];
- if (elem->key == NULL) {
- // not in table
+ mp_map_elem_t *slot = &map->table[pos];
+ if (slot->key == MP_OBJ_NULL) {
+ // found NULL slot, so index is not in table
if (lookup_kind & MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) {
- if (map->used + 1 >= map->alloc) {
- // not enough room in table, rehash it
- mp_map_rehash(map);
- // restart the search for the new element
- pos = hash % map->alloc;
- } else {
- map->used += 1;
- elem->key = index;
- if (!MP_OBJ_IS_QSTR(index)) {
- map->all_keys_are_qstrs = 0;
- }
- return elem;
+ map->used += 1;
+ if (avail_slot == NULL) {
+ avail_slot = slot;
+ }
+ slot->key = index;
+ slot->value = MP_OBJ_NULL;
+ if (!MP_OBJ_IS_QSTR(index)) {
+ map->all_keys_are_qstrs = 0;
}
+ return slot;
} else {
- return NULL;
+ return MP_OBJ_NULL;
}
- } else if (elem->key == index || (!map->all_keys_are_qstrs && 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) {
- elem->key = index;
+ } else if (slot->key == MP_OBJ_SENTINEL) {
+ // found deleted slot, remember for later
+ if (avail_slot == NULL) {
+ avail_slot = slot;
}
- */
+ } else if (slot->key == index || (!map->all_keys_are_qstrs && mp_obj_equal(slot->key, index))) {
+ // found index
+ // Note: CPython does not replace the index; try x={True:'true'};x[1]='one';x
if (lookup_kind & MP_MAP_LOOKUP_REMOVE_IF_FOUND) {
- map->used--;
// this leaks this memory (but see dict_get_helper)
mp_map_elem_t *retval = m_new(mp_map_elem_t, 1);
- retval->key = elem->key;
- retval->value = elem->value;
- elem->key = NULL;
- elem->value = NULL;
+ retval->key = slot->key;
+ retval->value = slot->value;
+ // delete element in this slot
+ map->used--;
+ if (map->table[(pos + 1) % map->alloc].key == MP_OBJ_NULL) {
+ // optimisation if next slot is empty
+ slot->key = MP_OBJ_NULL;
+ } else {
+ slot->key = MP_OBJ_SENTINEL;
+ }
return retval;
}
- return elem;
- } else {
- // not yet found, keep searching in this table
- pos = (pos + 1) % map->alloc;
+ return slot;
+ }
+
+ // not yet found, keep searching in this table
+ pos = (pos + 1) % map->alloc;
+
+ if (pos == start_pos) {
+ // search got back to starting position, so index is not in table
+ if (lookup_kind & MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) {
+ if (avail_slot != NULL) {
+ // there was an available slot, so use that
+ map->used++;
+ avail_slot->key = index;
+ avail_slot->value = MP_OBJ_NULL;
+ if (!MP_OBJ_IS_QSTR(index)) {
+ map->all_keys_are_qstrs = 0;
+ }
+ return avail_slot;
+ } else {
+ // not enough room in table, rehash it
+ mp_map_rehash(map);
+ // restart the search for the new element
+ start_pos = pos = hash % map->alloc;
+ }
+ } else {
+ return MP_OBJ_NULL;
+ }
}
}
}
@@ -179,16 +206,14 @@ STATIC void mp_set_rehash(mp_set_t *set) {
set->used = 0;
set->table = m_new0(mp_obj_t, set->alloc);
for (int i = 0; i < old_alloc; i++) {
- if (old_table[i] != NULL) {
- mp_set_lookup(set, old_table[i], true);
+ if (old_table[i] != MP_OBJ_NULL && old_table[i] != MP_OBJ_SENTINEL) {
+ mp_set_lookup(set, old_table[i], MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
}
}
m_del(mp_obj_t, old_table, old_alloc);
}
mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, mp_map_lookup_kind_t lookup_kind) {
- int hash;
- int pos;
if (set->alloc == 0) {
if (lookup_kind & MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) {
mp_set_rehash(set);
@@ -196,45 +221,84 @@ mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, mp_map_lookup_kind_t looku
return NULL;
}
}
- if (lookup_kind & MP_MAP_LOOKUP_FIRST) {
- hash = 0;
- pos = 0;
- } else {
- hash = mp_obj_hash(index);;
- pos = hash % set->alloc;
- }
+ machine_uint_t hash = mp_obj_hash(index);
+ uint pos = hash % set->alloc;
+ uint start_pos = pos;
+ mp_obj_t *avail_slot = NULL;
for (;;) {
mp_obj_t elem = set->table[pos];
if (elem == MP_OBJ_NULL) {
- // not in table
+ // found NULL slot, so index is not in table
if (lookup_kind & MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) {
- if (set->used + 1 >= set->alloc) {
+ if (avail_slot == NULL) {
+ avail_slot = &set->table[pos];
+ }
+ set->used++;
+ *avail_slot = index;
+ return index;
+ } else {
+ return MP_OBJ_NULL;
+ }
+ } else if (elem == MP_OBJ_SENTINEL) {
+ // found deleted slot, remember for later
+ if (avail_slot == NULL) {
+ avail_slot = &set->table[pos];
+ }
+ } else if (mp_obj_equal(elem, index)) {
+ // found index
+ if (lookup_kind & MP_MAP_LOOKUP_REMOVE_IF_FOUND) {
+ // delete element
+ set->used--;
+ if (set->table[(pos + 1) % set->alloc] == MP_OBJ_NULL) {
+ // optimisation if next slot is empty
+ set->table[pos] = MP_OBJ_NULL;
+ } else {
+ set->table[pos] = MP_OBJ_SENTINEL;
+ }
+ }
+ return elem;
+ }
+
+ // not yet found, keep searching in this table
+ pos = (pos + 1) % set->alloc;
+
+ if (pos == start_pos) {
+ // search got back to starting position, so index is not in table
+ if (lookup_kind & MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) {
+ if (avail_slot != NULL) {
+ // there was an available slot, so use that
+ set->used++;
+ *avail_slot = index;
+ return index;
+ } else {
// not enough room in table, rehash it
mp_set_rehash(set);
// restart the search for the new element
- pos = hash % set->alloc;
- } else {
- set->used += 1;
- set->table[pos] = index;
- return index;
+ start_pos = pos = hash % set->alloc;
}
- } else if (lookup_kind & MP_MAP_LOOKUP_FIRST) {
- pos++;
} else {
return MP_OBJ_NULL;
}
- } else if ((lookup_kind & MP_MAP_LOOKUP_FIRST) || mp_obj_equal(elem, index)) {
- // found it
- if (lookup_kind & MP_MAP_LOOKUP_REMOVE_IF_FOUND) {
- set->used--;
- set->table[pos] = NULL;
+ }
+ }
+}
+
+mp_obj_t mp_set_remove_first(mp_set_t *set) {
+ for (uint pos = 0; pos < set->alloc; pos++) {
+ if (set->table[pos] != MP_OBJ_NULL && set->table[pos] != MP_OBJ_SENTINEL) {
+ mp_obj_t elem = set->table[pos];
+ // delete element
+ set->used--;
+ if (set->table[(pos + 1) % set->alloc] == MP_OBJ_NULL) {
+ // optimisation if next slot is empty
+ set->table[pos] = MP_OBJ_NULL;
+ } else {
+ set->table[pos] = MP_OBJ_SENTINEL;
}
return elem;
- } else {
- // not yet found, keep searching in this table
- pos = (pos + 1) % set->alloc;
}
}
+ return MP_OBJ_NULL;
}
void mp_set_clear(mp_set_t *set) {
@@ -243,3 +307,17 @@ void mp_set_clear(mp_set_t *set) {
set->used = 0;
set->table = NULL;
}
+
+#if DEBUG_PRINT
+void mp_map_dump(mp_map_t *map) {
+ for (int i = 0; i < map->alloc; i++) {
+ if (map->table[i].key != NULL) {
+ mp_obj_print(map->table[i].key, PRINT_REPR);
+ } else {
+ printf("(nil)");
+ }
+ printf(": %p\n", map->table[i].value);
+ }
+ printf("---\n");
+}
+#endif
diff --git a/py/misc.h b/py/misc.h
index c99f819c6..df9a465e0 100644
--- a/py/misc.h
+++ b/py/misc.h
@@ -38,6 +38,7 @@ void *m_malloc_mp_obj(int num_bytes);
void *m_malloc0(int num_bytes);
void *m_realloc(void *ptr, int old_num_bytes, int new_num_bytes);
void m_free(void *ptr, int num_bytes);
+void *m_malloc_fail(int num_bytes);
int m_get_total_bytes_allocated(void);
int m_get_current_bytes_allocated(void);
diff --git a/py/modio.c b/py/modio.c
new file mode 100644
index 000000000..ced398358
--- /dev/null
+++ b/py/modio.c
@@ -0,0 +1,30 @@
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "obj.h"
+#include "builtin.h"
+
+#if MICROPY_ENABLE_MOD_IO
+
+STATIC const mp_map_elem_t mp_module_io_globals_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_io) },
+ // Note: mp_builtin_open_obj should be defined by port, it's not
+ // part of the core.
+ { MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj },
+};
+
+STATIC const mp_map_t mp_module_io_globals = {
+ .all_keys_are_qstrs = 1,
+ .table_is_fixed_array = 1,
+ .used = sizeof(mp_module_io_globals_table) / sizeof(mp_map_elem_t),
+ .alloc = sizeof(mp_module_io_globals_table) / sizeof(mp_map_elem_t),
+ .table = (mp_map_elem_t*)mp_module_io_globals_table,
+};
+
+const mp_obj_module_t mp_module_io = {
+ .base = { &mp_type_module },
+ .name = MP_QSTR_io,
+ .globals = (mp_map_t*)&mp_module_io_globals,
+};
+
+#endif
diff --git a/py/mpconfig.h b/py/mpconfig.h
index 09cc37913..65577f06c 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -105,6 +105,11 @@ typedef double mp_float_t;
#define MICROPY_ENABLE_FLOAT (0)
#endif
+// Whether to provide "io" module
+#ifndef MICROPY_ENABLE_MOD_IO
+#define MICROPY_ENABLE_MOD_IO (1)
+#endif
+
// Whether to support slice object and correspondingly
// slice subscript operators
#ifndef MICROPY_ENABLE_SLICE
diff --git a/py/mpz.c b/py/mpz.c
index 79d200d93..21b390996 100644
--- a/py/mpz.c
+++ b/py/mpz.c
@@ -993,8 +993,11 @@ void mpz_pow_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) {
if (mpz_is_odd(n)) {
mpz_mul_inpl(dest, dest, x);
}
- mpz_mul_inpl(x, x, x);
n->len = mpn_shr(n->dig, n->dig, n->len, 1);
+ if (n->len == 0) {
+ break;
+ }
+ mpz_mul_inpl(x, x, x);
}
mpz_free(x);
@@ -1139,6 +1142,7 @@ mpz_t *mpz_mod(const mpz_t *lhs, const mpz_t *rhs) {
}
#endif
+// TODO check that this correctly handles overflow in all cases
machine_int_t mpz_as_int(const mpz_t *i) {
machine_int_t val = 0;
mpz_dig_t *d = i->dig + i->len;
@@ -1147,11 +1151,13 @@ machine_int_t mpz_as_int(const mpz_t *i) {
machine_int_t oldval = val;
val = (val << DIG_SIZE) | *d;
if (val < oldval) {
- // TODO need better handling of conversion overflow
+ // overflow, return +/- "infinity"
if (i->neg == 0) {
- return 0x7fffffff;
+ // +infinity
+ return ~WORD_MSBIT_HIGH;
} else {
- return 0x80000000;
+ // -infinity
+ return WORD_MSBIT_HIGH;
}
}
}
@@ -1163,6 +1169,28 @@ machine_int_t mpz_as_int(const mpz_t *i) {
return val;
}
+// TODO check that this correctly handles overflow in all cases
+bool mpz_as_int_checked(const mpz_t *i, machine_int_t *value) {
+ machine_int_t val = 0;
+ mpz_dig_t *d = i->dig + i->len;
+
+ while (--d >= i->dig) {
+ machine_int_t oldval = val;
+ val = (val << DIG_SIZE) | *d;
+ if (val < oldval) {
+ // overflow
+ return false;
+ }
+ }
+
+ if (i->neg != 0) {
+ val = -val;
+ }
+
+ *value = val;
+ return true;
+}
+
#if MICROPY_ENABLE_FLOAT
mp_float_t mpz_as_float(const mpz_t *i) {
mp_float_t val = 0;
diff --git a/py/mpz.h b/py/mpz.h
index 777889322..cbe60eb8d 100644
--- a/py/mpz.h
+++ b/py/mpz.h
@@ -71,6 +71,7 @@ mpz_t *mpz_div(const mpz_t *lhs, const mpz_t *rhs);
mpz_t *mpz_mod(const mpz_t *lhs, const mpz_t *rhs);
machine_int_t mpz_as_int(const mpz_t *z);
+bool mpz_as_int_checked(const mpz_t *z, machine_int_t *value);
#if MICROPY_ENABLE_FLOAT
mp_float_t mpz_as_float(const mpz_t *z);
#endif
diff --git a/py/nlr.h b/py/nlr.h
index 4cc66d8c2..ce62334fd 100644
--- a/py/nlr.h
+++ b/py/nlr.h
@@ -11,7 +11,11 @@ struct _nlr_buf_t {
#if defined(__i386__)
void *regs[6];
#elif defined(__x86_64__)
+ #if defined(__CYGWIN__)
+ void *regs[12];
+ #else
void *regs[8];
+ #endif
#elif defined(__thumb2__)
void *regs[10];
#else
@@ -22,3 +26,16 @@ struct _nlr_buf_t {
unsigned int nlr_push(nlr_buf_t *);
void nlr_pop(void);
void nlr_jump(void *val) __attribute__((noreturn));
+
+// use nlr_raise instead of nlr_jump so that debugging is easier
+#ifndef DEBUG
+#define nlr_raise(val) nlr_jump(val)
+#else
+#define nlr_raise(val) \
+ do { \
+ void *_val = val; \
+ assert(_val != NULL); \
+ assert(mp_obj_is_exception_instance(_val)); \
+ nlr_jump(_val); \
+ } while (0)
+#endif
diff --git a/py/nlrx64.S b/py/nlrx64.S
index c5711001e..a4073981a 100644
--- a/py/nlrx64.S
+++ b/py/nlrx64.S
@@ -4,6 +4,8 @@
.file "nlr.s"
.text
+#if !defined(__CYGWIN__)
+
/* uint nlr_push(rdi=nlr_buf_t *nlr) */
#if !(defined(__APPLE__) && defined(__MACH__))
.globl nlr_push
@@ -82,4 +84,63 @@ nlr_jump:
.local nlr_top
#endif
.comm nlr_top,8,8
-#endif
+
+#else // !defined(__CYGWIN__)
+
+/* uint nlr_push(rcx=nlr_buf_t *nlr) */
+ .globl nlr_push
+nlr_push:
+ movq (%rsp), %rax # load return %rip
+ movq %rax, 16(%rcx) # store %rip into nlr_buf
+ movq %rbp, 24(%rcx) # store %rbp into nlr_buf
+ movq %rsp, 32(%rcx) # store %rsp into nlr_buf
+ movq %rbx, 40(%rcx) # store %rbx into nlr_buf
+ movq %r12, 48(%rcx) # store %r12 into nlr_buf
+ movq %r13, 56(%rcx) # store %r13 into nlr_buf
+ movq %r14, 64(%rcx) # store %r14 into nlr_buf
+ movq %r15, 72(%rcx) # store %r15 into
+ movq %rdi, 80(%rcx) # store %rdr into
+ movq %rsi, 88(%rcx) # store %rsi into
+ movq nlr_top(%rip), %rax # get last nlr_buf
+ movq %rax, (%rcx) # store it
+ movq %rcx, nlr_top(%rip) # stor new nlr_buf (to make linked list)
+ xorq %rax, %rax # return 0, normal return
+ ret # return
+
+/* void nlr_jump(rcx=uint val) */
+
+ .globl nlr_jump
+nlr_jump:
+ movq %rcx, %rax # put return value in %rax
+ movq nlr_top(%rip), %rcx # get nlr_top into %rsi
+ movq %rax, 8(%rcx) # store return value
+ movq (%rcx), %rax # load prev nlr_buf
+ movq %rax, nlr_top(%rip) # store prev nlr_buf (to unlink list)
+ movq 72(%rcx), %r15 # load saved %r15
+ movq 64(%rcx), %r14 # load saved %r14
+ movq 56(%rcx), %r13 # load saved %r13
+ movq 48(%rcx), %r12 # load saved %r12
+ movq 40(%rcx), %rbx # load saved %rbx
+ movq 32(%rcx), %rsp # load saved %rsp
+ movq 24(%rcx), %rbp # load saved %rbp
+ movq 16(%rcx), %rax # load saved %rip
+ movq 80(%rcx), %rdi # store %rdr into
+ movq 88(%rcx), %rsi # store %rsi into
+ movq %rax, (%rsp) # store saved %rip to stack
+ xorq %rax, %rax # clear return register
+ inc %al # increase to make 1, non-local return
+ ret # return
+
+ .comm nlr_top,8,8
+
+ /* void nlr_pop() */
+ .globl nlr_pop
+nlr_pop:
+ movq nlr_top(%rip), %rax # get nlr_top into %rax
+ movq (%rax), %rax # load prev nlr_buf
+ movq %rax, nlr_top(%rip) # store prev nlr_buf (to unlink list)
+ ret # return
+
+#endif // !defined(__CYGWIN__)
+
+#endif // __x86_64__
diff --git a/py/obj.c b/py/obj.c
index 95052d16d..8d5467c5e 100644
--- a/py/obj.c
+++ b/py/obj.c
@@ -118,12 +118,14 @@ machine_int_t mp_obj_hash(mp_obj_t o_in) {
return (machine_int_t)o_in;
} else if (MP_OBJ_IS_TYPE(o_in, &mp_type_tuple)) {
return mp_obj_tuple_hash(o_in);
+ } else if (MP_OBJ_IS_TYPE(o_in, &mp_type_type)) {
+ return (machine_int_t)o_in;
// TODO hash class and instances
// TODO delegate to __hash__ method if it exists
} else {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "unhashable type: '%s'", mp_obj_get_type_str(o_in)));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "unhashable type: '%s'", mp_obj_get_type_str(o_in)));
}
}
@@ -172,24 +174,16 @@ bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) {
}
}
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_NotImplementedError,
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_NotImplementedError,
"Equality for '%s' and '%s' types not yet implemented", mp_obj_get_type_str(o1), mp_obj_get_type_str(o2)));
return false;
}
}
-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);
- return false;
- }
-}
-
machine_int_t mp_obj_get_int(mp_obj_t arg) {
+ // This function essentially performs implicit type conversion to int
+ // Note that Python does NOT provide implicit type conversion from
+ // float to int in the core expression language, try some_list[1.0].
if (arg == mp_const_false) {
return 0;
} else if (arg == mp_const_true) {
@@ -199,8 +193,26 @@ machine_int_t mp_obj_get_int(mp_obj_t arg) {
} else if (MP_OBJ_IS_TYPE(arg, &mp_type_int)) {
return mp_obj_int_get_checked(arg);
} else {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "can't convert %s to int", mp_obj_get_type_str(arg)));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "can't convert %s to int", mp_obj_get_type_str(arg)));
+ }
+}
+
+// returns false if arg is not of integral type
+// returns true and sets *value if it is of integral type
+// can throw OverflowError if arg is of integral type, but doesn't fit in a machine_int_t
+bool mp_obj_get_int_maybe(mp_obj_t arg, machine_int_t *value) {
+ if (arg == mp_const_false) {
+ *value = 0;
+ } else if (arg == mp_const_true) {
+ *value = 1;
+ } else if (MP_OBJ_IS_SMALL_INT(arg)) {
+ *value = MP_OBJ_SMALL_INT_VALUE(arg);
+ } else if (MP_OBJ_IS_TYPE(arg, &mp_type_int)) {
+ *value = mp_obj_int_get_checked(arg);
+ } else {
+ return false;
}
+ return true;
}
#if MICROPY_ENABLE_FLOAT
@@ -216,7 +228,7 @@ mp_float_t mp_obj_get_float(mp_obj_t arg) {
} else if (MP_OBJ_IS_TYPE(arg, &mp_type_float)) {
return mp_obj_float_get(arg);
} else {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "can't convert %s to float", mp_obj_get_type_str(arg)));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "can't convert %s to float", mp_obj_get_type_str(arg)));
}
}
@@ -239,7 +251,7 @@ void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) {
} else if (MP_OBJ_IS_TYPE(arg, &mp_type_complex)) {
mp_obj_complex_get(arg, real, imag);
} else {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "can't convert %s to complex", mp_obj_get_type_str(arg)));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "can't convert %s to complex", mp_obj_get_type_str(arg)));
}
}
#endif
@@ -250,7 +262,7 @@ void mp_obj_get_array(mp_obj_t o, uint *len, mp_obj_t **items) {
} else if (MP_OBJ_IS_TYPE(o, &mp_type_list)) {
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)));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "object '%s' is not a tuple or list", mp_obj_get_type_str(o)));
}
}
@@ -263,10 +275,10 @@ void mp_obj_get_array_fixed_n(mp_obj_t o, uint len, mp_obj_t **items) {
mp_obj_list_get(o, &seq_len, items);
}
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));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_IndexError, "requested length %d but object has length %d", len, seq_len));
}
} 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)));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "object '%s' is not a tuple or list", mp_obj_get_type_str(o)));
}
}
@@ -278,7 +290,7 @@ uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index,
} else if (MP_OBJ_IS_TYPE(index, &mp_type_bool)) {
i = (index == mp_const_true ? 1 : 0);
} else {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "%s indices must be integers, not %s", qstr_str(type->name), mp_obj_get_type_str(index)));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "%s indices must be integers, not %s", qstr_str(type->name), mp_obj_get_type_str(index)));
}
if (i < 0) {
@@ -292,7 +304,7 @@ uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index,
}
} else {
if (i < 0 || i >= len) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_IndexError, "%s index out of range", qstr_str(type->name)));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_IndexError, "%s index out of range", qstr_str(type->name)));
}
}
return i;
diff --git a/py/obj.h b/py/obj.h
index 952187e46..eb447f916 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -23,6 +23,11 @@ typedef struct _mp_obj_base_t mp_obj_base_t;
#define MP_OBJ_NULL ((mp_obj_t)NULL)
+// The SENTINEL object is used for various internal purposes where one needs
+// an object which is unique from all other objects, including MP_OBJ_NULL.
+
+#define MP_OBJ_SENTINEL ((mp_obj_t)8)
+
// These macros check for small int, qstr or object, and access small int and qstr values
// - xxxx...xxx1: a small int, bits 1 and above are the value
// - xxxx...xx10: a qstr, bits 2 and above are the value
@@ -103,11 +108,11 @@ typedef struct _mp_map_t {
mp_map_elem_t *table;
} mp_map_t;
+// These can be or'd together
typedef enum _mp_map_lookup_kind_t {
MP_MAP_LOOKUP, // 0
MP_MAP_LOOKUP_ADD_IF_NOT_FOUND, // 1
MP_MAP_LOOKUP_REMOVE_IF_FOUND, // 2
- MP_MAP_LOOKUP_FIRST = 4,
} mp_map_lookup_kind_t;
void mp_map_init(mp_map_t *map, int n);
@@ -117,6 +122,7 @@ void mp_map_deinit(mp_map_t *map);
void mp_map_free(mp_map_t *map);
mp_map_elem_t* mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t lookup_kind);
void mp_map_clear(mp_map_t *map);
+void mp_map_dump(mp_map_t *map);
// Underlying set implementation (not set object)
@@ -128,6 +134,7 @@ typedef struct _mp_set_t {
void mp_set_init(mp_set_t *set, int n);
mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, mp_map_lookup_kind_t lookup_kind);
+mp_obj_t mp_set_remove_first(mp_set_t *set);
void mp_set_clear(mp_set_t *set);
// Type definitions for methods
@@ -306,6 +313,7 @@ extern const struct _mp_obj_bool_t mp_const_false_obj;
extern const struct _mp_obj_bool_t mp_const_true_obj;
extern const struct _mp_obj_tuple_t mp_const_empty_tuple_obj;
extern const struct _mp_obj_ellipsis_t mp_const_ellipsis_obj;
+extern const struct _mp_obj_exception_t mp_const_MemoryError_obj;
extern const struct _mp_obj_exception_t mp_const_GeneratorExit_obj;
// General API for objects
@@ -356,9 +364,9 @@ int mp_obj_is_true(mp_obj_t arg);
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 mp_obj_get_int(mp_obj_t arg);
+bool mp_obj_get_int_maybe(mp_obj_t arg, machine_int_t *value);
#if MICROPY_ENABLE_FLOAT
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);
@@ -438,6 +446,7 @@ typedef struct _mp_obj_dict_t {
} mp_obj_dict_t;
uint mp_obj_dict_len(mp_obj_t self_in);
mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value);
+mp_obj_t mp_obj_dict_delete(mp_obj_t self_in, mp_obj_t key);
mp_map_t *mp_obj_dict_get_map(mp_obj_t self_in);
// set
diff --git a/py/objarray.c b/py/objarray.c
index c91c553e3..0383cb17b 100644
--- a/py/objarray.c
+++ b/py/objarray.c
@@ -76,7 +76,7 @@ STATIC mp_obj_t array_construct(char typecode, mp_obj_t initializer) {
STATIC mp_obj_t array_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
if (n_args < 1 || n_args > 2) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "unexpected # of arguments, %d given", n_args));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "unexpected # of arguments, %d given", n_args));
}
// TODO check args
uint l;
diff --git a/py/objbool.c b/py/objbool.c
index 6afb6e950..11c736e3e 100644
--- a/py/objbool.c
+++ b/py/objbool.c
@@ -1,3 +1,4 @@
+#include <stdlib.h>
#include "nlr.h"
#include "misc.h"
@@ -27,7 +28,7 @@ STATIC mp_obj_t bool_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp
switch (n_args) {
case 0: return mp_const_false;
case 1: if (mp_obj_is_true(args[0])) { return mp_const_true; } else { return mp_const_false; }
- default: nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "bool takes at most 1 argument, %d given", n_args));
+ default: nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "bool takes at most 1 argument, %d given", n_args));
}
}
@@ -43,12 +44,21 @@ STATIC mp_obj_t bool_unary_op(int op, mp_obj_t o_in) {
}
}
+STATIC mp_obj_t bool_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
+ if (MP_BINARY_OP_OR <= op && op <= MP_BINARY_OP_NOT_EQUAL) {
+ return mp_binary_op(op, MP_OBJ_NEW_SMALL_INT((machine_int_t)mp_obj_is_true(lhs_in)), rhs_in);
+ }
+ // operation not supported
+ return MP_OBJ_NULL;
+}
+
const mp_obj_type_t mp_type_bool = {
{ &mp_type_type },
.name = MP_QSTR_bool,
.print = bool_print,
.make_new = bool_make_new,
.unary_op = bool_unary_op,
+ .binary_op = bool_binary_op,
};
const mp_obj_bool_t mp_const_false_obj = {{&mp_type_bool}, false};
diff --git a/py/objcomplex.c b/py/objcomplex.c
index 3fba56894..769977ad8 100644
--- a/py/objcomplex.c
+++ b/py/objcomplex.c
@@ -86,7 +86,7 @@ STATIC mp_obj_t complex_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const
}
default:
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "complex takes at most 2 arguments, %d given", n_args));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "complex takes at most 2 arguments, %d given", n_args));
}
}
diff --git a/py/objdict.c b/py/objdict.c
index afd1d0da0..c09ccfbee 100644
--- a/py/objdict.c
+++ b/py/objdict.c
@@ -32,8 +32,26 @@ STATIC void dict_print(void (*print)(void *env, const char *fmt, ...), void *env
}
STATIC mp_obj_t dict_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
- // TODO create from an iterable!
- return mp_obj_new_dict(0);
+ mp_obj_t dict;
+ switch (n_args) {
+ case 0:
+ dict = mp_obj_new_dict(0);
+ break;
+
+ case 1:
+ // TODO create dict from an iterable!
+ assert(false);
+
+ default:
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "dict takes at most 1 argument"));
+ }
+
+ // add to the new dict any keyword args
+ for (const mp_obj_t *a = args + n_args; n_kw > 0; n_kw--, a += 2) {
+ mp_obj_dict_store(dict, a[0], a[1]);
+ }
+
+ return dict;
}
STATIC mp_obj_t dict_unary_op(int op, mp_obj_t self_in) {
@@ -53,7 +71,7 @@ STATIC mp_obj_t dict_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
// dict load
mp_map_elem_t *elem = mp_map_lookup(&o->map, rhs_in, MP_MAP_LOOKUP);
if (elem == NULL) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_KeyError, "<value>"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_KeyError, "<value>"));
} else {
return elem->value;
}
@@ -85,7 +103,7 @@ STATIC mp_map_elem_t *dict_it_iternext_elem(mp_obj_t self_in) {
mp_map_elem_t *table = self->dict->map.table;
for (int i = self->cur; i < max; i++) {
- if (table[i].key != NULL) {
+ if (table[i].key != MP_OBJ_NULL && table[i].key != MP_OBJ_SENTINEL) {
self->cur = i + 1;
return &(table[i]);
}
@@ -181,7 +199,7 @@ STATIC mp_obj_t dict_get_helper(mp_map_t *self, mp_obj_t key, mp_obj_t deflt, mp
if (elem == NULL || elem->value == NULL) {
if (deflt == NULL) {
if (lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_KeyError, "<value>"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_KeyError, "<value>"));
} else {
value = mp_const_none;
}
@@ -240,7 +258,7 @@ STATIC mp_obj_t dict_popitem(mp_obj_t self_in) {
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_dict));
mp_obj_dict_t *self = self_in;
if (self->map.used == 0) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_KeyError, "popitem(): dictionary is empty"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_KeyError, "popitem(): dictionary is empty"));
}
mp_obj_dict_it_t *iter = mp_obj_new_dict_iterator(self, 0);
@@ -269,7 +287,7 @@ STATIC mp_obj_t dict_update(mp_obj_t self_in, mp_obj_t iterable) {
if (key == MP_OBJ_NULL
|| value == MP_OBJ_NULL
|| stop != MP_OBJ_NULL) {
- nlr_jump(mp_obj_new_exception_msg(
+ nlr_raise(mp_obj_new_exception_msg(
&mp_type_ValueError,
"dictionary update sequence has the wrong length"));
} else {
@@ -463,6 +481,13 @@ mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value) {
return self_in;
}
+mp_obj_t mp_obj_dict_delete(mp_obj_t self_in, mp_obj_t key) {
+ assert(MP_OBJ_IS_TYPE(self_in, &mp_type_dict));
+ mp_obj_dict_t *self = self_in;
+ dict_get_helper(&self->map, key, NULL, MP_MAP_LOOKUP_REMOVE_IF_FOUND);
+ return self_in;
+}
+
mp_map_t *mp_obj_dict_get_map(mp_obj_t self_in) {
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_dict));
mp_obj_dict_t *self = self_in;
diff --git a/py/objexcept.c b/py/objexcept.c
index 0efc21d36..51e7a2615 100644
--- a/py/objexcept.c
+++ b/py/objexcept.c
@@ -17,6 +17,9 @@ typedef struct _mp_obj_exception_t {
mp_obj_tuple_t args;
} mp_obj_exception_t;
+// Instance of MemoryError exception - needed by mp_malloc_fail
+const mp_obj_exception_t mp_const_MemoryError_obj = {{&mp_type_MemoryError}, MP_OBJ_NULL, {{&mp_type_tuple}, 0}};
+
// 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.
@@ -45,7 +48,7 @@ STATIC mp_obj_t mp_obj_exception_make_new(mp_obj_t type_in, uint n_args, uint n_
mp_obj_type_t *type = type_in;
if (n_kw != 0) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "%s does not take keyword arguments", mp_obj_get_type_str(type_in)));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "%s does not take keyword arguments", mp_obj_get_type_str(type_in)));
}
mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, mp_obj_t, n_args);
diff --git a/py/objfilter.c b/py/objfilter.c
index 466c98220..1224950bd 100644
--- a/py/objfilter.c
+++ b/py/objfilter.c
@@ -16,7 +16,7 @@ typedef struct _mp_obj_filter_t {
STATIC mp_obj_t filter_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
if (n_args != 2 || n_kw != 0) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "filter expected 2 arguments"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "filter expected 2 arguments"));
}
assert(n_args == 2);
mp_obj_filter_t *o = m_new_obj(mp_obj_filter_t);
diff --git a/py/objfloat.c b/py/objfloat.c
index d7bc6c7ff..1d4761aca 100644
--- a/py/objfloat.c
+++ b/py/objfloat.c
@@ -57,7 +57,7 @@ STATIC mp_obj_t float_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const m
}
default:
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "float takes at most 1 argument, %d given", n_args));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "float takes at most 1 argument, %d given", n_args));
}
}
@@ -121,7 +121,7 @@ mp_obj_t mp_obj_float_binary_op(int op, mp_float_t lhs_val, mp_obj_t rhs_in) {
lhs_val /= rhs_val;
check_zero_division:
if (isinf(lhs_val)){ // check for division by zero
- nlr_jump(mp_obj_new_exception_msg(&mp_type_ZeroDivisionError, "float division by zero"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ZeroDivisionError, "float division by zero"));
}
break;
case MP_BINARY_OP_POWER:
diff --git a/py/objfun.c b/py/objfun.c
index 3b48b570f..d006c8715 100644
--- a/py/objfun.c
+++ b/py/objfun.c
@@ -30,29 +30,39 @@ STATIC void check_nargs(mp_obj_fun_native_t *self, int n_args, int n_kw) {
void mp_check_nargs(int n_args, machine_uint_t n_args_min, machine_uint_t n_args_max, int n_kw, bool is_kw) {
if (n_kw && !is_kw) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError,
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
"function does not take keyword arguments"));
}
if (n_args_min == n_args_max) {
if (n_args != n_args_min) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"function takes %d positional arguments but %d were given",
n_args_min, n_args));
}
} else {
if (n_args < n_args_min) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"<fun name>() missing %d required positional arguments: <list of names of params>",
n_args_min - n_args));
} else if (n_args > n_args_max) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"<fun name> expected at most %d arguments, got %d",
n_args_max, n_args));
}
}
}
+STATIC mp_obj_t fun_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
+ switch (op) {
+ case MP_BINARY_OP_EQUAL:
+ // These objects can be equal only if it's the same underlying structure,
+ // we don't even need to check for 2nd arg type.
+ return MP_BOOL(lhs_in == rhs_in);
+ }
+ return NULL;
+}
+
STATIC mp_obj_t fun_native_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_fun_native));
mp_obj_fun_native_t *self = self_in;
@@ -102,6 +112,7 @@ const mp_obj_type_t mp_type_fun_native = {
{ &mp_type_type },
.name = MP_QSTR_function,
.call = fun_native_call,
+ .binary_op = fun_binary_op,
};
// fun must have the correct signature for n_args fixed arguments
@@ -196,7 +207,7 @@ bool mp_obj_fun_prepare_simple_args(mp_obj_t self_in, uint n_args, uint n_kw, co
return true;
arg_error:
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function takes %d positional arguments but %d were given", self->n_args, n_args));
+ 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));
}
STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
@@ -264,7 +275,7 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_o
for (uint j = 0; j < self->n_args; j++) {
if (arg_name == self->args[j]) {
if (flat_args[j] != MP_OBJ_NULL) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"function got multiple values for argument '%s'", qstr_str(arg_name)));
}
flat_args[j] = kwargs[2 * i + 1];
@@ -273,7 +284,7 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_o
}
// Didn't find name match with positional args
if (!self->takes_kw_args) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "function does not take keyword arguments"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "function does not take keyword arguments"));
}
mp_obj_dict_store(dict, kwargs[2 * i], kwargs[2 * i + 1]);
continue2:;
@@ -295,7 +306,7 @@ continue2:;
// Now check that all mandatory args specified
while (d >= flat_args) {
if (*d-- == MP_OBJ_NULL) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"function missing required positional argument #%d", d - flat_args));
}
}
@@ -327,17 +338,18 @@ continue2:;
if (vm_return_kind == MP_VM_RETURN_NORMAL) {
return result;
} else { // MP_VM_RETURN_EXCEPTION
- nlr_jump(result);
+ nlr_raise(result);
}
arg_error:
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function takes %d positional arguments but %d were given", self->n_args, n_args));
+ 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 = {
{ &mp_type_type },
.name = MP_QSTR_function,
.call = fun_bc_call,
+ .binary_op = fun_binary_op,
};
mp_obj_t mp_obj_new_fun_bc(uint scope_flags, qstr *args, uint n_args, mp_obj_t def_args_in, const byte *code) {
@@ -437,10 +449,10 @@ STATIC mp_obj_t fun_asm_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_
mp_obj_fun_asm_t *self = self_in;
if (n_args != self->n_args) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function takes %d positional arguments but %d were given", self->n_args, n_args));
+ 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));
}
if (n_kw != 0) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "function does not take keyword arguments"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "function does not take keyword arguments"));
}
machine_uint_t ret;
@@ -464,6 +476,7 @@ STATIC const mp_obj_type_t mp_type_fun_asm = {
{ &mp_type_type },
.name = MP_QSTR_function,
.call = fun_asm_call,
+ .binary_op = fun_binary_op,
};
mp_obj_t mp_obj_new_fun_asm(uint n_args, void *fun) {
diff --git a/py/objgenerator.c b/py/objgenerator.c
index 78694c866..975681af8 100644
--- a/py/objgenerator.c
+++ b/py/objgenerator.c
@@ -84,7 +84,7 @@ mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_
}
if (self->sp == self->state - 1) {
if (send_value != mp_const_none) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "can't send non-None value to a just-started generator"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "can't send non-None value to a just-started generator"));
}
} else {
*self->sp = send_value;
@@ -130,12 +130,12 @@ STATIC mp_obj_t gen_resume_and_raise(mp_obj_t self_in, mp_obj_t send_value, mp_o
if (ret == mp_const_none || ret == MP_OBJ_NULL) {
return MP_OBJ_NULL;
} else {
- nlr_jump(mp_obj_new_exception_args(&mp_type_StopIteration, 1, &ret));
+ nlr_raise(mp_obj_new_exception_args(&mp_type_StopIteration, 1, &ret));
}
case MP_VM_RETURN_YIELD:
if (throw_value != MP_OBJ_NULL && mp_obj_is_subclass_fast(mp_obj_get_type(throw_value), &mp_type_GeneratorExit)) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_RuntimeError, "generator ignored GeneratorExit"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "generator ignored GeneratorExit"));
}
return ret;
@@ -146,7 +146,7 @@ STATIC mp_obj_t gen_resume_and_raise(mp_obj_t self_in, mp_obj_t send_value, mp_o
if (mp_obj_is_subclass_fast(mp_obj_get_type(ret), &mp_type_StopIteration)) {
return MP_OBJ_NULL;
} else {
- nlr_jump(ret);
+ nlr_raise(ret);
}
default:
@@ -162,7 +162,7 @@ mp_obj_t gen_instance_iternext(mp_obj_t self_in) {
STATIC mp_obj_t gen_instance_send(mp_obj_t self_in, mp_obj_t send_value) {
mp_obj_t ret = gen_resume_and_raise(self_in, send_value, MP_OBJ_NULL);
if (ret == MP_OBJ_NULL) {
- nlr_jump(mp_obj_new_exception(&mp_type_StopIteration));
+ nlr_raise(mp_obj_new_exception(&mp_type_StopIteration));
} else {
return ret;
}
@@ -177,7 +177,7 @@ STATIC mp_obj_t gen_instance_throw(uint n_args, const mp_obj_t *args) {
mp_obj_t ret = gen_resume_and_raise(args[0], mp_const_none, exc);
if (ret == MP_OBJ_NULL) {
- nlr_jump(mp_obj_new_exception(&mp_type_StopIteration));
+ nlr_raise(mp_obj_new_exception(&mp_type_StopIteration));
} else {
return ret;
}
@@ -189,7 +189,7 @@ 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_const_GeneratorExit_obj, &ret)) {
case MP_VM_RETURN_YIELD:
- nlr_jump(mp_obj_new_exception_msg(&mp_type_RuntimeError, "generator ignored GeneratorExit"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "generator ignored GeneratorExit"));
// Swallow StopIteration & GeneratorExit (== successful close), and re-raise any other
case MP_VM_RETURN_EXCEPTION:
@@ -198,7 +198,7 @@ STATIC mp_obj_t gen_instance_close(mp_obj_t self_in) {
mp_obj_is_subclass_fast(mp_obj_get_type(ret), &mp_type_StopIteration)) {
return mp_const_none;
}
- nlr_jump(ret);
+ nlr_raise(ret);
default:
// The only choice left is MP_VM_RETURN_NORMAL which is successful close
diff --git a/py/objgetitemiter.c b/py/objgetitemiter.c
index da0e4760c..f848415b8 100644
--- a/py/objgetitemiter.c
+++ b/py/objgetitemiter.c
@@ -30,7 +30,7 @@ STATIC mp_obj_t it_iternext(mp_obj_t self_in) {
return MP_OBJ_NULL;
} else {
// re-raise exception
- nlr_jump(nlr.ret_val);
+ nlr_raise(nlr.ret_val);
}
}
}
diff --git a/py/objint.c b/py/objint.c
index 3a853eab8..a1d3924a2 100644
--- a/py/objint.c
+++ b/py/objint.c
@@ -17,9 +17,8 @@
#include <math.h>
#endif
-// This dispatcher function is expected to be independent of the implementation
-// of long int
-STATIC mp_obj_t int_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
+// This dispatcher function is expected to be independent of the implementation of long int
+STATIC mp_obj_t mp_obj_int_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
// TODO check n_kw == 0
switch (n_args) {
@@ -50,43 +49,37 @@ STATIC mp_obj_t int_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_
}
default:
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "int takes at most 2 arguments, %d given", n_args));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "int takes at most 2 arguments, %d given", n_args));
}
}
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE
-void int_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+void mp_obj_int_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
if (MP_OBJ_IS_SMALL_INT(self_in)) {
print(env, INT_FMT, MP_OBJ_SMALL_INT_VALUE(self_in));
}
}
// This is called for operations on SMALL_INT that are not handled by mp_unary_op
-mp_obj_t int_unary_op(int op, mp_obj_t o_in) {
+mp_obj_t mp_obj_int_unary_op(int op, mp_obj_t o_in) {
return MP_OBJ_NULL;
}
// This is called for operations on SMALL_INT that are not handled by mp_binary_op
-mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
- if (op == MP_BINARY_OP_MULTIPLY) {
- if (MP_OBJ_IS_STR(rhs_in) || MP_OBJ_IS_TYPE(rhs_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(rhs_in, &mp_type_list)) {
- // multiply is commutative for these types, so delegate to them
- return mp_binary_op(op, rhs_in, lhs_in);
- }
- }
- return MP_OBJ_NULL;
+mp_obj_t mp_obj_int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
+ return mp_obj_int_binary_op_extra_cases(op, lhs_in, rhs_in);
}
// This is called only with strings whose value doesn't fit in SMALL_INT
mp_obj_t mp_obj_new_int_from_long_str(const char *s) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_OverflowError, "long int not supported in this build"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OverflowError, "long int not supported in this build"));
return mp_const_none;
}
// This is called when an integer larger than a SMALL_INT is needed (although val might still fit in a SMALL_INT)
mp_obj_t mp_obj_new_int_from_ll(long long val) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_OverflowError, "small int overflow"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OverflowError, "small int overflow"));
return mp_const_none;
}
@@ -96,7 +89,7 @@ mp_obj_t mp_obj_new_int_from_uint(machine_uint_t value) {
if ((value & (WORD_MSBIT_HIGH | (WORD_MSBIT_HIGH >> 1))) == 0) {
return MP_OBJ_NEW_SMALL_INT(value);
}
- nlr_jump(mp_obj_new_exception_msg(&mp_type_OverflowError, "small int overflow"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OverflowError, "small int overflow"));
return mp_const_none;
}
@@ -104,7 +97,7 @@ mp_obj_t mp_obj_new_int(machine_int_t value) {
if (MP_OBJ_FITS_SMALL_INT(value)) {
return MP_OBJ_NEW_SMALL_INT(value);
}
- nlr_jump(mp_obj_new_exception_msg(&mp_type_OverflowError, "small int overflow"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OverflowError, "small int overflow"));
return mp_const_none;
}
@@ -124,11 +117,29 @@ mp_float_t mp_obj_int_as_float(mp_obj_t self_in) {
#endif // MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE
+// This dispatcher function is expected to be independent of the implementation of long int
+// It handles the extra cases for integer-like arithmetic
+mp_obj_t mp_obj_int_binary_op_extra_cases(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
+ if (rhs_in == mp_const_false) {
+ // false acts as 0
+ return mp_binary_op(op, lhs_in, MP_OBJ_NEW_SMALL_INT(0));
+ } else if (rhs_in == mp_const_true) {
+ // true acts as 0
+ return mp_binary_op(op, lhs_in, MP_OBJ_NEW_SMALL_INT(1));
+ } else if (op == MP_BINARY_OP_MULTIPLY) {
+ if (MP_OBJ_IS_STR(rhs_in) || MP_OBJ_IS_TYPE(rhs_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(rhs_in, &mp_type_list)) {
+ // multiply is commutative for these types, so delegate to them
+ return mp_binary_op(op, rhs_in, lhs_in);
+ }
+ }
+ return MP_OBJ_NULL;
+}
+
const mp_obj_type_t mp_type_int = {
{ &mp_type_type },
.name = MP_QSTR_int,
- .print = int_print,
- .make_new = int_make_new,
- .unary_op = int_unary_op,
- .binary_op = int_binary_op,
+ .print = mp_obj_int_print,
+ .make_new = mp_obj_int_make_new,
+ .unary_op = mp_obj_int_unary_op,
+ .binary_op = mp_obj_int_binary_op,
};
diff --git a/py/objint.h b/py/objint.h
index 53ee49e7d..fe7f60a2d 100644
--- a/py/objint.h
+++ b/py/objint.h
@@ -7,6 +7,7 @@ typedef struct _mp_obj_int_t {
#endif
} mp_obj_int_t;
-void int_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind);
-mp_obj_t int_unary_op(int op, mp_obj_t o_in);
-mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in);
+void mp_obj_int_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind);
+mp_obj_t mp_obj_int_unary_op(int op, mp_obj_t o_in);
+mp_obj_t mp_obj_int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in);
+mp_obj_t mp_obj_int_binary_op_extra_cases(int op, mp_obj_t lhs_in, mp_obj_t rhs_in);
diff --git a/py/objint_longlong.c b/py/objint_longlong.c
index acbd477a9..02389d673 100644
--- a/py/objint_longlong.c
+++ b/py/objint_longlong.c
@@ -21,7 +21,7 @@
#define SUFFIX ""
#endif
-void int_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+void mp_obj_int_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
if (MP_OBJ_IS_SMALL_INT(self_in)) {
print(env, INT_FMT, MP_OBJ_SMALL_INT_VALUE(self_in));
} else {
@@ -30,7 +30,7 @@ void int_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj
}
}
-mp_obj_t int_unary_op(int op, mp_obj_t o_in) {
+mp_obj_t mp_obj_int_unary_op(int op, mp_obj_t o_in) {
mp_obj_int_t *o = o_in;
switch (op) {
case MP_UNARY_OP_BOOL: return MP_BOOL(o->val != 0);
@@ -41,7 +41,7 @@ mp_obj_t int_unary_op(int op, mp_obj_t o_in) {
}
}
-mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
+mp_obj_t mp_obj_int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
long long lhs_val;
long long rhs_val;
@@ -58,14 +58,8 @@ mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
} else if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_int)) {
rhs_val = ((mp_obj_int_t*)rhs_in)->val;
} else {
- if (op == MP_BINARY_OP_MULTIPLY) {
- if (MP_OBJ_IS_STR(rhs_in) || MP_OBJ_IS_TYPE(rhs_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(rhs_in, &mp_type_list)) {
- // multiply is commutative for these types, so delegate to them
- return mp_binary_op(op, rhs_in, lhs_in);
- }
- }
- // unsupported operation/type
- return MP_OBJ_NULL;
+ // delegate to generic function to check for extra cases
+ return mp_obj_int_binary_op_extra_cases(op, lhs_in, rhs_in);
}
switch (op) {
@@ -150,7 +144,7 @@ mp_obj_t mp_obj_new_int_from_long_str(const char *s) {
// TODO: this doesn't handle Python hacked 0o octal syntax
v = strtoll(s, &end, 0);
if (*end != 0) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_SyntaxError, "invalid syntax for number"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_SyntaxError, "invalid syntax for number"));
}
mp_obj_int_t *o = m_new_obj(mp_obj_int_t);
o->base.type = &mp_type_int;
diff --git a/py/objint_mpz.c b/py/objint_mpz.c
index 27f77d14b..4ecc4017b 100644
--- a/py/objint_mpz.c
+++ b/py/objint_mpz.c
@@ -22,7 +22,7 @@ STATIC mp_obj_int_t *mp_obj_int_new_mpz(void) {
return o;
}
-void int_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+void mp_obj_int_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
if (MP_OBJ_IS_SMALL_INT(self_in)) {
print(env, INT_FMT, MP_OBJ_SMALL_INT_VALUE(self_in));
} else {
@@ -34,7 +34,7 @@ void int_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj
}
}
-mp_obj_t int_unary_op(int op, mp_obj_t o_in) {
+mp_obj_t mp_obj_int_unary_op(int op, mp_obj_t o_in) {
mp_obj_int_t *o = o_in;
switch (op) {
case MP_UNARY_OP_BOOL: return MP_BOOL(!mpz_is_zero(&o->mpz));
@@ -45,7 +45,7 @@ mp_obj_t int_unary_op(int op, mp_obj_t o_in) {
}
}
-mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
+mp_obj_t mp_obj_int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
const mpz_t *zlhs;
const mpz_t *zrhs;
mpz_t z_int;
@@ -75,14 +75,8 @@ mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
return mp_obj_complex_binary_op(op, mpz_as_float(zlhs), 0, rhs_in);
#endif
} else {
- if (op == MP_BINARY_OP_MULTIPLY) {
- if (MP_OBJ_IS_STR(rhs_in) || MP_OBJ_IS_TYPE(rhs_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(rhs_in, &mp_type_list)) {
- // multiply is commutative for these types, so delegate to them
- return mp_binary_op(op, rhs_in, lhs_in);
- }
- }
- // unsupported operation/type
- return MP_OBJ_NULL;
+ // delegate to generic function to check for extra cases
+ return mp_obj_int_binary_op_extra_cases(op, lhs_in, rhs_in);
}
if (0) {
@@ -113,7 +107,7 @@ mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE: {
mpz_t rem; mpz_init_zero(&rem);
mpz_divmod_inpl(&res->mpz, &rem, zlhs, zrhs);
- if (zlhs->neg != zrhs->neg) {
+ if (zlhs->neg != zrhs->neg) {
if (!mpz_is_zero(&rem)) {
mpz_t mpzone; mpz_init_from_int(&mpzone, -1);
mpz_add_inpl(&res->mpz, &res->mpz, &mpzone);
@@ -127,8 +121,8 @@ mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
mpz_t quo; mpz_init_zero(&quo);
mpz_divmod_inpl(&quo, &res->mpz, zlhs, zrhs);
mpz_deinit(&quo);
- // Check signs and do Python style modulo
- if (zlhs->neg != zrhs->neg) {
+ // Check signs and do Python style modulo
+ if (zlhs->neg != zrhs->neg) {
mpz_add_inpl(&res->mpz, &res->mpz, zrhs);
}
break;
@@ -154,7 +148,7 @@ mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
// TODO check conversion overflow
machine_int_t irhs = mpz_as_int(zrhs);
if (irhs < 0) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "negative shift count"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "negative shift count"));
}
if (op == MP_BINARY_OP_LSHIFT || op == MP_BINARY_OP_INPLACE_LSHIFT) {
mpz_shl_inpl(&res->mpz, zlhs, irhs);
@@ -228,7 +222,7 @@ mp_obj_t mp_obj_new_int_from_long_str(const char *str) {
len -= skip;
uint n = mpz_set_from_str(&o->mpz, str, len, false, base);
if (n != len) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_SyntaxError, "invalid syntax for number"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_SyntaxError, "invalid syntax for number"));
}
return o;
}
@@ -243,8 +237,18 @@ machine_int_t mp_obj_int_get(mp_obj_t self_in) {
}
machine_int_t mp_obj_int_get_checked(mp_obj_t self_in) {
- // TODO: Check overflow
- return mp_obj_int_get(self_in);
+ if (MP_OBJ_IS_SMALL_INT(self_in)) {
+ return MP_OBJ_SMALL_INT_VALUE(self_in);
+ } else {
+ mp_obj_int_t *self = self_in;
+ machine_int_t value;
+ if (mpz_as_int_checked(&self->mpz, &value)) {
+ return value;
+ } else {
+ // overflow
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OverflowError, "overflow converting long int to machine word"));
+ }
+ }
}
#if MICROPY_ENABLE_FLOAT
diff --git a/py/objlist.c b/py/objlist.c
index 244d4a596..620bf2944 100644
--- a/py/objlist.c
+++ b/py/objlist.c
@@ -59,7 +59,7 @@ STATIC mp_obj_t list_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp
}
default:
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "list takes at most 1 argument, %d given", n_args));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "list takes at most 1 argument, %d given", n_args));
}
return NULL;
}
@@ -122,12 +122,11 @@ STATIC mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
list_extend(lhs, rhs);
return o;
}
- case MP_BINARY_OP_MULTIPLY:
- {
- if (!MP_OBJ_IS_SMALL_INT(rhs)) {
+ case MP_BINARY_OP_MULTIPLY: {
+ machine_int_t n;
+ if (!mp_obj_get_int_maybe(rhs, &n)) {
return NULL;
}
- int n = MP_OBJ_SMALL_INT_VALUE(rhs);
mp_obj_list_t *s = list_new(o->len * n);
mp_seq_multiply(o->items, sizeof(*o->items), o->len, n, s->items);
return s;
@@ -185,7 +184,7 @@ STATIC mp_obj_t list_pop(uint n_args, const mp_obj_t *args) {
assert(MP_OBJ_IS_TYPE(args[0], &mp_type_list));
mp_obj_list_t *self = args[0];
if (self->len == 0) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_IndexError, "pop from empty list"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "pop from empty list"));
}
uint index = mp_get_index(self->base.type, self->len, n_args == 1 ? mp_obj_new_int(-1) : args[1], false);
mp_obj_t ret = self->items[index];
@@ -225,7 +224,7 @@ mp_obj_t mp_obj_list_sort(uint n_args, const mp_obj_t *args, mp_map_t *kwargs) {
assert(n_args >= 1);
assert(MP_OBJ_IS_TYPE(args[0], &mp_type_list));
if (n_args > 1) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError,
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
"list.sort takes no positional arguments"));
}
mp_obj_list_t *self = args[0];
diff --git a/py/objmap.c b/py/objmap.c
index 923ca861b..42bcc436f 100644
--- a/py/objmap.c
+++ b/py/objmap.c
@@ -17,7 +17,7 @@ typedef struct _mp_obj_map_t {
STATIC mp_obj_t map_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
if (n_args < 2 || n_kw != 0) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "map must have at least 2 arguments and no keyword arguments"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "map must have at least 2 arguments and no keyword arguments"));
}
assert(n_args >= 2);
mp_obj_map_t *o = m_new_obj_var(mp_obj_map_t, mp_obj_t, n_args - 1);
diff --git a/py/objnamedtuple.c b/py/objnamedtuple.c
index a9e6e7d8a..e18cd3ce5 100644
--- a/py/objnamedtuple.c
+++ b/py/objnamedtuple.c
@@ -102,7 +102,7 @@ STATIC void namedtuple_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
}
STATIC bool namedtuple_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_AttributeError, "can't set attribute"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_AttributeError, "can't set attribute"));
}
STATIC mp_obj_t namedtuple_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
@@ -110,7 +110,7 @@ STATIC mp_obj_t namedtuple_make_new(mp_obj_t type_in, uint n_args, uint n_kw, co
uint num_fields = namedtuple_count_fields(type->fields);
if (n_args != num_fields) {
// Counts include implicit "self"
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"__new__() takes %d positional arguments but %d were given",
num_fields + 1, n_args + 1));
}
diff --git a/py/objobject.c b/py/objobject.c
index 274135c6c..56daa956d 100644
--- a/py/objobject.c
+++ b/py/objobject.c
@@ -15,7 +15,7 @@ const mp_obj_type_t mp_type_object;
STATIC mp_obj_t object_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
if (n_args != 0 || n_kw != 0) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "object takes no arguments"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "object takes no arguments"));
}
mp_obj_object_t *o = m_new_obj(mp_obj_object_t);
diff --git a/py/objset.c b/py/objset.c
index 439c6e96e..12c8cd25a 100644
--- a/py/objset.c
+++ b/py/objset.c
@@ -32,7 +32,7 @@ STATIC void set_print(void (*print)(void *env, const char *fmt, ...), void *env,
bool first = true;
print(env, "{");
for (int i = 0; i < self->set.alloc; i++) {
- if (self->set.table[i] != MP_OBJ_NULL) {
+ if (self->set.table[i] != MP_OBJ_NULL && self->set.table[i] != MP_OBJ_SENTINEL) {
if (!first) {
print(env, ", ");
}
@@ -65,7 +65,7 @@ STATIC mp_obj_t set_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_
}
default:
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "set takes at most 1 argument, %d given", n_args));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "set takes at most 1 argument, %d given", n_args));
}
}
@@ -83,7 +83,7 @@ STATIC mp_obj_t set_it_iternext(mp_obj_t self_in) {
mp_obj_t *table = self->set->set.table;
for (machine_uint_t i = self->cur; i < max; i++) {
- if (table[i] != NULL) {
+ if (table[i] != MP_OBJ_NULL && table[i] != MP_OBJ_SENTINEL) {
self->cur = i + 1;
return table[i];
}
@@ -307,12 +307,10 @@ STATIC mp_obj_t set_equal(mp_obj_t self_in, mp_obj_t other_in) {
STATIC mp_obj_t set_pop(mp_obj_t self_in) {
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_set));
mp_obj_set_t *self = self_in;
-
- if (self->set.used == 0) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_KeyError, "pop from an empty set"));
+ mp_obj_t obj = mp_set_remove_first(&self->set);
+ if (obj == MP_OBJ_NULL) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_KeyError, "pop from an empty set"));
}
- mp_obj_t obj = mp_set_lookup(&self->set, NULL,
- MP_MAP_LOOKUP_REMOVE_IF_FOUND | MP_MAP_LOOKUP_FIRST);
return obj;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(set_pop_obj, set_pop);
@@ -321,7 +319,7 @@ STATIC mp_obj_t set_remove(mp_obj_t self_in, mp_obj_t item) {
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_set));
mp_obj_set_t *self = self_in;
if (mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_REMOVE_IF_FOUND) == MP_OBJ_NULL) {
- nlr_jump(mp_obj_new_exception(&mp_type_KeyError));
+ nlr_raise(mp_obj_new_exception(&mp_type_KeyError));
}
return mp_const_none;
}
@@ -375,6 +373,14 @@ STATIC mp_obj_t set_union(mp_obj_t self_in, mp_obj_t other_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_union_obj, set_union);
+STATIC mp_obj_t set_unary_op(int op, mp_obj_t self_in) {
+ mp_obj_set_t *self = self_in;
+ switch (op) {
+ case MP_UNARY_OP_BOOL: return MP_BOOL(self->set.used != 0);
+ case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT((machine_int_t)self->set.used);
+ default: return MP_OBJ_NULL; // op not supported for None
+ }
+}
STATIC mp_obj_t set_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
mp_obj_t args[] = {lhs, rhs};
@@ -450,6 +456,7 @@ const mp_obj_type_t mp_type_set = {
.name = MP_QSTR_set,
.print = set_print,
.make_new = set_make_new,
+ .unary_op = set_unary_op,
.binary_op = set_binary_op,
.getiter = set_getiter,
.locals_dict = (mp_obj_t)&set_locals_dict,
diff --git a/py/objstr.c b/py/objstr.c
index f22c6b1ba..7000ed1fb 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -102,7 +102,7 @@ STATIC mp_obj_t str_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_
{
// TODO: validate 2nd/3rd args
if (!MP_OBJ_IS_TYPE(args[0], &mp_type_bytes)) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "bytes expected"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "bytes expected"));
}
GET_STR_DATA_LEN(args[0], str_data, str_len);
GET_STR_HASH(args[0], str_hash);
@@ -113,7 +113,7 @@ STATIC mp_obj_t str_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_
}
default:
- nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "str takes at most 3 arguments"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "str takes at most 3 arguments"));
}
}
@@ -183,7 +183,7 @@ STATIC mp_obj_t bytes_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const m
return mp_obj_str_builder_end(o);
wrong_args:
- nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "wrong number of arguments"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "wrong number of arguments"));
}
// like strstr but with specified length and allows \0 bytes
@@ -237,7 +237,7 @@ STATIC mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
} else {
// Message doesn't match CPython, but we don't have so much bytes as they
// to spend them on verbose wording
- nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "index must be int"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "index must be int"));
}
case MP_BINARY_OP_ADD:
@@ -361,7 +361,7 @@ STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) {
return mp_obj_str_builder_end(joined_str);
bad_arg:
- nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "?str.join expecting a list of str's"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "?str.join expecting a list of str's"));
}
#define is_ws(c) ((c) == ' ' || (c) == '\t')
@@ -528,6 +528,15 @@ static bool arg_looks_numeric(mp_obj_t arg) {
;
}
+static machine_int_t arg_as_int(mp_obj_t arg) {
+#if MICROPY_ENABLE_FLOAT
+ if (MP_OBJ_IS_TYPE(arg, &mp_type_float)) {
+ return mp_obj_get_float(arg);
+ }
+#endif
+ return mp_obj_get_int(arg);
+}
+
mp_obj_t str_format(uint n_args, const mp_obj_t *args) {
assert(MP_OBJ_IS_STR(args[0]));
@@ -545,7 +554,7 @@ mp_obj_t str_format(uint n_args, const mp_obj_t *args) {
vstr_add_char(vstr, '}');
continue;
}
- nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "Single '}' encountered in format string"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Single '}' encountered in format string"));
}
if (*str != '{') {
vstr_add_char(vstr, *str);
@@ -579,7 +588,7 @@ mp_obj_t str_format(uint n_args, const mp_obj_t *args) {
if (str < top && (*str == 'r' || *str == 's')) {
conversion = *str++;
} else {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "end of format while looking for conversion specifier"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "end of format while looking for conversion specifier"));
}
}
@@ -599,24 +608,24 @@ mp_obj_t str_format(uint n_args, const mp_obj_t *args) {
}
}
if (str >= top) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "unmatched '{' in format"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "unmatched '{' in format"));
}
if (*str != '}') {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "expected ':' after format specifier"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "expected ':' after format specifier"));
}
mp_obj_t arg = mp_const_none;
if (field_name) {
if (arg_i > 0) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "cannot switch from automatic field numbering to manual field specification"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "cannot switch from automatic field numbering to manual field specification"));
}
int index;
if (str_to_int(vstr_str(field_name), &index) != vstr_len(field_name) - 1) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_KeyError, "attributes not supported yet"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_KeyError, "attributes not supported yet"));
}
if (index >= n_args - 1) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_IndexError, "tuple index out of range"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "tuple index out of range"));
}
arg = args[index + 1];
arg_i = -1;
@@ -624,10 +633,10 @@ mp_obj_t str_format(uint n_args, const mp_obj_t *args) {
field_name = NULL;
} else {
if (arg_i < 0) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "cannot switch from manual field specification to automatic field numbering"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "cannot switch from manual field specification to automatic field numbering"));
}
if (arg_i >= n_args - 1) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_IndexError, "tuple index out of range"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "tuple index out of range"));
}
arg = args[arg_i + 1];
arg_i++;
@@ -642,7 +651,7 @@ mp_obj_t str_format(uint n_args, const mp_obj_t *args) {
} else if (conversion == 'r') {
print_kind = PRINT_REPR;
} else {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Unknown conversion specifier %c", conversion));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Unknown conversion specifier %c", conversion));
}
vstr_t *arg_vstr = vstr_new();
mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf, arg_vstr, arg, print_kind);
@@ -709,7 +718,7 @@ mp_obj_t str_format(uint n_args, const mp_obj_t *args) {
type = *s++;
}
if (*s) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_KeyError, "Invalid conversion specification"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_KeyError, "Invalid conversion specification"));
}
vstr_free(format_spec);
format_spec = NULL;
@@ -727,10 +736,10 @@ mp_obj_t str_format(uint n_args, const mp_obj_t *args) {
if (sign) {
if (type == 's') {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "Sign not allowed in string format specifier"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Sign not allowed in string format specifier"));
}
if (type == 'c') {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "Sign not allowed with integer format specifier 'c'"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Sign not allowed with integer format specifier 'c'"));
}
} else {
sign = '-';
@@ -785,12 +794,14 @@ mp_obj_t str_format(uint n_args, const mp_obj_t *args) {
break;
default:
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
"Unknown format code '%c' for object of type '%s'", type, mp_obj_get_type_str(arg)));
}
+ }
-#if MICROPY_ENABLE_FLOAT
- } else if (arg_looks_numeric(arg)) {
+ // NOTE: no else here. We need the e, f, g etc formats for integer
+ // arguments (from above if) to take this if.
+ if (arg_looks_numeric(arg)) {
if (!type) {
// Even though the docs say that an unspecified type is the same
@@ -828,6 +839,7 @@ mp_obj_t str_format(uint n_args, const mp_obj_t *args) {
flags |= PF_FLAG_PAD_NAN_INF; // '{:06e}'.format(float('-inf')) should give '-00inf'
switch (type) {
+#if MICROPY_ENABLE_FLOAT
case 'e':
case 'E':
case 'f':
@@ -841,19 +853,18 @@ mp_obj_t str_format(uint n_args, const mp_obj_t *args) {
flags |= PF_FLAG_ADD_PERCENT;
pfenv_print_float(&pfenv_vstr, mp_obj_get_float(arg) * 100.0F, 'f', flags, fill, width, precision);
break;
+#endif
default:
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
"Unknown format code '%c' for object of type 'float'",
type, mp_obj_get_type_str(arg)));
}
-#endif
-
} else {
// arg doesn't look like a number
if (align == '=') {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "'=' alignment not allowed in string format specifier"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "'=' alignment not allowed in string format specifier"));
}
switch (type) {
@@ -876,7 +887,7 @@ mp_obj_t str_format(uint n_args, const mp_obj_t *args) {
}
default:
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
"Unknown format code '%c' for object of type 'str'",
type, mp_obj_get_type_str(arg)));
}
@@ -892,36 +903,166 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, uint n_args, const mp_obj_t
assert(MP_OBJ_IS_STR(pattern));
GET_STR_DATA_LEN(pattern, str, len);
+ const byte *start_str = str;
int arg_i = 0;
vstr_t *vstr = vstr_new();
+ pfenv_t pfenv_vstr;
+ pfenv_vstr.data = vstr;
+ pfenv_vstr.print_strn = pfenv_vstr_add_strn;
+
for (const byte *top = str + len; str < top; str++) {
+ if (*str != '%') {
+ vstr_add_char(vstr, *str);
+ continue;
+ }
+ if (++str >= top) {
+ break;
+ }
if (*str == '%') {
- if (++str >= top) {
- break;
- }
- if (*str == '%') {
- vstr_add_char(vstr, '%');
+ vstr_add_char(vstr, '%');
+ continue;
+ }
+ if (arg_i >= n_args) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "not enough arguments for format string"));
+ }
+ int flags = 0;
+ char fill = ' ';
+ bool alt = false;
+ while (str < top) {
+ if (*str == '-') flags |= PF_FLAG_LEFT_ADJUST;
+ else if (*str == '+') flags |= PF_FLAG_SHOW_SIGN;
+ else if (*str == ' ') flags |= PF_FLAG_SPACE_SIGN;
+ else if (*str == '#') alt = true;
+ else if (*str == '0') {
+ flags |= PF_FLAG_PAD_AFTER_SIGN;
+ fill = '0';
+ } else break;
+ str++;
+ }
+ // parse width, if it exists
+ int width = 0;
+ if (str < top) {
+ if (*str == '*') {
+ width = mp_obj_get_int(args[arg_i++]);
+ str++;
} else {
- if (arg_i >= n_args) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "not enough arguments for format string"));
+ for (; str < top && '0' <= *str && *str <= '9'; str++) {
+ width = width * 10 + *str - '0';
}
- switch (*str) {
- case 's':
- mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf, vstr, args[arg_i], PRINT_STR);
- break;
- case 'r':
- mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf, vstr, args[arg_i], PRINT_REPR);
+ }
+ }
+ int prec = -1;
+ if (str < top && *str == '.') {
+ if (++str < top) {
+ if (*str == '*') {
+ prec = mp_obj_get_int(args[arg_i++]);
+ str++;
+ } else {
+ prec = 0;
+ for (; str < top && '0' <= *str && *str <= '9'; str++) {
+ prec = prec * 10 + *str - '0';
+ }
+ }
+ }
+ }
+
+ if (str >= top) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "incomplete format"));
+ }
+ mp_obj_t arg = args[arg_i];
+ switch (*str) {
+ case 'c':
+ if (MP_OBJ_IS_STR(arg)) {
+ uint len;
+ const char *s = mp_obj_str_get_data(arg, &len);
+ if (len != 1) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "%c requires int or char"));
break;
+ }
+ pfenv_print_strn(&pfenv_vstr, s, 1, flags, ' ', width);
+ break;
+ }
+ if (arg_looks_integer(arg)) {
+ char ch = mp_obj_get_int(arg);
+ pfenv_print_strn(&pfenv_vstr, &ch, 1, flags, ' ', width);
+ break;
}
- arg_i++;
+#if MICROPY_ENABLE_FLOAT
+ // This is what CPython reports, so we report the same.
+ if (MP_OBJ_IS_TYPE(arg, &mp_type_float)) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "integer argument expected, got float"));
+
+ }
+#endif
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "an integer is required"));
+ break;
+
+ case 'd':
+ case 'i':
+ case 'u':
+ pfenv_print_int(&pfenv_vstr, arg_as_int(arg), 1, 10, 'a', flags, fill, width);
+ break;
+
+#if MICROPY_ENABLE_FLOAT
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'F':
+ case 'g':
+ case 'G':
+ pfenv_print_float(&pfenv_vstr, mp_obj_get_float(arg), *str, flags, fill, width, prec);
+ break;
+#endif
+
+ case 'o':
+ if (alt) {
+ flags |= PF_FLAG_SHOW_PREFIX;
+ }
+ pfenv_print_int(&pfenv_vstr, arg_as_int(arg), 1, 8, 'a', flags, fill, width);
+ break;
+
+ case 'r':
+ case 's':
+ {
+ vstr_t *arg_vstr = vstr_new();
+ mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf,
+ arg_vstr, arg, *str == 'r' ? PRINT_REPR : PRINT_STR);
+ uint len = vstr_len(arg_vstr);
+ if (prec < 0) {
+ prec = len;
+ }
+ if (len > prec) {
+ len = prec;
+ }
+ pfenv_print_strn(&pfenv_vstr, vstr_str(arg_vstr), len, flags, ' ', width);
+ vstr_free(arg_vstr);
+ break;
}
- } else {
- vstr_add_char(vstr, *str);
+
+ case 'x':
+ if (alt) {
+ flags |= PF_FLAG_SHOW_PREFIX;
+ }
+ pfenv_print_int(&pfenv_vstr, arg_as_int(arg), 1, 16, 'a', flags, fill, width);
+ break;
+
+ case 'X':
+ if (alt) {
+ flags |= PF_FLAG_SHOW_PREFIX;
+ }
+ pfenv_print_int(&pfenv_vstr, arg_as_int(arg), 1, 16, 'A', flags, fill, width);
+ break;
+
+ default:
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
+ "unsupported format character '%c' (0x%x) at index %d",
+ *str, *str, str - start_str));
}
+ arg_i++;
}
if (arg_i != n_args) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "not all arguments converted during string formatting"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "not all arguments converted during string formatting"));
}
mp_obj_t s = mp_obj_new_str((byte*)vstr->buf, vstr->len, false);
@@ -1050,7 +1191,7 @@ STATIC mp_obj_t str_count(uint n_args, const mp_obj_t *args) {
STATIC mp_obj_t str_partitioner(mp_obj_t self_in, mp_obj_t arg, machine_int_t direction) {
assert(MP_OBJ_IS_STR(self_in));
if (!MP_OBJ_IS_STR(arg)) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"Can't convert '%s' object to str implicitly", mp_obj_get_type_str(arg)));
}
@@ -1058,7 +1199,7 @@ STATIC mp_obj_t str_partitioner(mp_obj_t self_in, mp_obj_t arg, machine_int_t di
GET_STR_DATA_LEN(arg, sep, sep_len);
if (sep_len == 0) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "empty separator"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "empty separator"));
}
mp_obj_t result[] = {MP_OBJ_NEW_QSTR(MP_QSTR_), MP_OBJ_NEW_QSTR(MP_QSTR_), MP_OBJ_NEW_QSTR(MP_QSTR_)};
@@ -1226,7 +1367,7 @@ bool mp_obj_str_equal(mp_obj_t s1, mp_obj_t s2) {
void bad_implicit_conversion(mp_obj_t self_in) __attribute__((noreturn));
void bad_implicit_conversion(mp_obj_t self_in) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "Can't convert '%s' object to str implicitly", mp_obj_get_type_str(self_in)));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "Can't convert '%s' object to str implicitly", mp_obj_get_type_str(self_in)));
}
uint mp_obj_str_get_hash(mp_obj_t self_in) {
diff --git a/py/objtuple.c b/py/objtuple.c
index d6a5bb3d0..21313f7f9 100644
--- a/py/objtuple.c
+++ b/py/objtuple.c
@@ -67,7 +67,7 @@ mp_obj_t mp_obj_tuple_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const m
}
default:
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "tuple takes at most 1 argument, %d given", n_args));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "tuple takes at most 1 argument, %d given", n_args));
}
}
diff --git a/py/objtype.c b/py/objtype.c
index f4ce6a4f8..e8201ca07 100644
--- a/py/objtype.c
+++ b/py/objtype.c
@@ -107,13 +107,13 @@ STATIC mp_obj_t class_make_new(mp_obj_t self_in, uint n_args, uint n_kw, const m
m_del(mp_obj_t, args2, 1 + n_args + 2 * n_kw);
}
if (init_ret != mp_const_none) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "__init__() should return None, not '%s'", mp_obj_get_type_str(init_ret)));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_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_varg(&mp_type_TypeError, "function takes 0 positional arguments but %d were given", n_args));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function takes 0 positional arguments but %d were given", n_args));
}
}
@@ -298,7 +298,7 @@ STATIC mp_obj_t type_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp
return mp_obj_new_type(mp_obj_str_get_qstr(args[0]), args[1], args[2]);
default:
- nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "type takes 1 or 3 arguments"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "type takes 1 or 3 arguments"));
}
}
@@ -308,7 +308,7 @@ STATIC mp_obj_t type_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj
mp_obj_type_t *self = self_in;
if (self->make_new == NULL) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "cannot create '%s' instances", qstr_str(self->name)));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "cannot create '%s' instances", qstr_str(self->name)));
}
// make new instance
@@ -367,6 +367,16 @@ STATIC bool type_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {
return false;
}
+STATIC mp_obj_t type_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
+ switch (op) {
+ case MP_BINARY_OP_EQUAL:
+ // Types can be equal only if it's the same type structure,
+ // we don't even need to check for 2nd arg type.
+ return MP_BOOL(lhs_in == rhs_in);
+ }
+ return NULL;
+}
+
const mp_obj_type_t mp_type_type = {
{ &mp_type_type },
.name = MP_QSTR_type,
@@ -375,6 +385,7 @@ const mp_obj_type_t mp_type_type = {
.call = type_call,
.load_attr = type_load_attr,
.store_attr = type_store_attr,
+ .binary_op = type_binary_op,
};
mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) {
@@ -417,7 +428,7 @@ STATIC mp_obj_t super_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const m
if (n_args != 2 || n_kw != 0) {
// 0 arguments are turned into 2 in the compiler
// 1 argument is not yet implemented
- nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "super() requires 2 arguments"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "super() requires 2 arguments"));
}
return mp_obj_new_super(args[0], args[1]);
}
@@ -517,7 +528,7 @@ STATIC mp_obj_t mp_obj_is_subclass(mp_obj_t object, mp_obj_t classinfo) {
} else if (MP_OBJ_IS_TYPE(classinfo, &mp_type_tuple)) {
mp_obj_tuple_get(classinfo, &len, &items);
} else {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "issubclass() arg 2 must be a class or a tuple of classes"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "issubclass() arg 2 must be a class or a tuple of classes"));
}
for (uint i = 0; i < len; i++) {
@@ -530,7 +541,7 @@ STATIC mp_obj_t mp_obj_is_subclass(mp_obj_t object, mp_obj_t classinfo) {
STATIC mp_obj_t mp_builtin_issubclass(mp_obj_t object, mp_obj_t classinfo) {
if (!MP_OBJ_IS_TYPE(object, &mp_type_type)) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "issubclass() arg 1 must be a class"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "issubclass() arg 1 must be a class"));
}
return mp_obj_is_subclass(object, classinfo);
}
@@ -550,7 +561,7 @@ STATIC mp_obj_t static_class_method_make_new(mp_obj_t self_in, uint n_args, uint
assert(self_in == &mp_type_staticmethod || self_in == &mp_type_classmethod);
if (n_args != 1 || n_kw != 0) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function takes 1 positional argument but %d were given", n_args));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function takes 1 positional argument but %d were given", n_args));
}
mp_obj_static_class_method_t *o = m_new_obj(mp_obj_static_class_method_t);
diff --git a/py/parsenum.c b/py/parsenum.c
index 7be53897a..c7cf68dad 100644
--- a/py/parsenum.c
+++ b/py/parsenum.c
@@ -19,7 +19,7 @@ mp_obj_t mp_parse_num_integer(const char *restrict str, uint len, int base) {
// check radix base
if ((base != 0 && base < 2) || base > 36) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "ValueError: int() arg 2 must be >=2 and <= 36"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "ValueError: int() arg 2 must be >=2 and <= 36"));
}
// skip leading space
@@ -93,11 +93,11 @@ mp_obj_t mp_parse_num_integer(const char *restrict str, uint len, int base) {
return MP_OBJ_NEW_SMALL_INT(int_val);
value_error:
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid literal for int() with base %d: '%s'", base, str));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid literal for int() with base %d: '%s'", base, str));
overflow:
// TODO reparse using bignum
- nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "overflow parsing integer"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "overflow parsing integer"));
}
#define PARSE_DEC_IN_INTG (1)
@@ -208,7 +208,7 @@ mp_obj_t mp_parse_num_decimal(const char *str, uint len, bool allow_imag, bool f
// check we reached the end of the string
if (str != top) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_SyntaxError, "invalid syntax for number"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_SyntaxError, "invalid syntax for number"));
}
// return the object
@@ -221,6 +221,6 @@ mp_obj_t mp_parse_num_decimal(const char *str, uint len, bool allow_imag, bool f
}
#else
- nlr_jump(mp_obj_new_exception_msg(&mp_type_SyntaxError, "decimal numbers not supported"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_SyntaxError, "decimal numbers not supported"));
#endif
}
diff --git a/py/pfenv.c b/py/pfenv.c
index 7ce721aca..0d6fab3c4 100644
--- a/py/pfenv.c
+++ b/py/pfenv.c
@@ -79,10 +79,10 @@ int pfenv_print_strn(const pfenv_t *pfenv, const char *str, unsigned int len, in
// We can use 16 characters for 32-bit and 32 characters for 64-bit
#define INT_BUF_SIZE (sizeof(machine_int_t) * 4)
-int pfenv_print_int(const pfenv_t *pfenv, unsigned int x, int sgn, int base, int base_char, int flags, char fill, int width) {
+int pfenv_print_int(const pfenv_t *pfenv, machine_uint_t x, int sgn, int base, int base_char, int flags, char fill, int width) {
char sign = 0;
if (sgn) {
- if ((int)x < 0) {
+ if ((machine_int_t)x < 0) {
sign = '-';
x = -x;
} else if (flags & PF_FLAG_SHOW_SIGN) {
diff --git a/py/pfenv.h b/py/pfenv.h
index edceaf3e4..36b452b91 100644
--- a/py/pfenv.h
+++ b/py/pfenv.h
@@ -17,7 +17,7 @@ typedef struct _pfenv_t {
void pfenv_vstr_add_strn(void *data, const char *str, unsigned int len);
int pfenv_print_strn(const pfenv_t *pfenv, const char *str, unsigned int len, int flags, char fill, int width);
-int pfenv_print_int(const pfenv_t *pfenv, unsigned int x, int sgn, int base, int base_char, int flags, char fill, int width);
+int pfenv_print_int(const pfenv_t *pfenv, machine_uint_t x, int sgn, int base, int base_char, int flags, char fill, int width);
#if MICROPY_ENABLE_FLOAT
int pfenv_print_float(const pfenv_t *pfenv, mp_float_t f, char fmt, int flags, char fill, int width, int prec);
#endif
diff --git a/py/py-version.sh b/py/py-version.sh
new file mode 100755
index 000000000..f574b574f
--- /dev/null
+++ b/py/py-version.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+git_hash="$(git rev-parse --short HEAD 2> /dev/null || echo unknown)"
+git_files_are_clean=1
+# Check if there are any modified files.
+git diff --no-ext-diff --quiet --exit-code 2> /dev/null || git_files_are_clean=0
+# Check if there are any staged files.
+git diff-index --cached --quiet HEAD -- 2> /dev/null || git_files_are_clean=0
+if [ "${git_files_are_clean}" != "1" ]; then
+ git_hash="${git_hash}-dirty"
+fi
+cat <<EOF
+// This file was generated by py/py-version.sh
+#define MICROPY_GIT_HASH "${git_hash}"
+#define MICROPY_BUILD_DATE "$(date '+%Y-%m-%d')"
+EOF
diff --git a/py/py.mk b/py/py.mk
index e2e83eb36..08cfc189a 100644
--- a/py/py.mk
+++ b/py/py.mk
@@ -78,17 +78,26 @@ PY_O_BASENAME = \
builtintables.o \
modarray.o \
modcollections.o \
+ modio.o \
modmath.o \
modmicropython.o \
vm.o \
showbc.o \
repl.o \
- intdivmod.o \
+ smallint.o \
pfenv.o \
# prepend the build destination prefix to the py object files
PY_O = $(addprefix $(PY_BUILD)/, $(PY_O_BASENAME))
+# Anything that depends on FORCE will be considered out-of-date
+FORCE:
+.PHONY: FORCE
+
+$(PY_BUILD)/py-version.h: FORCE
+ $(Q)$(PY_SRC)/py-version.sh > $@.tmp
+ $(Q)if [ -f "$@" ] && cmp -s $@ $@.tmp; then rm $@.tmp; else echo "Generating $@"; mv $@.tmp $@; fi
+
# qstr data
# Adding an order only dependency on $(PY_BUILD) causes $(PY_BUILD) to get
@@ -103,7 +112,7 @@ $(PY_BUILD)/qstrdefs.generated.h: $(PY_QSTR_DEFS) $(QSTR_DEFS) $(PY_SRC)/makeqst
# the right .o's to get recompiled if the generated.h file changes. Adding
# an order-only dependendency to all of the .o's will cause the generated .h
# to get built before we try to compile any of them.
-$(PY_O): | $(PY_BUILD)/qstrdefs.generated.h
+$(PY_O): | $(PY_BUILD)/qstrdefs.generated.h $(PY_BUILD)/py-version.h
# emitters
diff --git a/py/qstrdefs.h b/py/qstrdefs.h
index 591c96a94..2271941a0 100644
--- a/py/qstrdefs.h
+++ b/py/qstrdefs.h
@@ -99,6 +99,7 @@ Q(float)
Q(getattr)
Q(hash)
Q(id)
+Q(io)
Q(int)
Q(isinstance)
Q(issubclass)
diff --git a/py/runtime.c b/py/runtime.c
index e2e349564..c7b34c1e1 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -16,7 +16,7 @@
#include "builtin.h"
#include "builtintables.h"
#include "bc.h"
-#include "intdivmod.h"
+#include "smallint.h"
#include "objgenerator.h"
#if 0 // print debugging info
@@ -33,6 +33,14 @@ STATIC mp_map_t *map_locals;
STATIC mp_map_t *map_globals;
STATIC mp_map_t map_builtins;
+STATIC mp_map_t map_main;
+
+const mp_obj_module_t mp_module___main__ = {
+ .base = { &mp_type_module },
+ .name = MP_QSTR___main__,
+ .globals = (mp_map_t*)&map_main,
+};
+
// 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;
@@ -41,17 +49,18 @@ STATIC void mp_map_add_qstr(mp_map_t *map, qstr qstr, mp_obj_t value) {
void mp_init(void) {
mp_emit_glue_init();
- // locals = globals for outer module (see Objects/frameobject.c/PyFrame_New())
- map_locals = map_globals = mp_map_new(1);
-
- // init built-in hash table
- mp_map_init(&map_builtins, 3);
-
// init global module stuff
mp_module_init();
+ mp_map_init(&map_main, 1);
// 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_main, MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR___main__));
+
+ // locals = globals for outer module (see Objects/frameobject.c/PyFrame_New())
+ map_locals = map_globals = &map_main;
+
+ // init built-in hash table
+ mp_map_init(&map_builtins, 3);
#if MICROPY_CPYTHON_COMPAT
// Precreate sys module, so "import sys" didn't throw exceptions.
@@ -93,13 +102,15 @@ mp_obj_t mp_load_const_bytes(qstr qstr) {
mp_obj_t mp_load_name(qstr qstr) {
// logic: search locals, globals, builtins
- DEBUG_OP_printf("load name %s\n", qstr_str(qstr));
- mp_map_elem_t *elem = mp_map_lookup(map_locals, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP);
- if (elem != NULL) {
- return elem->value;
- } else {
- return mp_load_global(qstr);
+ DEBUG_OP_printf("load name %s\n", map_locals, qstr_str(qstr));
+ // If we're at the outer scope (locals == globals), dispatch to load_global right away
+ if (map_locals != map_globals) {
+ mp_map_elem_t *elem = mp_map_lookup(map_locals, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP);
+ if (elem != NULL) {
+ return elem->value;
+ }
}
+ return mp_load_global(qstr);
}
mp_obj_t mp_load_global(qstr qstr) {
@@ -113,7 +124,7 @@ mp_obj_t mp_load_global(qstr 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)));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_NameError, "name '%s' is not defined", qstr_str(qstr)));
}
}
return elem->value;
@@ -139,6 +150,7 @@ void mp_store_name(qstr qstr, mp_obj_t obj) {
void mp_delete_name(qstr qstr) {
DEBUG_OP_printf("delete name %s\n", qstr_str(qstr));
+ // TODO raise NameError if qstr not found
mp_map_lookup(map_locals, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP_REMOVE_IF_FOUND);
}
@@ -179,7 +191,7 @@ mp_obj_t mp_unary_op(int op, mp_obj_t arg) {
}
}
// TODO specify in error message what the operator is
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "bad operand type for unary operator: '%s'", mp_obj_get_type_str(arg)));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "bad operand type for unary operator: '%s'", mp_obj_get_type_str(arg)));
}
}
@@ -259,7 +271,7 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
case MP_BINARY_OP_INPLACE_LSHIFT: {
if (rhs_val < 0) {
// negative shift not allowed
- nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "negative shift count"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "negative shift count"));
} else if (rhs_val >= BITS_PER_WORD || lhs_val > (MP_SMALL_INT_MAX >> rhs_val) || lhs_val < (MP_SMALL_INT_MIN >> rhs_val)) {
// left-shift will overflow, so use higher precision integer
lhs = mp_obj_new_int_from_ll(lhs_val);
@@ -274,7 +286,7 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
case MP_BINARY_OP_INPLACE_RSHIFT:
if (rhs_val < 0) {
// negative shift not allowed
- nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "negative shift count"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "negative shift count"));
} else {
// standard precision is enough for right-shift
lhs_val >>= rhs_val;
@@ -289,7 +301,7 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
// If long long type exists and is larger than machine_int_t, then
// we can use the following code to perform overflow-checked multiplication.
- // Otherwise (eg in x64 case) we must use the branching code below.
+ // Otherwise (eg in x64 case) we must use mp_small_int_mul_overflow.
#if 0
// compute result using long long precision
long long res = (long long)lhs_val * (long long)rhs_val;
@@ -302,36 +314,14 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
}
#endif
- if (lhs_val > 0) { // lhs_val is positive
- if (rhs_val > 0) { // lhs_val and rhs_val are positive
- if (lhs_val > (MP_SMALL_INT_MAX / rhs_val)) {
- goto mul_overflow;
- }
- } else { // lhs_val positive, rhs_val nonpositive
- if (rhs_val < (MP_SMALL_INT_MIN / lhs_val)) {
- goto mul_overflow;
- }
- } // lhs_val positive, rhs_val nonpositive
- } else { // lhs_val is nonpositive
- if (rhs_val > 0) { // lhs_val is nonpositive, rhs_val is positive
- if (lhs_val < (MP_SMALL_INT_MIN / rhs_val)) {
- goto mul_overflow;
- }
- } else { // lhs_val and rhs_val are nonpositive
- if (lhs_val != 0 && rhs_val < (MP_SMALL_INT_MAX / lhs_val)) {
- goto mul_overflow;
- }
- } // End if lhs_val and rhs_val are nonpositive
- } // End if lhs_val is nonpositive
-
- // use standard precision
- return MP_OBJ_NEW_SMALL_INT(lhs_val * rhs_val);
-
- mul_overflow:
- // use higher precision
- lhs = mp_obj_new_int_from_ll(lhs_val);
- goto generic_binary_op;
-
+ if (mp_small_int_mul_overflow(lhs_val, rhs_val)) {
+ // use higher precision
+ lhs = mp_obj_new_int_from_ll(lhs_val);
+ goto generic_binary_op;
+ } else {
+ // use standard precision
+ return MP_OBJ_NEW_SMALL_INT(lhs_val * rhs_val);
+ }
break;
}
case MP_BINARY_OP_FLOOR_DIVIDE:
@@ -339,7 +329,7 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
if (rhs_val == 0) {
goto zero_division;
}
- lhs_val = python_floor_divide(lhs_val, rhs_val);
+ lhs_val = mp_small_int_floor_divide(lhs_val, rhs_val);
break;
#if MICROPY_ENABLE_FLOAT
@@ -352,11 +342,11 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
#endif
case MP_BINARY_OP_MODULO:
- case MP_BINARY_OP_INPLACE_MODULO:
- {
- lhs_val = python_modulo(lhs_val, rhs_val);
+ case MP_BINARY_OP_INPLACE_MODULO: {
+ lhs_val = mp_small_int_modulo(lhs_val, rhs_val);
break;
}
+
case MP_BINARY_OP_POWER:
case MP_BINARY_OP_INPLACE_POWER:
if (rhs_val < 0) {
@@ -364,21 +354,35 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
lhs = mp_obj_new_float(lhs_val);
goto generic_binary_op;
#else
- nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "negative power with no float support"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "negative power with no float support"));
#endif
} else {
- // TODO check for overflow
machine_int_t ans = 1;
while (rhs_val > 0) {
if (rhs_val & 1) {
+ if (mp_small_int_mul_overflow(ans, lhs_val)) {
+ goto power_overflow;
+ }
ans *= lhs_val;
}
- lhs_val *= lhs_val;
+ if (rhs_val == 1) {
+ break;
+ }
rhs_val /= 2;
+ if (mp_small_int_mul_overflow(lhs_val, lhs_val)) {
+ goto power_overflow;
+ }
+ lhs_val *= lhs_val;
}
lhs_val = ans;
}
break;
+
+ power_overflow:
+ // use higher precision
+ lhs = mp_obj_new_int_from_ll(MP_OBJ_SMALL_INT_VALUE(lhs));
+ goto generic_binary_op;
+
case MP_BINARY_OP_LESS: return MP_BOOL(lhs_val < rhs_val); break;
case MP_BINARY_OP_MORE: return MP_BOOL(lhs_val > rhs_val); break;
case MP_BINARY_OP_LESS_EQUAL: return MP_BOOL(lhs_val <= rhs_val); break;
@@ -426,7 +430,7 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
return mp_const_false;
}
- nlr_jump(mp_obj_new_exception_msg_varg(
+ nlr_raise(mp_obj_new_exception_msg_varg(
&mp_type_TypeError, "'%s' object is not iterable",
mp_obj_get_type_str(rhs)));
return mp_const_none;
@@ -446,13 +450,13 @@ generic_binary_op:
// TODO implement dispatch for reverse binary ops
// TODO specify in error message what the operator is
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"unsupported operand types for binary operator: '%s', '%s'",
mp_obj_get_type_str(lhs), mp_obj_get_type_str(rhs)));
return mp_const_none;
zero_division:
- nlr_jump(mp_obj_new_exception_msg(&mp_type_ZeroDivisionError, "division by zero"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ZeroDivisionError, "division by zero"));
}
mp_obj_t mp_call_function_0(mp_obj_t fun) {
@@ -490,7 +494,7 @@ mp_obj_t mp_call_function_n_kw(mp_obj_t fun_in, uint n_args, uint n_kw, const mp
if (type->call != NULL) {
return type->call(fun_in, n_args, n_kw, args);
} else {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not callable", mp_obj_get_type_str(fun_in)));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not callable", mp_obj_get_type_str(fun_in)));
}
}
@@ -681,17 +685,19 @@ void mp_unpack_sequence(mp_obj_t seq_in, uint num, mp_obj_t *items) {
return;
too_short:
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "need more than %d values to unpack", seq_len));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "need more than %d values to unpack", seq_len));
too_long:
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "too many values to unpack (expected %d)", num));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "too many values to unpack (expected %d)", num));
}
-mp_obj_t mp_load_attr(mp_obj_t base, qstr attr) {
+mp_obj_t mp_load_attr_default(mp_obj_t base, qstr attr, mp_obj_t defval) {
DEBUG_OP_printf("load attr %p.%s\n", base, qstr_str(attr));
- // use load_method
mp_obj_t dest[2];
- mp_load_method(base, attr, dest);
- if (dest[1] == MP_OBJ_NULL) {
+ // use load_method, raising or not raising exception
+ ((defval == MP_OBJ_NULL) ? mp_load_method : mp_load_method_maybe)(base, attr, dest);
+ if (dest[0] == MP_OBJ_NULL) {
+ return defval;
+ } else if (dest[1] == MP_OBJ_NULL) {
// load_method returned just a normal attribute
return dest[0];
} else {
@@ -700,6 +706,10 @@ mp_obj_t mp_load_attr(mp_obj_t base, qstr attr) {
}
}
+mp_obj_t mp_load_attr(mp_obj_t base, qstr attr) {
+ return mp_load_attr_default(base, attr, MP_OBJ_NULL);
+}
+
// no attribute found, returns: dest[0] == MP_OBJ_NULL, dest[1] == MP_OBJ_NULL
// normal attribute found, returns: dest[0] == <attribute>, dest[1] == MP_OBJ_NULL
// method attribute found, returns: dest[0] == <method>, dest[1] == <self>
@@ -764,10 +774,10 @@ void mp_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,
+ nlr_raise(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)));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr)));
}
}
}
@@ -780,7 +790,7 @@ void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) {
return;
}
}
- 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)));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr)));
}
void mp_store_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) {
@@ -800,7 +810,22 @@ void mp_store_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) {
}
// TODO: call base classes here?
}
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object does not support item assignment", mp_obj_get_type_str(base)));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object does not support item assignment", mp_obj_get_type_str(base)));
+ }
+}
+
+void mp_delete_subscr(mp_obj_t base, mp_obj_t index) {
+ DEBUG_OP_printf("delete subscr %p[%p]\n", base, index);
+ /* list delete not implemented
+ if (MP_OBJ_IS_TYPE(base, &mp_type_list)) {
+ // list delete
+ mp_obj_list_delete(base, index);
+ } else */
+ if (MP_OBJ_IS_TYPE(base, &mp_type_dict)) {
+ // dict delete
+ mp_obj_dict_delete(base, index);
+ } else {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object does not support item deletion", mp_obj_get_type_str(base)));
}
}
@@ -822,7 +847,7 @@ mp_obj_t mp_getiter(mp_obj_t o_in) {
return mp_obj_new_getitem_iter(dest);
} else {
// object not iterable
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not iterable", mp_obj_get_type_str(o_in)));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not iterable", mp_obj_get_type_str(o_in)));
}
}
}
@@ -842,7 +867,7 @@ mp_obj_t mp_iternext_allow_raise(mp_obj_t o_in) {
// __next__ exists, call it and return its result
return mp_call_method_n_kw(0, 0, dest);
} else {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not an iterator", mp_obj_get_type_str(o_in)));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not an iterator", mp_obj_get_type_str(o_in)));
}
}
}
@@ -868,11 +893,11 @@ mp_obj_t mp_iternext(mp_obj_t o_in) {
if (mp_obj_is_subclass_fast(mp_obj_get_type(nlr.ret_val), &mp_type_StopIteration)) {
return MP_OBJ_NULL;
} else {
- nlr_jump(nlr.ret_val);
+ nlr_raise(nlr.ret_val);
}
}
} else {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not an iterator", mp_obj_get_type_str(o_in)));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not an iterator", mp_obj_get_type_str(o_in)));
}
}
}
@@ -929,7 +954,7 @@ mp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t th
if (dest[0] != MP_OBJ_NULL) {
*ret_val = mp_call_method_n_kw(1, 0, &throw_value);
// If .throw() method returned, we assume it's value to yield
- // - any exception would be thrown with nlr_jump().
+ // - any exception would be thrown with nlr_raise().
return MP_VM_RETURN_YIELD;
}
// If there's nowhere to throw exception into, then we assume that object
@@ -1018,6 +1043,11 @@ void mp_globals_set(mp_map_t *m) {
map_globals = m;
}
+void *m_malloc_fail(int num_bytes) {
+ DEBUG_printf("memory allocation failed, allocating %d bytes\n", num_bytes);
+ nlr_raise((mp_obj_t)&mp_const_MemoryError_obj);
+}
+
// these must correspond to the respective enum
void *const mp_fun_table[MP_F_NUMBER_OF] = {
mp_load_const_dec,
diff --git a/py/runtime.h b/py/runtime.h
index b233d23b4..6b3ab73d8 100644
--- a/py/runtime.h
+++ b/py/runtime.h
@@ -45,10 +45,12 @@ mp_obj_t mp_call_method_n_kw_var(bool have_self, uint n_args_n_kw, const mp_obj_
void mp_unpack_sequence(mp_obj_t seq, uint num, mp_obj_t *items);
mp_obj_t mp_store_map(mp_obj_t map, mp_obj_t key, mp_obj_t value);
mp_obj_t mp_load_attr(mp_obj_t base, qstr attr);
+mp_obj_t mp_load_attr_default(mp_obj_t base, qstr attr, mp_obj_t defval);
void mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest);
void mp_load_method_maybe(mp_obj_t base, qstr attr, mp_obj_t *dest);
void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t val);
void mp_store_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t val);
+void mp_delete_subscr(mp_obj_t base, mp_obj_t index);
mp_obj_t mp_getiter(mp_obj_t o);
mp_obj_t mp_iternext_allow_raise(mp_obj_t o); // may return MP_OBJ_NULL instead of raising StopIteration()
diff --git a/py/sequence.c b/py/sequence.c
index 3aae4b942..3a4d65d53 100644
--- a/py/sequence.c
+++ b/py/sequence.c
@@ -159,7 +159,7 @@ mp_obj_t mp_seq_index_obj(const mp_obj_t *items, uint len, uint n_args, const mp
}
}
- nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "object not in sequence"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "object not in sequence"));
}
mp_obj_t mp_seq_count_obj(const mp_obj_t *items, uint len, mp_obj_t value) {
diff --git a/py/smallint.c b/py/smallint.c
new file mode 100644
index 000000000..ac0cf2f5f
--- /dev/null
+++ b/py/smallint.c
@@ -0,0 +1,53 @@
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "obj.h"
+
+bool mp_small_int_mul_overflow(machine_int_t x, machine_int_t y) {
+ // Check for multiply overflow; see CERT INT32-C
+ if (x > 0) { // x is positive
+ if (y > 0) { // x and y are positive
+ if (x > (MP_SMALL_INT_MAX / y)) {
+ return true;
+ }
+ } else { // x positive, y nonpositive
+ if (y < (MP_SMALL_INT_MIN / x)) {
+ return true;
+ }
+ } // x positive, y nonpositive
+ } else { // x is nonpositive
+ if (y > 0) { // x is nonpositive, y is positive
+ if (x < (MP_SMALL_INT_MIN / y)) {
+ return true;
+ }
+ } else { // x and y are nonpositive
+ if (x != 0 && y < (MP_SMALL_INT_MAX / x)) {
+ return true;
+ }
+ } // End if x and y are nonpositive
+ } // End if x is nonpositive
+ return false;
+}
+
+machine_int_t mp_small_int_modulo(machine_int_t dividend, machine_int_t divisor) {
+ machine_int_t lsign = (dividend >= 0) ? 1 :-1;
+ machine_int_t rsign = (divisor >= 0) ? 1 :-1;
+ dividend %= divisor;
+ if (lsign != rsign) {
+ dividend += divisor;
+ }
+ return dividend;
+}
+
+
+machine_int_t mp_small_int_floor_divide(machine_int_t num, machine_int_t denom) {
+ machine_int_t lsign = num > 0 ? 1 : -1;
+ machine_int_t rsign = denom > 0 ? 1 : -1;
+ if (lsign == -1) {num *= -1;}
+ if (rsign == -1) {denom *= -1;}
+ if (lsign != rsign){
+ return - ( num + denom - 1) / denom;
+ } else {
+ return num / denom;
+ }
+}
diff --git a/py/smallint.h b/py/smallint.h
new file mode 100644
index 000000000..14234fa7b
--- /dev/null
+++ b/py/smallint.h
@@ -0,0 +1,5 @@
+// Functions for small integer arithmetic
+
+bool mp_small_int_mul_overflow(machine_int_t x, machine_int_t y);
+machine_int_t mp_small_int_modulo(machine_int_t dividend, machine_int_t divisor);
+machine_int_t mp_small_int_floor_divide(machine_int_t num, machine_int_t denom);
diff --git a/py/stream.c b/py/stream.c
index a0a2c68f8..56f475a0c 100644
--- a/py/stream.c
+++ b/py/stream.c
@@ -16,7 +16,7 @@ STATIC mp_obj_t stream_read(uint n_args, const mp_obj_t *args) {
struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)args[0];
if (o->type->stream_p.read == NULL) {
// CPython: io.UnsupportedOperation, OSError subclass
- nlr_jump(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported"));
}
machine_int_t sz;
@@ -27,7 +27,7 @@ STATIC mp_obj_t stream_read(uint n_args, const mp_obj_t *args) {
int error;
machine_int_t out_sz = o->type->stream_p.read(o, buf, sz, &error);
if (out_sz == -1) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", error));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", error));
} else {
mp_obj_t s = mp_obj_new_str(buf, out_sz, false); // will reallocate to use exact size
m_free(buf, sz);
@@ -39,7 +39,7 @@ STATIC mp_obj_t stream_write(mp_obj_t self_in, mp_obj_t arg) {
struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)self_in;
if (o->type->stream_p.write == NULL) {
// CPython: io.UnsupportedOperation, OSError subclass
- nlr_jump(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported"));
}
uint sz;
@@ -47,7 +47,7 @@ STATIC mp_obj_t stream_write(mp_obj_t self_in, mp_obj_t arg) {
int error;
machine_int_t out_sz = o->type->stream_p.write(self_in, buf, sz, &error);
if (out_sz == -1) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", error));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", error));
} else {
// http://docs.python.org/3/library/io.html#io.RawIOBase.write
// "None is returned if the raw stream is set not to block and no single byte could be readily written to it."
@@ -62,7 +62,7 @@ STATIC mp_obj_t stream_readall(mp_obj_t self_in) {
struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)self_in;
if (o->type->stream_p.read == NULL) {
// CPython: io.UnsupportedOperation, OSError subclass
- nlr_jump(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported"));
}
int total_size = 0;
@@ -74,7 +74,7 @@ STATIC mp_obj_t stream_readall(mp_obj_t self_in) {
while (true) {
machine_int_t out_sz = o->type->stream_p.read(self_in, p, current_read, &error);
if (out_sz == -1) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", error));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", error));
}
if (out_sz == 0) {
break;
@@ -88,7 +88,7 @@ STATIC mp_obj_t stream_readall(mp_obj_t self_in) {
p = vstr_extend(vstr, current_read);
if (p == NULL) {
// TODO
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError/*&mp_type_RuntimeError*/, "Out of memory"));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError/*&mp_type_RuntimeError*/, "Out of memory"));
}
}
}
@@ -103,7 +103,7 @@ STATIC mp_obj_t stream_unbuffered_readline(uint n_args, const mp_obj_t *args) {
struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)args[0];
if (o->type->stream_p.read == NULL) {
// CPython: io.UnsupportedOperation, OSError subclass
- nlr_jump(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported"));
}
machine_int_t max_size = -1;
@@ -123,12 +123,12 @@ STATIC mp_obj_t stream_unbuffered_readline(uint n_args, const mp_obj_t *args) {
char *p = vstr_add_len(vstr, 1);
if (p == NULL) {
// TODO
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError/*&mp_type_RuntimeError*/, "Out of memory"));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError/*&mp_type_RuntimeError*/, "Out of memory"));
}
machine_int_t out_sz = o->type->stream_p.read(o, p, 1, &error);
if (out_sz == -1) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", error));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", error));
}
if (out_sz == 0) {
// Back out previously added byte
diff --git a/py/vm.c b/py/vm.c
index 69f350f9f..277dccd95 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -158,7 +158,7 @@ outer_dispatch_loop:
if (inject_exc != MP_OBJ_NULL && *ip != MP_BC_YIELD_FROM) {
mp_obj_t t = inject_exc;
inject_exc = MP_OBJ_NULL;
- nlr_jump(mp_make_raise_obj(t));
+ nlr_raise(mp_make_raise_obj(t));
}
// loop to execute byte code
for (;;) {
@@ -324,6 +324,11 @@ dispatch_loop:
mp_delete_name(qst);
break;
+ case MP_BC_DELETE_SUBSCR:
+ mp_delete_subscr(sp[-1], sp[0]);
+ sp -= 2;
+ break;
+
case MP_BC_DUP_TOP:
obj1 = TOP();
PUSH(obj1);
@@ -503,7 +508,7 @@ unwind_jump:
// if TOS is an integer, does something else
// else error
if (mp_obj_is_exception_type(TOP())) {
- nlr_jump(sp[-1]);
+ nlr_raise(sp[-1]);
}
if (TOP() == mp_const_none) {
sp--;
@@ -744,12 +749,12 @@ unwind_return:
}
}
if (obj1 == MP_OBJ_NULL) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_RuntimeError, "No active exception to reraise"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "No active exception to reraise"));
}
} else {
obj1 = POP();
}
- nlr_jump(mp_make_raise_obj(obj1));
+ nlr_raise(mp_make_raise_obj(obj1));
case MP_BC_YIELD_VALUE:
yield:
@@ -762,7 +767,7 @@ yield:
case MP_BC_YIELD_FROM: {
//#define EXC_MATCH(exc, type) MP_OBJ_IS_TYPE(exc, type)
#define EXC_MATCH(exc, type) mp_obj_exception_match(exc, type)
-#define GENERATOR_EXIT_IF_NEEDED(t) if (t != MP_OBJ_NULL && EXC_MATCH(t, &mp_type_GeneratorExit)) { nlr_jump(t); }
+#define GENERATOR_EXIT_IF_NEEDED(t) if (t != MP_OBJ_NULL && EXC_MATCH(t, &mp_type_GeneratorExit)) { nlr_raise(t); }
mp_vm_return_kind_t ret_kind;
obj1 = POP();
mp_obj_t t_exc = MP_OBJ_NULL;
@@ -805,7 +810,7 @@ yield:
GENERATOR_EXIT_IF_NEEDED(t_exc);
break;
} else {
- nlr_jump(obj2);
+ nlr_raise(obj2);
}
}
}
@@ -849,8 +854,8 @@ yield:
// set file and line number that the exception occurred at
// TODO: don't set traceback for exceptions re-raised by END_FINALLY.
// But consider how to handle nested exceptions.
- // TODO need a better way of not adding traceback to constant objects (right now, just GeneratorExit_obj)
- if (mp_obj_is_exception_instance(nlr.ret_val) && nlr.ret_val != &mp_const_GeneratorExit_obj) {
+ // TODO need a better way of not adding traceback to constant objects (right now, just GeneratorExit_obj and MemoryError_obj)
+ if (mp_obj_is_exception_instance(nlr.ret_val) && nlr.ret_val != &mp_const_GeneratorExit_obj && nlr.ret_val != &mp_const_MemoryError_obj) {
machine_uint_t code_info_size = code_info[0] | (code_info[1] << 8) | (code_info[2] << 16) | (code_info[3] << 24);
qstr source_file = code_info[4] | (code_info[5] << 8) | (code_info[6] << 16) | (code_info[7] << 24);
qstr block_name = code_info[8] | (code_info[9] << 8) | (code_info[10] << 16) | (code_info[11] << 24);
diff --git a/stm/adc.c b/stm/adc.c
index c7cca0ec0..4caa6da12 100644
--- a/stm/adc.c
+++ b/stm/adc.c
@@ -429,7 +429,7 @@ mp_obj_t pyb_ADC(mp_obj_t pin_name_obj) {
}
if (i == ADC_NUM_CHANNELS) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin %s does not have ADC capabilities", pin_name));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin %s does not have ADC capabilities", pin_name));
}
// init ADC just for this channel
@@ -440,7 +440,7 @@ mp_obj_t pyb_ADC(mp_obj_t pin_name_obj) {
return o;
pin_error:
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin %s does not exist", pin_name));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin %s does not exist", pin_name));
}
MP_DEFINE_CONST_FUN_OBJ_1(pyb_ADC_obj, pyb_ADC);
diff --git a/stm/audio.c b/stm/audio.c
index a4e42918c..e9e872813 100644
--- a/stm/audio.c
+++ b/stm/audio.c
@@ -125,7 +125,7 @@ mp_obj_t pyb_audio_dma(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
mp_obj_type_t *type = mp_obj_get_type(args[1]);
if (type->buffer_p.get_buffer == NULL) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "buffer argument must support buffer protocol"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "buffer argument must support buffer protocol"));
}
buffer_info_t bufinfo;
type->buffer_p.get_buffer(args[1], &bufinfo, BUFFER_READ);
diff --git a/stm/exti.c b/stm/exti.c
index ab33481eb..c6dfd9d1a 100644
--- a/stm/exti.c
+++ b/stm/exti.c
@@ -110,10 +110,10 @@ uint exti_register(mp_obj_t pin_obj, mp_obj_t mode_obj, mp_obj_t trigger_obj, mp
// get both the port number and line number.
v_line = mp_obj_get_int(pin_obj);
if (v_line < 16) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "EXTI vector %d < 16, use a Pin object", v_line));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "EXTI vector %d < 16, use a Pin object", v_line));
}
if (v_line >= EXTI_NUM_VECTORS) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "EXTI vector %d >= max of %d", v_line, EXTI_NUM_VECTORS));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "EXTI vector %d >= max of %d", v_line, EXTI_NUM_VECTORS));
}
} else {
pin = pin_map_user_obj(pin_obj);
@@ -121,16 +121,16 @@ uint exti_register(mp_obj_t pin_obj, mp_obj_t mode_obj, mp_obj_t trigger_obj, mp
}
int mode = mp_obj_get_int(mode_obj);
if (!IS_EXTI_MODE(mode)) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Invalid EXTI Mode: %d", mode));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Invalid EXTI Mode: %d", mode));
}
int trigger = mp_obj_get_int(trigger_obj);
if (!IS_EXTI_TRIGGER(trigger)) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Invalid EXTI Trigger: %d", trigger));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Invalid EXTI Trigger: %d", trigger));
}
exti_vector_t *v = &exti_vector[v_line];
if (v->callback_obj != mp_const_none && callback_obj != mp_const_none) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "EXTI vector %d is already in use", v_line));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "EXTI vector %d is already in use", v_line));
}
// We need to update callback and param atomically, so we disable the line
diff --git a/stm/file.c b/stm/file.c
index a8f66f4b0..8abb45b4e 100644
--- a/stm/file.c
+++ b/stm/file.c
@@ -93,3 +93,5 @@ mp_obj_t pyb_io_open(mp_obj_t o_filename, mp_obj_t o_mode) {
}
return self;
}
+
+MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_open_obj, pyb_io_open);
diff --git a/stm/mpconfigport.h b/stm/mpconfigport.h
index 3f48c43f0..4c8338be5 100644
--- a/stm/mpconfigport.h
+++ b/stm/mpconfigport.h
@@ -18,6 +18,8 @@
#define MICROPY_ENABLE_LFN (0)
#define MICROPY_LFN_CODE_PAGE (1) /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */
+extern const struct _mp_obj_fun_native_t mp_builtin_open_obj;
+
// type definitions for the specific machine
#define BYTES_PER_WORD (4)
diff --git a/stm/pin_map.c b/stm/pin_map.c
index 9082afe49..c5754ca33 100644
--- a/stm/pin_map.c
+++ b/stm/pin_map.c
@@ -164,7 +164,7 @@ const pin_obj_t *pin_map_user_obj(mp_obj_t user_obj) {
pin_obj = mp_call_function_1(pin_map_obj.mapper, user_obj);
if (pin_obj != mp_const_none) {
if (!MP_OBJ_IS_TYPE(pin_obj, &pin_obj_type)) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "Pin.mapper didn't return a Pin object"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Pin.mapper didn't return a Pin object"));
}
if (pin_map_obj.debug) {
printf("Pin.mapper maps ");
@@ -222,5 +222,5 @@ const pin_obj_t *pin_map_user_obj(mp_obj_t user_obj) {
return pin_obj;
}
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin '%s' not a valid pin identifier", pin_name));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin '%s' not a valid pin identifier", pin_name));
}
diff --git a/stm/pybwlan.c b/stm/pybwlan.c
index 8d8ce3243..f4e6f8021 100644
--- a/stm/pybwlan.c
+++ b/stm/pybwlan.c
@@ -123,12 +123,12 @@ mp_obj_t pyb_wlan_http_get(mp_obj_t host_name, mp_obj_t host_path) {
last_ip = (192 << 24) | (168 << 16) | (0 << 8) | (3);
} else {
if (pyb_wlan_get_host(host_name) == mp_const_none) {
- nlr_jump(mp_obj_new_exception_msg(QSTR_FROM_STR_STATIC("WlanError"), "unknown host"));
+ nlr_raise(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(mp_obj_new_exception_msg_varg(QSTR_FROM_STR_STATIC("WlanError"), "socket failed: %d", sd));
+ nlr_raise(mp_obj_new_exception_msg_varg(QSTR_FROM_STR_STATIC("WlanError"), "socket failed: %d", sd));
}
//printf("socket seemed to work\n");
//sys_tick_delay_ms(200);
@@ -139,7 +139,7 @@ mp_obj_t pyb_wlan_http_get(mp_obj_t host_name, mp_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(mp_obj_new_exception_msg_varg(QSTR_FROM_STR_STATIC("WlanError"), "connect failed: %d", ret));
+ nlr_raise(mp_obj_new_exception_msg_varg(QSTR_FROM_STR_STATIC("WlanError"), "connect failed: %d", ret));
}
//printf("connect seemed to work\n");
//sys_tick_delay_ms(200);
@@ -160,7 +160,7 @@ mp_obj_t pyb_wlan_http_get(mp_obj_t host_name, mp_obj_t host_path) {
ret = send(sd, query + sent, strlen(query + sent), 0);
//printf("sent %d bytes\n", ret);
if (ret < 0) {
- nlr_jump(mp_obj_new_exception_msg(QSTR_FROM_STR_STATIC("WlanError"), "send failed"));
+ nlr_raise(mp_obj_new_exception_msg(QSTR_FROM_STR_STATIC("WlanError"), "send failed"));
}
sent += ret;
//sys_tick_delay_ms(200);
@@ -197,7 +197,7 @@ mp_obj_t pyb_wlan_http_get(mp_obj_t host_name, mp_obj_t host_path) {
// read data
ret = recv(sd, buf, 64, 0);
if (ret < 0) {
- nlr_jump(mp_obj_new_exception_msg_varg(QSTR_FROM_STR_STATIC("WlanError"), "recv failed %d", ret));
+ nlr_raise(mp_obj_new_exception_msg_varg(QSTR_FROM_STR_STATIC("WlanError"), "recv failed %d", ret));
}
vstr_add_strn(vstr, buf, ret);
}
@@ -217,7 +217,7 @@ mp_obj_t pyb_wlan_serve(void) {
sys_tick_delay_ms(500);
if (sd < 0) {
printf("socket fail\n");
- nlr_jump(mp_obj_new_exception_msg_varg(QSTR_FROM_STR_STATIC("WlanError"), "socket failed: %d", sd));
+ nlr_raise(mp_obj_new_exception_msg_varg(QSTR_FROM_STR_STATIC("WlanError"), "socket failed: %d", sd));
}
/*
@@ -238,7 +238,7 @@ mp_obj_t pyb_wlan_serve(void) {
sys_tick_delay_ms(100);
if (ret != 0) {
printf("bind fail\n");
- nlr_jump(mp_obj_new_exception_msg_varg(QSTR_FROM_STR_STATIC("WlanError"), "bind failed: %d", ret));
+ nlr_raise(mp_obj_new_exception_msg_varg(QSTR_FROM_STR_STATIC("WlanError"), "bind failed: %d", ret));
}
printf("bind seemed to work\n");
diff --git a/stmhal/adc.c b/stmhal/adc.c
index 0b4f3e23e..8a1c23c4f 100644
--- a/stmhal/adc.c
+++ b/stmhal/adc.c
@@ -131,16 +131,16 @@ STATIC mp_obj_t adc_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_
const pin_obj_t *pin = pin_map_user_obj(pin_obj);
if ((pin->adc_num & PIN_ADC1) == 0) {
// No ADC1 function on that pin
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin %s does not have ADC capabilities", pin->name));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin %s does not have ADC capabilities", pin->name));
}
channel = pin->adc_channel;
}
if (!IS_ADC_CHANNEL(channel)) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Not a valid ADC Channel: %d", channel));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Not a valid ADC Channel: %d", channel));
}
if (pin_adc1[channel] == NULL) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Channel %d not available on this board", channel));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Channel %d not available on this board", channel));
}
pyb_obj_adc_t *o = m_new_obj(pyb_obj_adc_t);
@@ -192,7 +192,7 @@ void adc_init_all(pyb_obj_adc_all_t *adc_all, uint32_t resolution) {
case 10: resolution = ADC_RESOLUTION10b; break;
case 12: resolution = ADC_RESOLUTION12b; break;
default:
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
"resolution %d not supported", resolution));
}
diff --git a/stmhal/autoflash b/stmhal/autoflash
index 0f4bfd039..dc28a97e2 100755
--- a/stmhal/autoflash
+++ b/stmhal/autoflash
@@ -1,7 +1,13 @@
#!/bin/sh
#
-# this script waits for a DFU device to be attached and then flashes it
-# it then waits until the DFU mode is exited, and then loops
+# This script loops doing the following:
+# - wait for DFU device
+# - flash DFU device
+# - wait for DFU to exit
+# - wait for serial port to appear
+# - run a terminal
+
+SERIAL=/dev/ttyACM0
while true; do
echo "waiting for DFU device..."
@@ -11,8 +17,10 @@ while true; do
fi
sleep 1s
done
+
echo "found DFU device, flashing"
dfu-util -a 0 -D build/flash.dfu
+
echo "waiting for DFU to exit..."
while true; do
if lsusb | grep -q DFU; then
@@ -21,4 +29,15 @@ while true; do
fi
break
done
+
+ echo "waiting for $SERIAL..."
+ while true; do
+ if ls /dev/tty* | grep -q $SERIAL; then
+ break
+ fi
+ sleep 1s
+ continue
+ done
+ sleep 1s
+ picocom $SERIAL
done
diff --git a/stmhal/dac.c b/stmhal/dac.c
index 4dbf70022..22622d474 100644
--- a/stmhal/dac.c
+++ b/stmhal/dac.c
@@ -77,7 +77,7 @@ STATIC mp_obj_t pyb_dac_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const
pin = GPIO_PIN_5;
dac_obj = &pyb_dac_channel_2;
} else {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Dac %d does not exist", dac_id));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Dac %d does not exist", dac_id));
}
// GPIO configuration
@@ -182,7 +182,7 @@ mp_obj_t pyb_dac_dma(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
mp_obj_type_t *type = mp_obj_get_type(args[1]);
if (type->buffer_p.get_buffer == NULL) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "buffer argument must support buffer protocol"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "buffer argument must support buffer protocol"));
}
buffer_info_t bufinfo;
type->buffer_p.get_buffer(args[1], &bufinfo, BUFFER_READ);
diff --git a/stmhal/exti.c b/stmhal/exti.c
index a9b05644c..afb8c8e13 100644
--- a/stmhal/exti.c
+++ b/stmhal/exti.c
@@ -116,10 +116,10 @@ uint exti_register(mp_obj_t pin_obj, mp_obj_t mode_obj, mp_obj_t pull_obj, mp_ob
// get both the port number and line number.
v_line = mp_obj_get_int(pin_obj);
if (v_line < 16) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "EXTI vector %d < 16, use a Pin object", v_line));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "EXTI vector %d < 16, use a Pin object", v_line));
}
if (v_line >= EXTI_NUM_VECTORS) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "EXTI vector %d >= max of %d", v_line, EXTI_NUM_VECTORS));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "EXTI vector %d >= max of %d", v_line, EXTI_NUM_VECTORS));
}
} else {
pin = pin_map_user_obj(pin_obj);
@@ -132,18 +132,18 @@ uint exti_register(mp_obj_t pin_obj, mp_obj_t mode_obj, mp_obj_t pull_obj, mp_ob
mode != GPIO_MODE_EVT_RISING &&
mode != GPIO_MODE_EVT_FALLING &&
mode != GPIO_MODE_EVT_RISING_FALLING) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Invalid EXTI Mode: %d", mode));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Invalid EXTI Mode: %d", mode));
}
int pull = mp_obj_get_int(pull_obj);
if (pull != GPIO_NOPULL &&
pull != GPIO_PULLUP &&
pull != GPIO_PULLDOWN) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Invalid EXTI Pull: %d", pull));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Invalid EXTI Pull: %d", pull));
}
exti_vector_t *v = &exti_vector[v_line];
if (v->callback_obj != mp_const_none && callback_obj != mp_const_none) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "EXTI vector %d is already in use", v_line));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "EXTI vector %d is already in use", v_line));
}
// We need to update callback and param atomically, so we disable the line
diff --git a/stmhal/file.c b/stmhal/file.c
index 9575ffd7e..a66b59b29 100644
--- a/stmhal/file.c
+++ b/stmhal/file.c
@@ -4,6 +4,8 @@
#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
+#include "runtime.h"
+#include "stream.h"
#include "file.h"
#include "ff.h"
@@ -16,27 +18,18 @@ void file_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, m
printf("<file %p>", self_in);
}
-mp_obj_t file_obj_read(mp_obj_t self_in, mp_obj_t arg) {
+STATIC machine_int_t file_read(mp_obj_t self_in, void *buf, machine_uint_t size, int *errcode) {
pyb_file_obj_t *self = self_in;
- int n = mp_obj_get_int(arg);
- byte *buf = m_new(byte, n);
- UINT n_out;
- f_read(&self->fp, buf, n, &n_out);
- return mp_obj_new_str(buf, n_out, false);
+ UINT sz_out;
+ *errcode = f_read(&self->fp, buf, size, &sz_out);
+ return sz_out;
}
-mp_obj_t file_obj_write(mp_obj_t self_in, mp_obj_t arg) {
+STATIC machine_int_t file_write(mp_obj_t self_in, const void *buf, machine_uint_t size, int *errcode) {
pyb_file_obj_t *self = self_in;
- uint l;
- const char *s = mp_obj_str_get_data(arg, &l);
- UINT n_out;
- FRESULT res = f_write(&self->fp, s, l, &n_out);
- if (res != FR_OK) {
- printf("File error: could not write to file; error code %d\n", res);
- } else if (n_out != l) {
- printf("File error: could not write all data to file; wrote %d / %d bytes\n", n_out, l);
- }
- return mp_const_none;
+ UINT sz_out;
+ *errcode = f_write(&self->fp, buf, size, &sz_out);
+ return sz_out;
}
mp_obj_t file_obj_close(mp_obj_t self_in) {
@@ -45,30 +38,49 @@ mp_obj_t file_obj_close(mp_obj_t self_in) {
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);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(file_obj_close_obj, file_obj_close);
+
+mp_obj_t file_obj___exit__(uint n_args, const mp_obj_t *args) {
+ return file_obj_close(args[0]);
+}
+static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(file_obj___exit___obj, 4, 4, file_obj___exit__);
// TODO gc hook to close the file if not already closed
STATIC const mp_map_elem_t file_locals_dict_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&file_obj_read_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&file_obj_write_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_readall), (mp_obj_t)&mp_stream_readall_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj},
+ { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&file_obj_close_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR___enter__), (mp_obj_t)&mp_identity_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR___exit__), (mp_obj_t)&file_obj___exit___obj },
};
STATIC MP_DEFINE_CONST_DICT(file_locals_dict, file_locals_dict_table);
+STATIC mp_obj_t file_obj_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args);
static const mp_obj_type_t file_obj_type = {
{ &mp_type_type },
.name = MP_QSTR_File,
+ .make_new = file_obj_make_new,
.print = file_obj_print,
+ .getiter = mp_identity,
+ .iternext = mp_stream_unbuffered_iter,
+ .stream_p = {
+ .read = file_read,
+ .write = file_write,
+ },
.locals_dict = (mp_obj_t)&file_locals_dict,
};
-STATIC mp_obj_t pyb_io_open(mp_obj_t o_filename, mp_obj_t o_mode) {
- const char *filename = mp_obj_str_get_str(o_filename);
- const char *mode = mp_obj_str_get_str(o_mode);
+STATIC mp_obj_t file_obj_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
+ mp_check_nargs(n_args, 1, 2, n_kw, false);
+ const char *filename = mp_obj_str_get_str(args[0]);
+ const char *mode = "r";
+ if (n_args > 1) {
+ mode = mp_obj_str_get_str(args[1]);
+ }
pyb_file_obj_t *self = m_new_obj(pyb_file_obj_t);
self->base.type = &file_obj_type;
if (mode[0] == 'r') {
@@ -92,4 +104,10 @@ STATIC mp_obj_t pyb_io_open(mp_obj_t o_filename, mp_obj_t o_mode) {
return self;
}
-MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_open_obj, pyb_io_open);
+// Factory function for I/O stream classes
+STATIC mp_obj_t pyb_io_open(uint n_args, const mp_obj_t *args) {
+ // TODO: analyze mode and buffering args and instantiate appropriate type
+ return file_obj_make_new((mp_obj_t)&file_obj_type, n_args, 0, args);
+}
+
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_open_obj, 1, 2, pyb_io_open);
diff --git a/stmhal/i2c.c b/stmhal/i2c.c
index f35d00b54..e998d5941 100644
--- a/stmhal/i2c.c
+++ b/stmhal/i2c.c
@@ -86,7 +86,7 @@ STATIC mp_obj_t pyb_i2c_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const
// check i2c number
if (!(0 <= i2c_id && i2c_id < PYB_NUM_I2C)) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "I2C bus %d does not exist", i2c_id + 1));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "I2C bus %d does not exist", i2c_id + 1));
}
// get i2c object
@@ -130,7 +130,7 @@ STATIC mp_obj_t pyb_i2c_mem_read(uint n_args, const mp_obj_t *args) {
if (status != HAL_OK) {
// TODO really need a HardwareError object, or something
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_I2C_Mem_Read failed with code %d", status));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_I2C_Mem_Read failed with code %d", status));
}
return mp_obj_str_builder_end(o);
@@ -152,14 +152,14 @@ STATIC mp_obj_t pyb_i2c_mem_write(uint n_args, const mp_obj_t *args) {
uint8_t data[1] = {mp_obj_get_int(args[3])};
status = HAL_I2C_Mem_Write(self->i2c_handle, i2c_addr, mem_addr, I2C_MEMADD_SIZE_8BIT, data, 1, 200);
} else {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "data argument must be an integer or support the buffer protocol"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "data argument must be an integer or support the buffer protocol"));
}
//printf("Write got %d\n", status);
if (status != HAL_OK) {
// TODO really need a HardwareError object, or something
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_I2C_Mem_Write failed with code %d", status));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_I2C_Mem_Write failed with code %d", status));
}
return mp_const_none;
diff --git a/stmhal/input.c b/stmhal/input.c
index d704c2cf7..0ded89866 100644
--- a/stmhal/input.c
+++ b/stmhal/input.c
@@ -14,7 +14,7 @@ STATIC mp_obj_t mp_builtin_input(uint n_args, const mp_obj_t *args) {
vstr_init(&line, 16);
int ret = readline(&line, "");
if (line.len == 0 && ret == VCP_CHAR_CTRL_D) {
- nlr_jump(mp_obj_new_exception(&mp_type_EOFError));
+ nlr_raise(mp_obj_new_exception(&mp_type_EOFError));
}
mp_obj_t o = mp_obj_new_str((const byte*)line.buf, line.len, false);
vstr_clear(&line);
diff --git a/stmhal/led.c b/stmhal/led.c
index 3108ee779..5c2d2c60a 100644
--- a/stmhal/led.c
+++ b/stmhal/led.c
@@ -204,7 +204,7 @@ STATIC mp_obj_t led_obj_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const
// check led number
if (!(0 <= led_id && led_id < NUM_LEDS)) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Led %d does not exist", led_id));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Led %d does not exist", led_id));
}
// return static led object
diff --git a/stmhal/main.c b/stmhal/main.c
index afef84e29..897271d14 100644
--- a/stmhal/main.c
+++ b/stmhal/main.c
@@ -434,7 +434,7 @@ soft_reset:
#endif
// run main script
- if (reset_mode == 1) {
+ if (reset_mode == 1 && pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) {
vstr_t *vstr = vstr_new();
vstr_add_str(vstr, "0:/");
if (pyb_config_source_dir == MP_OBJ_NULL) {
diff --git a/stmhal/math.c b/stmhal/math.c
index 8afdc82a6..9b815f118 100644
--- a/stmhal/math.c
+++ b/stmhal/math.c
@@ -1,4 +1,6 @@
#include <stdint.h>
+#include <math.h>
+
typedef float float_t;
typedef union {
float f;
@@ -44,12 +46,6 @@ double __aeabi_dmul(double x , double y) {
return 0.0;
}
-/*
-double sqrt(double x) {
- // TODO
- return 0.0;
-}
-*/
float sqrtf(float x) {
asm volatile (
@@ -59,12 +55,18 @@ float sqrtf(float x) {
return x;
}
+// some compilers define log2f in terms of logf
+#ifdef log2f
+#undef log2f
+#endif
+float log2f(float x) { return logf(x) / (float)_M_LN2; }
+
+static const float _M_LN10 = 2.30258509299404; // 0x40135d8e
+float log10f(float x) { return logf(x) / (float)_M_LN10; }
+
+float tanhf(float x) { return sinhf(x) / coshf(x); }
+
// TODO we need import these functions from some library (eg musl or newlib)
-float powf(float x, float y) { return 0.0; }
-float logf(float x) { return 0.0; }
-float log2f(float x) { return 0.0; }
-float log10f(float x) { return 0.0; }
-float tanhf(float x) { return 0.0; }
float acoshf(float x) { return 0.0; }
float asinhf(float x) { return 0.0; }
float atanhf(float x) { return 0.0; }
@@ -86,10 +88,12 @@ float erfcf(float x) { return 0.0; }
float modff(float x, float *y) { return 0.0; }
float frexpf(float x, int *exp) { return 0.0; }
float ldexpf(float x, int exp) { return 0.0; }
-int __fpclassifyf(float x) { return 0; }
/*****************************************************************************/
+/*****************************************************************************/
// from musl-0.9.15 libm.h
+/*****************************************************************************/
+/*****************************************************************************/
/* origin: FreeBSD /usr/src/lib/msun/src/math_private.h */
/*
@@ -136,7 +140,25 @@ do { \
} while (0)
/*****************************************************************************/
+/*****************************************************************************/
+// __fpclassifyf from musl-0.9.15
+/*****************************************************************************/
+/*****************************************************************************/
+
+int __fpclassifyf(float x)
+{
+ union {float f; uint32_t i;} u = {x};
+ int e = u.i>>23 & 0xff;
+ if (!e) return u.i<<1 ? FP_SUBNORMAL : FP_ZERO;
+ if (e==0xff) return u.i<<9 ? FP_NAN : FP_INFINITE;
+ return FP_NORMAL;
+}
+
+/*****************************************************************************/
+/*****************************************************************************/
// scalbnf from musl-0.9.15
+/*****************************************************************************/
+/*****************************************************************************/
float scalbnf(float x, int n)
{
@@ -168,7 +190,274 @@ float scalbnf(float x, int n)
}
/*****************************************************************************/
+/*****************************************************************************/
+// powf from musl-0.9.15
+/*****************************************************************************/
+/*****************************************************************************/
+
+/* origin: FreeBSD /usr/src/lib/msun/src/e_powf.c */
+/*
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+static const float
+bp[] = {1.0, 1.5,},
+dp_h[] = { 0.0, 5.84960938e-01,}, /* 0x3f15c000 */
+dp_l[] = { 0.0, 1.56322085e-06,}, /* 0x35d1cfdc */
+two24 = 16777216.0, /* 0x4b800000 */
+huge = 1.0e30,
+tiny = 1.0e-30,
+/* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */
+L1 = 6.0000002384e-01, /* 0x3f19999a */
+L2 = 4.2857143283e-01, /* 0x3edb6db7 */
+L3 = 3.3333334327e-01, /* 0x3eaaaaab */
+L4 = 2.7272811532e-01, /* 0x3e8ba305 */
+L5 = 2.3066075146e-01, /* 0x3e6c3255 */
+L6 = 2.0697501302e-01, /* 0x3e53f142 */
+P1 = 1.6666667163e-01, /* 0x3e2aaaab */
+P2 = -2.7777778450e-03, /* 0xbb360b61 */
+P3 = 6.6137559770e-05, /* 0x388ab355 */
+P4 = -1.6533901999e-06, /* 0xb5ddea0e */
+P5 = 4.1381369442e-08, /* 0x3331bb4c */
+lg2 = 6.9314718246e-01, /* 0x3f317218 */
+lg2_h = 6.93145752e-01, /* 0x3f317200 */
+lg2_l = 1.42860654e-06, /* 0x35bfbe8c */
+ovt = 4.2995665694e-08, /* -(128-log2(ovfl+.5ulp)) */
+cp = 9.6179670095e-01, /* 0x3f76384f =2/(3ln2) */
+cp_h = 9.6191406250e-01, /* 0x3f764000 =12b cp */
+cp_l = -1.1736857402e-04, /* 0xb8f623c6 =tail of cp_h */
+ivln2 = 1.4426950216e+00, /* 0x3fb8aa3b =1/ln2 */
+ivln2_h = 1.4426879883e+00, /* 0x3fb8aa00 =16b 1/ln2*/
+ivln2_l = 7.0526075433e-06; /* 0x36eca570 =1/ln2 tail*/
+
+float powf(float x, float y)
+{
+ float z,ax,z_h,z_l,p_h,p_l;
+ float y1,t1,t2,r,s,sn,t,u,v,w;
+ int32_t i,j,k,yisint,n;
+ int32_t hx,hy,ix,iy,is;
+
+ GET_FLOAT_WORD(hx, x);
+ GET_FLOAT_WORD(hy, y);
+ ix = hx & 0x7fffffff;
+ iy = hy & 0x7fffffff;
+
+ /* x**0 = 1, even if x is NaN */
+ if (iy == 0)
+ return 1.0f;
+ /* 1**y = 1, even if y is NaN */
+ if (hx == 0x3f800000)
+ return 1.0f;
+ /* NaN if either arg is NaN */
+ if (ix > 0x7f800000 || iy > 0x7f800000)
+ return x + y;
+
+ /* determine if y is an odd int when x < 0
+ * yisint = 0 ... y is not an integer
+ * yisint = 1 ... y is an odd int
+ * yisint = 2 ... y is an even int
+ */
+ yisint = 0;
+ if (hx < 0) {
+ if (iy >= 0x4b800000)
+ yisint = 2; /* even integer y */
+ else if (iy >= 0x3f800000) {
+ k = (iy>>23) - 0x7f; /* exponent */
+ j = iy>>(23-k);
+ if ((j<<(23-k)) == iy)
+ yisint = 2 - (j & 1);
+ }
+ }
+
+ /* special value of y */
+ if (iy == 0x7f800000) { /* y is +-inf */
+ if (ix == 0x3f800000) /* (-1)**+-inf is 1 */
+ return 1.0f;
+ else if (ix > 0x3f800000) /* (|x|>1)**+-inf = inf,0 */
+ return hy >= 0 ? y : 0.0f;
+ else if (ix != 0) /* (|x|<1)**+-inf = 0,inf if x!=0 */
+ return hy >= 0 ? 0.0f: -y;
+ }
+ if (iy == 0x3f800000) /* y is +-1 */
+ return hy >= 0 ? x : 1.0f/x;
+ if (hy == 0x40000000) /* y is 2 */
+ return x*x;
+ if (hy == 0x3f000000) { /* y is 0.5 */
+ if (hx >= 0) /* x >= +0 */
+ return sqrtf(x);
+ }
+
+ ax = fabsf(x);
+ /* special value of x */
+ if (ix == 0x7f800000 || ix == 0 || ix == 0x3f800000) { /* x is +-0,+-inf,+-1 */
+ z = ax;
+ if (hy < 0) /* z = (1/|x|) */
+ z = 1.0f/z;
+ if (hx < 0) {
+ if (((ix-0x3f800000)|yisint) == 0) {
+ z = (z-z)/(z-z); /* (-1)**non-int is NaN */
+ } else if (yisint == 1)
+ z = -z; /* (x<0)**odd = -(|x|**odd) */
+ }
+ return z;
+ }
+
+ sn = 1.0f; /* sign of result */
+ if (hx < 0) {
+ if (yisint == 0) /* (x<0)**(non-int) is NaN */
+ return (x-x)/(x-x);
+ if (yisint == 1) /* (x<0)**(odd int) */
+ sn = -1.0f;
+ }
+
+ /* |y| is huge */
+ if (iy > 0x4d000000) { /* if |y| > 2**27 */
+ /* over/underflow if x is not close to one */
+ if (ix < 0x3f7ffff8)
+ return hy < 0 ? sn*huge*huge : sn*tiny*tiny;
+ if (ix > 0x3f800007)
+ return hy > 0 ? sn*huge*huge : sn*tiny*tiny;
+ /* now |1-x| is tiny <= 2**-20, suffice to compute
+ log(x) by x-x^2/2+x^3/3-x^4/4 */
+ t = ax - 1; /* t has 20 trailing zeros */
+ w = (t*t)*(0.5f - t*(0.333333333333f - t*0.25f));
+ u = ivln2_h*t; /* ivln2_h has 16 sig. bits */
+ v = t*ivln2_l - w*ivln2;
+ t1 = u + v;
+ GET_FLOAT_WORD(is, t1);
+ SET_FLOAT_WORD(t1, is & 0xfffff000);
+ t2 = v - (t1-u);
+ } else {
+ float s2,s_h,s_l,t_h,t_l;
+ n = 0;
+ /* take care subnormal number */
+ if (ix < 0x00800000) {
+ ax *= two24;
+ n -= 24;
+ GET_FLOAT_WORD(ix, ax);
+ }
+ n += ((ix)>>23) - 0x7f;
+ j = ix & 0x007fffff;
+ /* determine interval */
+ ix = j | 0x3f800000; /* normalize ix */
+ if (j <= 0x1cc471) /* |x|<sqrt(3/2) */
+ k = 0;
+ else if (j < 0x5db3d7) /* |x|<sqrt(3) */
+ k = 1;
+ else {
+ k = 0;
+ n += 1;
+ ix -= 0x00800000;
+ }
+ SET_FLOAT_WORD(ax, ix);
+
+ /* compute s = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
+ u = ax - bp[k]; /* bp[0]=1.0, bp[1]=1.5 */
+ v = 1.0f/(ax+bp[k]);
+ s = u*v;
+ s_h = s;
+ GET_FLOAT_WORD(is, s_h);
+ SET_FLOAT_WORD(s_h, is & 0xfffff000);
+ /* t_h=ax+bp[k] High */
+ is = ((ix>>1) & 0xfffff000) | 0x20000000;
+ SET_FLOAT_WORD(t_h, is + 0x00400000 + (k<<21));
+ t_l = ax - (t_h - bp[k]);
+ s_l = v*((u - s_h*t_h) - s_h*t_l);
+ /* compute log(ax) */
+ s2 = s*s;
+ r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6)))));
+ r += s_l*(s_h+s);
+ s2 = s_h*s_h;
+ t_h = 3.0f + s2 + r;
+ GET_FLOAT_WORD(is, t_h);
+ SET_FLOAT_WORD(t_h, is & 0xfffff000);
+ t_l = r - ((t_h - 3.0f) - s2);
+ /* u+v = s*(1+...) */
+ u = s_h*t_h;
+ v = s_l*t_h + t_l*s;
+ /* 2/(3log2)*(s+...) */
+ p_h = u + v;
+ GET_FLOAT_WORD(is, p_h);
+ SET_FLOAT_WORD(p_h, is & 0xfffff000);
+ p_l = v - (p_h - u);
+ z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */
+ z_l = cp_l*p_h + p_l*cp+dp_l[k];
+ /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */
+ t = (float)n;
+ t1 = (((z_h + z_l) + dp_h[k]) + t);
+ GET_FLOAT_WORD(is, t1);
+ SET_FLOAT_WORD(t1, is & 0xfffff000);
+ t2 = z_l - (((t1 - t) - dp_h[k]) - z_h);
+ }
+
+ /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */
+ GET_FLOAT_WORD(is, y);
+ SET_FLOAT_WORD(y1, is & 0xfffff000);
+ p_l = (y-y1)*t1 + y*t2;
+ p_h = y1*t1;
+ z = p_l + p_h;
+ GET_FLOAT_WORD(j, z);
+ if (j > 0x43000000) /* if z > 128 */
+ return sn*huge*huge; /* overflow */
+ else if (j == 0x43000000) { /* if z == 128 */
+ if (p_l + ovt > z - p_h)
+ return sn*huge*huge; /* overflow */
+ } else if ((j&0x7fffffff) > 0x43160000) /* z < -150 */ // FIXME: check should be (uint32_t)j > 0xc3160000
+ return sn*tiny*tiny; /* underflow */
+ else if (j == 0xc3160000) { /* z == -150 */
+ if (p_l <= z-p_h)
+ return sn*tiny*tiny; /* underflow */
+ }
+ /*
+ * compute 2**(p_h+p_l)
+ */
+ i = j & 0x7fffffff;
+ k = (i>>23) - 0x7f;
+ n = 0;
+ if (i > 0x3f000000) { /* if |z| > 0.5, set n = [z+0.5] */
+ n = j + (0x00800000>>(k+1));
+ k = ((n&0x7fffffff)>>23) - 0x7f; /* new k for n */
+ SET_FLOAT_WORD(t, n & ~(0x007fffff>>k));
+ n = ((n&0x007fffff)|0x00800000)>>(23-k);
+ if (j < 0)
+ n = -n;
+ p_h -= t;
+ }
+ t = p_l + p_h;
+ GET_FLOAT_WORD(is, t);
+ SET_FLOAT_WORD(t, is & 0xffff8000);
+ u = t*lg2_h;
+ v = (p_l-(t-p_h))*lg2 + t*lg2_l;
+ z = u + v;
+ w = v - (z - u);
+ t = z*z;
+ t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
+ r = (z*t1)/(t1-2.0f) - (w+z*w);
+ z = 1.0f - (r - z);
+ GET_FLOAT_WORD(j, z);
+ j += n<<23;
+ if ((j>>23) <= 0) /* subnormal output */
+ z = scalbnf(z, n);
+ else
+ SET_FLOAT_WORD(z, j);
+ return sn*z;
+}
+
+/*****************************************************************************/
+/*****************************************************************************/
// expf from musl-0.9.15
+/*****************************************************************************/
+/*****************************************************************************/
/* origin: FreeBSD /usr/src/lib/msun/src/e_expf.c */
/*
@@ -194,8 +483,8 @@ invln2 = 1.4426950216e+0f, /* 0x3fb8aa3b */
* Domain [-0.34568, 0.34568], range ~[-4.278e-9, 4.447e-9]:
* |x*(exp(x)+1)/(exp(x)-1) - p(x)| < 2**-27.74
*/
-P1 = 1.6666625440e-1f, /* 0xaaaa8f.0p-26 */
-P2 = -2.7667332906e-3f; /* -0xb55215.0p-32 */
+expf_P1 = 1.6666625440e-1f, /* 0xaaaa8f.0p-26 */
+expf_P2 = -2.7667332906e-3f; /* -0xb55215.0p-32 */
float expf(float x)
{
@@ -243,7 +532,7 @@ float expf(float x)
/* x is now in primary range */
xx = x*x;
- c = x - xx*(P1+xx*P2);
+ c = x - xx*(expf_P1+xx*expf_P2);
y = 1 + (x*c/(2-c) - lo + hi);
if (k == 0)
return y;
@@ -251,7 +540,10 @@ float expf(float x)
}
/*****************************************************************************/
+/*****************************************************************************/
// expm1f from musl-0.9.15
+/*****************************************************************************/
+/*****************************************************************************/
/* origin: FreeBSD /usr/src/lib/msun/src/s_expm1f.c */
/*
@@ -364,7 +656,10 @@ float expm1f(float x)
}
/*****************************************************************************/
+/*****************************************************************************/
// __expo2f from musl-0.9.15
+/*****************************************************************************/
+/*****************************************************************************/
/* k is such that k*ln2 has minimal relative error and x - kln2 > log(FLT_MIN) */
static const int k = 235;
@@ -382,7 +677,81 @@ float __expo2f(float x)
}
/*****************************************************************************/
+/*****************************************************************************/
+// logf from musl-0.9.15
+/*****************************************************************************/
+/*****************************************************************************/
+
+/* origin: FreeBSD /usr/src/lib/msun/src/e_logf.c */
+/*
+ * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
+ */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+static const float
+/* |(log(1+s)-log(1-s))/s - Lg(s)| < 2**-34.24 (~[-4.95e-11, 4.97e-11]). */
+Lg1 = 0xaaaaaa.0p-24, /* 0.66666662693 */
+Lg2 = 0xccce13.0p-25, /* 0.40000972152 */
+Lg3 = 0x91e9ee.0p-25, /* 0.28498786688 */
+Lg4 = 0xf89e26.0p-26; /* 0.24279078841 */
+
+float logf(float x)
+{
+ union {float f; uint32_t i;} u = {x};
+ float_t hfsq,f,s,z,R,w,t1,t2,dk;
+ uint32_t ix;
+ int k;
+
+ ix = u.i;
+ k = 0;
+ if (ix < 0x00800000 || ix>>31) { /* x < 2**-126 */
+ if (ix<<1 == 0)
+ return -1/(x*x); /* log(+-0)=-inf */
+ if (ix>>31)
+ return (x-x)/0.0f; /* log(-#) = NaN */
+ /* subnormal number, scale up x */
+ k -= 25;
+ x *= 0x1p25f;
+ u.f = x;
+ ix = u.i;
+ } else if (ix >= 0x7f800000) {
+ return x;
+ } else if (ix == 0x3f800000)
+ return 0;
+
+ /* reduce x into [sqrt(2)/2, sqrt(2)] */
+ ix += 0x3f800000 - 0x3f3504f3;
+ k += (int)(ix>>23) - 0x7f;
+ ix = (ix&0x007fffff) + 0x3f3504f3;
+ u.i = ix;
+ x = u.f;
+
+ f = x - 1.0f;
+ s = f/(2.0f + f);
+ z = s*s;
+ w = z*z;
+ t1= w*(Lg2+w*Lg4);
+ t2= z*(Lg1+w*Lg3);
+ R = t2 + t1;
+ hfsq = 0.5f*f*f;
+ dk = k;
+ return s*(hfsq+R) + dk*ln2_lo - hfsq + f + dk*ln2_hi;
+}
+
+/*****************************************************************************/
+/*****************************************************************************/
// coshf from musl-0.9.15
+/*****************************************************************************/
+/*****************************************************************************/
float coshf(float x)
{
@@ -417,7 +786,10 @@ float coshf(float x)
}
/*****************************************************************************/
+/*****************************************************************************/
// sinhf from musl-0.9.15
+/*****************************************************************************/
+/*****************************************************************************/
float sinhf(float x)
{
diff --git a/stmhal/modos.c b/stmhal/modos.c
index 5684d1105..6103b1b4f 100644
--- a/stmhal/modos.c
+++ b/stmhal/modos.c
@@ -38,7 +38,7 @@ STATIC mp_obj_t os_listdir(uint n_args, const mp_obj_t *args) {
res = f_opendir(&dir, path); /* Open the directory */
if (res != FR_OK) {
// TODO should be mp_type_FileNotFoundError
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "No such file or directory: '%s'", path));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "No such file or directory: '%s'", path));
}
mp_obj_t dir_list = mp_obj_new_list(0, NULL);
@@ -91,9 +91,9 @@ STATIC mp_obj_t os_mkdir(mp_obj_t path_o) {
return mp_const_none;
case FR_EXIST:
// TODO should be FileExistsError
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "File exists: '%s'", path));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "File exists: '%s'", path));
default:
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error creating directory '%s'", path));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error creating directory '%s'", path));
}
}
@@ -107,7 +107,7 @@ STATIC mp_obj_t os_remove(mp_obj_t path_o) {
case FR_OK:
return mp_const_none;
default:
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error removing file '%s'", path));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error removing file '%s'", path));
}
}
@@ -121,7 +121,7 @@ STATIC mp_obj_t os_rmdir(mp_obj_t path_o) {
case FR_OK:
return mp_const_none;
default:
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error removing directory '%s'", path));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error removing directory '%s'", path));
}
}
diff --git a/stmhal/pin_map.c b/stmhal/pin_map.c
index 2313540a3..c0c6910b2 100644
--- a/stmhal/pin_map.c
+++ b/stmhal/pin_map.c
@@ -164,7 +164,7 @@ const pin_obj_t *pin_map_user_obj(mp_obj_t user_obj) {
pin_obj = mp_call_function_1(pin_map_obj.mapper, user_obj);
if (pin_obj != mp_const_none) {
if (!MP_OBJ_IS_TYPE(pin_obj, &pin_obj_type)) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "Pin.mapper didn't return a Pin object"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Pin.mapper didn't return a Pin object"));
}
if (pin_map_obj.debug) {
printf("Pin.mapper maps ");
@@ -222,5 +222,5 @@ const pin_obj_t *pin_map_user_obj(mp_obj_t user_obj) {
return pin_obj;
}
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin '%s' not a valid pin identifier", pin_name));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin '%s' not a valid pin identifier", pin_name));
}
diff --git a/stmhal/pyexec.c b/stmhal/pyexec.c
index ffee4dd2e..8bc3ec6e5 100644
--- a/stmhal/pyexec.c
+++ b/stmhal/pyexec.c
@@ -23,6 +23,7 @@
#include "pyexec.h"
#include "storage.h"
#include "usb.h"
+#include "build/py/py-version.h"
pyexec_mode_kind_t pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL;
STATIC bool repl_display_debugging_info = 0;
@@ -120,9 +121,8 @@ raw_repl_reset:
} else if (c == VCP_CHAR_CTRL_D) {
// input finished
break;
- } else if (c == '\r') {
- vstr_add_char(&line, '\n');
- } else if (32 <= c && c <= 126) {
+ } else if (c <= 127) {
+ // let through any other ASCII character
vstr_add_char(&line, c);
}
}
@@ -156,7 +156,7 @@ int pyexec_friendly_repl(void) {
#endif
friendly_repl_reset:
- stdout_tx_str("Micro Python build <git hash> on 25/1/2014; " MICROPY_HW_BOARD_NAME " with STM32F405RG\r\n");
+ stdout_tx_str("Micro Python build " MICROPY_GIT_HASH " on " MICROPY_BUILD_DATE "; " MICROPY_HW_BOARD_NAME " with STM32F405RG\r\n");
stdout_tx_str("Type \"help()\" for more information.\r\n");
// to test ctrl-C
diff --git a/stmhal/qstrdefsport.h b/stmhal/qstrdefsport.h
index 0a7fe821d..3212de85b 100644
--- a/stmhal/qstrdefsport.h
+++ b/stmhal/qstrdefsport.h
@@ -21,6 +21,8 @@ Q(SW)
Q(servo)
Q(pwm)
Q(read)
+Q(readall)
+Q(readline)
Q(write)
Q(hid)
Q(time)
diff --git a/stmhal/readline.c b/stmhal/readline.c
index 7df347f03..13c2dc93c 100644
--- a/stmhal/readline.c
+++ b/stmhal/readline.c
@@ -1,3 +1,4 @@
+#include <stdio.h>
#include <string.h>
#include <stm32f4xx_hal.h>
@@ -11,10 +12,19 @@
#include "readline.h"
#include "usb.h"
+#if 0 // print debugging info
+#define DEBUG_PRINT (1)
+#define DEBUG_printf printf
+#else // don't print debugging info
+#define DEBUG_printf(...) (void)0
+#endif
+
#define READLINE_HIST_SIZE (8)
static const char *readline_hist[READLINE_HIST_SIZE] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
+enum { ESEQ_NONE, ESEQ_ESC, ESEQ_ESC_BRACKET, ESEQ_ESC_BRACKET_DIGIT, ESEQ_ESC_O };
+
void readline_init(void) {
memset(readline_hist, 0, READLINE_HIST_SIZE * sizeof(const char*));
}
@@ -30,7 +40,8 @@ STATIC char *str_dup(const char *str) {
int readline(vstr_t *line, const char *prompt) {
stdout_tx_str(prompt);
int orig_line_len = line->len;
- int escape_seq = 0;
+ int escape_seq = ESEQ_NONE;
+ char escape_seq_buf[1] = {0};
int hist_cur = -1;
int cursor_pos = orig_line_len;
for (;;) {
@@ -39,10 +50,16 @@ int readline(vstr_t *line, const char *prompt) {
int redraw_step_back = 0;
bool redraw_from_cursor = false;
int redraw_step_forward = 0;
- if (escape_seq == 0) {
+ if (escape_seq == ESEQ_NONE) {
if (VCP_CHAR_CTRL_A <= c && c <= VCP_CHAR_CTRL_D && vstr_len(line) == orig_line_len) {
// control character with empty line
return c;
+ } else if (c == VCP_CHAR_CTRL_A) {
+ // CTRL-A with non-empty line is go-to-start-of-line
+ goto home_key;
+ } else if (c == VCP_CHAR_CTRL_E) {
+ // CTRL-E is go-to-end-of-line
+ goto end_key;
} else if (c == '\r') {
// newline
stdout_tx_str("\r\n");
@@ -57,7 +74,7 @@ int readline(vstr_t *line, const char *prompt) {
return 0;
} else if (c == 27) {
// escape sequence
- escape_seq = 1;
+ escape_seq = ESEQ_ESC;
} else if (c == 8 || c == 127) {
// backspace/delete
if (cursor_pos > orig_line_len) {
@@ -73,55 +90,99 @@ int readline(vstr_t *line, const char *prompt) {
redraw_from_cursor = true;
redraw_step_forward = 1;
}
- } else if (escape_seq == 1) {
- if (c == '[') {
- escape_seq = 2;
- } else {
- escape_seq = 0;
+ } else if (escape_seq == ESEQ_ESC) {
+ switch (c) {
+ case '[':
+ escape_seq = ESEQ_ESC_BRACKET;
+ break;
+ case 'O':
+ escape_seq = ESEQ_ESC_O;
+ break;
+ default:
+ DEBUG_printf("(ESC %d)", c);
+ escape_seq = ESEQ_NONE;
}
- } else if (escape_seq == 2) {
- escape_seq = 0;
- if (c == 'A') {
- // up arrow
- if (hist_cur + 1 < READLINE_HIST_SIZE && readline_hist[hist_cur + 1] != NULL) {
- // increase hist num
- hist_cur += 1;
- // set line to history
- line->len = orig_line_len;
- vstr_add_str(line, readline_hist[hist_cur]);
- // set redraw parameters
- redraw_step_back = cursor_pos - orig_line_len;
- redraw_from_cursor = true;
- redraw_step_forward = line->len - orig_line_len;
- }
- } else if (c == 'B') {
- // down arrow
- if (hist_cur >= 0) {
- // decrease hist num
- hist_cur -= 1;
- // set line to history
- vstr_cut_tail_bytes(line, line->len - orig_line_len);
- if (hist_cur >= 0) {
+ } else if (escape_seq == ESEQ_ESC_BRACKET) {
+ if ('0' <= c && c <= '9') {
+ escape_seq = ESEQ_ESC_BRACKET_DIGIT;
+ escape_seq_buf[0] = c;
+ } else {
+ escape_seq = ESEQ_NONE;
+ if (c == 'A') {
+ // up arrow
+ if (hist_cur + 1 < READLINE_HIST_SIZE && readline_hist[hist_cur + 1] != NULL) {
+ // increase hist num
+ hist_cur += 1;
+ // set line to history
+ line->len = orig_line_len;
vstr_add_str(line, readline_hist[hist_cur]);
+ // set redraw parameters
+ redraw_step_back = cursor_pos - orig_line_len;
+ redraw_from_cursor = true;
+ redraw_step_forward = line->len - orig_line_len;
}
- // set redraw parameters
- redraw_step_back = cursor_pos - orig_line_len;
- redraw_from_cursor = true;
- redraw_step_forward = line->len - orig_line_len;
- }
- } else if (c == 'C') {
- // right arrow
- if (cursor_pos < line->len) {
- redraw_step_forward = 1;
+ } else if (c == 'B') {
+ // down arrow
+ if (hist_cur >= 0) {
+ // decrease hist num
+ hist_cur -= 1;
+ // set line to history
+ vstr_cut_tail_bytes(line, line->len - orig_line_len);
+ if (hist_cur >= 0) {
+ vstr_add_str(line, readline_hist[hist_cur]);
+ }
+ // set redraw parameters
+ redraw_step_back = cursor_pos - orig_line_len;
+ redraw_from_cursor = true;
+ redraw_step_forward = line->len - orig_line_len;
+ }
+ } else if (c == 'C') {
+ // right arrow
+ if (cursor_pos < line->len) {
+ redraw_step_forward = 1;
+ }
+ } else if (c == 'D') {
+ // left arrow
+ if (cursor_pos > orig_line_len) {
+ redraw_step_back = 1;
+ }
+ } else if (c == 'H') {
+ // home
+ goto home_key;
+ } else if (c == 'F') {
+ // end
+ goto end_key;
+ } else {
+ DEBUG_printf("(ESC [ %d)", c);
}
- } else if (c == 'D') {
- // left arrow
- if (cursor_pos > orig_line_len) {
- redraw_step_back = 1;
+ }
+ } else if (escape_seq == ESEQ_ESC_BRACKET_DIGIT) {
+ if (c == '~') {
+ if (escape_seq_buf[0] == '1' || escape_seq_buf[0] == '7') {
+home_key:
+ redraw_step_back = cursor_pos - orig_line_len;
+ } else if (escape_seq_buf[0] == '4' || escape_seq_buf[0] == '8') {
+end_key:
+ redraw_step_forward = line->len - cursor_pos;
+ } else {
+ DEBUG_printf("(ESC [ %c %d)", escape_seq_buf[0], c);
}
+ } else {
+ DEBUG_printf("(ESC [ %c %d)", escape_seq_buf[0], c);
+ }
+ escape_seq = ESEQ_NONE;
+ } else if (escape_seq == ESEQ_ESC_O) {
+ switch (c) {
+ case 'H':
+ goto home_key;
+ case 'F':
+ goto end_key;
+ default:
+ DEBUG_printf("(ESC O %d)", c);
+ escape_seq = ESEQ_NONE;
}
} else {
- escape_seq = 0;
+ escape_seq = ESEQ_NONE;
}
// redraw command prompt, efficiently
diff --git a/stmhal/servo.c b/stmhal/servo.c
index 9c757c565..79a6843b7 100644
--- a/stmhal/servo.c
+++ b/stmhal/servo.c
@@ -27,8 +27,6 @@ typedef struct _pyb_servo_obj_t {
uint16_t pulse_dest;
} pyb_servo_obj_t;
-STATIC const mp_obj_type_t servo_obj_type;
-
STATIC pyb_servo_obj_t pyb_servo_obj[PYB_SERVO_NUM];
void servo_init(void) {
@@ -36,7 +34,7 @@ void servo_init(void) {
// reset servo objects
for (int i = 0; i < PYB_SERVO_NUM; i++) {
- pyb_servo_obj[i].base.type = &servo_obj_type;
+ pyb_servo_obj[i].base.type = &pyb_servo_type;
pyb_servo_obj[i].servo_id = i + 1;
pyb_servo_obj[i].time_left = 0;
pyb_servo_obj[i].pulse_cur = 150; // units of 10us
@@ -149,7 +147,7 @@ STATIC mp_obj_t pyb_servo_make_new(mp_obj_t type_in, uint n_args, uint n_kw, con
// check servo number
if (!(0 <= servo_id && servo_id < PYB_SERVO_NUM)) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Servo %d does not exist", servo_id));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Servo %d does not exist", servo_id + 1));
}
// get and init servo object
diff --git a/stmhal/timer.c b/stmhal/timer.c
index cfdb93587..1e77f0fea 100644
--- a/stmhal/timer.c
+++ b/stmhal/timer.c
@@ -174,7 +174,7 @@ void timer_interrupt(void) {
mp_obj_t pyb_Timer(mp_obj_t timx_in) {
TIM_TypeDef *TIMx = (TIM_TypeDef*)mp_obj_get_int(timx_in);
if (!IS_TIM_INSTANCE(TIMx)) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "argument 1 is not a TIM instance"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "argument 1 is not a TIM instance"));
}
pyb_hal_tim_t *tim = m_new_obj(pyb_hal_tim_t);
tim->htim.Instance = TIMx;
diff --git a/stmhal/usart.c b/stmhal/usart.c
index 9bcc6be28..3cf8da6de 100644
--- a/stmhal/usart.c
+++ b/stmhal/usart.c
@@ -145,7 +145,7 @@ STATIC void usart_obj_print(void (*print)(void *env, const char *fmt, ...), void
STATIC mp_obj_t usart_obj_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
// check arguments
if (!(n_args == 2 && n_kw == 0)) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "Usart accepts 2 arguments"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Usart accepts 2 arguments"));
}
if (mp_obj_get_int(args[0]) > PYB_USART_MAX) {
diff --git a/stmhal/usb.h b/stmhal/usb.h
index 014b51eef..a235c4765 100644
--- a/stmhal/usb.h
+++ b/stmhal/usb.h
@@ -3,6 +3,7 @@
#define VCP_CHAR_CTRL_B (2)
#define VCP_CHAR_CTRL_C (3)
#define VCP_CHAR_CTRL_D (4)
+#define VCP_CHAR_CTRL_E (5)
typedef enum {
USB_DEVICE_MODE_CDC_MSC,
diff --git a/teensy/main.c b/teensy/main.c
index ea8726f76..740d0b238 100644
--- a/teensy/main.c
+++ b/teensy/main.c
@@ -190,7 +190,7 @@ mp_obj_t pyb_gpio(int n_args, mp_obj_t *args) {
return mp_const_none;
pin_error:
- nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_ValueError, "pin %d does not exist", pin));
+ nlr_raise(mp_obj_new_exception_msg_varg(MP_QSTR_ValueError, "pin %d does not exist", pin));
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_gpio_obj, 1, 2, pyb_gpio);
diff --git a/teensy/servo.c b/teensy/servo.c
index 51714dbcc..6ccdb05e9 100644
--- a/teensy/servo.c
+++ b/teensy/servo.c
@@ -70,7 +70,7 @@ static mp_obj_t servo_obj_attach(mp_obj_t self_in, mp_obj_t pin_obj) {
return mp_const_none;
pin_error:
- nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_ValueError, "pin %d does not exist", pin));
+ nlr_raise(mp_obj_new_exception_msg_varg(MP_QSTR_ValueError, "pin %d does not exist", pin));
}
static mp_obj_t servo_obj_detach(mp_obj_t self_in) {
@@ -217,7 +217,7 @@ mp_obj_t pyb_Servo(void) {
self->servo_id++;
}
m_del_obj(pyb_servo_obj_t, self);
- nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "No available servo ids"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "No available servo ids"));
return mp_const_none;
}
diff --git a/tests/basics/dict-del.py b/tests/basics/dict-del.py
new file mode 100644
index 000000000..d908fea42
--- /dev/null
+++ b/tests/basics/dict-del.py
@@ -0,0 +1,21 @@
+for n in range(20):
+ print('testing dict with {} items'.format(n))
+ for i in range(n):
+ # create dict
+ d = dict()
+ for j in range(n):
+ d[str(j)] = j
+ print(len(d))
+
+ # delete an item
+ del d[str(i)]
+ print(len(d))
+
+ # check items
+ for j in range(n):
+ if str(j) in d:
+ if j == i:
+ print(j, 'in d, but it should not be')
+ else:
+ if j != i:
+ print(j, 'not in d, but it should be')
diff --git a/tests/basics/getattr1.py b/tests/basics/getattr1.py
index 7b7e07392..9a96154ca 100644
--- a/tests/basics/getattr1.py
+++ b/tests/basics/getattr1.py
@@ -13,3 +13,5 @@ a = A()
print(getattr(a, "var"))
print(getattr(a, "var2"))
print(getattr(a, "meth")(5))
+print(getattr(a, "_none_such", 123))
+print(getattr(list, "foo", 456))
diff --git a/tests/basics/globals-del.py b/tests/basics/globals-del.py
new file mode 100644
index 000000000..a1638ac27
--- /dev/null
+++ b/tests/basics/globals-del.py
@@ -0,0 +1,27 @@
+"""
+1
+"""
+
+def _f(): pass
+FunctionType = type(_f)
+LambdaType = type(lambda: None)
+CodeType = None
+MappingProxyType = None
+SimpleNamespace = None
+
+def _g():
+ yield 1
+GeneratorType = type(_g())
+
+class _C:
+ def _m(self): pass
+MethodType = type(_C()._m)
+
+BuiltinFunctionType = type(len)
+BuiltinMethodType = type([].append)
+
+del _f
+
+# print only the first 8 chars, since we have different str rep to CPython
+print(str(FunctionType)[:8])
+print(str(BuiltinFunctionType)[:8])
diff --git a/tests/basics/math-fun.py b/tests/basics/math-fun.py
index eb80ab0f5..7a37c5845 100644
--- a/tests/basics/math-fun.py
+++ b/tests/basics/math-fun.py
@@ -34,7 +34,7 @@ functions = [('sqrt', sqrt, p_test_values),
for function_name, function, test_vals in functions:
print(function_name)
for value in test_vals:
- print("{:8.7g}".format(function(value)))
+ print("{:.7g}".format(function(value)))
binary_functions = [('copysign', copysign, [(23., 42.), (-23., 42.), (23., -42.),
(-23., -42.), (1., 0.0), (1., -0.0)])
@@ -43,4 +43,4 @@ binary_functions = [('copysign', copysign, [(23., 42.), (-23., 42.), (23., -42.)
for function_name, function, test_vals in binary_functions:
print(function_name)
for value1, value2 in test_vals:
- print("{:8.7g}".format(function(value1, value2)))
+ print("{:.7g}".format(function(value1, value2)))
diff --git a/tests/basics/memoryerror.py b/tests/basics/memoryerror.py
new file mode 100644
index 000000000..b4be420c3
--- /dev/null
+++ b/tests/basics/memoryerror.py
@@ -0,0 +1,6 @@
+l = list(range(10000))
+try:
+ 100000000 * l
+except MemoryError:
+ print('MemoryError')
+print(len(l), l[0], l[-1])
diff --git a/tests/basics/set_remove.py b/tests/basics/set_remove.py
index 208ab137f..5627516c4 100644
--- a/tests/basics/set_remove.py
+++ b/tests/basics/set_remove.py
@@ -1,3 +1,4 @@
+# basic test
s = {1}
print(s.remove(1))
print(list(s))
@@ -7,3 +8,26 @@ except KeyError:
pass
else:
print("failed to raise KeyError")
+
+# test sets of varying size
+for n in range(20):
+ print('testing set with {} items'.format(n))
+ for i in range(n):
+ # create set
+ s = set()
+ for j in range(n):
+ s.add(str(j))
+ print(len(s))
+
+ # delete an item
+ s.remove(str(i))
+ print(len(s))
+
+ # check items
+ for j in range(n):
+ if str(j) in s:
+ if j == i:
+ print(j, 'in s, but it should not be')
+ else:
+ if j != i:
+ print(j, 'not in s, but it should be')
diff --git a/tests/basics/string-format-modulo.py b/tests/basics/string-format-modulo.py
index 0b50c2674..b736e2a73 100644
--- a/tests/basics/string-format-modulo.py
+++ b/tests/basics/string-format-modulo.py
@@ -20,3 +20,44 @@ try:
print("=%s=" % (1, 2))
except TypeError:
print("TypeError")
+
+print("%s" % True)
+print("%s" % 1)
+print("%s" % 1.0)
+
+print("%r" % True)
+print("%r" % 1)
+print("%r" % 1.0)
+
+print("%c" % 48)
+print("%c" % 'a')
+print("%10s" % 'abc')
+print("%-10s" % 'abc')
+print("%d" % 10)
+print("%+d" % 10)
+print("% d" % 10)
+print("%d" % -10)
+print("%d" % 1.0)
+print("%d" % True)
+print("%i" % -10)
+print("%i" % 1.0)
+print("%i" % True)
+print("%u" % -10)
+print("%u" % 1.0)
+print("%u" % True)
+print("%x" % 18)
+print("%x" % 18.0)
+print("%o" % 18)
+print("%o" % 18.0)
+print("%X" % 18)
+print("%X" % 18.0)
+print("%#x" % 18)
+print("%#X" % 18)
+print("%#6x" % 18)
+print("%#06x" % 18)
+print("%e" % 1.23456)
+print("%E" % 1.23456)
+print("%f" % 1.23456)
+print("%F" % 1.23456)
+print("%g" % 1.23456)
+print("%G" % 1.23456)
diff --git a/tests/basics/string-format.py b/tests/basics/string-format.py
index 290030a9e..8049c6f73 100644
--- a/tests/basics/string-format.py
+++ b/tests/basics/string-format.py
@@ -58,6 +58,9 @@ test("{:10.4f}", 123.456)
test("{:10.4f}", -123.456)
test("{:10.4g}", 123.456)
test("{:10.4g}", -123.456)
+test("{:e}", 100)
+test("{:f}", 200)
+test("{:g}", 300)
test("{:10.4E}", 123.456)
test("{:10.4E}", -123.456)
diff --git a/tests/basics/types2.py b/tests/basics/types2.py
new file mode 100644
index 000000000..83a69c918
--- /dev/null
+++ b/tests/basics/types2.py
@@ -0,0 +1,12 @@
+# Types are hashable
+print(hash(type) != 0)
+print(hash(int) != 0)
+print(hash(list) != 0)
+class Foo: pass
+print(hash(Foo) != 0)
+
+print(int == int)
+print(int != list)
+
+d = {}
+d[int] = float
diff --git a/tests/io/file-with.py b/tests/io/file-with.py
new file mode 100644
index 000000000..ee1e70242
--- /dev/null
+++ b/tests/io/file-with.py
@@ -0,0 +1,21 @@
+f = open("io/data/file1")
+
+with f as f2:
+ print(f2.read())
+
+# File should be closed
+try:
+ f.read()
+except:
+ # Note: CPython and us throw different exception trying to read from
+ # close file.
+ print("can't read file after with")
+
+
+# Regression test: test that exception in with initialization properly
+# thrown and doesn't crash.
+try:
+ with open('__non_existent', 'r'):
+ pass
+except OSError:
+ print("OSError")
diff --git a/tests/misc/rge-sm.py b/tests/misc/rge-sm.py
index 40c6029b4..1860f7a31 100644
--- a/tests/misc/rge-sm.py
+++ b/tests/misc/rge-sm.py
@@ -111,4 +111,4 @@ def singleTraj(system, trajStart, h=0.02, tend=1.0):
#phaseDiagram(sysSM, (lambda i, j: [0.354, 0.654, 1.278, 0.8 + 0.2 * i, 0.1 + 0.1 * j]), (lambda a: (a[4], a[5])), h=0.1, tend=math.log(10**17))
# initial conditions at M_Z
-singleTraj(sysSM, [0.354, 0.654, 1.278, 0.983, 0.131], h=0.1, tend=math.log(10**17)) # true values
+singleTraj(sysSM, [0.354, 0.654, 1.278, 0.983, 0.131], h=0.5, tend=math.log(10**17)) # true values
diff --git a/tests/run-tests b/tests/run-tests
index 834f1f930..22ddbe58e 100755
--- a/tests/run-tests
+++ b/tests/run-tests
@@ -5,11 +5,14 @@ import subprocess
import sys
from glob import glob
+# Tests require at least CPython 3.3. If your default python3 executable
+# is of lower version, you can point MICROPY_CPYTHON3 environment var
+# to the correct executable.
if os.name == 'nt':
- CPYTHON3 = 'python3.exe'
+ CPYTHON3 = os.getenv('MICROPY_CPYTHON3', 'python3.exe')
MP_PY = '../windows/micropython.exe'
else:
- CPYTHON3 = 'python3'
+ CPYTHON3 = os.getenv('MICROPY_CPYTHON3', 'python3')
MP_PY = '../unix/micropython'
def rm_f(fname):
@@ -27,12 +30,28 @@ if not sys.argv[1:]:
else:
tests = sys.argv[1:]
+test_on_pyboard = False
+if test_on_pyboard:
+ import pyboard
+ pyb = pyboard.Pyboard('/dev/ttyACM0')
+ pyb.enter_raw_repl()
+
for test_file in tests:
test_name = os.path.splitext(os.path.basename(test_file))[0]
- output_expected = subprocess.check_output([CPYTHON3, '-B', test_file])
+ # run CPython
+ try:
+ output_expected = subprocess.check_output([CPYTHON3, '-B', test_file])
+ except subprocess.CalledProcessError:
+ output_expected = b'CPYTHON3 CRASH'
+
+ # run Micro Python
try:
- output_mupy = subprocess.check_output([MP_PY, test_file])
+ if test_on_pyboard:
+ pyb.enter_raw_repl()
+ output_mupy = pyb.execfile(test_file).replace(b'\r\n', b'\n')
+ else:
+ output_mupy = subprocess.check_output([MP_PY, test_file])
except subprocess.CalledProcessError:
output_mupy = b'CRASH'
diff --git a/tools/pyboard.py b/tools/pyboard.py
index 3ce6da521..1c5c84f30 100644
--- a/tools/pyboard.py
+++ b/tools/pyboard.py
@@ -12,6 +12,11 @@ Example usage:
pyb.exec('pyb.Led(1).on()')
pyb.exit_raw_repl()
+To run a script from the local machine on the board and print out the results:
+
+ import pyboard
+ pyboard.execfile('test.py', device='/dev/ttyACM0')
+
"""
import time
@@ -45,29 +50,51 @@ class Pyboard:
def exec(self, command):
command_bytes = bytes(command, encoding='ascii')
- for i in range(0, len(command_bytes), 10):
- self.serial.write(command_bytes[i:min(i+10, len(command_bytes))])
+ for i in range(0, len(command_bytes), 32):
+ self.serial.write(command_bytes[i:min(i+32, len(command_bytes))])
time.sleep(0.01)
self.serial.write(b'\x04')
data = self.serial.read(2)
if data != b'OK':
raise Exception('could not exec command')
data = self.serial.read(2)
- while self.serial.inWaiting() > 0:
- data = data + self.serial.read(self.serial.inWaiting())
- time.sleep(0.1)
+ timeout = 0
+ while True:
+ if self.serial.inWaiting() > 0:
+ data = data + self.serial.read(self.serial.inWaiting())
+ timeout = 0
+ elif data.endswith(b'\x04>'):
+ break
+ else:
+ timeout += 1
+ if timeout > 100:
+ break
+ time.sleep(0.1)
if not data.endswith(b'\x04>'):
print(data)
- raise Exception('could not exec command')
+ raise Exception('timeout waiting for EOF reception')
if data.startswith(b'Traceback') or data.startswith(b' File '):
print(data)
raise Exception('command failed')
return data[:-2]
+ def execfile(self, filename):
+ with open(filename) as f:
+ pyfile = f.read()
+ return self.exec(pyfile)
+
def get_time(self):
t = str(self.exec('pyb.time()'), encoding='ascii').strip().split()[1].split(':')
return int(t[0]) * 3600 + int(t[1]) * 60 + int(t[2])
+def execfile(filename, device='/dev/ttyACM0'):
+ pyb = Pyboard(device)
+ pyb.enter_raw_repl()
+ output = pyb.execfile(filename)
+ print(str(output, encoding='ascii'), end='')
+ pyb.exit_raw_repl()
+ pyb.close()
+
def run_test():
device = '/dev/ttyACM0'
pyb = Pyboard(device)
diff --git a/unix-cpy/mpconfigport.h b/unix-cpy/mpconfigport.h
index 6351f0c4f..752df4f49 100644
--- a/unix-cpy/mpconfigport.h
+++ b/unix-cpy/mpconfigport.h
@@ -3,6 +3,7 @@
#define MICROPY_EMIT_CPYTHON (1)
#define MICROPY_ENABLE_LEXER_UNIX (1)
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE)
+#define MICROPY_ENABLE_MOD_IO (0)
// type definitions for the specific machine
diff --git a/unix/Makefile b/unix/Makefile
index b0899ecac..ac1baf3d0 100644
--- a/unix/Makefile
+++ b/unix/Makefile
@@ -28,12 +28,12 @@ LDFLAGS_MOD += -lreadline
endif
ifeq ($(MICROPY_MOD_TIME),1)
CFLAGS_MOD += -DMICROPY_MOD_TIME=1
-SRC_MOD += time.c
+SRC_MOD += modtime.c
endif
ifeq ($(MICROPY_MOD_FFI),1)
CFLAGS_MOD += `pkg-config --cflags libffi` -DMICROPY_MOD_FFI=1
LDFLAGS_MOD += -ldl -lffi
-SRC_MOD += ffi.c
+SRC_MOD += modffi.c
endif
@@ -50,7 +50,7 @@ SRC_C = \
main.c \
gccollect.c \
file.c \
- socket.c \
+ modsocket.c \
$(SRC_MOD)
OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
diff --git a/unix/file.c b/unix/file.c
index bd54e7482..780e84718 100644
--- a/unix/file.c
+++ b/unix/file.c
@@ -17,14 +17,14 @@ typedef struct _mp_obj_fdfile_t {
int fd;
} mp_obj_fdfile_t;
-static const mp_obj_type_t rawfile_type;
+STATIC const mp_obj_type_t rawfile_type;
-static void fdfile_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+STATIC void fdfile_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
mp_obj_fdfile_t *self = self_in;
print(env, "<io.FileIO %d>", self->fd);
}
-static machine_int_t fdfile_read(mp_obj_t o_in, void *buf, machine_uint_t size, int *errcode) {
+STATIC machine_int_t fdfile_read(mp_obj_t o_in, void *buf, machine_uint_t size, int *errcode) {
mp_obj_fdfile_t *o = o_in;
machine_int_t r = read(o->fd, buf, size);
if (r == -1) {
@@ -33,7 +33,7 @@ static machine_int_t fdfile_read(mp_obj_t o_in, void *buf, machine_uint_t size,
return r;
}
-static machine_int_t fdfile_write(mp_obj_t o_in, const void *buf, machine_uint_t size, int *errcode) {
+STATIC machine_int_t fdfile_write(mp_obj_t o_in, const void *buf, machine_uint_t size, int *errcode) {
mp_obj_fdfile_t *o = o_in;
machine_int_t r = write(o->fd, buf, size);
if (r == -1) {
@@ -42,27 +42,32 @@ static machine_int_t fdfile_write(mp_obj_t o_in, const void *buf, machine_uint_t
return r;
}
-static mp_obj_t fdfile_close(mp_obj_t self_in) {
+STATIC mp_obj_t fdfile_close(mp_obj_t self_in) {
mp_obj_fdfile_t *self = self_in;
close(self->fd);
return mp_const_none;
}
-static MP_DEFINE_CONST_FUN_OBJ_1(fdfile_close_obj, fdfile_close);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(fdfile_close_obj, fdfile_close);
-static mp_obj_t fdfile_fileno(mp_obj_t self_in) {
+mp_obj_t fdfile___exit__(uint n_args, const mp_obj_t *args) {
+ return fdfile_close(args[0]);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fdfile___exit___obj, 4, 4, fdfile___exit__);
+
+STATIC mp_obj_t fdfile_fileno(mp_obj_t self_in) {
mp_obj_fdfile_t *self = self_in;
return MP_OBJ_NEW_SMALL_INT((machine_int_t)self->fd);
}
-static MP_DEFINE_CONST_FUN_OBJ_1(fdfile_fileno_obj, fdfile_fileno);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(fdfile_fileno_obj, fdfile_fileno);
-static mp_obj_fdfile_t *fdfile_new(int fd) {
+STATIC mp_obj_fdfile_t *fdfile_new(int fd) {
mp_obj_fdfile_t *o = m_new_obj(mp_obj_fdfile_t);
o->base.type = &rawfile_type;
o->fd = fd;
return o;
}
-static mp_obj_t fdfile_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
+STATIC mp_obj_t fdfile_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
mp_obj_fdfile_t *o = m_new_obj(mp_obj_fdfile_t);
o->base.type = type_in;
@@ -100,7 +105,7 @@ static mp_obj_t fdfile_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const
int fd = open(fname, mode, 0644);
if (fd == -1) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", errno));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", errno));
}
return fdfile_new(fd);
}
@@ -112,11 +117,13 @@ STATIC const mp_map_elem_t rawfile_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj},
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&fdfile_close_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR___enter__), (mp_obj_t)&mp_identity_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR___exit__), (mp_obj_t)&fdfile___exit___obj },
};
STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table);
-static const mp_obj_type_t rawfile_type = {
+STATIC const mp_obj_type_t rawfile_type = {
{ &mp_type_type },
.name = MP_QSTR_io_dot_FileIO,
.print = fdfile_print,
diff --git a/unix/gccollect.c b/unix/gccollect.c
index 450a69778..33748d240 100644
--- a/unix/gccollect.c
+++ b/unix/gccollect.c
@@ -78,9 +78,14 @@ void gc_collect(void) {
gc_collect_start();
// this traces .data and .bss sections
- extern char __bss_start, _end;
- //printf(".bss: %p-%p\n", &__bss_start, &_end);
- gc_collect_root((void**)&__bss_start, ((machine_uint_t)&_end - (machine_uint_t)&__bss_start) / sizeof(machine_uint_t));
+#ifdef __CYGWIN__
+#define BSS_START __bss_start__
+#else
+#define BSS_START __bss_start
+#endif
+ extern char BSS_START, _end;
+ //printf(".bss: %p-%p\n", &BSS_START, &_end);
+ gc_collect_root((void**)&BSS_START, ((machine_uint_t)&_end - (machine_uint_t)&BSS_START) / sizeof(machine_uint_t));
regs_t regs;
gc_helper_get_regs(regs);
// GC stack (and regs because we captured them)
diff --git a/unix/main.c b/unix/main.c
index 57eaa1997..b4a1646c2 100644
--- a/unix/main.c
+++ b/unix/main.c
@@ -6,6 +6,7 @@
#include <stdarg.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <errno.h>
#include "nlr.h"
#include "misc.h"
@@ -29,7 +30,8 @@
#if MICROPY_ENABLE_GC
// Heap size of GC heap (if enabled)
-long heap_size = 128*1024;
+// Make it larger on a 64 bit machine, because pointers are larger.
+long heap_size = 128*1024 * (sizeof(machine_uint_t) / 4);
#endif
// Stack top at the start of program
@@ -40,7 +42,7 @@ void microsocket_init();
void time_init();
void ffi_init();
-static void execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, bool is_repl) {
+STATIC void execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, bool is_repl) {
if (lex == NULL) {
return;
}
@@ -92,10 +94,10 @@ static void execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind
}
}
-static char *strjoin(const char *s1, int sep_char, const char *s2) {
+STATIC char *strjoin(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);
+ char *s = malloc(l1 + l2 + 2);
memcpy(s, s1, l1);
if (sep_char != 0) {
s[l1] = sep_char;
@@ -106,7 +108,7 @@ static char *strjoin(const char *s1, int sep_char, const char *s2) {
return s;
}
-static char *prompt(char *p) {
+STATIC char *prompt(char *p) {
#if MICROPY_USE_READLINE
char *line = readline(p);
if (line) {
@@ -131,7 +133,7 @@ static char *prompt(char *p) {
return line;
}
-static void do_repl(void) {
+STATIC void do_repl(void) {
for (;;) {
char *line = prompt(">>> ");
if (line == NULL) {
@@ -157,12 +159,12 @@ static void do_repl(void) {
}
}
-static void do_file(const char *file) {
+STATIC void do_file(const char *file) {
mp_lexer_t *lex = mp_lexer_new_from_file(file);
execute_from_lexer(lex, MP_PARSE_FILE_INPUT, false);
}
-static void do_str(const char *str) {
+STATIC void do_str(const char *str) {
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, str, strlen(str), false);
execute_from_lexer(lex, MP_PARSE_SINGLE_INPUT, false);
}
@@ -172,33 +174,33 @@ typedef struct _test_obj_t {
int value;
} test_obj_t;
-static void test_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+STATIC void test_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
test_obj_t *self = self_in;
print(env, "<test %d>", self->value);
}
-static mp_obj_t test_get(mp_obj_t self_in) {
+STATIC mp_obj_t test_get(mp_obj_t self_in) {
test_obj_t *self = self_in;
return mp_obj_new_int(self->value);
}
-static mp_obj_t test_set(mp_obj_t self_in, mp_obj_t arg) {
+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;
}
-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 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_map_elem_t test_locals_dict_table[] = {
+STATIC const mp_map_elem_t test_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_get), (mp_obj_t)&test_get_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_set), (mp_obj_t)&test_set_obj },
};
STATIC MP_DEFINE_CONST_DICT(test_locals_dict, test_locals_dict_table);
-static const mp_obj_type_t test_type = {
+STATIC const mp_obj_type_t test_type = {
{ &mp_type_type },
.name = MP_QSTR_Test,
.print = test_print,
@@ -212,13 +214,24 @@ mp_obj_t test_obj_new(int value) {
return o;
}
-int usage(void) {
+int usage(char **argv) {
printf(
-"usage: py [-X <opt>] [-c <command>] [<filename>]\n"
+"usage: %s [-X <opt>] [-c <command>] [<filename>]\n"
"\n"
-"Implementation specific options:\n"
+"Implementation specific options:\n", argv[0]
+);
+ int impl_opts_cnt = 0;
+#if MICROPY_ENABLE_GC
+ printf(
" heapsize=<n> -- set the heap size for the GC\n"
);
+ impl_opts_cnt++;
+#endif
+
+ if (impl_opts_cnt == 0) {
+ printf(" (none)\n");
+ }
+
return 1;
}
@@ -236,7 +249,7 @@ mp_obj_t qstr_info(void) {
#if MICROPY_ENABLE_GC
// TODO: this doesn't belong here
-static mp_obj_t pyb_gc(void) {
+STATIC mp_obj_t pyb_gc(void) {
gc_collect();
return mp_const_none;
}
@@ -249,7 +262,7 @@ void pre_process_options(int argc, char **argv) {
if (argv[a][0] == '-') {
if (strcmp(argv[a], "-X") == 0) {
if (a + 1 >= argc) {
- exit(usage());
+ exit(usage(argv));
}
if (0) {
#if MICROPY_ENABLE_GC
@@ -257,7 +270,7 @@ void pre_process_options(int argc, char **argv) {
heap_size = strtol(argv[a + 1] + sizeof("heapsize=") - 1, NULL, 0);
#endif
} else {
- exit(usage());
+ exit(usage(argv));
}
a++;
}
@@ -358,7 +371,7 @@ int main(int argc, char **argv) {
if (argv[a][0] == '-') {
if (strcmp(argv[a], "-c") == 0) {
if (a + 1 >= argc) {
- return usage();
+ return usage(argv);
}
do_str(argv[a + 1]);
executed = true;
@@ -366,16 +379,22 @@ int main(int argc, char **argv) {
} else if (strcmp(argv[a], "-X") == 0) {
a += 1;
} else {
- return usage();
+ return usage(argv);
}
} else {
- // Set base dir of the script as first entry in sys.path
char *basedir = realpath(argv[a], NULL);
- if (basedir != NULL) {
- char *p = strrchr(basedir, '/');
- path_items[0] = MP_OBJ_NEW_QSTR(qstr_from_strn(basedir, p - basedir));
- free(basedir);
+ if (basedir == NULL) {
+ fprintf(stderr, "%s: can't open file '%s': [Errno %d] ", argv[0], argv[1], errno);
+ perror("");
+ // CPython exits with 2 in such case
+ exit(2);
}
+
+ // Set base dir of the script as first entry in sys.path
+ char *p = strrchr(basedir, '/');
+ path_items[0] = MP_OBJ_NEW_QSTR(qstr_from_strn(basedir, p - basedir));
+ free(basedir);
+
for (int i = a; i < argc; i++) {
mp_obj_list_append(py_argv, MP_OBJ_NEW_QSTR(qstr_from_str(argv[i])));
}
diff --git a/unix/ffi.c b/unix/modffi.c
index cb63869e0..dd4c7012f 100644
--- a/unix/ffi.c
+++ b/unix/modffi.c
@@ -80,7 +80,7 @@ STATIC ffi_type *get_ffi_type(mp_obj_t o_in)
}
// TODO: Support actual libffi type objects
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Unknown type"));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Unknown type"));
}
STATIC mp_obj_t return_ffi_value(ffi_arg val, char type)
@@ -118,7 +118,7 @@ STATIC mp_obj_t ffimod_func(uint n_args, const mp_obj_t *args) {
void *sym = dlsym(self->handle, symname);
if (sym == NULL) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", errno));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", errno));
}
int nparams = MP_OBJ_SMALL_INT_VALUE(mp_obj_len_maybe(args[3]));
mp_obj_ffifunc_t *o = m_new_obj_var(mp_obj_ffifunc_t, ffi_type*, nparams);
@@ -136,7 +136,7 @@ STATIC mp_obj_t ffimod_func(uint n_args, const mp_obj_t *args) {
int res = ffi_prep_cif(&o->cif, FFI_DEFAULT_ABI, nparams, char2ffi_type(*rettype), o->params);
if (res != FFI_OK) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error in ffi_prep_cif"));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error in ffi_prep_cif"));
}
return o;
@@ -173,12 +173,12 @@ STATIC mp_obj_t mod_ffi_callback(mp_obj_t rettype_in, mp_obj_t func_in, mp_obj_t
int res = ffi_prep_cif(&o->cif, FFI_DEFAULT_ABI, nparams, char2ffi_type(*rettype), o->params);
if (res != FFI_OK) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error in ffi_prep_cif"));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error in ffi_prep_cif"));
}
res = ffi_prep_closure_loc(o->clo, &o->cif, call_py_func, func_in, o->func);
if (res != FFI_OK) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "ffi_prep_closure_loc"));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "ffi_prep_closure_loc"));
}
return o;
@@ -192,7 +192,7 @@ STATIC mp_obj_t ffimod_var(mp_obj_t self_in, mp_obj_t vartype_in, mp_obj_t symna
void *sym = dlsym(self->handle, symname);
if (sym == NULL) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", errno));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", errno));
}
mp_obj_ffivar_t *o = m_new_obj(mp_obj_ffivar_t);
o->base.type = &ffivar_type;
@@ -208,7 +208,7 @@ STATIC mp_obj_t ffimod_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const
void *mod = dlopen(fname, RTLD_NOW | RTLD_LOCAL);
if (mod == NULL) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", errno));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", errno));
}
mp_obj_ffimod_t *o = m_new_obj(mp_obj_ffimod_t);
o->base.type = type_in;
diff --git a/unix/socket.c b/unix/modsocket.c
index 915400e44..6bdbc889d 100644
--- a/unix/socket.c
+++ b/unix/modsocket.c
@@ -27,14 +27,14 @@ typedef struct _mp_obj_socket_t {
int fd;
} mp_obj_socket_t;
-static const mp_obj_type_t microsocket_type;
+STATIC const mp_obj_type_t microsocket_type;
// Helper functions
#define RAISE_ERRNO(err_flag, error_val) \
{ if (err_flag == -1) \
- { nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", error_val)); } }
+ { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", error_val)); } }
-static void get_buffer(mp_obj_t obj, buffer_info_t *bufinfo) {
+STATIC void 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) {
goto error;
@@ -46,10 +46,10 @@ static void get_buffer(mp_obj_t obj, buffer_info_t *bufinfo) {
return;
error:
- nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "Operation not supported"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "Operation not supported"));
}
-static mp_obj_socket_t *socket_new(int fd) {
+STATIC mp_obj_socket_t *socket_new(int fd) {
mp_obj_socket_t *o = m_new_obj(mp_obj_socket_t);
o->base.type = &microsocket_type;
o->fd = fd;
@@ -57,12 +57,12 @@ static mp_obj_socket_t *socket_new(int fd) {
}
-static void socket_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
+STATIC void socket_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
mp_obj_socket_t *self = self_in;
print(env, "<_socket %d>", self->fd);
}
-static machine_int_t socket_read(mp_obj_t o_in, void *buf, machine_uint_t size, int *errcode) {
+STATIC machine_int_t socket_read(mp_obj_t o_in, void *buf, machine_uint_t size, int *errcode) {
mp_obj_socket_t *o = o_in;
machine_int_t r = read(o->fd, buf, size);
if (r == -1) {
@@ -71,7 +71,7 @@ static machine_int_t socket_read(mp_obj_t o_in, void *buf, machine_uint_t size,
return r;
}
-static machine_int_t socket_write(mp_obj_t o_in, const void *buf, machine_uint_t size, int *errcode) {
+STATIC machine_int_t socket_write(mp_obj_t o_in, const void *buf, machine_uint_t size, int *errcode) {
mp_obj_socket_t *o = o_in;
machine_int_t r = write(o->fd, buf, size);
if (r == -1) {
@@ -80,20 +80,20 @@ static machine_int_t socket_write(mp_obj_t o_in, const void *buf, machine_uint_t
return r;
}
-static mp_obj_t socket_close(mp_obj_t self_in) {
+STATIC mp_obj_t socket_close(mp_obj_t self_in) {
mp_obj_socket_t *self = self_in;
close(self->fd);
return mp_const_none;
}
-static MP_DEFINE_CONST_FUN_OBJ_1(socket_close_obj, socket_close);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_close_obj, socket_close);
-static mp_obj_t socket_fileno(mp_obj_t self_in) {
+STATIC mp_obj_t socket_fileno(mp_obj_t self_in) {
mp_obj_socket_t *self = self_in;
return MP_OBJ_NEW_SMALL_INT((machine_int_t)self->fd);
}
-static MP_DEFINE_CONST_FUN_OBJ_1(socket_fileno_obj, socket_fileno);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_fileno_obj, socket_fileno);
-static mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
+STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
mp_obj_socket_t *self = self_in;
buffer_info_t bufinfo;
get_buffer(addr_in, &bufinfo);
@@ -101,9 +101,9 @@ static mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
RAISE_ERRNO(r, errno);
return mp_const_none;
}
-static MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect);
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect);
-static mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) {
+STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) {
mp_obj_socket_t *self = self_in;
buffer_info_t bufinfo;
get_buffer(addr_in, &bufinfo);
@@ -111,17 +111,17 @@ static mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) {
RAISE_ERRNO(r, errno);
return mp_const_none;
}
-static MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind);
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind);
-static mp_obj_t socket_listen(mp_obj_t self_in, mp_obj_t backlog_in) {
+STATIC mp_obj_t socket_listen(mp_obj_t self_in, mp_obj_t backlog_in) {
mp_obj_socket_t *self = self_in;
int r = listen(self->fd, MP_OBJ_SMALL_INT_VALUE(backlog_in));
RAISE_ERRNO(r, errno);
return mp_const_none;
}
-static MP_DEFINE_CONST_FUN_OBJ_2(socket_listen_obj, socket_listen);
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_listen_obj, socket_listen);
-static mp_obj_t socket_accept(mp_obj_t self_in) {
+STATIC mp_obj_t socket_accept(mp_obj_t self_in) {
mp_obj_socket_t *self = self_in;
struct sockaddr addr;
socklen_t addr_len = sizeof(addr);
@@ -134,9 +134,9 @@ static mp_obj_t socket_accept(mp_obj_t self_in) {
return t;
}
-static MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept);
-static mp_obj_t socket_recv(uint n_args, const mp_obj_t *args) {
+STATIC mp_obj_t socket_recv(uint n_args, const mp_obj_t *args) {
mp_obj_socket_t *self = args[0];
int sz = MP_OBJ_SMALL_INT_VALUE(args[1]);
int flags = 0;
@@ -152,9 +152,9 @@ static mp_obj_t socket_recv(uint n_args, const mp_obj_t *args) {
buf = m_realloc(buf, sz, out_sz);
return MP_OBJ_NEW_QSTR(qstr_from_strn_take(buf, out_sz, out_sz));
}
-static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_recv_obj, 2, 3, socket_recv);
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_recv_obj, 2, 3, socket_recv);
-static mp_obj_t socket_send(uint n_args, const mp_obj_t *args) {
+STATIC mp_obj_t socket_send(uint n_args, const mp_obj_t *args) {
mp_obj_socket_t *self = args[0];
int flags = 0;
@@ -169,9 +169,9 @@ static mp_obj_t socket_send(uint n_args, const mp_obj_t *args) {
return MP_OBJ_NEW_SMALL_INT((machine_int_t)out_sz);
}
-static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_send_obj, 2, 3, socket_send);
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_send_obj, 2, 3, socket_send);
-static mp_obj_t socket_setsockopt(uint n_args, const mp_obj_t *args) {
+STATIC mp_obj_t socket_setsockopt(uint n_args, const mp_obj_t *args) {
mp_obj_socket_t *self = args[0];
int level = MP_OBJ_SMALL_INT_VALUE(args[1]);
int option = mp_obj_get_int(args[2]);
@@ -192,9 +192,9 @@ static mp_obj_t socket_setsockopt(uint n_args, const mp_obj_t *args) {
RAISE_ERRNO(r, errno);
return mp_const_none;
}
-static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_setsockopt);
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_setsockopt);
-static mp_obj_t socket_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
+STATIC mp_obj_t socket_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
int family = AF_INET;
int type = SOCK_STREAM;
int proto = 0;
@@ -217,7 +217,7 @@ static mp_obj_t socket_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const
return socket_new(fd);
}
-static const mp_map_elem_t microsocket_locals_dict_table[] = {
+STATIC const mp_map_elem_t microsocket_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_fileno), (mp_obj_t)&socket_fileno_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_makefile), (mp_obj_t)&mp_identity_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
@@ -240,7 +240,7 @@ static const mp_map_elem_t microsocket_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(microsocket_locals_dict, microsocket_locals_dict_table);
-static const mp_obj_type_t microsocket_type = {
+STATIC const mp_obj_type_t microsocket_type = {
{ &mp_type_type },
.name = MP_QSTR_socket,
.print = socket_print,
@@ -254,38 +254,38 @@ static const mp_obj_type_t microsocket_type = {
.locals_dict = (mp_obj_t)&microsocket_locals_dict,
};
-static mp_obj_t mod_socket_htons(mp_obj_t arg) {
+STATIC mp_obj_t mod_socket_htons(mp_obj_t arg) {
return MP_OBJ_NEW_SMALL_INT((machine_int_t)htons(MP_OBJ_SMALL_INT_VALUE(arg)));
}
-static MP_DEFINE_CONST_FUN_OBJ_1(mod_socket_htons_obj, mod_socket_htons);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_socket_htons_obj, mod_socket_htons);
-static mp_obj_t mod_socket_inet_aton(mp_obj_t arg) {
+STATIC mp_obj_t mod_socket_inet_aton(mp_obj_t arg) {
assert(MP_OBJ_IS_TYPE(arg, &mp_type_str));
const char *s = mp_obj_str_get_str(arg);
struct in_addr addr;
if (!inet_aton(s, &addr)) {
- nlr_jump(mp_obj_new_exception_msg(&mp_type_OSError, "Invalid IP address"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Invalid IP address"));
}
return mp_obj_new_int(addr.s_addr);
}
-static MP_DEFINE_CONST_FUN_OBJ_1(mod_socket_inet_aton_obj, mod_socket_inet_aton);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_socket_inet_aton_obj, mod_socket_inet_aton);
#if MICROPY_SOCKET_EXTRA
-static mp_obj_t mod_socket_gethostbyname(mp_obj_t arg) {
+STATIC mp_obj_t mod_socket_gethostbyname(mp_obj_t arg) {
assert(MP_OBJ_IS_TYPE(arg, &mp_type_str));
const char *s = mp_obj_str_get_str(arg);
struct hostent *h = gethostbyname(s);
if (h == NULL) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", errno));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", errno));
}
assert(h->h_length == 4);
return mp_obj_new_int(*(int*)*h->h_addr_list);
}
-static MP_DEFINE_CONST_FUN_OBJ_1(mod_socket_gethostbyname_obj, mod_socket_gethostbyname);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_socket_gethostbyname_obj, mod_socket_gethostbyname);
#endif
-static mp_obj_t mod_socket_getaddrinfo(uint n_args, const mp_obj_t *args) {
+STATIC mp_obj_t mod_socket_getaddrinfo(uint n_args, const mp_obj_t *args) {
// TODO: Implement all args
assert(n_args == 2);
assert(MP_OBJ_IS_STR(args[0]));
@@ -309,7 +309,7 @@ static mp_obj_t mod_socket_getaddrinfo(uint n_args, const mp_obj_t *args) {
int res = getaddrinfo(host, serv, NULL/*&hints*/, &addr);
if (res != 0) {
- nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[addrinfo error %d]", res));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[addrinfo error %d]", res));
}
assert(addr);
@@ -331,13 +331,13 @@ static mp_obj_t mod_socket_getaddrinfo(uint n_args, const mp_obj_t *args) {
}
return list;
}
-static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_socket_getaddrinfo_obj, 2, 6, mod_socket_getaddrinfo);
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_socket_getaddrinfo_obj, 2, 6, mod_socket_getaddrinfo);
extern mp_obj_type_t sockaddr_in_type;
#define C(name) { #name, name }
-static const struct sym_entry {
+STATIC const struct sym_entry {
const char *sym;
int val;
} constants[] = {
diff --git a/unix/time.c b/unix/modtime.c
index fb5213358..032528947 100644
--- a/unix/time.c
+++ b/unix/modtime.c
@@ -10,13 +10,13 @@
#include "obj.h"
#include "runtime.h"
-static mp_obj_t mod_time_time() {
+STATIC mp_obj_t mod_time_time() {
return mp_obj_new_int((machine_int_t)time(NULL));
}
-static MP_DEFINE_CONST_FUN_OBJ_0(mod_time_time_obj, mod_time_time);
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_time_time_obj, mod_time_time);
// Note: this is deprecated since CPy3.3, but pystone still uses it.
-static mp_obj_t mod_time_clock() {
+STATIC mp_obj_t mod_time_clock() {
// return mp_obj_new_int((machine_int_t)clock());
// POSIX requires CLOCKS_PER_SEC equals 1000000, so that's what we assume
// float cannot represent full range of int32 precisely, so we pre-divide
@@ -24,9 +24,9 @@ static mp_obj_t mod_time_clock() {
// to preserve integer part resolution.
return mp_obj_new_float((float)(clock() / 1000) / 1000.0);
}
-static MP_DEFINE_CONST_FUN_OBJ_0(mod_time_clock_obj, mod_time_clock);
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_time_clock_obj, mod_time_clock);
-static mp_obj_t mod_time_sleep(mp_obj_t arg) {
+STATIC mp_obj_t mod_time_sleep(mp_obj_t arg) {
#if MICROPY_ENABLE_FLOAT
struct timeval tv;
mp_float_t val = mp_obj_get_float(arg);
@@ -39,7 +39,7 @@ static mp_obj_t mod_time_sleep(mp_obj_t arg) {
#endif
return mp_const_none;
}
-static MP_DEFINE_CONST_FUN_OBJ_1(mod_time_sleep_obj, mod_time_sleep);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_time_sleep_obj, mod_time_sleep);
void time_init() {
mp_obj_t m = mp_obj_new_module(QSTR_FROM_STR_STATIC("time"));
diff --git a/unix/mpconfigport.h b/unix/mpconfigport.h
index 8950337d4..254d14d98 100644
--- a/unix/mpconfigport.h
+++ b/unix/mpconfigport.h
@@ -3,6 +3,7 @@
#define MICROPY_EMIT_X64 (1)
#define MICROPY_EMIT_THUMB (0)
#define MICROPY_EMIT_INLINE_THUMB (0)
+#define MICROPY_ENABLE_GC (1)
#define MICROPY_MEM_STATS (1)
#define MICROPY_DEBUG_PRINTERS (1)
#define MICROPY_ENABLE_REPL_HELPERS (1)