diff --git a/py/builtinmath.c b/py/builtinmath.c index 59af5a021d..818ac1d9dd 100644 --- a/py/builtinmath.c +++ b/py/builtinmath.c @@ -9,6 +9,7 @@ #if MICROPY_ENABLE_FLOAT +//TODO: Change macros to check for overflow and raise OverflowError or RangeError #define MATH_FUN_1(py_name, c_name) \ mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { return mp_obj_new_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj))); } \ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name); @@ -17,6 +18,10 @@ mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj, mp_obj_t y_obj) { return mp_obj_new_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj), mp_obj_get_float(y_obj))); } \ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_math_## py_name ## _obj, mp_math_ ## py_name); +#define MATH_FUN_BOOL1(py_name, c_name) \ + mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { return MP_BOOL(c_name(mp_obj_get_float(x_obj))); } \ + STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name); + STATIC const mp_obj_float_t mp_math_e_obj = {{&mp_type_float}, M_E}; STATIC const mp_obj_float_t mp_math_pi_obj = {{&mp_type_float}, M_PI}; @@ -45,13 +50,49 @@ MATH_FUN_2(copysign, copysign) MATH_FUN_1(fabs, fabs) MATH_FUN_1(floor, floor) //TODO: delegate to x.__floor__() if x is not a float MATH_FUN_2(fmod, fmod) -//MATH_FUN_1(frexp, frexp) -//MATH_FUN_1(isfinite, isfinite) -//MATH_FUN_1(isinf, isinf) -//MATH_FUN_1(isnan, isnan) +MATH_FUN_BOOL1(isfinite, isfinite) +MATH_FUN_BOOL1(isinf, isinf) +MATH_FUN_BOOL1(isnan, isnan) MATH_FUN_1(trunc, trunc) +MATH_FUN_2(ldexp, ldexp) +MATH_FUN_1(erf, erf) +MATH_FUN_1(erfc, erfc) +MATH_FUN_1(gamma, gamma) +MATH_FUN_1(lgamma, lgamma) +//TODO: factorial, fsum + +// Functions that return a tuple +mp_obj_t mp_math_frexp(mp_obj_t x_obj){ + machine_int_t int_exponent = 0; + mp_float_t significand = frexp(mp_obj_get_float(x_obj), &int_exponent); + mp_obj_t tuple[2]; + tuple[0] = mp_obj_new_float(significand); + tuple[1] = mp_obj_new_int(int_exponent); + return mp_obj_new_tuple(2, tuple); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_frexp_obj, mp_math_frexp); + +mp_obj_t mp_math_modf(mp_obj_t x_obj){ + mp_float_t int_part = 0.0; + mp_float_t fractional_part = modf(mp_obj_get_float(x_obj), &int_part); + mp_obj_t tuple[2]; + tuple[0] = mp_obj_new_float(fractional_part); + tuple[1] = mp_obj_new_float(int_part); + return mp_obj_new_tuple(2, tuple); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_modf_obj, mp_math_modf); + +// Angular conversions +mp_obj_t mp_math_radians(mp_obj_t x_obj){ + return mp_obj_new_float(mp_obj_get_float(x_obj) * M_PI / 180.0); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_radians_obj, mp_math_radians); + +mp_obj_t mp_math_degrees(mp_obj_t x_obj){ + return mp_obj_new_float(mp_obj_get_float(x_obj) * 180.0 / M_PI); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_degrees_obj, mp_math_degrees); -//TODO: factorial, fsum, frexp, ldexp, modf STATIC const mp_map_elem_t mp_module_math_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_math) }, @@ -81,12 +122,19 @@ STATIC const mp_map_elem_t mp_module_math_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_copysign), (mp_obj_t)&mp_math_copysign_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_fabs), (mp_obj_t)&mp_math_fabs_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_floor), (mp_obj_t)&mp_math_floor_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_fmod), (mp_obj_t)&mp_math_fmod_obj }, - //{ MP_OBJ_NEW_QSTR(MP_QSTR_frexp), (mp_obj_t)&mp_math_frexp_obj }, - //{ MP_OBJ_NEW_QSTR(MP_QSTR_isfinite), (mp_obj_t)&mp_math_isfinite_obj }, - //{ MP_OBJ_NEW_QSTR(MP_QSTR_isinf), (mp_obj_t)&mp_math_isinf_obj }, - //{ MP_OBJ_NEW_QSTR(MP_QSTR_isnan), (mp_obj_t)&mp_math_isnan_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_frexp), (mp_obj_t)&mp_math_frexp_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ldexp), (mp_obj_t)&mp_math_ldexp_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_modf), (mp_obj_t)&mp_math_modf_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_isfinite), (mp_obj_t)&mp_math_isfinite_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_isinf), (mp_obj_t)&mp_math_isinf_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_isnan), (mp_obj_t)&mp_math_isnan_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_trunc), (mp_obj_t)&mp_math_trunc_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_radians), (mp_obj_t)&mp_math_radians_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_degrees), (mp_obj_t)&mp_math_degrees_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_erf), (mp_obj_t)&mp_math_erf_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_erfc), (mp_obj_t)&mp_math_erfc_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_gamma), (mp_obj_t)&mp_math_gamma_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_lgamma), (mp_obj_t)&mp_math_lgamma_obj }, }; STATIC const mp_map_t mp_module_math_globals = { diff --git a/py/compile.c b/py/compile.c index bb688d5d8e..0a10b81768 100644 --- a/py/compile.c +++ b/py/compile.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "misc.h" #include "mpconfig.h" @@ -15,6 +16,7 @@ #include "obj.h" #include "compile.h" #include "runtime.h" +#include "intdivmod.h" // TODO need to mangle __attr names @@ -140,11 +142,13 @@ mp_parse_node_t fold_constants(mp_parse_node_t pn) { } 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)) { - // XXX implement this properly as Python's % operator acts differently to C's - pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 % arg1); + pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, python_modulo(arg0, arg1)); } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_SLASH)) { - // XXX implement this properly as Python's // operator acts differently to C's - pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 / arg1); + //pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, + // floor((mp_float_t)arg0 / arg1)); + pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, + python_floor_divide(arg0, arg1)); + } else { // shouldn't happen assert(0); diff --git a/py/obj.h b/py/obj.h index 1daa943447..3217c4a4d1 100644 --- a/py/obj.h +++ b/py/obj.h @@ -184,9 +184,53 @@ struct _mp_obj_type_t { typedef struct _mp_obj_type_t mp_obj_type_t; // Constant types, globally accessible - extern const mp_obj_type_t mp_type_type; + +// Exceptions extern const mp_obj_type_t mp_type_BaseException; +extern const mp_obj_type_t mp_type_ArithmeticError; +extern const mp_obj_type_t mp_type_AssertionError; +extern const mp_obj_type_t mp_type_AttributeError; +extern const mp_obj_type_t mp_type_BufferError; +extern const mp_obj_type_t mp_type_BytesWarning; +extern const mp_obj_type_t mp_type_DeprecationWarning; +extern const mp_obj_type_t mp_type_EOFError; +extern const mp_obj_type_t mp_type_EnvironmentError; +extern const mp_obj_type_t mp_type_Exception; +extern const mp_obj_type_t mp_type_FloatingPointError; +extern const mp_obj_type_t mp_type_FutureWarning; +extern const mp_obj_type_t mp_type_GeneratorExit; +extern const mp_obj_type_t mp_type_IOError; +extern const mp_obj_type_t mp_type_ImportError; +extern const mp_obj_type_t mp_type_ImportWarning; +extern const mp_obj_type_t mp_type_IndentationError; +extern const mp_obj_type_t mp_type_IndexError; +extern const mp_obj_type_t mp_type_KeyError; +extern const mp_obj_type_t mp_type_LookupError; +extern const mp_obj_type_t mp_type_MemoryError; +extern const mp_obj_type_t mp_type_NameError; +extern const mp_obj_type_t mp_type_NotImplementedError; +extern const mp_obj_type_t mp_type_OSError; +extern const mp_obj_type_t mp_type_OverflowError; +extern const mp_obj_type_t mp_type_PendingDeprecationWarning; +extern const mp_obj_type_t mp_type_ReferenceError; +extern const mp_obj_type_t mp_type_ResourceWarning; +extern const mp_obj_type_t mp_type_RuntimeError; +extern const mp_obj_type_t mp_type_RuntimeWarning; +extern const mp_obj_type_t mp_type_SyntaxError; +extern const mp_obj_type_t mp_type_SyntaxWarning; +extern const mp_obj_type_t mp_type_SystemError; +extern const mp_obj_type_t mp_type_SystemExit; +extern const mp_obj_type_t mp_type_TabError; +extern const mp_obj_type_t mp_type_TypeError; +extern const mp_obj_type_t mp_type_UnboundLocalError; +extern const mp_obj_type_t mp_type_UserWarning; +extern const mp_obj_type_t mp_type_ValueError; +extern const mp_obj_type_t mp_type_Warning; +extern const mp_obj_type_t mp_type_ZeroDivisionError; + +extern const mp_obj_type_t mp_type_StopIteration; +/*extern const mp_obj_type_t mp_type_BaseException; extern const mp_obj_type_t mp_type_AssertionError; extern const mp_obj_type_t mp_type_AttributeError; extern const mp_obj_type_t mp_type_ImportError; @@ -201,6 +245,7 @@ extern const mp_obj_type_t mp_type_OverflowError; extern const mp_obj_type_t mp_type_OSError; extern const mp_obj_type_t mp_type_NotImplementedError; extern const mp_obj_type_t mp_type_StopIteration; +extern const mp_obj_type_t mp_type_ZeroDivisionError;*/ // Constant objects, globally accessible diff --git a/py/objexcept.c b/py/objexcept.c index 11177724da..7fd783b3a4 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -77,22 +77,78 @@ const mp_obj_type_t mp_type_ ## exc_name = { \ .bases_tuple = (mp_obj_t)&mp_type_ ## base_name ## _base_tuple, \ }; +// List of all exceptions, arranged as in the table at: +// http://docs.python.org/3.3/library/exceptions.html MP_DEFINE_EXCEPTION_BASE(BaseException) - -MP_DEFINE_EXCEPTION(AssertionError, BaseException) -MP_DEFINE_EXCEPTION(AttributeError, BaseException) -MP_DEFINE_EXCEPTION(ImportError, BaseException) -MP_DEFINE_EXCEPTION(IndentationError, BaseException) -MP_DEFINE_EXCEPTION(IndexError, BaseException) -MP_DEFINE_EXCEPTION(KeyError, BaseException) -MP_DEFINE_EXCEPTION(NameError, BaseException) -MP_DEFINE_EXCEPTION(SyntaxError, BaseException) -MP_DEFINE_EXCEPTION(TypeError, BaseException) -MP_DEFINE_EXCEPTION(ValueError, BaseException) -MP_DEFINE_EXCEPTION(OverflowError, BaseException) -MP_DEFINE_EXCEPTION(OSError, BaseException) -MP_DEFINE_EXCEPTION(NotImplementedError, BaseException) -MP_DEFINE_EXCEPTION(StopIteration, BaseException) +MP_DEFINE_EXCEPTION(SystemExit, BaseException) +//MP_DEFINE_EXCEPTION(KeyboardInterrupt, BaseException) +MP_DEFINE_EXCEPTION(GeneratorExit, BaseException) +MP_DEFINE_EXCEPTION(Exception, BaseException) + MP_DEFINE_EXCEPTION_BASE(Exception) + MP_DEFINE_EXCEPTION(StopIteration, Exception) + MP_DEFINE_EXCEPTION(ArithmeticError, Exception) + MP_DEFINE_EXCEPTION_BASE(ArithmeticError) + MP_DEFINE_EXCEPTION(FloatingPointError, ArithmeticError) + MP_DEFINE_EXCEPTION(OverflowError, ArithmeticError) + MP_DEFINE_EXCEPTION(ZeroDivisionError, ArithmeticError) + MP_DEFINE_EXCEPTION(AssertionError, Exception) + MP_DEFINE_EXCEPTION(AttributeError, Exception) + MP_DEFINE_EXCEPTION(BufferError, Exception) + MP_DEFINE_EXCEPTION(EnvironmentError, Exception) + MP_DEFINE_EXCEPTION(EOFError, Exception) + MP_DEFINE_EXCEPTION(ImportError, Exception) + MP_DEFINE_EXCEPTION(IOError, Exception) + MP_DEFINE_EXCEPTION(LookupError, Exception) + MP_DEFINE_EXCEPTION_BASE(LookupError) + MP_DEFINE_EXCEPTION(IndexError, LookupError) + MP_DEFINE_EXCEPTION(KeyError, LookupError) + MP_DEFINE_EXCEPTION(MemoryError, Exception) + MP_DEFINE_EXCEPTION(NameError, Exception) + MP_DEFINE_EXCEPTION_BASE(NameError) + MP_DEFINE_EXCEPTION(UnboundLocalError, NameError) + MP_DEFINE_EXCEPTION(OSError, Exception) + // Probably don't need these + /*MP_DEFINE_EXCEPTION_BASE(OSError) + MP_DEFINE_EXCEPTION(BlockingIOError, OSError) + MP_DEFINE_EXCEPTION(ChildProcessError, OSError) + MP_DEFINE_EXCEPTION(ConnectionError, OSError) + MP_DEFINE_EXCEPTION(BrokenPipeError, ConnectionError) + MP_DEFINE_EXCEPTION(ConnectionAbortedError, ConnectionError) + MP_DEFINE_EXCEPTION(ConnectionRefusedError, ConnectionError) + MP_DEFINE_EXCEPTION(ConnectionResetError, ConnectionError) + MP_DEFINE_EXCEPTION(FileExistsError, OSError) + MP_DEFINE_EXCEPTION(FileNotFoundError, OSError) + MP_DEFINE_EXCEPTION(InterruptedError, OSError) + MP_DEFINE_EXCEPTION(IsADirectoryError, OSError) + MP_DEFINE_EXCEPTION(NotADirectoryError, OSError) + MP_DEFINE_EXCEPTION(PermissionError, OSError) + MP_DEFINE_EXCEPTION(ProcessLookupError, OSError) + MP_DEFINE_EXCEPTION(TimeoutError, OSError)*/ + MP_DEFINE_EXCEPTION(ReferenceError, Exception) + MP_DEFINE_EXCEPTION(RuntimeError, Exception) + MP_DEFINE_EXCEPTION_BASE(RuntimeError) + MP_DEFINE_EXCEPTION(NotImplementedError, RuntimeError) + MP_DEFINE_EXCEPTION(SyntaxError, Exception) + MP_DEFINE_EXCEPTION_BASE(SyntaxError) + MP_DEFINE_EXCEPTION(IndentationError, SyntaxError) + MP_DEFINE_EXCEPTION_BASE(IndentationError) + MP_DEFINE_EXCEPTION(TabError, IndentationError) + MP_DEFINE_EXCEPTION(SystemError, Exception) + MP_DEFINE_EXCEPTION(TypeError, Exception) + MP_DEFINE_EXCEPTION(ValueError, Exception) + //TODO: Implement UnicodeErrors which take arguments + MP_DEFINE_EXCEPTION(Warning, Exception) + MP_DEFINE_EXCEPTION_BASE(Warning) + MP_DEFINE_EXCEPTION(DeprecationWarning, Warning) + MP_DEFINE_EXCEPTION(PendingDeprecationWarning, Warning) + MP_DEFINE_EXCEPTION(RuntimeWarning, Warning) + MP_DEFINE_EXCEPTION(SyntaxWarning, Warning) + MP_DEFINE_EXCEPTION(UserWarning, Warning) + MP_DEFINE_EXCEPTION(FutureWarning, Warning) + MP_DEFINE_EXCEPTION(ImportWarning, Warning) + MP_DEFINE_EXCEPTION(UnicodeWarning, Warning) + MP_DEFINE_EXCEPTION(BytesWarning, Warning) + MP_DEFINE_EXCEPTION(ResourceWarning, Warning) mp_obj_t mp_obj_new_exception(const mp_obj_type_t *exc_type) { return mp_obj_new_exception_msg_varg(exc_type, NULL); diff --git a/py/objfloat.c b/py/objfloat.c index c51e13e7a1..c4567c4a38 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -1,5 +1,6 @@ #include #include +#include #include "nlr.h" #include "misc.h" @@ -107,8 +108,12 @@ mp_obj_t mp_obj_float_binary_op(int op, mp_float_t lhs_val, mp_obj_t rhs_in) { case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: val = lhs_val / rhs_val; break; */ case RT_BINARY_OP_TRUE_DIVIDE: - case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: lhs_val /= rhs_val; break; - + case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: + lhs_val /= rhs_val; + if (isinf(lhs_val)){ // check for division by zero + nlr_jump(mp_obj_new_exception_msg(&mp_type_ZeroDivisionError, "float division by zero")); + } + break; case RT_BINARY_OP_LESS: return MP_BOOL(lhs_val < rhs_val); case RT_BINARY_OP_MORE: return MP_BOOL(lhs_val > rhs_val); case RT_BINARY_OP_LESS_EQUAL: return MP_BOOL(lhs_val <= rhs_val); diff --git a/py/objint_mpz.c b/py/objint_mpz.c index 21e3202a95..39ea7ca115 100644 --- a/py/objint_mpz.c +++ b/py/objint_mpz.c @@ -1,5 +1,6 @@ #include #include +#include #include "nlr.h" #include "misc.h" @@ -97,15 +98,24 @@ mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { case RT_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 (!mpz_is_zero(&rem)) { + mpz_t mpzone; mpz_init_from_int(&mpzone, -1); + mpz_add_inpl(&res->mpz, &res->mpz, &mpzone); + } + } mpz_deinit(&rem); break; } case RT_BINARY_OP_MODULO: case RT_BINARY_OP_INPLACE_MODULO: { - // TODO check that this operation matches the CPython operation 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) { + mpz_add_inpl(&res->mpz, &res->mpz, zrhs); + } break; } diff --git a/py/py.mk b/py/py.mk index 0814176815..add871632f 100644 --- a/py/py.mk +++ b/py/py.mk @@ -78,6 +78,7 @@ PY_O_BASENAME = \ vm.o \ showbc.o \ repl.o \ + intdivmod.o \ # prepend the build destination prefix to the py object files PY_O = $(addprefix $(PY_BUILD)/, $(PY_O_BASENAME)) diff --git a/py/qstrdefs.h b/py/qstrdefs.h index 649f89eb1e..96d94d937d 100644 --- a/py/qstrdefs.h +++ b/py/qstrdefs.h @@ -34,19 +34,63 @@ Q(Ellipsis) Q(StopIteration) Q(BaseException) +Q(ArithmeticError) Q(AssertionError) Q(AttributeError) +Q(BlockingIOError) +Q(BrokenPipeError) +Q(BufferError) +Q(BytesWarning) +Q(ChildProcessError) +Q(ConnectionAbortedError) +Q(ConnectionError) +Q(ConnectionRefusedError) +Q(ConnectionResetError) +Q(DeprecationWarning) +Q(EOFError) +Q(EnvironmentError) +Q(Exception) +Q(FileExistsError) +Q(FileNotFoundError) +Q(FloatingPointError) +Q(FutureWarning) +Q(GeneratorExit) +Q(IOError) Q(ImportError) +Q(ImportWarning) Q(IndentationError) Q(IndexError) +Q(InterruptedError) +Q(IsADirectoryError) Q(KeyError) +Q(LookupError) +Q(MemoryError) Q(NameError) +Q(NotADirectoryError) Q(NotImplementedError) Q(OSError) -Q(SyntaxError) -Q(TypeError) -Q(ValueError) Q(OverflowError) +Q(PendingDeprecationWarning) +Q(PermissionError) +Q(ProcessLookupError) +Q(ReferenceError) +Q(ResourceWarning) +Q(RuntimeError) +Q(RuntimeWarning) +Q(SyntaxError) +Q(SyntaxWarning) +Q(SystemError) +Q(SystemExit) +Q(TabError) +Q(TimeoutError) +Q(TypeError) +Q(UnboundLocalError) +Q(UnicodeWarning) +Q(UserWarning) +Q(ValueError) +Q(Warning) +Q(ZeroDivisionError) + Q(NoneType) @@ -144,13 +188,21 @@ Q(atan2) Q(ceil) Q(copysign) Q(fabs) -Q(floor) Q(fmod) -Q(frexp) +Q(floor) Q(isfinite) Q(isinf) Q(isnan) Q(trunc) +Q(modf) +Q(frexp) +Q(ldexp) +Q(degrees) +Q(radians) +Q(erf) +Q(erfc) +Q(gamma) +Q(lgamma) Q(mem_total) Q(mem_current) diff --git a/py/runtime.c b/py/runtime.c index 4bcb91c547..94f3190566 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "nlr.h" #include "misc.h" @@ -18,6 +19,7 @@ #include "builtin.h" #include "objarray.h" #include "bc.h" +#include "intdivmod.h" #if 0 // print debugging info #define DEBUG_PRINT (1) @@ -142,22 +144,49 @@ STATIC const mp_builtin_elem_t builtin_table[] = { // built-in exceptions { MP_QSTR_BaseException, (mp_obj_t)&mp_type_BaseException }, + { MP_QSTR_ArithmeticError, (mp_obj_t)&mp_type_ArithmeticError }, { MP_QSTR_AssertionError, (mp_obj_t)&mp_type_AssertionError }, { MP_QSTR_AttributeError, (mp_obj_t)&mp_type_AttributeError }, + { MP_QSTR_BufferError, (mp_obj_t)&mp_type_BufferError }, + { MP_QSTR_BytesWarning, (mp_obj_t)&mp_type_BytesWarning }, + { MP_QSTR_DeprecationWarning, (mp_obj_t)&mp_type_DeprecationWarning }, + { MP_QSTR_EOFError, (mp_obj_t)&mp_type_EOFError }, + { MP_QSTR_EnvironmentError, (mp_obj_t)&mp_type_EnvironmentError }, + { MP_QSTR_Exception, (mp_obj_t)&mp_type_Exception }, + { MP_QSTR_FloatingPointError, (mp_obj_t)&mp_type_FloatingPointError }, + { MP_QSTR_FutureWarning, (mp_obj_t)&mp_type_FutureWarning }, + { MP_QSTR_GeneratorExit, (mp_obj_t)&mp_type_GeneratorExit }, + { MP_QSTR_IOError, (mp_obj_t)&mp_type_IOError }, { MP_QSTR_ImportError, (mp_obj_t)&mp_type_ImportError }, + { MP_QSTR_ImportWarning, (mp_obj_t)&mp_type_ImportWarning }, { MP_QSTR_IndentationError, (mp_obj_t)&mp_type_IndentationError }, { MP_QSTR_IndexError, (mp_obj_t)&mp_type_IndexError }, { MP_QSTR_KeyError, (mp_obj_t)&mp_type_KeyError }, + { MP_QSTR_LookupError, (mp_obj_t)&mp_type_LookupError }, + { MP_QSTR_MemoryError, (mp_obj_t)&mp_type_MemoryError }, { MP_QSTR_NameError, (mp_obj_t)&mp_type_NameError }, + { MP_QSTR_NotImplementedError, (mp_obj_t)&mp_type_NotImplementedError }, + { MP_QSTR_OSError, (mp_obj_t)&mp_type_OSError }, + { MP_QSTR_OverflowError, (mp_obj_t)&mp_type_OverflowError }, + { MP_QSTR_PendingDeprecationWarning, (mp_obj_t)&mp_type_PendingDeprecationWarning }, + { MP_QSTR_ReferenceError, (mp_obj_t)&mp_type_ReferenceError }, + { MP_QSTR_ResourceWarning, (mp_obj_t)&mp_type_ResourceWarning }, + { MP_QSTR_RuntimeError, (mp_obj_t)&mp_type_RuntimeError }, + { MP_QSTR_RuntimeWarning, (mp_obj_t)&mp_type_RuntimeWarning }, { MP_QSTR_SyntaxError, (mp_obj_t)&mp_type_SyntaxError }, + { MP_QSTR_SyntaxWarning, (mp_obj_t)&mp_type_SyntaxWarning }, + { MP_QSTR_SystemError, (mp_obj_t)&mp_type_SystemError }, + { MP_QSTR_SystemExit, (mp_obj_t)&mp_type_SystemExit }, + { MP_QSTR_TabError, (mp_obj_t)&mp_type_TabError }, { MP_QSTR_TypeError, (mp_obj_t)&mp_type_TypeError }, + { MP_QSTR_UnboundLocalError, (mp_obj_t)&mp_type_UnboundLocalError }, + { MP_QSTR_UserWarning, (mp_obj_t)&mp_type_UserWarning }, { MP_QSTR_ValueError, (mp_obj_t)&mp_type_ValueError }, + { MP_QSTR_Warning, (mp_obj_t)&mp_type_Warning }, + { MP_QSTR_ZeroDivisionError, (mp_obj_t)&mp_type_ZeroDivisionError }, + { MP_QSTR_StopIteration, (mp_obj_t)&mp_type_StopIteration }, // Somehow CPython managed to have OverflowError not inherit from ValueError ;-/ // TODO: For MICROPY_CPYTHON_COMPAT==0 use ValueError to avoid exc proliferation - { MP_QSTR_OverflowError, (mp_obj_t)&mp_type_OverflowError }, - { MP_QSTR_OSError, (mp_obj_t)&mp_type_OSError }, - { MP_QSTR_NotImplementedError, (mp_obj_t)&mp_type_NotImplementedError }, - { MP_QSTR_StopIteration, (mp_obj_t)&mp_type_StopIteration }, // Extra builtins as defined by a port MICROPY_EXTRA_BUILTINS @@ -633,16 +662,22 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { break; } case RT_BINARY_OP_FLOOR_DIVIDE: - case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: lhs_val /= rhs_val; break; + case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: + { + lhs_val = python_floor_divide(lhs_val, rhs_val); + break; + } #if MICROPY_ENABLE_FLOAT case RT_BINARY_OP_TRUE_DIVIDE: case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: return mp_obj_new_float((mp_float_t)lhs_val / (mp_float_t)rhs_val); #endif - // TODO implement modulo as specified by Python case RT_BINARY_OP_MODULO: - case RT_BINARY_OP_INPLACE_MODULO: lhs_val %= rhs_val; break; - + case RT_BINARY_OP_INPLACE_MODULO: + { + lhs_val = python_modulo(lhs_val, rhs_val); + break; + } case RT_BINARY_OP_POWER: case RT_BINARY_OP_INPLACE_POWER: if (rhs_val < 0) { diff --git a/tests/basics/exceptpoly.py b/tests/basics/exceptpoly.py new file mode 100644 index 0000000000..0e5ac2d1a3 --- /dev/null +++ b/tests/basics/exceptpoly.py @@ -0,0 +1,380 @@ +try: + raise ArithmeticError +except Exception: + print("Caught ArithmeticError via Exception") + +try: + raise ArithmeticError +except ArithmeticError: + print("Caught ArithmeticError") + +try: + raise AssertionError +except Exception: + print("Caught AssertionError via Exception") + +try: + raise AssertionError +except AssertionError: + print("Caught AssertionError") + +try: + raise AttributeError +except Exception: + print("Caught AttributeError via Exception") + +try: + raise AttributeError +except AttributeError: + print("Caught AttributeError") + +try: + raise BufferError +except Exception: + print("Caught BufferError via Exception") + +try: + raise BufferError +except BufferError: + print("Caught BufferError") + +try: + raise BytesWarning +except Warning: + print("Caught BytesWarning via Warning") + +try: + raise BytesWarning +except BytesWarning: + print("Caught BytesWarning") + +try: + raise DeprecationWarning +except Warning: + print("Caught DeprecationWarning via Warning") + +try: + raise DeprecationWarning +except DeprecationWarning: + print("Caught DeprecationWarning") + +try: + raise EOFError +except Exception: + print("Caught EOFError via Exception") + +try: + raise EOFError +except EOFError: + print("Caught EOFError") + +try: + raise EnvironmentError +except Exception: + print("Caught EnvironmentError via Exception") + +try: + raise EnvironmentError +except EnvironmentError: + print("Caught EnvironmentError") + +try: + raise Exception +except BaseException: + print("Caught Exception via BaseException") + +try: + raise Exception +except Exception: + print("Caught Exception") + +try: + raise FloatingPointError +except ArithmeticError: + print("Caught FloatingPointError via ArithmeticError") + +try: + raise FloatingPointError +except FloatingPointError: + print("Caught FloatingPointError") + +try: + raise FutureWarning +except Warning: + print("Caught FutureWarning via Warning") + +try: + raise FutureWarning +except FutureWarning: + print("Caught FutureWarning") + +try: + raise IOError +except Exception: + print("Caught IOError via Exception") + +try: + raise IOError +except IOError: + print("Caught IOError") + +try: + raise ImportError +except Exception: + print("Caught ImportError via Exception") + +try: + raise ImportError +except ImportError: + print("Caught ImportError") + +try: + raise ImportWarning +except Warning: + print("Caught ImportWarning via Warning") + +try: + raise ImportWarning +except ImportWarning: + print("Caught ImportWarning") + +try: + raise IndentationError +except SyntaxError: + print("Caught IndentationError via SyntaxError") + +try: + raise IndentationError +except IndentationError: + print("Caught IndentationError") + +try: + raise IndexError +except LookupError: + print("Caught IndexError via LookupError") + +try: + raise IndexError +except IndexError: + print("Caught IndexError") + +try: + raise KeyError +except LookupError: + print("Caught KeyError via LookupError") + +try: + raise KeyError +except KeyError: + print("Caught KeyError") + +try: + raise LookupError +except Exception: + print("Caught LookupError via Exception") + +try: + raise LookupError +except LookupError: + print("Caught LookupError") + +try: + raise MemoryError +except Exception: + print("Caught MemoryError via Exception") + +try: + raise MemoryError +except MemoryError: + print("Caught MemoryError") + +try: + raise NameError +except Exception: + print("Caught NameError via Exception") + +try: + raise NameError +except NameError: + print("Caught NameError") + +try: + raise NotImplementedError +except RuntimeError: + print("Caught NotImplementedError via RuntimeError") + +try: + raise NotImplementedError +except NotImplementedError: + print("Caught NotImplementedError") + +try: + raise OSError +except Exception: + print("Caught OSError via Exception") + +try: + raise OSError +except OSError: + print("Caught OSError") + +try: + raise OverflowError +except ArithmeticError: + print("Caught OverflowError via ArithmeticError") + +try: + raise OverflowError +except OverflowError: + print("Caught OverflowError") + +try: + raise PendingDeprecationWarning +except Warning: + print("Caught PendingDeprecationWarning via Warning") + +try: + raise PendingDeprecationWarning +except PendingDeprecationWarning: + print("Caught PendingDeprecationWarning") + +try: + raise ReferenceError +except Exception: + print("Caught ReferenceError via Exception") + +try: + raise ReferenceError +except ReferenceError: + print("Caught ReferenceError") + +try: + raise ResourceWarning +except Warning: + print("Caught ResourceWarning via Warning") + +try: + raise ResourceWarning +except ResourceWarning: + print("Caught ResourceWarning") + +try: + raise RuntimeError +except Exception: + print("Caught RuntimeError via Exception") + +try: + raise RuntimeError +except RuntimeError: + print("Caught RuntimeError") + +try: + raise RuntimeWarning +except Warning: + print("Caught RuntimeWarning via Warning") + +try: + raise RuntimeWarning +except RuntimeWarning: + print("Caught RuntimeWarning") + +try: + raise SyntaxError +except Exception: + print("Caught SyntaxError via Exception") + +try: + raise SyntaxError +except SyntaxError: + print("Caught SyntaxError") + +try: + raise SyntaxWarning +except Warning: + print("Caught SyntaxWarning via Warning") + +try: + raise SyntaxWarning +except SyntaxWarning: + print("Caught SyntaxWarning") + +try: + raise SystemError +except Exception: + print("Caught SystemError via Exception") + +try: + raise SystemError +except SystemError: + print("Caught SystemError") + +try: + raise TabError +except IndentationError: + print("Caught TabError via IndentationError") + +try: + raise TabError +except TabError: + print("Caught TabError") + +try: + raise TypeError +except Exception: + print("Caught TypeError via Exception") + +try: + raise TypeError +except TypeError: + print("Caught TypeError") + +try: + raise UnboundLocalError +except NameError: + print("Caught UnboundLocalError via NameError") + +try: + raise UnboundLocalError +except UnboundLocalError: + print("Caught UnboundLocalError") + +try: + raise UserWarning +except Warning: + print("Caught UserWarning via Warning") + +try: + raise UserWarning +except UserWarning: + print("Caught UserWarning") + +try: + raise ValueError +except Exception: + print("Caught ValueError via Exception") + +try: + raise ValueError +except ValueError: + print("Caught ValueError") + +try: + raise Warning +except Exception: + print("Caught Warning via Exception") + +try: + raise Warning +except Warning: + print("Caught Warning") + +try: + raise ZeroDivisionError +except ArithmeticError: + print("Caught ZeroDivisionError via ArithmeticError") + +try: + raise ZeroDivisionError +except ZeroDivisionError: + print("Caught ZeroDivisionError") + diff --git a/tests/basics/floordivide.py b/tests/basics/floordivide.py new file mode 100644 index 0000000000..930313d6c1 --- /dev/null +++ b/tests/basics/floordivide.py @@ -0,0 +1,29 @@ +# check modulo matches python definition + +# This tests compiler version +print(123 // 7) +print(-123 // 7) +print(123 // -7) +print(-123 // -7) + +a = 10000001 +b = 10000000 +print(a // b) +print(a // -b) +print(-a // b) +print(-a // -b) + +if True: + a = 987654321987987987987987987987 + b = 19 + + print(a // b) + print(a // -b) + print(-a // b) + print(-a // -b) + a = 10000000000000000000000000000000000000000000 + b = 100 + print(a // b) + print(a // -b) + print(-a // b) + print(-a // -b) diff --git a/tests/basics/math-fun-bool.py b/tests/basics/math-fun-bool.py new file mode 100644 index 0000000000..cf718d4b80 --- /dev/null +++ b/tests/basics/math-fun-bool.py @@ -0,0 +1,12 @@ +# Test the bool functions from math + +from math import isfinite, isnan, isinf + +test_values = [1, 0, -1, 1.0, 0.0, -1.0, float('NaN'), float('Inf'), + -float('NaN'), -float('Inf')] + +functions = [isfinite, isnan, isinf] + +for val in test_values: + for f in functions: + print(f(val)) diff --git a/tests/basics/math-fun.py b/tests/basics/math-fun.py index f5ffbf40d5..1301dc2a5b 100644 --- a/tests/basics/math-fun.py +++ b/tests/basics/math-fun.py @@ -5,8 +5,6 @@ from math import * test_values = [-100., -1.23456, -1, -0.5, 0.0, 0.5, 1.23456, 100.] p_test_values = [0.1, 0.5, 1.23456] unit_range_test_values = [-1., -0.75, -0.5, -0.25, 0., 0.25, 0.5, 0.75, 1.] -#IEEE_test_values = [1, 0, float('NaN'), float('Inf'), -float('NaN'), -float('Inf')] -#TODO: float('NaN') functions = [(sqrt, p_test_values), (exp, test_values), @@ -30,7 +28,6 @@ functions = [(sqrt, p_test_values), (fabs, test_values), (floor, test_values), #(frexp, test_values), - #(isfinite, [1, 0, float('NaN'), float('Inf')]) (trunc, test_values) ] @@ -42,8 +39,8 @@ binary_functions = [(copysign, [(23., 42.), (-23., 42.), (23., -42.), (-23., -42.), (1., 0.0), (1., -0.0)]) ] -#for function, test_vals in binary_functions: -# for value1, value2 in test_vals: -# print("{:8.7f}".format(function(value1, value2))) +for function, test_vals in binary_functions: + for value1, value2 in test_vals: + print("{:8.7f}".format(function(value1, value2))) diff --git a/tests/basics/modulo.py b/tests/basics/modulo.py new file mode 100644 index 0000000000..4d83db6ec8 --- /dev/null +++ b/tests/basics/modulo.py @@ -0,0 +1,36 @@ +# check modulo matches python definition +# This test compiler version +print(123 % 7) +print(-123 % 7) +print(123 % -7) +print(-123 % -7) + +a = 321 +b = 19 +print(a % b) +print(a % -b) +print(-a % b) +print(-a % -b) + + +a = 987654321987987987987987987987 +b = 19 + +print(a % b) +print(a % -b) +print(-a % b) +print(-a % -b) + +if False: + print(1.23456 % 0.7) + print(-1.23456 % 0.7) + print(1.23456 % -0.7) + print(-1.23456 % -0.7) + + a = 1.23456 + b = 0.7 + print(a % b) + print(a % -b) + print(-a % b) + print(-a % -b) +