diff --git a/include/pocketpy/pocketpy.h b/include/pocketpy/pocketpy.h index 590f3914..0872390d 100644 --- a/include/pocketpy/pocketpy.h +++ b/include/pocketpy/pocketpy.h @@ -385,6 +385,7 @@ void py_clearexc(py_StackRef p0); #define ValueError(...) py_exception(tp_ValueError, __VA_ARGS__) #define IndexError(...) py_exception(tp_IndexError, __VA_ARGS__) #define ImportError(...) py_exception(tp_ImportError, __VA_ARGS__) +#define ZeroDivisionError(...) py_exception(tp_ZeroDivisionError, __VA_ARGS__) #define NotImplementedError() py_exception(tp_NotImplementedError, "") #define AttributeError(self, n) \ py_exception(tp_AttributeError, "'%t' object has no attribute '%n'", (self)->type, (n)) diff --git a/src/public/modules.c b/src/public/modules.c index b173d262..7e917e18 100644 --- a/src/public/modules.c +++ b/src/public/modules.c @@ -288,6 +288,11 @@ static bool builtins_sum(int argc, py_Ref argv) { return true; } +static bool builtins_divmod(int argc, py_Ref argv) { + PY_CHECK_ARGC(2); + return pk_callmagic(__divmod__, 2, argv); +} + static bool builtins_print(int argc, py_Ref argv) { int length; py_TValue* args = pk_arrayview(argv, &length); @@ -443,6 +448,7 @@ py_TValue pk_builtins__register() { py_bindfunc(builtins, "hash", builtins_hash); py_bindfunc(builtins, "abs", builtins_abs); py_bindfunc(builtins, "sum", builtins_sum); + py_bindfunc(builtins, "divmod", builtins_divmod); py_bindfunc(builtins, "exec", builtins_exec); py_bindfunc(builtins, "eval", builtins_eval); diff --git a/src/public/py_number.c b/src/public/py_number.c index 1a5003d6..07df271a 100644 --- a/src/public/py_number.c +++ b/src/public/py_number.c @@ -83,8 +83,6 @@ static bool float__truediv__(int argc, py_Ref argv) { return true; } -#define ZeroDivisionError(msg) false - static bool number__pow__(int argc, py_Ref argv) { PY_CHECK_ARGC(2); if(py_isint(&argv[0]) && py_isint(&argv[1])) { @@ -124,7 +122,7 @@ static bool int__floordiv__(int argc, py_Ref argv) { py_i64 lhs = py_toint(&argv[0]); if(py_isint(&argv[1])) { py_i64 rhs = py_toint(&argv[1]); - if(rhs == 0) return -1; + if(rhs == 0) return ZeroDivisionError("integer division or modulo by zero"); py_newint(py_retval(), lhs / rhs); } else { py_newnotimplemented(py_retval()); @@ -145,6 +143,19 @@ static bool int__mod__(int argc, py_Ref argv) { return true; } +static bool int__divmod__(int argc, py_Ref argv) { + PY_CHECK_ARGC(2); + PY_CHECK_ARG_TYPE(1, tp_int); + py_i64 lhs = py_toint(&argv[0]); + py_i64 rhs = py_toint(&argv[1]); + if(rhs == 0) return ZeroDivisionError("integer division or modulo by zero"); + py_newtuple(py_retval(), 2); + ldiv_t res = ldiv(lhs, rhs); + py_newint(py_getslot(py_retval(), 0), res.quot); + py_newint(py_getslot(py_retval(), 1), res.rem); + return true; +} + static bool int__invert__(int argc, py_Ref argv) { PY_CHECK_ARGC(1); py_i64 val = py_toint(&argv[0]); @@ -459,9 +470,10 @@ void pk_number__register() { py_bindmagic(tp_int, __pow__, number__pow__); py_bindmagic(tp_float, __pow__, number__pow__); - // __floordiv__ & __mod__ + // __floordiv__ & __mod__ & __divmod__ py_bindmagic(tp_int, __floordiv__, int__floordiv__); py_bindmagic(tp_int, __mod__, int__mod__); + py_bindmagic(tp_int, __divmod__, int__divmod__); // int.__invert__ & int. py_bindmagic(tp_int, __invert__, int__invert__);