Commit 99f364e5 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #837 from Daetalus/test_int

Some improvements for int to let test_int could pass
parents 1b9d802e c5669633
# expected: fail
import sys
import unittest
......
# expected: fail
# Python test set -- math module
# XXXX Should not do tests around zero only
......
......@@ -1932,12 +1932,7 @@ extern "C" PyObject* _PyNumber_ConvertIntegralToInt(PyObject* integral, const ch
non_integral_error:
if (PyInstance_Check(integral)) {
fatalOrError(PyExc_NotImplementedError, "unimplemented");
return nullptr;
/* cpython has this:
type_name = PyString_AS_STRING(((PyInstanceObject *)integral)
->in_class->cl_name);
*/
type_name = static_cast<BoxedInstance*>(integral)->inst_cls->name->data();
} else {
type_name = integral->cls->tp_name;
}
......
......@@ -102,6 +102,19 @@ extern "C" Box* abs_(Box* x) {
}
}
extern "C" Box* binFunc(Box* x) {
static BoxedString* bin_str = internStringImmortal("__bin__");
CallattrFlags callattr_flags{.cls_only = true, .null_on_nonexistent = true, .argspec = ArgPassSpec(0) };
Box* r = callattr(x, bin_str, callattr_flags, NULL, NULL, NULL, NULL, NULL);
if (!r)
raiseExcHelper(TypeError, "bin() argument can't be converted to bin");
if (!PyString_Check(r))
raiseExcHelper(TypeError, "__bin__() returned non-string (type %.200s)", r->cls->tp_name);
return r;
}
extern "C" Box* hexFunc(Box* x) {
static BoxedString* hex_str = internStringImmortal("__hex__");
CallattrFlags callattr_flags{.cls_only = true, .null_on_nonexistent = true, .argspec = ArgPassSpec(0) };
......@@ -1483,6 +1496,8 @@ void setupBuiltins() {
builtins_module->giveAttr("hash", hash_obj);
abs_obj = new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)abs_, UNKNOWN, 1), "abs");
builtins_module->giveAttr("abs", abs_obj);
builtins_module->giveAttr("bin",
new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)binFunc, UNKNOWN, 1), "bin"));
builtins_module->giveAttr("hex",
new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)hexFunc, UNKNOWN, 1), "hex"));
builtins_module->giveAttr("oct",
......
......@@ -1292,13 +1292,33 @@ Box* instanceInvert(Box* _inst) {
return runtimeCall(invert_func, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
}
Box* instanceTrunc(BoxedInstance* _inst) {
RELEASE_ASSERT(_inst->cls == instance_cls, "");
BoxedInstance* inst = static_cast<BoxedInstance*>(_inst);
static BoxedString* trunc_str = internStringImmortal("__trunc__");
Box* trunc_func = _instanceGetattribute(inst, trunc_str, true);
return runtimeCall(trunc_func, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
}
Box* instanceInt(Box* _inst) {
RELEASE_ASSERT(_inst->cls == instance_cls, "");
BoxedInstance* inst = static_cast<BoxedInstance*>(_inst);
static BoxedString* int_str = internStringImmortal("__int__");
Box* int_func = _instanceGetattribute(inst, int_str, true);
return runtimeCall(int_func, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
if (PyObject_HasAttr((PyObject*)inst, int_str)) {
Box* int_func = _instanceGetattribute(inst, int_str, true);
return runtimeCall(int_func, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
}
Box* truncated = instanceTrunc(inst);
/* __trunc__ is specified to return an Integral type, but
int() needs to return an int. */
Box* res = _PyNumber_ConvertIntegralToInt(truncated, "__trunc__ returned non-Integral (type %.200s)");
if (!res)
throwCAPIException();
return res;
}
Box* instanceLong(Box* _inst) {
......
......@@ -320,8 +320,8 @@ extern "C" Box* div_i64_i64(i64 lhs, i64 rhs) {
#if PYSTON_INT_MIN < -PYSTON_INT_MAX
static_assert(PYSTON_INT_MIN == -PYSTON_INT_MAX - 1, "");
if (lhs == PYSTON_INT_MIN && rhs == -1) {
return longDiv(boxLong(lhs), boxLong(rhs));
if (lhs == PYSTON_INT_MIN) {
return longInt(longDiv(boxLong(lhs), boxLong(rhs)));
}
#endif
......@@ -828,6 +828,14 @@ extern "C" Box* intHash(BoxedInt* self) {
return boxInt(self->n);
}
extern "C" Box* intBin(BoxedInt* self) {
if (!PyInt_Check(self))
raiseExcHelper(TypeError, "descriptor '__bin__' requires a 'int' object but received a '%s'",
getTypeName(self));
return _PyInt_Format(reinterpret_cast<PyIntObject*>(self), 2, 0);
}
extern "C" Box* intHex(BoxedInt* self) {
if (!PyInt_Check(self))
raiseExcHelper(TypeError, "descriptor '__hex__' requires a 'int' object but received a '%s'",
......@@ -886,12 +894,30 @@ extern "C" Box* intIndex(BoxedInt* v) {
template <ExceptionStyle S> static Box* _intNew(Box* val, Box* base) noexcept(S == CAPI) {
if (val->cls == int_cls) {
RELEASE_ASSERT(!base, "");
if (base) {
if (S == CAPI) {
PyErr_Format(TypeError, "int() missing string argument");
return NULL;
} else
raiseExcHelper(TypeError, "int() missing string argument");
}
BoxedInt* n = static_cast<BoxedInt*>(val);
if (val->cls == int_cls)
return n;
return new BoxedInt(n->n);
} else if (PyString_Check(val)) {
}
if (!base) {
Box* r = PyNumber_Int(val);
if (!r) {
if (S == CAPI) {
return NULL;
} else
throwCAPIException();
}
return r;
}
if (PyString_Check(val)) {
int base_n;
if (!base)
base_n = 10;
......@@ -899,10 +925,19 @@ template <ExceptionStyle S> static Box* _intNew(Box* val, Box* base) noexcept(S
RELEASE_ASSERT(base->cls == int_cls, "");
base_n = static_cast<BoxedInt*>(base)->n;
}
BoxedString* s = static_cast<BoxedString*>(val);
RELEASE_ASSERT(s->size() == strlen(s->data()), "");
if (s->size() != strlen(s->data())) {
Box* srepr = PyObject_Repr(val);
if (S == CAPI) {
PyErr_Format(PyExc_ValueError, "invalid literal for int() with base %d: %s", base_n,
PyString_AS_STRING(srepr));
return NULL;
} else {
raiseExcHelper(ValueError, "invalid literal for int() with base %d: %s", base_n,
PyString_AS_STRING(srepr));
}
}
Box* r = PyInt_FromString(s->data(), NULL, base_n);
if (!r) {
if (S == CAPI)
......@@ -958,7 +993,8 @@ template <ExceptionStyle S> static Box* _intNew(Box* val, Box* base) noexcept(S
}
return PyLong_FromDouble(wholepart);
} else {
RELEASE_ASSERT(!base, "");
if (base)
raiseExcHelper(TypeError, "TypeError: int() can't convert non-string with explicit base");
static BoxedString* int_str = internStringImmortal("__int__");
Box* r = callattrInternal<S>(val, int_str, CLASS_ONLY, NULL, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
......@@ -1168,6 +1204,7 @@ void setupInt() {
int_cls->tp_hash = (hashfunc)int_hash;
int_cls->giveAttr("__divmod__", new BoxedFunction(boxRTFunction((void*)intDivmod, UNKNOWN, 2)));
int_cls->giveAttr("__bin__", new BoxedFunction(boxRTFunction((void*)intBin, STR, 1)));
int_cls->giveAttr("__hex__", new BoxedFunction(boxRTFunction((void*)intHex, STR, 1)));
int_cls->giveAttr("__oct__", new BoxedFunction(boxRTFunction((void*)intOct, STR, 1)));
......
......@@ -167,8 +167,6 @@ extern "C" PY_LONG_LONG PyLong_AsLongLongAndOverflow(PyObject* obj, int* overflo
}
extern "C" PyObject* PyLong_FromString(const char* str, char** pend, int base) noexcept {
RELEASE_ASSERT(pend == NULL, "unsupported");
int sign = 1;
if ((base != 0 && base < 2) || base > 36) {
PyErr_SetString(PyExc_ValueError, "long() arg 2 must be >= 2 and <= 36");
......@@ -207,15 +205,20 @@ extern "C" PyObject* PyLong_FromString(const char* str, char** pend, int base) n
|| (base == 2 && (str[1] == 'b' || str[1] == 'B'))))
str += 2;
BoxedLong* rtn = new BoxedLong();
int r = 0;
if (str[strlen(str) - 1] == 'L') {
std::string without_l(str, strlen(str) - 1);
int r = mpz_init_set_str(rtn->n, without_l.c_str(), base);
RELEASE_ASSERT(r == 0, "");
r = mpz_init_set_str(rtn->n, without_l.c_str(), base);
} else {
int r = mpz_init_set_str(rtn->n, str, base);
RELEASE_ASSERT(r == 0, "");
r = mpz_init_set_str(rtn->n, str, base);
}
if (pend)
*pend = const_cast<char*>(str) + strlen(str);
if (r != 0) {
PyErr_Format(PyExc_ValueError, "invalid literal for long() with base %d: %s", base, str);
return NULL;
}
if (sign == -1)
......@@ -741,6 +744,12 @@ Box* longStr(BoxedLong* v) {
return _PyLong_Format(v, 10, 0 /* no L */, 0);
}
Box* longBin(BoxedLong* v) {
if (!PyLong_Check(v))
raiseExcHelper(TypeError, "descriptor '__bin__' requires a 'long' object but received a '%s'", getTypeName(v));
return _PyLong_Format(v, 2, 0 /* no L */, 0);
}
Box* longHex(BoxedLong* v) {
if (!PyLong_Check(v))
raiseExcHelper(TypeError, "descriptor '__hex__' requires a 'long' object but received a '%s'", getTypeName(v));
......@@ -1368,6 +1377,14 @@ extern "C" Box* longIndex(BoxedLong* v) noexcept {
return rtn;
}
extern "C" Box* longBitLength(BoxedLong* self) noexcept {
if (!PyLong_Check(self))
raiseExcHelper(TypeError, "descriptor 'bit_length' requires a 'long' object but received a '%s'",
getTypeName(self));
size_t bits = mpz_sizeinbase(self->n, 2);
return boxLong(bits);
}
static int convert_binop(PyObject* v, PyObject* w, PyLongObject** a, PyLongObject** b) noexcept {
if (PyLong_Check(v)) {
*a = (PyLongObject*)v;
......@@ -1470,6 +1487,7 @@ void setupLong() {
long_cls->giveAttr("__float__", new BoxedFunction(boxRTFunction((void*)longFloat, UNKNOWN, 1)));
long_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)longRepr, STR, 1)));
long_cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)longStr, STR, 1)));
long_cls->giveAttr("__bin__", new BoxedFunction(boxRTFunction((void*)longBin, STR, 1)));
long_cls->giveAttr("__hex__", new BoxedFunction(boxRTFunction((void*)longHex, STR, 1)));
long_cls->giveAttr("__oct__", new BoxedFunction(boxRTFunction((void*)longOct, STR, 1)));
......@@ -1482,6 +1500,7 @@ void setupLong() {
long_cls->giveAttr("__trunc__", new BoxedFunction(boxRTFunction((void*)longTrunc, UNKNOWN, 1)));
long_cls->giveAttr("__index__", new BoxedFunction(boxRTFunction((void*)longIndex, LONG, 1)));
long_cls->giveAttr("bit_length", new BoxedFunction(boxRTFunction((void*)longBitLength, LONG, 1)));
long_cls->giveAttr("real", new (pyston_getset_cls) BoxedGetsetDescriptor(longLong, NULL, NULL));
long_cls->giveAttr("imag", new (pyston_getset_cls) BoxedGetsetDescriptor(long0, NULL, NULL));
long_cls->giveAttr("conjugate", new BoxedFunction(boxRTFunction((void*)longLong, UNKNOWN, 1)));
......
......@@ -41,23 +41,19 @@ test_extcall f(**kw) crashes if kw isn't a dict
test_file wontfix: we don't destruct file objects when the test wants
test_file2k we abort when you try to open() a directory
test_file_eintr not sure
test_float float(long), a couple unknown things
test_funcattrs we don't allow changing numing of function defaults
test_functools unknown errors
test_generators crash when sending non-None to a just-started generator
test_genexps parser not raising a SyntaxError when assigning to a genexp
test_global SyntaxWarnings for global statements after uses
test_grammar bug in our tokenizer
test_hash number of hash bugs (all representations of '1' don't have the same hash; empty string is supposed to have 0 hash, etc)
test_index slice.indices, old-styl-class __mul__
test_int we assert instead of throw exception
test_io memory/gc issue?
test_iterlen [unknown]
test_itertools [unknown]
test_json 'from test.script_helper import assert_python_ok' fails; sounds like it is trying to look at pycs
test_list longs as slice indices
test_long sys.long_info
test_math float(long); sys.float_info, sys.displayhook
test_module unicode docstrings
test_mutants unknown failure
test_operator PyNumber_Absolute()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment