Commit 1c40ea0f authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #552 from undingen/misc_stuff2

Add a bunch of capi and fix a bug inside PyNumber_Int (was throwing a c++ exception)
parents a921480a 76ed92dd
......@@ -79,6 +79,8 @@ PyAPI_FUNC(PyObject *) PyMethod_Class(PyObject *) PYSTON_NOEXCEPT;
*/
PyAPI_FUNC(PyObject *) _PyInstance_Lookup(PyObject *pinst, PyObject *name) PYSTON_NOEXCEPT;
// Pyston change: no longer macros
#if 0
/* Macros for direct access to these values. Type checks are *not*
done, so use with care. */
#define PyMethod_GET_FUNCTION(meth) \
......@@ -87,6 +89,11 @@ PyAPI_FUNC(PyObject *) _PyInstance_Lookup(PyObject *pinst, PyObject *name) PYSTO
(((PyMethodObject *)meth) -> im_self)
#define PyMethod_GET_CLASS(meth) \
(((PyMethodObject *)meth) -> im_class)
#else
#define PyMethod_GET_FUNCTION(meth) PyMethod_Function((PyObject *)(meth))
#define PyMethod_GET_SELF(meth) PyMethod_Self((PyObject *)(meth))
#define PyMethod_GET_CLASS(meth) PyMethod_Class((PyObject *)(meth))
#endif
PyAPI_FUNC(int) PyClass_IsSubclass(PyObject *, PyObject *) PYSTON_NOEXCEPT;
......
......@@ -1808,6 +1808,22 @@ non_integral_error:
return NULL;
}
/* Add a check for embedded NULL-bytes in the argument. */
static PyObject* int_from_string(const char* s, Py_ssize_t len) noexcept {
char* end;
PyObject* x;
x = PyInt_FromString(s, &end, 10);
if (x == NULL)
return NULL;
if (end != s + len) {
PyErr_SetString(PyExc_ValueError, "null byte in argument for int()");
Py_DECREF(x);
return NULL;
}
return x;
}
extern "C" PyObject* PyNumber_Int(PyObject* o) noexcept {
PyNumberMethods* m;
const char* buffer;
......@@ -1837,7 +1853,7 @@ extern "C" PyObject* PyNumber_Int(PyObject* o) noexcept {
return PyInt_FromLong(io->n);
}
PyObject* trunc_func = getattr(o, "__trunc__");
PyObject* trunc_func = PyObject_GetAttrString(o, "__trunc__");
if (trunc_func) {
PyObject* truncated = PyEval_CallObject(trunc_func, NULL);
Py_DECREF(trunc_func);
......@@ -1848,26 +1864,18 @@ extern "C" PyObject* PyNumber_Int(PyObject* o) noexcept {
}
PyErr_Clear(); /* It's not an error if o.__trunc__ doesn't exist. */
// the remainder of PyNumber_Int deals with converting from unicode/string to int
fatalOrError(PyExc_NotImplementedError, "unimplemented string -> int conversion");
return nullptr;
#if 0
if (PyString_Check(o))
return int_from_string(PyString_AS_STRING(o),
PyString_GET_SIZE(o));
return int_from_string(PyString_AS_STRING(o), PyString_GET_SIZE(o));
#ifdef Py_USING_UNICODE
if (PyUnicode_Check(o))
return PyInt_FromUnicode(PyUnicode_AS_UNICODE(o),
PyUnicode_GET_SIZE(o),
10);
return PyInt_FromUnicode(PyUnicode_AS_UNICODE(o), PyUnicode_GET_SIZE(o), 10);
#endif
if (!PyObject_AsCharBuffer(o, &buffer, &buffer_len))
return int_from_string((char*)buffer, buffer_len);
return int_from_string(buffer, buffer_len);
return type_error("int() argument must be a string or a "
"number, not '%.200s'", o);
#endif
"number, not '%.200s'",
o);
}
extern "C" PyObject* PyNumber_Long(PyObject* o) noexcept {
......
......@@ -127,6 +127,12 @@ static PyObject* do_mkvalue(const char** p_format, va_list* p_va, int flags) noe
case 'd':
return PyFloat_FromDouble(va_arg(*p_va, double));
case 'c': {
char p[1];
p[0] = (char)va_arg(*p_va, int);
return PyString_FromStringAndSize(p, 1);
}
case 'N':
case 'S':
case 'O':
......
......@@ -478,6 +478,16 @@ extern "C" PyObject* PyObject_GetAttrString(PyObject* o, const char* attr) noexc
}
}
extern "C" int PyObject_HasAttr(PyObject* v, PyObject* name) noexcept {
PyObject* res = PyObject_GetAttr(v, name);
if (res != NULL) {
Py_DECREF(res);
return 1;
}
PyErr_Clear();
return 0;
}
extern "C" int PyObject_HasAttrString(PyObject* v, const char* name) noexcept {
PyObject* res = PyObject_GetAttrString(v, name);
if (res != NULL) {
......
......@@ -301,8 +301,13 @@ extern "C" int PyObject_SetItem(PyObject* o, PyObject* key, PyObject* v) noexcep
}
extern "C" int PyObject_DelItem(PyObject* o, PyObject* key) noexcept {
fatalOrError(PyExc_NotImplementedError, "unimplemented");
return -1;
try {
delitem(o, key);
return 0;
} catch (ExcInfo e) {
setCAPIException(e);
return -1;
}
}
extern "C" long PyObject_Hash(PyObject* o) noexcept {
......@@ -324,6 +329,63 @@ extern "C" PyObject* _PyObject_NextNotImplemented(PyObject* self) noexcept {
return NULL;
}
extern "C" long _Py_HashDouble(double v) noexcept {
double intpart, fractpart;
int expo;
long hipart;
long x; /* the final hash value */
/* This is designed so that Python numbers of different types
* that compare equal hash to the same value; otherwise comparisons
* of mapping keys will turn out weird.
*/
if (!std::isfinite(v)) {
if (Py_IS_INFINITY(v))
return v < 0 ? -271828 : 314159;
else
return 0;
}
fractpart = modf(v, &intpart);
if (fractpart == 0.0) {
/* This must return the same hash as an equal int or long. */
if (intpart > LONG_MAX / 2 || -intpart > LONG_MAX / 2) {
/* Convert to long and use its hash. */
PyObject* plong; /* converted to Python long */
plong = PyLong_FromDouble(v);
if (plong == NULL)
return -1;
x = PyObject_Hash(plong);
Py_DECREF(plong);
return x;
}
/* Fits in a C long == a Python int, so is its own hash. */
x = (long)intpart;
if (x == -1)
x = -2;
return x;
}
/* The fractional part is non-zero, so we don't have to worry about
* making this match the hash of some other type.
* Use frexp to get at the bits in the double.
* Since the VAX D double format has 56 mantissa bits, which is the
* most of any double format in use, each of these parts may have as
* many as (but no more than) 56 significant bits.
* So, assuming sizeof(long) >= 4, each part can be broken into two
* longs; frexp and multiplication are used to do that.
* Also, since the Cray double format has 15 exponent bits, which is
* the most of any double format in use, shifting the exponent field
* left by 15 won't overflow a long (again assuming sizeof(long) >= 4).
*/
v = frexp(v, &expo);
v *= 2147483648.0; /* 2**31 */
hipart = (long)v; /* take the top 32 bits */
v = (v - (double)hipart) * 2147483648.0; /* get the next 32 bits */
x = hipart + (long)v + (expo << 15);
if (x == -1)
x = -2;
return x;
}
extern "C" long _Py_HashPointer(void* p) noexcept {
long x;
size_t y = (size_t)p;
......
......@@ -636,6 +636,30 @@ extern "C" PyObject* PyMethod_New(PyObject* func, PyObject* self, PyObject* klas
}
}
extern "C" PyObject* PyMethod_Function(PyObject* im) noexcept {
if (!PyMethod_Check(im)) {
PyErr_BadInternalCall();
return NULL;
}
return ((BoxedInstanceMethod*)im)->func;
}
extern "C" PyObject* PyMethod_Self(PyObject* im) noexcept {
if (!PyMethod_Check(im)) {
PyErr_BadInternalCall();
return NULL;
}
return ((BoxedInstanceMethod*)im)->obj;
}
extern "C" PyObject* PyMethod_Class(PyObject* im) noexcept {
if (!PyMethod_Check(im)) {
PyErr_BadInternalCall();
return NULL;
}
return ((BoxedInstanceMethod*)im)->im_class;
}
void setupClassobj() {
classobj_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedClassobj::gcHandler,
offsetof(BoxedClassobj, attrs), 0, sizeof(BoxedClassobj), false, "classobj");
......
......@@ -50,6 +50,10 @@ extern "C" double PyComplex_ImagAsDouble(PyObject* op) noexcept {
}
}
extern "C" PyObject* PyComplex_FromDoubles(double real, double imag) noexcept {
return new BoxedComplex(real, imag);
}
extern "C" PyObject* PyComplex_FromCComplex(Py_complex val) noexcept {
return new BoxedComplex(val.real, val.imag);
}
......
......@@ -728,6 +728,14 @@ Box* floatTrunc(BoxedFloat* self) {
return PyLong_FromDouble(wholepart);
}
Box* floatHash(BoxedFloat* self) {
if (!isSubclass(self->cls, float_cls))
raiseExcHelper(TypeError, "descriptor '__hash__' requires a 'float' object but received a '%s'",
getTypeName(self));
return boxInt(_Py_HashDouble(self->d));
}
extern "C" void printFloat(double d) {
std::string s = floatFmt(d, 12, 'g');
printf("%s", s.c_str());
......@@ -1475,6 +1483,7 @@ void setupFloat() {
float_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)floatRepr, STR, 1)));
float_cls->giveAttr("__trunc__", new BoxedFunction(boxRTFunction((void*)floatTrunc, BOXED_INT, 1)));
float_cls->giveAttr("__hash__", new BoxedFunction(boxRTFunction((void*)floatHash, BOXED_INT, 1)));
float_cls->giveAttr("real", new (pyston_getset_cls) BoxedGetsetDescriptor(floatFloat, NULL, NULL));
float_cls->giveAttr("imag", new (pyston_getset_cls) BoxedGetsetDescriptor(float0, NULL, NULL));
......
......@@ -226,7 +226,7 @@ extern "C" PyObject* PyInt_FromString(const char* s, char** pend, int base) noex
}
#ifdef Py_USING_UNICODE
PyObject* PyInt_FromUnicode(Py_UNICODE* s, Py_ssize_t length, int base) noexcept {
extern "C" PyObject* PyInt_FromUnicode(Py_UNICODE* s, Py_ssize_t length, int base) noexcept {
PyObject* result;
char* buffer = (char*)PyMem_MALLOC(length + 1);
......
......@@ -539,6 +539,24 @@ extern "C" Box* listInsert(BoxedList* self, Box* idx, Box* v) {
return None;
}
extern "C" int PyList_Insert(PyObject* op, Py_ssize_t where, PyObject* newitem) noexcept {
try {
if (!PyList_Check(op)) {
PyErr_BadInternalCall();
return -1;
}
if (newitem == NULL) {
PyErr_BadInternalCall();
return -1;
}
listInsert((BoxedList*)op, boxInt(where), newitem);
return 0;
} catch (ExcInfo e) {
setCAPIException(e);
return -1;
}
}
Box* listMul(BoxedList* self, Box* rhs) {
STAT_TIMER(t0, "us_timer_listMul");
......
......@@ -249,6 +249,15 @@ Box* setClear(BoxedSet* self, Box* v) {
return None;
}
extern "C" int PySet_Clear(PyObject* set) noexcept {
if (!PySet_Check(set)) {
PyErr_BadInternalCall();
return -1;
}
((BoxedSet*)set)->s.clear();
return 0;
}
Box* setUpdate(BoxedSet* self, BoxedTuple* args) {
RELEASE_ASSERT(isSubclass(self->cls, set_cls), "");
......
......@@ -2018,6 +2018,14 @@ static int compareStringRefs(llvm::StringRef a, size_t a_pos, size_t len, llvm::
return llvm::StringRef(a.data() + a_pos, len).compare(str);
}
extern "C" int _PyString_Eq(PyObject* o1, PyObject* o2) noexcept {
assert(PyString_Check(o1));
assert(PyString_Check(o2));
BoxedString* a = (BoxedString*)o1;
BoxedString* b = (BoxedString*)o2;
return a->s() == b->s();
}
Box* strStartswith(BoxedString* self, Box* elt, Box* start, Box** _args) {
Box* end = _args[0];
......
......@@ -1142,6 +1142,16 @@ extern "C" int PySlice_GetIndicesEx(PySliceObject* _r, Py_ssize_t length, Py_ssi
return 0;
}
extern "C" PyObject* PySlice_New(PyObject* start, PyObject* stop, PyObject* step) noexcept {
if (step == NULL)
step = Py_None;
if (start == NULL)
start = Py_None;
if (stop == NULL)
stop = Py_None;
return createSlice(start, stop, step);
}
Box* typeRepr(BoxedClass* self) {
std::string O("");
llvm::raw_string_ostream os(O);
......
......@@ -64,3 +64,4 @@ print (5.0).hex()
print (0.5).as_integer_ratio()
print (0.5).is_integer()
print (1.0).is_integer()
print 1.0.__hash__(), 1.1.__hash__(), -1.1.__hash__()
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